一、简要回答下列问题
1. 简述C
语言中标识符的规定;在给变量、数组和函数起名时,应注意什么?
答:在计算机高级语言中,用来对变量、符号常量名、函数、数组、类型等命名的有效字符序列统称为标识符,C
语言规定标识符只能由字母、数字、下划线3种字符组成,且第1个字符必须为字母或下划线。
2. 什么是表达式?若在某程序中,已有定义int x
:请问x=5
是表达式吗?若是,其值和类型各是什么?
答:用C
语言运算符将运算对象连接起来的式子叫做表达式,x=5
是表达式,其类型为int
,值为5。
3. 有定义语句char ch
;ch
是什么类型的变量?在内存中占几个字节?可用什么函数求其字节数?此类型变量通常存放什么数据?试举一例。
答:ch
是字符型变量,在内存中占用1个字节,可以通过sizeof
函数求其对应的字节数,此类型变量通常用来存放字符,如char ch = 'A'
定义了一个字符变量ch
其初值为A
,由于其实质上是一个字节的整型变量,故可以将0~127之间的整数赋给一个字符变量。
4. 写出if...else
语句的一般形式,并画出流程图。
答:一般形式如下:
if(表达式){ 语句1 }else{ 语句2 }
流程图如下:
上图中,p
表示判断条件,当判断条件成立时,执行A
框中的程序,若判断条件不成立,则执行B
框中的程序。
5. 写出for
语句的一般形式,并画出流程图。
答:一般形式如下:
for(表达式1;表达式2;表达式3){ 语句 }
其中,表达式1用来设置初始条件,只执行一次;表达式2是循环条件表达式,用来判定是否继续循环;表达式3作为循环调整,一般在循环体后才执行。
流程图如下:
6. 若有以下二维数组的定义float x[3][4]
:请按在内存中的存放次序一一列出x
的每个元素;一般而言,若一个数组有m
列,请问该数组第i
行,第j
列的元素之前有多少个元素?
答:二维数组在内存中的排列顺序是按行存放的,即在内存中先顺序存放第1行元素,接着再存放第2行元素,依此类推,对于二维数组float x[3][4]
来说,其在内存中的存放次序为:x[0][0],x[0][1],x[0][2],x[0][3],x[1][0],x[1][1],x[1][2],x[1][3],x[2][0],x[2][1],x[2][2],x[2][3]
,对于一个有m
列的数组,数组元素a[i][j]
之前有i*m+j
个元素。
7. 一个程序最多能有一个main
函数?main
函数由谁调用?返回值一般用来做什么?
答:一个程序最多有一个main
函数,main
函数是被操作系统调用的,其返回值用于说明程序的退出状态,如果返回0,则代表程序正常退出,返回其他数字的含义则由系统决定,通常情况下,返回非零代表程序异常退出。
8. 若一个指针p
指向了一个整型变量a
,请问变量p
中存放的内容是什么?表达式(char *)p
指向了什么?表达式(char *)p+1
又指向了什么?
答:变量p
中存放的是整型变量a
的地址,(char *)p
指向了一个字符型指针,(char *)p+1
同样也指向一个字符型指针,(char *)p+1
和(char *)p
两个指针之间所指的位置相差一个字节。
请看演示案例:
#include<stdio.h> #include<stdlib.h> int main(){ int a = 3; int *p = &a; printf("%d\n",(char *)(p+1)-(char *)p); // 4 printf("%d\n",(char *)p+1-(char *)p); // 1 return0; }
9. 在一程序中有struct pos2d{int x,int y;};
这个语句定义了什么?pos2d
是什么?系统给它分配内存吗?在此之后又有struct pos2d point;
请问定义了什么?给point
分配了内存吗?若分配,如何得到分配的字节数?
答:该语句定义了一个结构体名为pos2d
的结构体,其中包含了2个成员,分别是整型变量x
和整型变量y
;pos2d
是结构体名;由于上述代码只是建立了一个结构体模型,并没有定义变量,其中并无具体的数据,系统对之也不分配存储单元;struct pos2d point;
定义了一个名为point
的结构体变量,系统会对其分配存储单元,共占用8(4+4)个字节。
10. 某个程序中调用了文件打开函数如下:fp=fopen("file.dat","rb");
请叙述其功能,另外请说出文本文件和二进制文件的区别。
答:该行代码通过fopen
函数以二进制读取模式打开file.dat
文件,若成功打开该文件,则返回一个FILE
类型的指针,若打开失败,则返回NULL
,其返回值被保存在fp
中。
二进制文件和文本文件的区别:
二进制文件 是指数据在内存中以二进制形式存储,且不加转换的输出到外存,可以认为它就是存储在内存的数据映像,即映像文件;如果要求在外存上以ASCII
代码形式存储,则需要在存储前进行转换,ASCII
文件又称 文本文件,每一个字节存放一个字符的ASCII
代码。一般情况下,字符一律以ASCII
形式存储,数值型数据既可以用ASCII
形式存储,也可以用二进制形式存储。
二、程序阅读题
1. 字符指针变量
#include<stdio.h> void f1(char *t,char *s); int main() { char *p="a1b2c3d4e5", st[20]; printf("%s\n",p+2); f1(st,p); printf("%s\n",st); return0; } void f1(char *t,char *s) { int i; for(i=0;*(s+i)!='\0';i++) { *(t++)=*(s+2*i); if(*(s+2*i)=='\0'|| *(s+2*i+1)=='\0'){ break; } } *t='\0'; return ; }
答:程序输出结果如下:
b2c3d4e5 abcde
该程序首先声明了一个名为f1
的函数,该函数接收两个参数,分别为指向char
类型的指针变量t
和指向char
类型的指针变量s
,在f1
函数中,有一个for
循环,用来将指针变量s
所指字符串中偶数位置的字符复制到指针变量t
所指的字符串中,即指针变量t
所指的字符串中存放的是指针变量s
所指字符串中偶数位置对应的字符,执行完成上述操作,在指针变量t
所指的字符串末尾手动添加\0
作为有效字符串的结束标志,在主程序中,首先定义了一个字符指针变量p
,默认情况下该指针变量p
中保存的是字符串a1b2c3d4e5
第一个字符的地址,接着通过printf("%s\n",p+2);
进行输出,则指针变量p+2
应指向字符b
的位置,故最终输出结果为:b2c3d4e5
,接着在主程序中调用f1
函数,并进行输出,即将原字符串中偶数位置的字符进行输出,即abcde
。
2. switch-case
语句
#include<stdio.h> int main() { float score; char grade; int i,k; for(i=0;i<5;i++) { scanf("%f",&score); k=(int)(score/10); if(score>100){ k++; } switch(k) { case0: case1: case2: case3: case4: case5:grade='E';break; case6:grade='D';break; case7:grade='C';break; case8:grade='B';break; case9: case10:grade='A';break; default: grade='n'; } if(grade=='n') { printf("input data wrong!\n"); } else { printf("score=%6.1f-->grade=%c\n",score,grade); } } return0; }
答:程序输出结果如下:
33.5 score= 33.5-->grade=E 89.2 score= 89.2-->grade=B 93.6 score= 93.6-->grade=A 100 score= 100.0-->grade=A 101 input data wrong!
该程序中首先声明了一个float
类型的变量score
和一个char
类型的变量grade
,接着声明了两个整型变量i
和k
,在for
循环中,首先从键盘上接收用户输入的score
值,接着将score
值除以10并强制取整,将其计算结果赋值给整型变量k
,若score
值大于100,则执行k++
操作,接着执行switch-case
语句,根据不同的k
值返回不同的grade
值,最后根据if..else
选择语句进行判断,如果对应grade
值为n
,则输出input data wrong!
字样,否则输出对应score
值及其对应的grade
值,循环共执行5次。
举例如下,当输入score
值为33.5时,k=3
,grade
值为E
,故最终输出结果为:score= 33.5-->grade=E
;当输入score
值为89.2时,k=8
,grade
值为B
,故最终输出结果为:score= 89.2-->grade=B
;当输入score
值为93.6时,k=9
,grade
值为A
,故最终输出结果为:score= 93.6-->grade=A
;当输入值score
为100时,k=10
,grade
值为A
,故最终输出结果为:score= 100.0-->grade=A
;当输入score
值为101时候,k=11
,grade
值为n
,故最终输出结果为:input data wrong!
。
3. 字符相减
#include<stdio.h> int MyStrCmp(char *s,char *t); int main() { char *str1="ab",*str2="ac",*str3="AB"; char *str4="abc",*str5="ab",*str6="a"; printf("%d\n",MyStrCmp(str1,str2)); printf("%d\n",MyStrCmp(str1,str3)); printf("%d\n",MyStrCmp(str1,str4)); printf("%d\n",MyStrCmp(str1,str5)); printf("%d\n",MyStrCmp(str1,str6)); return0; } int MyStrCmp(char *s,char *t) { int r; while(*s !='\0' && *t !='\0') { if(*s!=*t){ break; } s++; t++; } r=*s - *t; return r; }
答:程序运行输出结果如下:
-1 32 -99 0 98
该程序首先声明了一个名为MyStrCmp
的函数,该函数接收两个参数,用于对两个字符串参数进行比较,比较过程中遇到第一个不相等的字符时,返回其对应字符相减的差值,若两字符串相等,则返回值为0。在主程序中,定义了6个字符指针变量,接着分别调用5次MyStrCmp
函数返回其对应结果。
举例如下:当MyStrCmpy
函数的参数为字符指针变量str1
和str2
时,其最终返回结果为-1,即98-99=-1
;当MyStrCmpy
函数的参数为字符指针变量str1
和str3
时,其最终返回结果为32,即97-65=32
;当MyStrCmpy
函数的参数为字符指针变量str1
和str4
时,其最终返回结果为-99,即0-99=-99
;当MyStrCmpy
函数的参数为字符指针变量str1
和str5
时,其最终返回结果为0,即0-0=0
;当MyStrCmpy
函数的参数为字符指针变量str1
和str6
时,其最终返回结果为98,即98-0=98
。
4. 静态局部变量static
#include<stdio.h> int fun(void); int main() { int i; for(i=0;i<5;i++){ printf("%d\n",fun()); } return0; } int fun(void) { staticint f1=1,f2=1; int r; r=f1+f2; f1=f2; f2=r; return r; }
答:程序运行输出结果如下:
2 3 5 8 13
该程序首先声明了一个名为fun
的无参函数,接着在主程序中通过for
循环调用了5次fun
函数,在fun
函数的定义中,整型变量f1
和f2
被声明为静态局部变量,故其值在函数调用完成后不消失,在下一次调用该函数时,该变量对应的值即为上一次函数调用结束时的值。
举例如下:当第一次循环结束时,各变量对应值分别为:r= f1+f2=1+1=2,f1=1,f2=2
,故第一次程序返回结果为2;当第二次循环结束时,各变量对应值分别为:r=f1+f2=1+2=3,f1=2,f2=3
,故第二次程序返回结果为3;当第三次循环结束时,各变量对应值分别为:r=f1+f2=2+3=5,f1=3,f2=5
,故第三次程序返回结果为5;当第四次循环结束时,各变量对应值分别为:r=f1+f2=3+5=8,f1=5,f2=8
,故第四次程序返回结果为8;当第五次循环结束时,各变量对应值分别为:r=f1+f2=5+8=13,f1=8,f2=13
,故第五次程序返回结果为13,综上所述,以上五次循环结束时程序的返回结果即为本程序的最终输出结果。
5. 结构体 + 文件操作 + 排序
#include<stdio.h> struct person { char name[40]; int age; }; void MyFunc (struct person *ps,int n); int main() { struct person team[5]; FILE *fp; int i; fp=fopen("input.txt","r"); if(fp==NULL) return1; for(i=0;i<5;i++){ fscanf(fp,"%s%d",team[i].name,&(team[i].age)); } fclose(fp); MyFunc (team,5); for(i=0;i<5;i++){ printf("%s %d\n",team[i].name,team[i].age); } return0; } void MyFunc (struct person *ps,int n){ int i,j,k; struct person t; for(i=0;i<n-1;i++) { k=i; for(j=i+1;j<n;j++){ if(ps[j].age>ps[k].age)k=j; } t=ps[i]; ps[i]=ps[k]; ps[k]=t; } return; }
答:程序运行输出结果如下:
zh3 88 li4 55 ma6 35 zhao7 28 wang5 10
本程序首先定义了一个名为person
的结构体,其中包含name
和age
两个成员,接着,在主程序中以只读模式打开input.txt
数据文件,成功打开后,逐个读入name
和age
对应的内容,读取完成后关闭该文件,继续执行MyFunc
函数,该函数的功能是对结构体中的数据按照年龄从大到小进行排序,故所得结果如上所示。
三、编程题
1. 编写程序输出100到200之间的全部素数(素数指只能被1和自己整除,而不能被其他数整除的整数)。
答:程序如下所示:
#include<stdio.h> int main(){ int i, j; for (i = 100; i <=200; i++){ for (j = 2; j < i; j++){ if (i%j == 0){ break; } } if (j==i){ printf("%d\n", i); } } return0; }
2. 编写一个函数完成两个整型变量内容的对换,要求采用指针参数;并编写一个调用该函数的主函数,读入键盘输入的10个整数,并对其从小到大排序,将其排序结果输出。
答:交换两整型变量内容的程序如下所示:
#include<stdio.h> int main(){ void swap(int *p1,int *p2); int a,b; int *pointer_1,*pointer_2; printf("请输入两个整数:"); scanf("%d %d",&a,&b); pointer_1 = &a; pointer_2 = &b; swap(pointer_1, pointer_2); printf("a = %d,b = %d\n",a,b); return0; } // 交换两个指针所指向的内容 void swap(int *p1,int *p2){ int temp; temp = *p1; *p1 = *p2; *p2 = temp; }
排序的代码如下:(提示:选择排序、冒泡排序均可)
#include<stdio.h> int main(){ void sort(int arr[],int n); int *p,arr[10]; p = arr; printf("请输入数组元素:"); for (int i = 0; i < 10; i++) { scanf("%d",p++); } p = arr; sort(p, 10); printf("由小到大的顺序为:\n"); for (p = arr; p < (arr+10); p++) { printf("%3d",*p); } printf("\n"); return0; } // 选择排序 void sort(int *arr,int n){ void swap(int *p1,int *p2); int i,j,k; for (i = 0; i < n-1; i++) { k = i; for (j = k+1; j < n; j++) { if(*(arr+j)<*(arr+k)){ k = j; } } if(k!=i){ swap(arr+i,arr+k); } } } // 交换两个指针所指向的内容 void swap(int *p1,int *p2){ int temp; temp = *p1; *p1 = *p2; *p2 = temp; }
3. 编写一函数,统计给定字符串中某字符出现的次数,并编写一个调用它的主函数,对键盘输入的字符串,分别统计@
和#
出现的次数。
答:程序如下所示:
#include<stdio.h> int main(){ int chCount(char str[],char ch); char str[100]; printf("请输入一个字符串:\n"); scanf("%s",str); printf("@出现的次数为:%d,#出现的次数为:%d\n",chCount(str,'@'),chCount(str,'#')); return0; } // 统计特定字符出现的次数 int chCount(char str[],char ch){ int count = 0; for (int i = 0; str[i]!='\0'; i++) { if(str[i]==ch){ count++; } } return count; }
4. 从键盘输入40个学生的数据,每个学生的数据包括姓名(假定中间无空格)、三门课成绩,计算每个同学三门课的平均成绩,并将每个同学的姓名、三门课成绩以及平均成绩写入一个文本文件ouput.txt
。
答:程序如下所示:
#include<stdio.h> #include<stdlib.h> #define NUM 40 struct Student{ char name[20]; float score[3]; float aver; }; int main(){ void input(struct Student student[]); void writeToText(struct Student student[]); void read(struct Student student[]); struct Student student[NUM],*p = student; input(p); writeToText(p); /* 以二进制形式写入文件,为了验证写入文件的正确性,重新定义一个read函数,并以二进制形式进行读取,如果能够正确读出内容,则 表示程序正确,考试时,可不写read函数进行验证。 */ read(p); return0; } // 读入数据并计算aver值 void input(struct Student student[]){ for (int i = 0; i < NUM; i++) { printf("请输入第%d个学生的姓名、三门课成绩:\n",i+1); scanf("%s %f %f %f",student[i].name,&student[i].score[0],&student[i].score[1],&student[i].score[2]); student[i].aver = (student[i].score[0]+student[i].score[1]+student[i].score[2])/3.0; } } // 写入文件 void writeToText(struct Student student[]){ FILE *fp; if((fp=fopen("output.txt", "wb"))==NULL){ printf("文件打开失败!\n"); exit(0); } for (int i = 0; i < NUM; i++) { if(fwrite(&student[i], sizeof(struct Student), 1, fp)!=1){ printf("写入文件错误!\n"); } } fclose(fp); printf("文件写入成功!\n"); } // 验证写入文件中的数据是否正确,考试时可写可不写。 void read(struct Student student[]){ FILE *fp; if((fp = fopen("output.txt", "rb"))==NULL){ printf("不能打开文件!\n"); exit(0); } for (int i = 0; i < NUM; i++) { fread(&student[i], sizeof(struct Student), 1, fp); printf("姓名:%s\t三门课成绩:%.2f、%.2f、%.2f\t平均成绩:%.2f\n",student[i].name,student[i].score[0],student[i].score[1],student[i].score[2],student[i].aver); } fclose(fp); }
5. 写一个单向链表处理程序,节点定义如下:
struct student { char name[40]; int score; struct student *next; };
根据键盘输入的5个人的姓名和分数,建立一个单向链表,并按照成绩进行排序(升降序自己决定),最后输出链表(已排好序)各节点的姓名和分数。
答:程序如下所示:
#include<stdio.h> #include<stdlib.h> #include<string.h> #define NUM 5 struct student{ char name[40]; int score; struct student *next; }; struct student *createList(); struct student *bubbleSort(struct student *head); void displayList(struct student *head); struct student *head = NULL; struct student *bubble_head = NULL; int main(){ head = createList(); bubble_head = bubbleSort(head); displayList(bubble_head); return0; } // 1.建立学生信息 struct student *createList(){ struct student *head;//头节点 struct student *p1;//开辟新节点 struct student *p2;//与p1连接 char name[40]; int score; head = NULL; for (int count = 1; count <= NUM; count++){ printf("请输入第%d个学生的姓名、分数(用空格分隔):",count); scanf("%s %d",name,&score); p1 = (struct student*)malloc(sizeof(struct student)); strcpy(p1->name,name); p1->score = score; p1->next = NULL; if(head == NULL){ head = p1; }else{ p2->next = p1; } p2 = p1; } return head; } // 2. 冒泡排序 struct student *bubbleSort(struct student *head){ struct student *p,*q; int temp1,i; char temp2[40]; for (p = head,i=1;i < NUM; i++,p=p->next) { for (q = p->next; q!=NULL; q = q->next) { if(p->score < q->score){ // 交换score temp1 = p->score; p->score = q->score; q->score = temp1; // 交换name strcpy(temp2, p->name); strcpy(p->name, q->name); strcpy(q->name, temp2); } } } return head; } // 3. 与建立顺序相同输出学生信息 void displayList(struct student *head){ struct student *p; int n = 0; if(head!=NULL){ printf("顺序输出链表中学生信息如下:\n"); for(p=head;p!=NULL;p=p->next){ printf("姓名:%20s 分数:%6d\n",p->name,p->score); n++; } printf("学生总数:%d\n",n); }else{ printf("空链表!\n"); } }