1、下面程序的输出结果是
int x=3; do { printf(“%d\n”,x-=2); }while(!(--x));
输出:1
-2
解析:x初始值为3,第一次循环中运行printf函数,参数x -= 2的值为1,输出1,此时x = 1,进行判断!(-- x),x先自减1,为0,取非为1(真),进行第二次循环,x先减2,输出-2,此时x=-2,判断!(-- x),x先自减1为-3,取非为0(假),结束循环。
“!”取非操作:不管数值是多少,只要不是0,取非后则为0,若为0,则取非后为1
2、下面程序的输出结果是
void main(){ int a[]={1,7,12,15}; int *p1=a,*p2 = p1++; *p1 += *p2++; printf(“%d %d”,*p1,*p2); }
输出:8、8
解析:首先定义指针p1指向数组a首地址,然后定义指针p2,也指向数组首地址,然后p1自加,也就指向了数组第二个元素。*p1 += *p2++;语句先将p2指向的第一个元素的值加到p1指向的第二个元素的值上,也就是第二个元素值为8,然后p2自加,指向第二个元素(*p2++,*与++优先级相同,从右自左结合,先与++结合,表示语句执行完后p2指向下一个元素,然后与*结合,表示p2现在所指向的第一个元素的值)
3、下面程序的输出结果是
int func(int *p){ return (*p-- = 3) - 1; } void main(){ int arr[]={10,7,5}; int *p = arr + 1; printf(“%d”,func(p) + *p); }
输出:5
解析:p指针首先指向数组arr的第二个元素,首先调用func函数,将实参指针p指向的地址传递给函数形参p,形参执行*p-- = 3,使得p指向的数组第二个元素值为3,然后形参p自减指向第一个元素,但是实参p不变,还是指向第二个元素,此时func返回的值为3 - 1 = 2,然后2 + *p,这里实参p指向第二个元素,值为3
4、下面程序的输出结果是
long fib(int n) { if(n > 2) return (fib(n - 1) + fib(n - 2)); else return 2; //16年这里返回1,注意区别 } void main(){ printf(“%d\n”,fib(3)); }
输出:4
分析:调用fib(3),由于3>2,所以返回fib(2)+fib(1),fib(2)和fib(1)都返回2
5、下面程序的输出结果是
void main() { char c = 48; int i,mark = 01; for(i = 0;i < 5;i ++) { printf(“%c”,c|mark); mark = mark << 1; } }
输出:12480
分析:C=48转换成二进制数就是110000,mark初始为八进制1,循环执行5次,每次先输出c|mark(按位或运算)对应的ASCII字符,然后mark左移1位,即乘以2。第一次循环c为110000,mark为1,c|mark为110001,即十进制49,对应ASCII字符‘1’,然后mark左移为2;第二次循环c|mark为110010,即十进制50,对应ASCII字符‘2’,然后mark左移为4;第三次循环c|mark为110100,即十进制52,对应ASCII字符‘4’,然后mark左移为8;第四次循环c|mark为111000,即十进制56,对应ASCII字符‘8’,然后mark左移为16;第五次循环c|mark为110000,即十进制48,对应ASCII字符‘0’,然后mark左移为32。
在C语言里,整数有三种表示形式:十进制,八进制,十六进制。
其中以数字0开头,由0~7组成的数是八进制。以0X或0x开头,由0~9,A~F或a~f 组成是十六进制。除表示正负的符号外,以1~9开头,由0~9组成是十进制。
1.十进制:除表示正负的符号外,以1~9开头,由0~9组成。如,128,+234,-278。
2,八进制:以0开头,由0~7组成的数。如,0126,050000.
3,十六进制:以0X或0x开头,由0~9,A~F或a~f 组成。如,0x12A,0x5a000.
6、
输出:12480
分析:
“!”取非操作:不管数值是多少,只要不是0,取非后则为0,若为0,则取非后为1
7、下面程序的输出结果是
void main(){ int a,b=0; static int c[10]={9,2,3,4,5,6,7,8,0,1}; for(a=0;a<10;a++) b+=c[a]; printf("%d",b); }
输出:45
分析:程序遍历数组c,将c的每个元素的值累加到b上
8、
struct Stu{ Int num; Int score; }; void main(){ struct Stu stu[3] = {{50,50}, {60,60}, {70,70}}; struct Stu *p; p = stu[0]; }
分析:问哪个选项是不对的?
选*p.num= 50,因为.的优先级高于*,而.是直接取值,改为(*p).num
9、改错
Void main() { char data[]="There are some mistakes in the program"; char *point; char array[30]; //数组长度不够
int i,length; length=0; while(data[1ength]!='\0') length++; //指针运算前没有赋值 for(i=0; i<length; i++,point++) // ‘\0‘也被复制进来 *point=data[i]; array=point; printf("%s\n",array); }分析:程序的目的是将这个字符串输出,原程序中的主要错误是在指 针运算前没有赋初始地址
改正后:
Void main()
{ char data[]="there are some mistakes in the program"; char *point; char array[100];//定义一个数组 int i,length; length=0; while(data[length]!='\0')//求字符串的长度 length++; point=array;//给指针赋首地址,主要修改部分 for(i=0; i<=length; i++,point++) //输出字符串注意这里是<=,\0也被复制进去了 *point=data[i]; printf("%s\n",array); }
10、改错
Int *p,*q; p=malloc(sizeof(int)*20); q=malloc(sizeof(int)*10); … q=p; … free(p); free(q);
分析:由于free(p);已经将p所指内存区域释放掉,又q和p都指向同个内存区域,之后free(q);试图释放一个已经被释放的内存区域,会使程序崩溃。此外原来q指向的内存区域由于指针丢失,会导致内存泄露。
修正方法:删除语句q=p;
11、改错:交换两个字符串
Void swap(char *p, char *q) { Char *temp; *temp=*p; *p=*q; *q=*temp; }
分析:*temp、*p、*q都是指向的一个字符,所以该函数只实现了交换两个字符串的首字符而已
修正:
void swap(char *p, char *q) { char temp[100]; strcpy(temp, p); strcpy(p, q); strcpy(q, temp); }
字符串赋值函数:strcpy(字符数组名1,字符串2),将字符串2的所有字符一个一个复制到字符数组中,直到遇到结束标志 '\0'为止,并将结束标识符也写入字符数组1中
12、改错:用Eratoshenes筛选法求素数,好像程序是个错的,让你修改其中三行,提高效率
Eratoshenes筛选法:
算法分析:
采样筛选法:
(1)、取最小的数2,并声明它是素数,同时筛去它及它的所有倍数
(2)、取未被筛去的数中最小者,声明它是素数,同时筛去它及它的所有倍数
(3)、重复步骤(2),至筛中无数为至,得到所有的素数
本例可使用数组,使数组下标就是200以内的数,让数组元素的值作为筛去与否的标志,这里设数组元素的初值为0,筛去以后就是1
为提高筛选效率:一个合数n必有一个不大于sqrt(n)的正因子,故一个数若是没有小于sqrt(n)的正因子,则说明它是一个素数
代码:
void main() { int prime[201] = {0}; // 已筛去的值为1.未筛去的值为0 int d; int k; int i; for(d = 2;d <= sqrt(200);d++) { // 筛去d的所有倍数 if(prime[d] == 0) { for(k = 2*d;k <= 200;k = k + d) { prime[k] = 1; } } } k = 0; for(i = 2;i <= 200;i++) { if(prime[i] == 0) { printf("%d\t",i); k++; //一行输出5个数 if(k % 5 == 0) { printf("\n"); } } } }
13、输入3.5,输出结果是什么?为什么?如何修改?
void main() { float t; scanf("%f",&t); if(t == 3.5) putchar("Y"); else putchar("N"); }
分析:输出Y(经VC6验证过)因为恰好输入3.5,数位由0补齐,与3.5刚好相等,故输出Y。但是由于浮点数表示都是不精确的,所以不能用“==”判断相等,有几率出现错误结果。
修改方法:为if条件变成“d减3.5”的绝对值小于某一精度
14、C提高效率的方法和原因
①使⽤指针:有些程序⽤其他语⾔也可以实现,但C能够更有效地实现;有些程序⽆法⽤其它语⾔实现,如直接访问硬件,但C却可以。正因为指针可以拥有类似于汇编的寻址⽅式,所以可以使程序更⾼效。
②使⽤宏函数:宏函数仅仅作为预先写好的代码嵌⼊到当前程序,不会产⽣函数调⽤,所以仅仅是占⽤了空间,⽽使程序可以⾼效运⾏。在频繁调⽤同⼀个宏函数的时候,该现象尤其突出。函数和宏函数的区别就在于,宏函数占⽤了⼤量的空间,⽽函数占⽤了时间。
宏函数的例⼦:
③.使⽤位操作:位操作可以减少除法和取模的运算。在计算机程序中数据的位是可以操作的最⼩数据单位,理论上可以⽤"位运算"来完成所有的运算和操作。灵活的位操作可以有效地提⾼程序运⾏的效率。
④.循环嵌套中将较长循环设为内置循环,较短循环设为外置循环,以减少cpu跨切循环层的次数,提⾼程序的运⾏效率。(操作系统页⾯置换相关,减少页⾯置换次数)
⑤.将汇编指令嵌⼊到 C 语⾔程序中,汇编语⾔是效率最⾼的计算机语⾔,因此为了获得程序的⾼效率,可以在C语⾔程序中嵌⼊汇编,从⽽充分利⽤⾼级语⾔和汇编语⾔各⾃的特点。
⑥.在C语⾔程序中可以调⽤系统API,接近底层,从⽽提⾼程序的运⾏效率。
⑦.⼀般情况下,C语⾔源程序中的每⼀⾏代码.都要参加编译。但有时候出于对程序代码优化的考虑.希望只对其中⼀部分内容进⾏编译.此时就需要在程序中加上条件,让编译器只对满⾜条件的代码进⾏编译,将不满
⾜条件的代码舍弃,这就是条件编译
15、C语言,除了关键字,还有哪些单词类型?C的存储类型关键字有哪四个?
分析:
(1)标识符,运算符、分隔符、常量、注释符
(2)关键字:auto、extern、register、static
答: 标识符【只能由字母、常量、下划线、数字组成,且第一个字符必须是字母或者下划线】、运算符、常量和分隔符【空格、制表符、换行符】。
存储类型关键字:anto、extern、register、staticC语言变量有四种存储类型:
自动型(auto)
外部型(extern)
静态型(static)
寄存器型(register)
16、if(B) S1 else S2 用显示结构表示
答:
if(b)goto L1;
s2;goto L2;
L1:s1;
L2:;
17、变量常量填表
类似2018年真题:
7、程序⽚段为: (14分)
当程序执⾏进⼊fun函数时,请列出各个数据(包括常量、变量)在内存中对应存储区的名称和数据的存储顺序以及所占⽤的存储空间的字节数。
假设整数占2个字节,字符占2个字节,指针占4个字节;⽽内存按2个字节进⾏编址。存储区名称1分,其他每3个1分
int n = 2018; void main() { char * p=”COMPUTER”, *q; int mm, arr[2018]; char ch2; ... fun(mm); ... } void fun(int nn) { int mm = 10; static int snum; ... }
18、四个空
19、读程序
void main() { char p[10]="UESTC"; char q[]="xyz"; //记不清这是啥了,不影响做题 int i,j; i=0; while(*(p+i)!='\0') i++; j=0;i++; while(*(q+j)!='\0') { *(p+i)=*(q+j); j++; } printf("%s", p); }
输出: UESTC
20、该程序功能是什么?输出结果是啥?题目给的输入n为5
void main() { char str[][30] = {"turbo c","turbo br","dbase","mdanreiaw","lfjwae","jfawlej"}; int n,i,j; scanf("%d",&n); for(i = 0;i < n - 1;i++) { for(j = i + 1;j <= n - 1;j++) { if(str[i] > str[j]) { swap(str[i],str[j]); } } } }
功能:对前n个字符串进行字典排序;
21、读程序的功能 【2018原题】
#include<stdio.h> void main() { int i,j,k,d,flag1,flag2; scanf("%d",&d); printf("d=%d\n", d); for(i=1; i<=100; i++) { //判断i中是否含有n j=i; flag1 = 0; while((j>0) && (!flag1)) { k=j%10; j=j/10; if(k==d) flag1=1; } //判断j中是否含有n if(flag1) { j=i*i; //j是i 的平方 flag2 = 0; while((j>0) && (!flag2)) { k=j%10; j=j/10 ; if(k==d) flag2=1; } if(flag2) printf("%-5d %-5d\n", i, i*i); } } }
功能:从1-100中找出符合以下条件的数,该数和该数的平方中都含有输入的数字d
22、快排找第K小 【2018原题】
Low=0; high=n-1; do { i=low; j=high; t=a[i]; //填空 do { While(a[j--]>t); While(a[i++]<t); If(i<j) swap(a[j],a[i]);//具体代码实在忘了,反正不是空空,我这样写运行是一样的 }while(i<j); //填空 If(i==k) Return t; //填空 If(i>k) high=i-1; //填空 if(i<k) low=i+1; //填空 }while(low<high); //填空 Return a[low]; //填空
23、在str1中删除出现在str2中的字符,原程序想不起来了,不过是用指针做的。题目的思路就是对于str1中的每一个字符,遍历一遍str2,有则删除0
#include<stdio.h> #include<string.h> main() { char s1[100],s2[100]; int i,j=0,k=0,len; scanf("%s",s1); scanf("%s",s2); len=strlen(s2); for(i=0;s1[i]!='\0';i++) { while(s1[i]!=s2[j]) j++; if(j>=len) {
//填空部分 s1[k]=s1[i]; // 后面的补上 k++; } j=0; } s1[k]='\0'; printf("%s",s1); }
错误!!!书中:
24、链表逆序
方法一:头插法
代码:
#include <stdio.h> #include <stdlib.h> typedef struct slist { int data; struct slist *next; }; struct slist *head; // 尾插法建立链表 void creatslist() { int x; head = (struct slist *)malloc(sizeof(struct slist)); //头结点 struct slist *p,*node; // q为尾指针 p = head; printf("请输入元素:"); scanf("%d",&x); while(x != 9999) { node = (struct slist *)malloc(sizeof(struct slist)); node ->data = x; p ->next = node; p = node; printf("请输入元素:"); scanf("%d",&x); } p ->next = NULL; } //链表输出打印 void inputslist() { struct slist *q;//q是工作指针 q = head ->next; //头结点无元素 while(q != NULL) { printf("%d\t",q ->data); q = q ->next; } } // 方法一:头插法 逆序链表 void reverseslist1() { struct slist *p,*r; // p是工作指针,r是p的后继,以防断链 p = head ->next; //从第一个元素开始 head ->next = NULL; //将头节点后置null,断开 while(p != NULL) { r = p ->next; // r暂存s后继 p ->next = head ->next; // 依次将元素结点摘下 head ->next = p; p = r; } } void main() { creatslist(); inputslist(); printf("\n逆序后:\n"); reverseslist1(); inputslist(); }
方法二: 后继指针指向前驱结点
代码:
#include <stdio.h> #include <stdlib.h> typedef struct slist { int data; struct slist *next; }; struct slist *head; // 尾插法建立链表 void creatslist() { int x; head = (struct slist *)malloc(sizeof(struct slist)); //头结点 struct slist *p,*node; // q为尾指针 p = head; printf("请输入元素:"); scanf("%d",&x); while(x != 9999) { node = (struct slist *)malloc(sizeof(struct slist)); node ->data = x; p ->next = node; p = node; printf("请输入元素:"); scanf("%d",&x); } p ->next = NULL; } //链表输出打印 void inputslist() { struct slist *q;//q是工作指针 q = head ->next; //头结点无元素 while(q != NULL) { printf("%d\t",q ->data); q = q ->next; } } // 方法二:后继指针指向前驱结点 void reverseslist2() { struct slist *pre,*p = head ->next,*r =p ->next; p ->next = NULL; //处理第一个结点 while(r != NULL) // r若为空,则p为最后一个节点 { pre = p; p = r; r = r ->next; p ->next = pre; } head ->next = p; //处理最后一个结点 } void main() { creatslist(); inputslist(); printf("\n逆序后:\n"); reverseslist2(); inputslist(); }
25、如果有两个数,每一个数它的所有约数(除了它本身之外)的和正好等于对方的所有约数(除了它本身之外)的和,则称这两个数为互满数,求出30以内所有的互满数,并输出显示。求互满数函数原型(int factor(int j))
代码:
#include<stdio.h> #define N 30 int k[40]; int factor(int j) { int i,n,s; n=-1; s=j; for (i=1; i<j; i++) { if((j%i)==0) { n++; s=s - i; k[n]=i; // 将每个因子赋给数组K } } s=1; for (i=1; i<=n; i++) s+=k[i]; // 将每个因子累加 return s; } void main() { int s1,s2,m,n; for (m=2; m<N; m++) { s1=factor(m); for (n=m+1; n<N; n++) { s2=factor(n); if(s1==s2)printf("%d和%d是互满数\n",m,n); } } }
26、输入一个字符串,将连续相同的字符删减为一个,以“*”结
代码:
#include <stdio.h> #include <stdlib.h> void main() { char ch_old, ch_new; ch_old = '*'; do { scanf("%c", &ch_new); //scanf():接受用户从键盘上输入的数据,每次接受一个字符 //若输入*,则输出结束,若相同,则结束本次循环,下面的不再执行 if (ch_old == ch_new) continue; ch_old = ch_new; printf("%c", ch_old); }while(ch_new != '*'); }