1 如果要将某个宏定义的作用域限定在定义点到某条语句之前,则应该在该条语句前面插入一条命令________________。
【分析】关于宏定义的定义域,教材中有明确说明(pl95)。如果源程序清单中没有命令“#undef”则定义域为定义点到本程序的末尾;如果有命令“ #undef”,则定义域是从定义点到该命令之前。
【答案】 #undef
2 设有下列两条宏定义命令,则表达式“B/B”的值为()
# define A 3+2
# define B A * A
① 1 ② 5 ③25 ④ 17
【分析】首先对表达式中的宏名“B”进行宏替换,替换后的表达式为“A*A/A*A”,再对其中的定名“A”进行宏替换,替换后的表达式为“3+2* 3+2/3+ 2*3+2”,按照算术运算符的优先级别,计算结果为17,所以本题的答案应为④。
【答案】 ④
3 设有宏定义命令“#define ABC(A,B,c)(A)?(B):(c)”,则表达式“ABC(ABC(1,2,3,ABC(2,3,1), ABC(3,2,1))”的运算结果是________________。
【分析】这是带参数的宏,替换后的表达式如下:
((1)?(2):(3))?((2)?(3):(1)):((3)?(2):(1))
第1个圆括号中的条件表达式的值为2;第2个圆括号中的条件表达式的值为3;第3个圆括号中的条件表达式的值为2。上述表达式最后形成的条件表达式为:2?3:2,结果为3。
【答案】 3
4 使用包含命令时,如果包含文件名是用尖括号括住的(即<包含文件名>),则系统将在_____________路径下寻找该包含文件。
【分析】教材中有明确答案(P198)。
【答案】系统规定的
5 假定有下列4个名为p1.c、p2.c、p3.c、p4.c的源程序文件,则其中能正确编译并执行的源程序是()
/* p1.c的文件内容:*/ /* pZ.C的文件内容:*/
main() float f()
{ float x; { float y;
x=f(); scanf("%f",&y);
printf("%f\n",x); return(y);
} }
#include"p1.c"
/* p3.c的文件内容:*/ /* p4.c的文件内容:*/
# include"p1.c" # include"p2.c"
# Include"p2.c" # Include"p1.c"
① p1.c ②p2.c ③p3.c ④p4.c
【分析】分析备选答案①:该程序编译时,将会出现函数f()没有定义的错误。分析备选答案②:该程序清单在预编译时,包含命令将用p1.c的程序清单替换,函数f()的定义在调用之前,所以该程序将会顺利通过编译,并且可以执行,该答案是正确的,符合题意。至于备选答案③和④,均会出现有两个主函数的错误。
【答案】 ②
6 假定前面已经有宏定义命令“#define A 1”,则下列条件编译命令中,正确的是()
① #if A ② #ifdef A ③ #undef A ④#ifndef A
3+2; 3+2; 3+2; 3+2;
#else #elsedef #elseundef #else
3-2; 3-2; 3-2; 3-2;
#endif #enddef #end #end
【分析】分析备选答案①:这是符合教材中介绍的第一种条件编译命令的格式,其中的条件是“A”,这是一个表达式,宏替换后的结果为1(逻辑真),所以该答案是正确的,符合题意。显然其他的备选答案都是错误的。答案②中的#elsedef和#enddef都是错误的;答案③中的#undef、#elseundef和#end都是错误的。答案④中的#end是错误的。
【答案】 ①
7 带参数的主函数中,形式参数argc的数据类型是________________型;argv是指向______________型数据的指针型数组,该数组的长度是_______________。
【分析】教材中有明确答案(p202)。
【答案】 整 或者 int
字符 或者 char
argc 或者 执行主函数时,命令行中的参数数目
8 下列带参宏的功能是交换两个参数值,请填写所缺少的语句。并说明这个宏引用时的注意事项。
#define H(X,Y){X=X+Y;Y=X-Y;_____________;}
宏引用时的注意事项:___________________________________________
【分析】带参宏H(X,Y)对应的一串符号是3条语句,其功能将完成参数X和Y值的交换。
我们来分析这3条语句的具体功能:
第1条语句:X=X+Y X中是X和Y的和,Y值没变,仍是原Y值;
第2条语句:Y=X-Y X没变,仍是X和Y的和,Y中是原X值;.
第3条语句应该完成的功能是:X的值是原Y的位,由于现在的X中是X和Y
的和,Y中是原X的值,所以使用“X=X-Y’就可以使得X获得的是原Y值。
由于带参宏的两个参数(X、Y)在定名对应的一串符号中出现在赋值表达式的左边,所以宏引用时,这些参数对应的实际参数必须是变量。数组元素、*指针变量等,不能是表达式。此外,由于本宏对应的“一串符号”是一个复合语句,因此,本宏的引用只能作为语句,不能作为表达式。
【答案】X=X-Y
实际参数只能是变量、数组元素、*指针变量等,不能是表达式;此外本宏的引用只能是语句形式。
9 阅读下列程序,写出程序运行后的输出结果。
# define XY(X)X?1:0
main()
{ char s[]={"1234567890"},*p=s;
int i= 0;
do{ printf("%c",*( p+i));
# if XY(1)
i+=2;
# else
1++;
#endif
}
while(i<10);
}
【分析】在程序的do-while循环的循环体中有一条条件编译命令,我们来分析一下编译预处理后的这个do-while循环语句是什么。
首先是宏替换,该语句如下:
do{ printf("%c",*(p+i));
# if 1?1:0
i+=2;
# else
1++;
# endif
}
while (i<10);
分析条件编译命令的条件(1?1:0),其值为 1(成立),所以参加编译的是“i+=2;”。因此,实际参加编译的do-while语句如下:
do{ printf("%c",*(p+i));
i+=2;
}
while(i<10);
显然这个循环是输出字符数组s的第0、2、4、6、8个字符。
【答案】13579
10 阅读下列程序,写出程序的主要功能。
main(argc,argv)
int argc;
char *argv[];
{ int i;
for (i=0;i<argc; i++)
printf("%s", argv[i]);
printf("\n");
}
【分析】程序中的次数型循环的控制变量i从0开始,依次等于1、2、3、4、…、直到 i等于argc-1为止。循环体中依次输出argv[i]指向的字符串,即argv[0]指向程序名、argv[1]指向的第1个参数、argv[2]指向的第2个参数、…、直到argv[argv-1]指向的最后一个参数。
【答案】原样输出命令行。
11 编写一个带参数的主函数,将随命令行输入的12个实数按照每行4个数据、共计3行的矩阵格式输出。
【分析】定义一个3行4列的数组,用来存放这12个实数。利用转换函数atof()(在头函数math.h中定义的),将参数argv[1]、argv[2]、…、argv[12]指向的字符率转换成对应的实数存入上述数组。然后利用标准的两重循环按照矩阵格式输出数组中的数据。
【答案】 #include“math.h”
main(argc,argv)
int argc;
char *atgv[];
{ static float[3][4];
int i,j,k=0 ;
for(i=0;i<3;i十十)
for(j=0;j<4;j++)
a[i][j]=atof(argv[i*4+j+1]);
for( i=0 ;i<3 ;i++)
{ for(j=0;j<4;j++)
printf("%10.2f",a[i][j]);
printf("\n");
}
}
12 编一个带参数的主函数,显示某文本文件的内容。文本文件名随命令行输入。
【分析】随命令行输入的文件名对应的字符串是由argv[ l]所指向的,打开文件时可以使用这个指针来指向文件名。依次读取文件中的字符并显示在屏幕上是一个标准的当型循环结构,控制循环的条件可以用“文件尾函数”进行判断。
【答案】#include"stdio.h"
main(argc,argv)
int argc;
char *argv[];
{ FILE *fp;
if((fp=fopen(argv[1],"r"))==NULL)
{ printf("Can not open file!\n");
exit(0);
}
while(!feof(fp))
putcnar(fgetc(fp));
fclose(fp);
}