“ 关注hahaCoder 获取最新资讯”
一、简要回答下列问题
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
return 0;
}
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);
return 0;
}
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) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:grade='E';break;
case 6:grade='D';break;
case 7:grade='C';break;
case 8:grade='B';break;
case 9:
case 10:grade='A';break;
default: grade='n';
}
if(grade=='n') {
printf("input data wrong!\n");
} else {
printf("score=%6.1f-->grade=%c\n",score,grade);
}
}
return 0;
}
答:程序输出结果如下:
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));
return 0;
}
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());
}
return 0;
}
int fun(void) {
static int 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) return 1;
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);
}
return 0;
}
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);
}
}
return 0;
}
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);
return 0;
}
// 交换两个指针所指向的内容
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");
return 0;
}
// 选择排序
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,'#'));
return 0;
}
// 统计特定字符出现的次数
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);
return 0;
}
// 读入数据并计算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);
return 0;
}
// 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");
}
}