1.
根据定义,p 是一个指向 int 的指针,现在它指向 x[1][1] 这个起始位置。
x[3][3]这个数组可以想象为一个 3x3 的网格,其中 x[0][0]
是网格的左上角元素,x[2][2]
是网格的右下角元素。数组元素按照行优先的顺序存储,即先填充第一行,然后是第二行,最后是第三行。在这个特定的数组中,x[1][1]
表示的是第二行第二列的元素,即元素5。
9 8 7
6 5(x[1][1]) 4
3 2 1
i=0,输出p[0],也就是x[1][1],输出5。(i=1→p[1][2]→元素4)
i=2,输出p[2],也就是x[2][0],输出3。
所以结果是53.
2.
①a=0,b=5,条件为真,a++,b--
②a=1,b=4,条件为真,a++,b--
③a=2,b=3,条件为真,a++,b--
④a=3,b=2,3<2 || 'a'!='@' 条件为真,a++,b--
⑤a=4,b=1,4<1 || 'b'!='@' 条件为真,a++,b--
⑥a=5,b=0,5<0 || '@'!='@' 条件为假,输出结果
即结果是5,0
3.问:循环体A与循环体B的执行次数相同吗?
第一个循环结构:
这个结构首先执行一次do块内的while循环(包括其循环体A),无论条件表达式1的初始值是什么。
如果在第一次执行while(条件表达式1)循环时,条件表达式1就为假,则循环体A不会被执行。但如果为真,则循环体A会反复执行,直到条件表达式1变为假。
随后,外层do-while循环会检查条件表达式2。如果为真,则再次执行内层的while循环(包括循环体A);如果为假,则整个循环结构结束。
第二个循环结构:
这个结构首先检查条件表达式1。如果为真,则执行do-while循环(包括其循环体B),无论条件表达式2的初始值是什么。
循环体B至少会被执行一次,因为这是一个do-while循环。
然后,do-while循环内部会检查条件表达式2。如果为真,则循环体B会再次执行;如果为假,则退出内层do-while循环,但外层while循环可能会根据条件表达式1的当前值继续或结束。
结论:
在给定条件下(即条件表达式1和条件表达式2的初始值、循环体内的操作以及循环体A与B的完全相同),循环体A和循环体B的执行次数将一样。
4.
在 main 函数中,有一个 do-while 循环,循环三次,每次调用 fun 函数并传入 a+i 作为参数。这意味着 fun 函数将分别处理数组 a 的前四个元素(因为 i 从 0 到 2):
当 i=0 时,处理 a[0] 到 a[3],交换 a[0] 和 a[3],即 1 和 4。
当 i=1 时,处理 a[1] 到 a[4],但这里只有 a[1] 和 a[4] 之间的交换是有效的(因为 a[4] 是数组的有效元素,而 a[5] 虽然是数组的一部分但不在本次交换的考虑范围内),即 2 和 5 交换。
当 i=2 时,处理 a[2] 到 a[5],但同样只有 a[2] 和 a[5] 之间的交换是有效的,即 3 和 6 交换。
最后,打印出数组 a 的所有元素。
根据上述逻辑,数组 a 的最终状态将是 {4, 5, 6, 1, 2, 3}。
5.库函数rand()的功能是产生一个在0~32767之间的随机数。若要用此函数随机产生一个0~99.99(2位小数)之间的数,以能实现此要求的表达式是_
A.(rand ()%10000)/100.0
B.(rand()%10000)/100
C.(rand ()%9000+1000.0)/100.0
D.(rand()%100)/100.0
解析:
A. (rand() % 10000) / 100.0
rand() % 10000 产生一个0到9999之间的整数。
除以100.0后,结果是一个0.00到99.99之间的浮点数,包括两位小数,满足要求。
B. (rand() % 10000) / 100
这将产生一个整数或浮点数(取决于编程语言的整数除法行为),但通常会被截断为整数,不满足题目要求的两位小数。
C. (rand() % 9000 + 1000.0) / 100.0
rand() % 9000 产生一个0到8999之间的整数。
加上1000.0后,范围是1000.0到9999.0。
除以100.0后,结果是10.00到99.99之间的浮点数,虽然满足两位小数的要求,但不包括0.00到9.99的范围,因此不完全符合题目要求。
D. (rand() % 100) / 100.0
rand() % 100 产生一个0到99之间的整数。
除以100.0后,结果是一个0.00到0.99之间的浮点数,不包括1.00到99.99的范围,因此不满足题目要求。
综上所述,只有选项A能够产生一个0到99.99之间(包含两位小数)的随机数。
6.
主函数中,pa指向a的值,pb指向b的值。函数fun()中,pa指向的值减1,则a的值减1,得到1.5,最后按照格式输出1.500000。
7.给定定义:
int a = 3;
int *p = &a;
int **q = &p;
则以下叙述中错误的是
A.q是指针变量,*q就是变量a
B.p是指针变量,p指向变量a
C.q指向变量p,所以*q指向变量a
D.*p与**q都代表变量a
解析:
a 是一个整型变量,其值为 3。
p 是一个指向整型的指针,它存储了 a 的地址。
q 是一个指向指针的指针(或称为二级指针),它存储了 p 的地址,即 p 的地址存储在 q 中。
A. q是指针变量,*q就是变量a
这是错误的。q 确实是指针变量,但 *q 是 p,而不是 a。因为 q 指向 p,所以 *q(即 p)是指向 a 的指针,而不是 a 本身。
B. p是指针变量,p指向变量a
这是正确的。p 确实是指针变量,且它指向整型变量 a。
C. q指向变量p,所以*q指向变量a
这是正确的。q 指向 p,而 p 指向 a,所以 *q(即 p)指向 a。
D. *p与**q都代表变量a
这是正确的。*p 是通过 p 指针访问 a 的值,而 **q 首先通过 q 指针访问 p,然后通过 p 指针访问 a 的值,两者都代表 a 的值。
综上所述,错误的选项是 A:q是指针变量,*q就是变量a。
8.有以下不完整函数
int fun(char*p) {
char *t=p;
while( *t++);
return(__);
}
该函数的功能是:计算p所指字符串占用内存单元的个数作为函数值返回。return语句下划线处应填入的是()。
在这个函数中,char *t = p;
首先将 p
指针的值赋给 t
指针,这样 t
和 p
都指向同一个字符串的开始位置。接着,while( *t++ );
这个循环会遍历字符串直到遇到字符串的终止符 \0
。在这个循环中,*t++
首先取得 t
指向的字符(在第一次循环中是字符串的第一个字符),然后 t
指针自增,指向字符串的下一个字符。由于循环的条件是 *t++
的结果(即 t
指向的字符),循环会在 *t
为 \0
(即字符串的结束符)时停止,此时 t
指针已经指向了字符串的末尾字符的下一个位置(即 \0
的位置)。
要计算字符串占用的内存单元个数(包括终止符 \0
),我们需要知道 t
指针最终停止的位置和 p
指针(即字符串开始的位置)之间的差。
因此,return
语句下划线处应填入的是 t - p
。
9.
sub函数的作用是将形参y和x的差赋给了z指向的那个内存地址,所以在sub(10,5,&a),10和5属于值传递,直接将数值10和5分别传递给了变量x和y,而对于a是属于地址传递,也就是a与z指向了同一个存储单元,在执行函数后,a的值随*z变化,但b, c值并不改变,所以此次函数被调用后,a的值为y-x=-5,同理可知,在sub(7,a,&b)后,b的值发生变化,其值为-5-7=-12,在sub(a, b,&c)后,c的值发生变化,其值为-12-(-5)=-7。故本题答案为-5,-12,-7。
10.
根据C语言的语法,x++是在使用x之后,再将x的值加1,在if语句中x的值为5,由于条件判断的结果是false
,所以执行else
分支中的printf ("%d\n",x--);
。这里,x--
是后缀递减运算符,它会在输出x
的当前值(现在为6
,因为x
在if
条件判断后递增了)之后,递减x
的值。但是,重要的是要注意,递减发生在输出之后,所以输出的是x
递减前的值,即6
。
11.
解析:j=&i,j的值就是i的地址,即j*=100,再将j的地址赋给k,即*k=j,那么**k=*j,而j*=100,所以**k=100,最终打印结果为100.
12.
答案:D
解析:
A. a[p-a]
p-a
计算的是指针 p
(指向 a[0]
)与数组名 a
(也视为指向 a[0]
的指针)之间的偏移量,以元素为单位。因为 p
和 a
都指向 a[0]
,所以 p-a
的结果是 0
。因此,a[p-a]
等同于 a[0]
,这是一个正确的引用。
B. *(&a[i])
&a[i]
获取数组 a
中第 i
个元素的地址。然后,*(&a[i])
是对这个地址的解引用,即获取 a[i]
的值。这也是一个正确的引用。
C. p[i]
由于 p
被初始化为指向 a[0]
的指针,p[i]
实际上是对数组 a
中第 i
个元素的引用(因为指针算术会将 i
解释为偏移量)。所以,p[i]
等同于 a[i]
,这是一个正确的引用。
D. *(*(a+i))
在这个表达式中,a+i
计算的是数组 a
中第 i+1
个元素的地址(因为数组索引从0开始)。
*(a+i)
是对这个地址的解引用,即获取 a[i]
的值(一个整数)。但是,外层的 *
试图对这个整数(a[i]
)再次进行解引用,这在C语言中是不合法的,因为整数不是指针。因此,*(*(a+i))
是一个错误的引用。
13.
结果:xyabcABC
解析:
strcat(p1,p2)结果是abcABC,strcpy(str+2,strcat(p1,p2))结果是把字符串"abcABC"复制到str+2开始的位置。
字符串复制函数strcpy():
格式:strcpy(字符串1,字符串2)
功能:将字符串2复制到字符串1
注意:参数字符串2可以是字符数组名,也可以是字符串常量。但参数字符串1必须是字符数组名。
字符串1必须有足够的空间,以便能容纳字符串2。
部分复制:strncpy(字符串1,字符串2,n),复制前n个字符。
字符串连接函数strcat():
格式:strcat(字符串1,字符串2)
功能:连接两个字符串
注意:参数字符串2可以是字符数组名,也可以是字符串常量。但参数字符串1必须是字符数组名。
字符串1必须有足够的空间,以便能容纳字符串2。
14.
解析:
这个二维数组被初始化为只有对角线元素被明确赋值(2, 4, 6),其他元素默认初始化为0。因此,数组aa
的内容是:
2 0 0
0 4 0
0 0 6
这里定义了一个整型变量i
和一个指向整型的指针p
,并将p
初始化为指向aa[0][0]
的地址。
- 当
i=0
时,执行if
语句块:aa[0][1] = *p + 1
,即aa[0][1] = 2 + 1 = 3
。此时p
仍然指向aa[0][0]
。 - 然后打印
*p
的值,即aa[0][0]
的值,输出2
。 - 当
i=1
时,不执行if
语句块,直接执行++p
,使得p
指向aa[0][1]
。 - 然后打印
*p
的值,即aa[0][1]
的值,输出3。
最终程序的输出结果是:23
15.
解析:
当switch后面括孤内的表达式的值与某一个case后面的常量的表达式的值相等时,就执行此case后面的语句(因为case后面的语句没有break,所以后面的语句都会执行一遍),若所有的ease中的常量表达式的值都没有与表达式的值匹配的,就执行default后面的语句。
所以输出结果是:v1=5,v2=8,v3=6,v4=1
16.
答案:C
解析:
w = k; // 将w初始化为k的值
LB: // 标签LB,用于goto语句跳转
if (w == 0) goto LE; // 如果w等于0,跳转到LE标签处
w--; // 将w减1
printf("*"); // 打印一个*
goto LB; // 跳转到标签LB处,形成循环
LE: // 标签LE,表示循环结束
这个程序段的逻辑是:
- 首先,将变量
w
初始化为k
的值。 - 然后,检查
w
是否等于0。如果是,就跳转到标签LE
处,跳出循环。 - 如果
w
不等于0,就执行w--
将w
的值减1,并打印一个*
字符。 - 使用
goto
语句跳转到标签LB
处,再次检查w
的值,如果仍然不等于0,则重复上述步骤(减1并打印*
),直到w
变为0为止。 - 当
w
变为0时,跳过w--
和printf("*")
语句,直接执行到标签LE:
处,表示循环结束。
这个循环的目的是打印出k
个*
字符,其中k
是w
的初始值。例如,如果k
是5,那么程序将打印*****
。
现在,我们来看一下每个选项与这个goto
程序段的等价性:
A. for(w=k; w!=0; w--) printf("*");
- 这个
for
循环与goto
程序段完全等价。它首先初始化w
为k
,然后在w
不等于0的条件下循环,每次循环都将w
减1并打印一个*
。
B. w=k; while(w--!=0) printf("*"); w++;
- 这个循环在逻辑上与
goto
程序段相似,由于w--
在比较之前先对w
进行了减1操作,因此它实际上会在w
从1变为0时停止循环(因为w--
在比较中的值是减1之前的值)。
C. w=k; do { w--; printf("*"); } while(w != 0);
- 这个选项中的
do-while
循环首先无条件地执行一次循环体,其中w
被减1,并打印一个*
。然后,它检查w
是否不等于0。如果w
仍然不等于0(即它还没有被减到0),循环就会继续。这个过程会一直重复,直到w
变为0,此时循环条件变为假,循环结束。 - 但考虑k=0的情况,此选项会无限循环
"*",其他选项不会输出"*",因此不符合题目要求。
D. for(w=k; w; --w) printf("*");
- 这个
for
循环也与goto
程序段等价。它利用了for
循环的隐式条件检查(w
作为条件,当w
为0时视为假),并在每次循环结束时将w
减1。只要w
不为0,就会执行循环体打印*
。
17、有以下程序
#include <stdio.h>
main(){
int a=7, b=0;
do{
b+= a;
a-=1 ;
}while (a--);
printf("%d,%D\n", b, a);
}
执行后的输出结果是
A.16,-1
B.28,1
C.16,0
D.28,0
解析:
第一次循环:b=b+a=0+7=7 ,a=a-1=7-1=6,此时a--,a=5
第二次循环:b=b+a=7+5=12 ,a=a-1=5-1=4,此时a--,a=3
第三次循环:b=b+a=12+3=15 ,a=a-1=3-1=2,此时a--,a=1
第四次循环:b=b+a=15+1=16 ,a=a-1=1-1=0,此时a--(条件为假,退出循环),a=-1
所以输出结果为16,-1,答案选A。
18、有以下程序
#include <stdio.h>
main(){
int x, y=0,z=0,t ;
do
{
scanf(" %d",&x);
t=x>0;
switch (t)
{
case 0 : break;
case 1:y+=x; continue;
}
z+=x;
}while(x);
printf ("%d,%d\n" ,y,z);
}
程序运行时输入:-1 1 -2 2 0<回车>,则输出结果是_
A.1,1 B.1,0 C.3,-3 D.3,0
解析:
第一步输入-1,x=-1, x>0不成立,t=0,跳出switch语句,z=z+x=-1;
第二步输入1,x=1,x>0成立,t=1,y=y+x=1,跳出本次循环,直接执行下一次循环;
第三步输入-2,x=-2,x>0不成立,t=0,跳出switch语句,z=z+x=-3;
第四步输入2,x=2,x>0成立, t=1,y=y+x=3,跳出本次循环,直接执行下一次循环;
第五步输入0,x=0, x>0不成立,t=0,跳出switch语句,z=-z+x=-3,结束do-while循环。
最后输出y=3,z=-3,故选项C正确。
19、有以下程序
#include <stdio.h>
main(){
int x, a=1, b=1 ;
while(1){
scanf("%d",&x);
if(x>0) { a*=x ; break; }
if(x<0)( b*=x ; continue; }
printf("%d,%d\n",a, b);
}
}
程序运行时输入:-1 -2 0 1 2<回车>,则输出结果是
A.1,2 B.2,2 C.-1,1 D.-2,1
解析:
第一步x=-1,x<0成立,b=b*x=-1,a=1,执行continue语句,结束本次循环。
第二步x=-2,x<0成立,b=b*x=2,a=1,执行continue语句,结束本次循环。
第三步x=0,直接执行输出语句,输出1,2。
第四步x=1, x>0成立,b=b*×=2,a=1,执行break语句,直接跳出循环。
故本题答案选A。
20、有以下程序
#include <stdio.h>
main(){
int i, j;
for( i=3; i>0; i--){
for(j=1; j<=i; j++)
putchar ( '*');
for(j=1;j<=3-i; j++)
putchar('#');
putchar('\n');
}
}
执行后输出结果是
A.*** **# *##
B.**# *## ###
C.### ##* #**
D.##* #** ***
解析:
第一步 i=3:第二个for循环j=1, j<=i成立,输出*; j=2,j<=i成立,输出*, j=3, j<=i成立,输出*;第三个for循环中,j=1,j<=3-i=0不成立,直接输出换行符。此时结果为***
第二步 i=2:第二个for循环j=1,j<=i成立,输出*, j=2,j<=i成立,输出*,j=3,j<=i不成立,循环结束;第三个for循环中,j=1,j<=3-i=1成立,输出#;j=2,j<=3-i=1不成立,直接输出换行符。此时结果为*** **#
第三步 i=1:第二个for循环j=1, j<=i成立,输出*,j=2,j<=i不成立,循环结束;第三个for循环中,j=1,j<=3-i=2成立,输出#,j=2,j<=3-i=2成立,输出#,j=3,j<=3-i=2不成立,直接输出换行符。此时结果为*** **# *##
故选项A正确。所以本题答案选A。
21、有以下程序
#include <stdio.h>
int *f(int *s) {
s[1] += 6;
*s = 7;
s += 2; // 指针 s 向前移动两个整数的位置
return s;
}
int main() {
int a[5] = {1, 2, 3, 4, 5}, *p = a;
p = f(p);
printf("%d,%d,%d\n", a[0], a[1], *p);
return 0;
}
程序运行后输出的结果是
A.7,8,3
B.7,8,7
C.9,8,9
D.1,2,1
解析:
1.数组 a
被初始化为 {1, 2, 3, 4, 5}
。
2.指针 p
初始化为指向数组 a
的第一个元素(即 a[0]
)。
3.函数 f
被调用,传入指针 p
(此时 p
指向 a[0]
)。
1.在函数内部,s[1]
被修改为 2 + 6 = 8
(因为 s
指向 a[0]
,所以 s[1]
是 a[1]
)。
2.*s
被设置为 7
,即 a[0]
被修改为 7
。
3.指针 s
向前移动两个整数的位置,现在它指向 a[2]
。
4.函数返回修改后的指针 s
,即指向 a[2]
的指针。
4.在 main
函数中,p
被更新为 f
函数返回的指针,即现在 p
指向 a[2]
。
5.打印 a[0]
、a[1]
和 *p
的值。a[0]
是 7
(因为 *s = 7;
)。a[1]
是 8
(因为 s[1] += 6;
)。*p
是 a[2]
的值,即 3
(因为虽然 p
指向 a[2]
,但 a[2]
的值在 f
函数中未被 修 改)。
因此,程序运行后输出的结果是:7,8,3
22、有以下程序
#include <stdio.h>
void fun(int a[], int n, int flag) {
int i = 0, j, t;
for (i = 0; i < n - 1; i++)
for (j = i + 1; j < n; j++)
if (flag) {
if (a[i] < a[j]) {
t = a[i];
a[i] = a[j];
a[j] = t;
}
} else {
if (a[i] > a[j]) {
t = a[i];
a[i] = a[j];
a[j] = t;
}
}
}
main(){
int c[10]={7,9,10,8,3,5,1,6,2,4}, i ;
fun( c,4,1 );
fun( c+4,6,0);
for ( i=0;i<10; i++ )
printf("%d,",c[i] );
printf("\n");
}
程序运行后输出的结果是:
A.10,9,8,7,1,2,3,4,5,6
B.10,9,8,7,6,5,4,3,2,1
C.7,8,9,10,6,5,4,3,2,1
D.1,2,3,4,5,6,7,8,9,10
解析:
程序中的 fun
函数用于根据 flag
参数对数组进行排序。如果 flag
为 1,则进行降序排序;如果 flag
为 0,则进行升序排序。
首先,程序对数组 c
的前 4 个元素进行降序排序(fun(c, 4, 1);
),然后对其余的 6 个元素(从 c+4
开始)进行升序排序(fun(c+4, 6, 0);
)。
- 降序排序部分 (
fun(c, 4, 1);
):- 原始数组:
7, 9, 10, 8, 3, 5, 1, 6, 2, 4
- 降序排序后(前 4 个元素): 10
, 9, 8, 7, 3, 5, 1, 6, 2, 4
- 原始数组:
- 升序排序部分 (
fun(c+4, 6, 0);
):- 排序前的后半部分:
3, 5, 1, 6, 2, 4
- 升序排序后(后 6 个元素):
1, 2, 3, 4, 5, 6
- 排序前的后半部分:
因此,程序运行后的输出结果是:10,9,8,7,1,2,3,4,5,6
23、有以下程序
#include <stdio.h>
void f1(char *a, char b) {
char c;
c = *a;
*a = b;
b = c; // 注意:这里不能修改b的值,因为b是按值传递的
}
void f2(char a, char b) {
char c;
c = a;
// 注意:这里不能修改a和b的值,因为它们是按值传递的
b = c; // 只在函数内部有效
}
void f3(char *a, char *b) {
char c;
c = *a;
*a = *b;
*b = c;
}
int main() {
char t1, t2;
t1 = 'A';
t2 = 'B';
f3(&t1, &t2);
putchar(t1);
putchar(t2);
t1 = 'A';
t2 = 'B';
f2(t1, t2);
putchar(t1);
putchar(t2);
t1 = 'A';
t2 = 'B';
f1(&t1, t2);
putchar(t1);
putchar(t2);
printf("\n");
return 0;
}
程序运行后输出的结果是:
A.BAABBB
B.ABBABB
C.BABABA
D.BABAAB
解析:
f3 函数:这个函数交换了两个字符变量 t1
和 t2
的值。通过指针,函数内部修改了这两个变量的值。因此,t1
变为 'B'
,t2
变为 'A'
。输出为 BA
。
f2 函数:这个函数尝试交换两个字符变量 a
和 b
的值,但由于它们是按值传递的,函数内部的修改不会影响到原始的变量。因此,t1
和 t2
的值在调用 f2
后不变。输出为 AB
。
f1 函数:这个函数接收一个字符指针 a
和一个字符 b
,然后交换了 *a
(即指针指向的字符)和 b
的值。注意,b
是按值传递的,所以原始的 t2
不会被修改,但 t1
的值会被修改为 b
的值(即 'B'
)。输出为 BB
。
因此,程序运行后的输出结果是:BAABBB。选择答案A。
24、若有语句: int a[3][4],(*p)[4],p = a,则以下选项中叙述错误的是:
A.系统将开辟一个名为p的二维数组,p[0][0]中的值即为a[0][0]中的值
B.p+1代表a[1][0]的地址
C.p中将存放a数组的首地址
D.p+2代表a数组最后一行的首地址
解析:
int a[3][4];
定义了一个3行4列的二维数组 a。
int (*p)[4];
定义了一个指针 p
,这个指针指向一个包含4个整数的数组(即指向一个4元素的整数数组)。
p = a;
将 a
的地址(实际上是 a
数组第一行的地址)赋给 p
。
现在,我们逐一分析每个选项:
A. 系统将开辟一个名为p的二维数组,p[0][0]中的值即为a[0][0]中的值
- 错误。
p
是一个指针,不是二维数组。它指向一个包含4个整数的数组,而不是直接存储这些整数。p[0]
实际上是指向a[0]
(即a
的第一行)的指针,而p[0][0]
则等价于a[0][0]
,但这里的逻辑解释(系统开辟一个名为p的二维数组)是不正确的。
B. p+1代表a[1][0]的地址
- 正确。在对指针进行加减运算时,数字"1是指一个存储单元长度。增1表示指向地址值大(高地址)的方向移动一个存储单元,减1表示向地址值小(低地址)的方向移动一个存储单元。
p
指向a[0]
,因此p+1
指向a
的下一行,即a[1]
,而a[1]
的地址可以视为a[1][0]
的地址(在二维数组的上下文中)。
C. p中将存放a数组的首地址
- 正确(但表述略有模糊)。更准确地说,
p
中将存放a
数组第一行(即a[0]
)的地址。由于二维数组在内存中是连续存储的,且每行大小相同,所以a
数组的首地址和a[0]
的地址在数值上是相同的。
D. p+2代表a数组最后一行的首地址
- 正确。由于
p
指向a[0]
,p+1
指向a[1]
,那么p+2
自然指向a
的第三行(即最后一行),也就是a[2]
的首地址。
综上所述,错误的选项是 A。
25、有以下程序
#include <stdio.h>
int new_div(double a,double b){
return a/b+0.5;
}
main(){
printf(" %d" , new_div(7.8,3.1));
}
程序运行后的输出结果是:
A.0 B.1 C.2 D.3
解析:
new div函数被定义为int类型,所以返回值a/b、+0.5也是int类型。a/b+0.5=8/3+0.5=2+0.5=2.5,转换为整型后,四舍五入经计算得出,返回值为3,故D选项正确。所以本题答案为D。
26、有以下程序
#include <stdio.h>
void change( char* array,int len ){
for(len--; len>=0; len--)
array[len] += 1 ;
}
main()
{
int i;
char array [5]="ABCD";change (array,4);
for(i=0; i<4; i++)
printf("%c," , array[i]);
}
程序运行后的输出结果是:
A. B,C,D,E
B. A,B,C,D
C. C,D,E,F
D. B,D,F,H
解析:
- 循环开始:
len
是4,进入循环体。len--
:len
变为3。array[len]
即array[3]
是'D'
(ASCII 68)。array[len] += 1
:'D'
(ASCII 68)变为'E'
(ASCII 69)。
- 循环继续:
len
是3,继续循环。array[len]
即array[2]
是'C'
(ASCII 67)。array[len] += 1
:'C'
(ASCII 67)变为'D'
(ASCII 68)。
- 循环继续:
len
是2,继续循环。array[len]
即array[1]
是'B'
(ASCII 66)。array[len] += 1
:'B'
(ASCII 66)变为'C'
(ASCII 67)。
- 循环继续:
len
是1,继续循环。array[len]
即array[0]
是'A'
(ASCII 65)。array[len] += 1
:'A'
(ASCII 65)变为'B'
(ASCII 66)。
- 循环结束:
len
是0,但循环条件是len >= 0
,所以这一轮不执行循环体。循环结束。
在for(len--; len>=0; len--)
这个循环中,有两个len--
表达式,但它们的作用和时机是不同的,因此它们是“互不干扰”的。
最后程序输出的结果是:B,C,D,E。选择答案A。
27、设有定义: int x[10],*p=x, i若要为数组x读入数据,以下选项正确的是:
A.
for(i=0; i<10; i++)
scanf(" %d" , p+i);
B.
for (i=0;i<10; i++)
scanf("%d",*p+i);
C.
for(i=0;i<10; i++)
scanf(" %d",*(p+i));
D.
for(i=0; i<10; i++)
scanf("%d",x[i]);
解析:
1.int x[10]
定义了一个整型数组 x
,它有 10 个元素。
2.*p = x
定义了一个整型指针 p
,并将其初始化为指向数组 x
的第一个元素。
3.使用 p+i
可以访问数组 x
的第 i+1
个元素(因为 p
指向 x[0]
,所以 p+1
指向 x[1]
,依此类推)。
4.使用 *(p+i)
或 p[i]
(这两者等价)可以获取数组 x
的第 i
个元素的值。
现在,我们逐一分析选项:
A. for(i=0; i<10; i++) scanf(" %d" , p+i);
这个选项是正确的。p+i
是一个指向 x[i]
的指针,scanf
需要一个指向变量的指针来存储输入的数据,这里 p+i
正好满足这个要求。
B. for (i=0;i<10; i++) scanf("%d",*p+i);
这个选项是错误的。*p
是 x[0]
的值,一个整数,而不是一个指针。因此,*p+i
试图将一个整数和一个整数相加,结果仍然是一个整数,而不是一个地址。scanf
需要一个地址来存储输入的数据,所以这里会导致未定义行为。
C. for(i=0;i<10; i++) scanf(" %d",*(p+i));
这个选项也是错误的。虽然 *(p+i)
可以获取 x[i]
的值,但 scanf
需要一个指向变量的指针,而不是变量的值。因此,这里传递了一个整数(x[i]
的值)给 scanf
,而不是一个地址。
D. for(i=0; i<10; i++) scanf("%d",x[i]);
这个选项同样是错误的。x[i]
是数组 x
的第 i
个元素的值,不是一个地址。scanf
需要一个地址来存储输入的数据,所以这里同样会导致未定义行为。
综上所述,只有选项 A 是正确的。
28、若在定义语句: int a,b,c, *p=&c;之后,接着执行以下选项中的语句,则能正确执行的语句是____。
A.scanf("%d",a,b,c);
B.scanf(”%d%d%d”,a,b, c);
C.scanf("%d”,p);
D.scanf("%d" ,&p);
解析:
A. scanf("%d",a,b,c);
这个语句是错误的,因为scanf
的第二个参数应该是一个地址,而这里a
、b
、c
都是变量名,不是地址。正确的形式应该是使用&
操作符来获取变量的地址,例如&a
、&b
、&c
。
B. scanf("%d%d%d",a,b, c);
这个语句同样是错误的,原因与A选项相同,a
、b
、c
都应该被替换为它们的地址&a
、&b
、&c
。
C. scanf("%d",p);
这个语句是正确的。因为p
是一个指向c
的指针,所以p
存储的是c
的地址。scanf
函数可以通过指针p
来向c
中写入数据。
D. scanf("%d", &p);
这个语句是错误的,因为&p
取得的是指针p
的地址,而不是一个整数变量的地址。p
本身是一个指针变量,存储了c
的地址,但&p
存储的是p
这个指针变量自身的地址,这与我们想要通过scanf
读取一个整数到c
中的目标不符。
因此,答案选择C。
29、有以下函数
int aaa (char *s)
{ char *t=s;
while(*t++);
t--;
return(t-s);
}
以下关于aaa函数的功能叙述正确的是_
A.求字符串s的长度
B.比较两个串的大小
C.将串s复制到串t
D.求字符串s所占字节数
解析:
char *t = s; // 创建一个指针t,并将其初始化为指向s所指向的地址
while(*t++); // 这个循环会一直执行,直到遇到字符串s的末尾('\0'字符)。每次循环,指针t都会向前移动一位。
t--; // 循环结束后,t指向了字符串s的末尾字符'\0'的下一个位置。这里将t回退到'\0'的位置。
return(t-s); // t - s计算的是从s到t(即'\0'字符的位置)之间有多少个字符,也就是字符串s的长度(不包括末尾的'\0'字符)。
答案选择A。
30、若有定义语句: int a[2][3],*p[3];则以下语句正确的是___。
A.p=a;
B.p[0]=a;
C.p[0]=&a[1][2];
D.p[1]=&a;
解析:
int a[2][3];
:这是一个二维数组,有2行3列,总共6个整数元素。
int *p[3];
:这是一个指针数组,包含3个指向整数的指针。
A. p=a;
这个选项是错误的。因为p
是一个指针数组(即一个包含指针的数组),而a
是一个二维数组(或数组的数组)。在C语言中,二维数组名(如a
)可以被视为指向其第一行(即一个包含3个整数的数组)的指针,但这不是一个普通的整数指针,而是一个指向数组的指针,即int (*)[3]
类型,与int *[]
(即p
的类型)不兼容。
B. p[0]=a;
这个选项同样是错误的,但原因与A选项略有不同。p[0]
是一个指向整数的指针(int *
),而a
(或更准确地说是&a[0]
)是一个指向包含3个整数的数组的指针(int (*)[3]
)。因此,类型不匹配,赋值不合法。
C. p[0]=&a[1][2];
这个选项是正确的。&a[1][2]
是取地址操作,它获取的是a
数组中第二行第三个元素的地址(即a[1][2]
的地址)。这个地址是一个指向整数的指针,与p[0]
的类型(int *
)相匹配。
D. p[1]=&a;
这个选项是错误的。&a
是二维数组a
的地址,其类型是指向包含2个int[3]
数组的指针(即int (*)[2][3]
),这与p[1]
(一个int *
类型的指针)不兼容。
综上所述,正确答案是C。
31、有以下程序
#include <stdio.h>
void fun(char *t, char *s) {
while (*t != 0) t++; // 移动到t的末尾
while (*t++ = *s++) != 0); // 从s复制字符到t的末尾,直到遇到s的末尾字符'\0'
}
int main() {
char ss[10] = "acc ";
char aa[10] = "bbxxyy";
fun(ss, aa);
printf("%s,%s\n", ss, aa);
return 0;
}
程序的运行结果是()
A.accxyy, bbxxyy
B.acc, bbxxyy
C.accxxyy,bbxxyy
D.accbbxxyy,bbxxyy
解析:
本题fun函数中第一个while循环是找到字符串t的结束字符,第二个while循环的功能是将宁符串s中的各字符依次存入到字符串t的尾部,由于数组ss与指针变量t指向同一存储单元,所以输出的ss的字符串为" accbbxyy”,字符串aa的内容不变,即"bbxyy"。故本题答案为D
32、已有定义: char str[5][10]={"Monday","Tuesday", "Wednesday" "Thursday" "Friday"},可以正确输出day的语句是
A. puts(*str+15);
B. puts(*(str+1));
C. puts(*str+3);
D. puts((*(str+4)+2));
解析:根据题意,定义了5行10列的二维数组str并存放了五个字符串,其中数组名str代表数组首素地址相当于个行指针,*str等价于str[0]代表二维数组第一行的地址。
因为数组str每一行都有10个元素,所以*str+15代表第二行第六个元素'a'的地址值,puts(*str+15)输出字符串"ay"。str相当于行指针,str+1代表第二行首地址,所以puts(*str+1)输出字符串"Tuesday"; *str+3代表第一行第四个元索'd'的地址值,所以puts(*str+3)输出字符串"day"; *(str+4)+2)代表第五行第三个元素"i"的地址值,所以输出字符串"iday"。因此,本题答案为C。
33、若有定义:int w[3][5];,则以下不能正确表示该数组元素的表达方式是_
A.*(*w+3)
B.*(w+1)[4]
C.*(*(w+1))
D.*(&w[0][0]+1)
解析:本题考查的是数组的表达方式。
选项A:*(*w +3)=*(*(w+0)+3)=*(w[0]+3)=w[0][3],符合数组定义的范围可以正确表示数据元素。
选项B:*( w+1)[4]=*(*(w+1)+4)=*w[5]=w[5][0],超出了数据定义的范围。
选项C:*(*(w+1))=*w[1]=w[1][0],符合数组定义的范围可以正确表示数据元素。
选项D:*(&w[0][0]+1)=*(w[0]+1)=w[0][1],符合数组定义的范围可以正确表示数据元素。
故本题答案为B。
34、以下语句或语句组中,能正确进行字符串赋值的是__。
A.char *sp;*sp="right!";
B.char s[10];s="right!";
C.char s[10];*s= "right!";
D.char *sp="rig ht!";
【正确答案】D
【题目解析】
本题考查的是字符串的赋值。
选项A定义了一个字符型的指针变量sp,则*sp存储的是第一个字符,而选项A中给它赋的是字符串,所以错误,如果将*sp="right"改成sp= "right"就对了,即把字符审"right'的首地址赋始给了指针变量sp;
选项B定义了一个字符型的数组s[10],则s表示代表数组的首地址,而题中给它赋的是字符串,所以错误,要对字符数组赋值,只能在定义数组时,对其进行初始化.
选项C定义了一个字符型的数组s[10],再通过*s给数组元素赋初值,在此,由于*s指的是数组的第一个元素,而题中给它赋的是字符串,所以错误。
故本题答案为D。
35、若有定义:char *x="abcdefghi”;,以下选项中正确运用了strcpy函数的是___。
A.char y[10]; strcpy(y,x[4]);
B.char y[10]; strcpy(++y,&x[1]);
C. char y[10],*s; strcpy(s=y+5,x);
D.char y[10],*s;strcpy(s=y+1,x+1);
【正确答案】D
【题目解析】
本题考查的是用于字符串处理的函数。
选项A中x[4]是取字符e,也就是将宁符复制到y中,strcpy实现的是地址的复制.所以选项A错误.
选项B中++y是错误的,不允许对常量进行自加运算(是一个确定的地址值)所以选项B错.
选项C指针变量s指向了y向后的第5位,则存放时会出现越界问题,所以选项C错。
选项D中,指针变量s指向了y向后的第一位,此时s可存放数据的长度为9,而地址×+1起的字符串的地址长度也刚好为9(包括“\0”),所以开始复制不会出现地址越界问题。
故本题答案为D。
36、