2020_883《C程序设计》

2021-12-02 12:23:40 浏览数 (1)

一、简要回答下列问题

1. 简述C语言中标识符的规定;在给变量、数组和函数起名时,应注意什么?

答:在计算机高级语言中,用来对变量、符号常量名、函数、数组、类型等命名的有效字符序列统称为标识符,C语言规定标识符只能由字母、数字、下划线3种字符组成,且第1个字符必须为字母或下划线。

2. 什么是表达式?若在某程序中,已有定义int x:请问x=5是表达式吗?若是,其值和类型各是什么?

答:用C语言运算符将运算对象连接起来的式子叫做表达式,x=5是表达式,其类型为int,值为5。

3. 有定义语句char chch是什么类型的变量?在内存中占几个字节?可用什么函数求其字节数?此类型变量通常存放什么数据?试举一例。

答:ch是字符型变量,在内存中占用1个字节,可以通过sizeof函数求其对应的字节数,此类型变量通常用来存放字符,如char ch = 'A'定义了一个字符变量ch其初值为A,由于其实质上是一个字节的整型变量,故可以将0~127之间的整数赋给一个字符变量。

4. 写出if...else语句的一般形式,并画出流程图。

答:一般形式如下:

代码语言:javascript复制
if(表达式){
	语句1
}else{
	语句2
}

流程图如下:

上图中,p表示判断条件,当判断条件成立时,执行A框中的程序,若判断条件不成立,则执行B框中的程序。

5. 写出for语句的一般形式,并画出流程图。

答:一般形式如下:

代码语言:javascript复制
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两个指针之间所指的位置相差一个字节。

请看演示案例:

代码语言:javascript复制
#include<stdio.h>
#include<stdlib.h>
int main(){
    int a = 3;
    int *p = &a;
    printf("%dn",(char *)(p 1)-(char *)p); // 4
    printf("%dn",(char *)p 1-(char *)p); // 1
    return 0;
}

9. 在一程序中有struct pos2d{int x,int y;};这个语句定义了什么?pos2d是什么?系统给它分配内存吗?在此之后又有struct pos2d point;请问定义了什么?给point分配了内存吗?若分配,如何得到分配的字节数?

答:该语句定义了一个结构体名为pos2d的结构体,其中包含了2个成员,分别是整型变量x和整型变量ypos2d是结构体名;由于上述代码只是建立了一个结构体模型,并没有定义变量,其中并无具体的数据,系统对之也不分配存储单元;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. 字符指针变量

代码语言:javascript复制
#include<stdio.h>
void f1(char *t,char *s);
int main() {
    char *p="a1b2c3d4e5", st[20];
    printf("%sn",p 2);
    f1(st,p);
    printf("%sn",st);
    return 0;
}
void f1(char *t,char *s) {
    int i;
    for(i=0;*(s i)!='';i  ) {
        *(t  )=*(s 2*i);
        if(*(s 2*i)==''|| *(s 2*i 1)==''){
            break;
        }
    }
    *t='';
    return ;
}

答:程序输出结果如下:

代码语言:javascript复制
b2c3d4e5
abcde

该程序首先声明了一个名为f1的函数,该函数接收两个参数,分别为指向char类型的指针变量t和指向char类型的指针变量s,在f1函数中,有一个for循环,用来将指针变量s所指字符串中偶数位置的字符复制到指针变量t所指的字符串中,即指针变量t所指的字符串中存放的是指针变量s所指字符串中偶数位置对应的字符,执行完成上述操作,在指针变量t所指的字符串末尾手动添加作为有效字符串的结束标志,在主程序中,首先定义了一个字符指针变量p,默认情况下该指针变量p中保存的是字符串a1b2c3d4e5第一个字符的地址,接着通过printf("%sn",p 2);进行输出,则指针变量p 2应指向字符b的位置,故最终输出结果为:b2c3d4e5,接着在主程序中调用f1函数,并进行输出,即将原字符串中偶数位置的字符进行输出,即abcde

2. switch-case语句

代码语言:javascript复制
#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=%cn",score,grade);
        }
    }
    return 0;
}

答:程序输出结果如下:

代码语言:javascript复制
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,接着声明了两个整型变量ik,在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=3grade值为E,故最终输出结果为:score= 33.5-->grade=E;当输入score值为89.2时,k=8grade值为B,故最终输出结果为:score= 89.2-->grade=B;当输入score值为93.6时,k=9grade值为A,故最终输出结果为:score= 93.6-->grade=A;当输入值score为100时,k=10grade值为A,故最终输出结果为:score= 100.0-->grade=A;当输入score值为101时候,k=11grade值为n,故最终输出结果为:input data wrong!

3. 字符相减

代码语言:javascript复制
#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("%dn",MyStrCmp(str1,str2));
    printf("%dn",MyStrCmp(str1,str3));
    printf("%dn",MyStrCmp(str1,str4));
    printf("%dn",MyStrCmp(str1,str5));
    printf("%dn",MyStrCmp(str1,str6));
    return 0;
    
}
int MyStrCmp(char *s,char *t) {
    int r;
    while(*s !='' && *t !='') {
        if(*s!=*t){
            break;
        }
        s  ;
        t  ;
    }
    r=*s - *t;
    return r;
}

答:程序运行输出结果如下:

代码语言:javascript复制
-1
32
-99
0
98

该程序首先声明了一个名为MyStrCmp的函数,该函数接收两个参数,用于对两个字符串参数进行比较,比较过程中遇到第一个不相等的字符时,返回其对应字符相减的差值,若两字符串相等,则返回值为0。在主程序中,定义了6个字符指针变量,接着分别调用5次MyStrCmp函数返回其对应结果。

举例如下:当MyStrCmpy函数的参数为字符指针变量str1str2时,其最终返回结果为-1,即98-99=-1;当MyStrCmpy函数的参数为字符指针变量str1str3时,其最终返回结果为32,即97-65=32;当MyStrCmpy函数的参数为字符指针变量str1str4时,其最终返回结果为-99,即0-99=-99;当MyStrCmpy函数的参数为字符指针变量str1str5时,其最终返回结果为0,即0-0=0;当MyStrCmpy函数的参数为字符指针变量str1str6时,其最终返回结果为98,即98-0=98

4. 静态局部变量static

代码语言:javascript复制
#include<stdio.h>
int fun(void);
int main() {
    int i;
    for(i=0;i<5;i  ){
        printf("%dn",fun());
    }
    return 0;
}
int fun(void) {
    static int f1=1,f2=1;
    int r;
    r=f1 f2;
    f1=f2;
    f2=r;
    return r;
}

答:程序运行输出结果如下:

代码语言:javascript复制
2
3
5
8
13

该程序首先声明了一个名为fun的无参函数,接着在主程序中通过for循环调用了5次fun函数,在fun函数的定义中,整型变量f1f2被声明为静态局部变量,故其值在函数调用完成后不消失,在下一次调用该函数时,该变量对应的值即为上一次函数调用结束时的值。

举例如下:当第一次循环结束时,各变量对应值分别为: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. 结构体 文件操作 排序

代码语言:javascript复制
#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 %dn",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;
}

答:程序运行输出结果如下:

代码语言:javascript复制
zh3 88
li4 55
ma6 35
zhao7 28
wang5 10

本程序首先定义了一个名为person的结构体,其中包含nameage两个成员,接着,在主程序中以只读模式打开input.txt数据文件,成功打开后,逐个读入nameage对应的内容,读取完成后关闭该文件,继续执行MyFunc函数,该函数的功能是对结构体中的数据按照年龄从大到小进行排序,故所得结果如上所示。

三、编程题

1. 编写程序输出100到200之间的全部素数(素数指只能被1和自己整除,而不能被其他数整除的整数)。

答:程序如下所示:

代码语言:javascript复制
#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("%dn", i);
        }
    }
    return 0;
 }

2. 编写一个函数完成两个整型变量内容的对换,要求采用指针参数;并编写一个调用该函数的主函数,读入键盘输入的10个整数,并对其从小到大排序,将其排序结果输出。

答:交换两整型变量内容的程序如下所示:

代码语言:javascript复制
#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 = %dn",a,b);
    return 0;
}
// 交换两个指针所指向的内容
void swap(int *p1,int *p2){
    int temp;
    temp = *p1;
    *p1 = *p2;
    *p2 = temp;
}

排序的代码如下:(提示:选择排序、冒泡排序均可)

代码语言:javascript复制
#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("=",*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. 编写一函数,统计给定字符串中某字符出现的次数,并编写一个调用它的主函数,对键盘输入的字符串,分别统计@#出现的次数。

答:程序如下所示:

代码语言:javascript复制
#include<stdio.h>

int main(){
    int chCount(char str[],char ch);
    char str[100];
    printf("请输入一个字符串:n");
    scanf("%s",str);
    printf("@出现的次数为:%d,#出现的次数为:%dn",chCount(str,'@'),chCount(str,'#'));
    return 0;
}
// 统计特定字符出现的次数
int chCount(char str[],char ch){
    int count = 0;
    for (int i = 0; str[i]!=''; i  ) {
        if(str[i]==ch){
            count  ;
        }
    }
    return count;
}

4. 从键盘输入40个学生的数据,每个学生的数据包括姓名(假定中间无空格)、三门课成绩,计算每个同学三门课的平均成绩,并将每个同学的姓名、三门课成绩以及平均成绩写入一个文本文件ouput.txt

答:程序如下所示:

代码语言:javascript复制
#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("姓名:%st三门课成绩:%.2f、%.2f、%.2ft平均成绩:%.2fn",student[i].name,student[i].score[0],student[i].score[1],student[i].score[2],student[i].aver);
    }
    fclose(fp);
}

5. 写一个单向链表处理程序,节点定义如下:

代码语言:javascript复制
struct student { 
	char name[40]; 
	int score; 
	struct student *next; 
}; 

根据键盘输入的5个人的姓名和分数,建立一个单向链表,并按照成绩进行排序(升降序自己决定),最后输出链表(已排好序)各节点的姓名和分数。

答:程序如下所示:

代码语言:javascript复制
#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("姓名: s 分数:mn",p->name,p->score);
            n  ;
        }
        printf("学生总数:%dn",n);
    }else{
        printf("空链表!n");
    }
}

0 人点赞