关于c:C语言程序设计谭浩强第五版-第10章-对文件的输入输出-习题答案

4次阅读

共计 12374 个字符,预计需要花费 31 分钟才能阅读完成。

你也能够上程序咖(https://meta.chengxuka.com),关上大学幕题板块,岂但有答案,解说,还能够在线答题。

题目 1:什么是文件型指针? 通过文件指针拜访文件有什么益处?

答:

缓冲文件系统中,要害的概念是“文件类型指针”,简称“文件指针”。每个被应用的文件都在内存中开拓一个相应的文件信息区,用来寄存文件的无关信息(如文件的名字、文件状态及文件以后地位等)。这些信息是保留在一个构造体变量中的。该构造体类型是由零碎申明的,取名为 FILE。所以,在 C 语言上,文件型指针就是指 FILE 类型的指针,它指向一个文件类型的构造,构造里蕴含着该文件的各种属性。

通过文件指针拜访文件的益处是:能够随机拜访文件,无效示意数据结构,动静分配内存,方便使用字符串,无效应用数组。

题目 2:对文件的关上与敞开的含意是什么? 为什么要关上和敞开文件?

答:

关上文件,是建设文件的各种相干信息,并使文件类型指针指向该文件,以便进行其它操作。而敞开文件操作可强制把缓冲区中的数据写入磁盘文件,保障文件的完整性,同时还将开释文件缓冲区单元和 FILE 构造,使文件类型指针与具体文件脱钩。

要对一个文件进行操作,必须先将其关上,读写结束后还要将其敞开,以避免不失常的操作。

”关上“是指为文件建设相应的信息区 (用来寄存无关文件的信息) 和文件缓冲区(用来临时寄存输入的数据)。

”敞开“是指撤销文件信息区和文件缓冲区,使文件指针变量不再指向该文件,显然就无奈进行对文件的读写了。

题目 3:从键盘输入一个字符串,将其中的小写字母全副转换成大写字母,而后输入到一个磁盘文件 test 中保留,输出的字符串以 ”!” 完结。

解:

答案代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
    FILE *fp;
    char str[100];
    int i = 0;
    if ((fp = fopen("test.txt", "w")) == NULL)
    {printf("can not open file\n");
        exit(0);
    }
    printf("input a string:\n");
    gets(str);
    while (str[i] != '!')
    {if (str[i] >= 'a' && str[i] <= 'z')
            str[i] = str[i] - 32;
        fputc(str[i], fp);
        i++;
    }
    fclose(fp);
    fp = fopen("test.txt", "r");
    fgets(str, strlen(str) + 1, fp);
    printf("%s\n", str);
    fclose(fp);
    return 0;
}

运行后果:

能够发现多了一个文件:test.txt,咱们关上它:

题目 4:有两个磁盘文件 A 和 B,各寄存一行字母,今要求把这两个文件中的信息合并(按字母顺序排列),输入到一个新文件 C 中去。

解:先用第 3 题的程序别离建设两个文件 A 和 B,其中内容别离是 “I LOVE CHINA” 和 “I LOVE BEIJING”。在程序中先别离将 A,B 文件的内容读出放到数组 c 中,再对数组 c 排序。最初将数组内容写到 C 文件中。流程图如图 10.1 所示。

程序如下∶

#include <stdio.h>
#include <stdlib.h>
int main()
{
    FILE *fp;
    int i, j, n, i1;
    char c[100], t, ch;
    if ((fp = fopen("a1", "r")) == NULL)
    {printf("\ncan not open file\n");
        exit(0);
    }
    printf("file A :\n");
    for (i = 0; (ch = fgetc(fp)) != EOF; i++)
    {c[i] = ch;
        putchar(c[i]);
    }
    fclose(fp);

    i1 = i;
    if ((fp = fopen("b1", "r")) == NULL)
    {printf("\ncan not open file\n");
        exit(0);
    }
    printf("\nfile B:\n");
    for (i = i1; (ch = fgetc(fp)) != EOF; i++)
    {c[i] = ch;
        putchar(c[i]);
    }
    fclose(fp);

    n = i;
    for (i = 0; i < n; i++)
        for (j = i + 1; j < n; j++)
            if (c[i] > c[j])
            {t = c[i];
                c[i] = c[j];
                c[j] = t;
            }
    printf("\nfile C :\n");
    fp = fopen("c1", "w");
    for (i = 0; i < n; i++)
    {putc(c[i], fp);
        putchar(c[i]);
    }
    printf("\n");
    fclose(fp);
    return 0;
}

首先要创立文件 a1 和 b1,外面别离存入题目要求的文本内容。而后再运行程序。

运行后果:

题目 5:有 5 个学生,每个学生有 3 门课程的问题,从键盘输入学生数据(包含学号,姓名,3 门课程问题),计算出均匀问题,将原有数据和计算出的均匀分数寄存在磁盘文件 stud 中。

解:

解法一:N- S 图如图 10.2 所示。

答案代码:

#include <stdio.h>
struct student
{char num[10];
    char name[8];
    int score[3];
    float ave;
} stu[5];

int main()
{
    int i, j, sum;
    FILE *fp;
    for (i = 0; i < 5; i++)
    {printf("\ninput score of student %d:\n", i + 1);
        printf("NO.:");
        scanf("%s", stu[i].num);
        printf("name:");
        scanf("%s", stu[i].name);
        sum = 0;
        for (j = 0; j < 3; j++)
        {printf("score %d:", j + 1);
            scanf("%d", &stu[i].score[j]);
            sum += stu[i].score[j];
        }
        stu[i].ave = sum / 3.0;
    }
    // 将数据写入文件
    fp = fopen("stud", "w");
    for (i = 0; i < 5; i++)
        if (fwrite(&stu[i], sizeof(struct student), 1, fp) != 1)
            printf("file write error\n");
    fclose(fp);
    fp = fopen("stud", "r");
    for (i = 0; i < 5; i++)
    {fread(&stu[i], sizeof(struct student), 1, fp);
        printf("\n%s,%s,%d,%d,%d,%6.2f\n", stu[i].num, stu[i].name, stu[i].score[0], stu[i].score[1], stu[i].score[2], stu[i].ave);
    }

    return 0;
}

运行后果:

阐明:在程序的第 1 个 for 循环中,有两个 printf 函数语句用来提醒用户输出数据,即 ”printf(”input score of student %d∶\n”,i+1);” 和 “printf(”score %d;”,j+1);”,其中用 “i 十 1 ” 和 “j 十 1 ” 而不是用 i 和 j 的用意是使显示提醒时,序号从 1 起,即学生 1 和问题 1(而不是学生 0 和问题 0),以合乎们的习惯,但在内存中数组元素下标仍从 0 算起。

程序最初 5 行用来查看文件 stud 中的内容是否正确,从后果来看,是正确的。请留神:用 fwrite 函数向文件输入数据时不是按 ASCII 码形式输入的,而是按内存中存储数据的形式输入的(例如一个整数占 2 个或 4 个字节,一个实数占 4 个字节),因而不能用 DOS 的 type 命令输入该文件中的数据。

解法二:也能够用上面的程序来实现:

#include <stdio.h>
#define SIZE 5
struct student
{char name[10];
    int num;
    int score[3];
    float ave;
} stud[SIZE];

int main()
{void save(void); // 函数申明
    int i;
    float sum[SIZE];
    FILE *fp1;
    for (i = 0; i < SIZE; i++) // 输出数据,并求每个学生的平均分
    {scanf("%s %d %d %d %d", stud[i].name, &stud[i].num, &stud[i].score[0], &stud[i].score[1], &stud[i].score[2]);
        sum[i] = stud[i].score[0] + stud[i].score[1] + stud[i].score[2];
        stud[i].ave = sum[i] / 3;
    }
    save(); // 调用 save 函数,向文件 stu.dat 输入数据

    fp1 = fopen("stu.dat", "rb"); // 用只读形式关上 stu. dat 文件
    printf("\n name        NO.    score1 score2 score3 ave\n");
    printf("----------------------------------------\n"); // 输出表头
    for (i = 0; i < SIZE; i++)                              // 从文件读入数据并在屏幕输入
    {fread(&stud[i], sizeof(struct student), 1, fp1);
        printf("%-10s %3d %7d %7d %7d %8.2f\n", stud[i].name, stud[i].num, stud[i].score[0], stud[i].score[1], stud[i].score[2], stud[i].ave);
    }
    fclose(fp1);
    return 0;
}
void save(void) // 向文件输入数据的函数:{
    FILE *fp;
    int i;
    if ((fp = fopen("stu.dat", "wb")) == NULL)
    {printf("The file can not open\n");
        return;
    }
    for (i = 0; i < SIZE; i++)
        if (fwrite(&stud[i], sizeof(struct student), 1, fp) != 1)
        {printf("file write error\n");
            return;
        }
    fclose(fp);
}

运行后果∶

本程序用 save 函数将数据写到磁盘文件上,再从文件读回,而后用 printf 函数输入,从运行后果能够看到文件中的数据是正确的。

题目 6:将第 5 题 stud 文件中的学生数据,按平均分进行排序解决,将已排序的学生数据存入一个新文件 stu_sort 中。

解:

解法一:N- S 图如图 10.3 所示。

答案代码:

#include <stdio.h>
#include <stdlib.h>
#define N 10
struct student
{char num[10];
    char name[8];
    int score[3];
    float ave;
} st[N], temp;

int main()
{
    FILE *fp;
    int i, j, n;
    // 读文件
    if ((fp = fopen("stud", "r")) == NULL)
    {printf("can not open.\n");
        exit(0);
    }
    printf("File'stud':");
    for (i = 0; fread(&st[i], sizeof(struct student), 1, fp) != 0; i++)
    {printf("\n%8s%8s", st[i].num, st[i].name);
        for (j = 0; j < 3; j++)
            printf("%8d", st[i].score[j]);
        printf("%10.2f", st[i].ave);
    }
    printf("\n");
    fclose(fp);
    n = i;

    // 排序
    for (i = 0; i < n; i++)
        for (j = i + 1; j < n; j++)
            if (st[i].ave < st[j].ave)
            {temp = st[i];
                st[i] = st[j];
                st[j] = temp;
            }
    // 输入
    printf("\nNow:");
    fp = fopen("stu_sort", "w");
    for (i = 0; i < n; i++)
    {fwrite(&st[i], sizeof(struct student), 1, fp);
        printf("\n%8s%8s", st[i].num, st[i].name);
        for (j = 0; j < 3; j++)
            printf("%8d", st[i].score[j]);
        printf("%10.2f", st[i].ave);
    }
    printf("\n");
    fclose(fp);
    return 0;
}

运行后果:

解法二:与第 5 题解法二相应,能够接着应用上面的程序来实现本题要求。

#include <stdio.h>
#include <stdlib.h>
#define SIZE 5
struct student
{char name[10];
    int num;
    int score[3];
    float ave;
} stud[SIZE], work;

int main()
{void sort(void);
    int i;
    FILE *fp;
    sort();
    fp = fopen("stud_sort.dat", "rb");
    printf("sorted student's scores list as follow\n");
    printf("------------------------------------------------------\n");
    printf("NAME        N0.        SCORE1    SCORE2    SCORE3    AVE\n");
    printf("------------------------------------------------------\n");

    for (i = 0; i < SIZE; i++)
    {fread(&stud[i], sizeof(struct student), 1, fp);
        printf("%-10s %3d %8d %8d %8d %9.2f\n", stud[i].name, stud[i].num, stud[i].score[0], stud[i].score[1], stud[i].score[2], stud[i].ave);
    }
    fclose(fp);
    return 0;
}

void sort(void)
{
    FILE *fp1, *fp2;
    int i, j;
    if ((fp1 = fopen("stu.dat", "rb")) == NULL)
    {printf("The file can not open\n\n");
        exit(0);
    }
    if ((fp2 = fopen("stud_sort.dat", "wb")) == NULL)
    {printf("The file write error\n");
        exit(0);
    }
    for (i = 0; i < SIZE; i++)
        if (fread(&stud[i], sizeof(struct student), 1, fp1) != 1)
        {printf("file read error\n");
            exit(0);
        }
    for (i = 0; i < SIZE; i++)
    {for (j = i + 1; j < SIZE; j++)
            if (stud[i].ave < stud[j].ave)
            {work = stud[i];
                stud[i] = stud[j];
                stud[j] = work;
            }
        fwrite(&stud[i], sizeof(struct student), 1, fp2);
    }
    fclose(fp1);
    fclose(fp2);
}

运行后果:

题目 7:将第 6 题已排序的学生问题文件进行插入解决。插入一个学生的 3 门课程问题,程序先计算新插入学生的均匀问题,而后将它按问题高下程序插入,插入后建设一个新文件。

解:N- S 图如图 10.4 所示。

答案代码:

#include <stdio.h>
#include <stdlib.h>
struct student
{char num[10];
    char name[8];
    int score[3];
    float ave;
} st[10], s;

int main()
{
    FILE *fp, *fp1;
    int i, j, t, n;
    printf("\nNO.:");
    scanf("%s", s.num);
    printf("name:");
    scanf("%s", s.name);
    printf("score1,score2,score3:");
    scanf("%d,%d,%d", &s.score[0], &s.score[1], &s.score[2]);
    s.ave = (s.score[0] + s.score[1] + s.score[2]) / 3.0;

    // 从文件读数据
    if ((fp = fopen("stu_sort", "r")) == NULL)
    {printf("can not open file.");
        exit(0);
    }
    printf("original data:\n");
    for (i = 0; fread(&st[i], sizeof(struct student), 1, fp) != 0; i++)
    {printf("\n%8s%8s", st[i].num, st[i].name);
        for (j = 0; j < 3; j++)
            printf("%8d", st[i].score[j]);
        printf("%10.2f", st[i].ave);
    }
    n = i;
    for (t = 0; st[t].ave > s.ave && t < n; t++)
        ;
    // 向文件写数据
    printf("\nNow:\n");
    fp1 = fopen("sort1.dat", "w");
    for (i = 0; i < t; i++)
    {fwrite(&st[i], sizeof(struct student), 1, fp1);
        printf("\n %8s%8s", st[i].num, st[i].name);
        for (j = 0; j < 3; j++)
            printf("%8d", st[i].score[j]);
        printf("%10.2f", st[i].ave);
    }
    fwrite(&s, sizeof(struct student), 1, fp1);
    printf("\n %8s %7s %7d %7d%7d%10.2f", s.num, s.name, s.score[0], s.score[1], s.score[2], s.ave);
    for (i = t; i < n; i++)
    {fwrite(&st[i], sizeof(struct student), 1, fp1);
        printf("\n %8s%8s", st[i].num, st[i].name);
        for (j = 0; j < 3; j++)
            printf("%8d", st[i].score[j]);
        printf("%10.2f", st[i].ave);
    }
    printf("\n");
    fclose(fp);
    fclose(fp1);
    return 0;
}

运行后果:

为节俭篇幅,本题和第 8 题不再给出第 6 题 ” 解法二 ” 的程序,请读者自已编写程序。

题目 8:将第 7 题后果仍存入原有的 stu_sort 文件而不另建设新文件。

解:

答案代码:

#include <stdio.h>
#include <stdlib.h>
struct student
{char num[10];
    char name[8];
    int score[3];
    float ave;
} st[10], s;

int main()
{
    FILE *fp, *fp1;
    int i, j, t, n;
    printf("\nNO.:");
    scanf("%s", s.num);
    printf("name:");
    scanf("%s", s.name);
    printf("score1,score2,score3:");
    scanf("%d,%d,%d", &s.score[0], &s.score[1], &s.score[2]);
    s.ave = (s.score[0] + s.score[1] + s.score[2]) / 3.0;

    // 从文件读数据
    if ((fp = fopen("stu_sort", "r")) == NULL)
    {printf("can not open file.");
        exit(0);
    }
    printf("original data:\n");
    for (i = 0; fread(&st[i], sizeof(struct student), 1, fp) != 0; i++)
    {printf("\n%8s%8s", st[i].num, st[i].name);
        for (j = 0; j < 3; j++)
            printf("%8d", st[i].score[j]);
        printf("%10.2f", st[i].ave);
    }
    n = i;
    for (t = 0; st[t].ave > s.ave && t < n; t++)
        ;
    // 向文件写数据
    printf("\nNow:\n");
    fp1 = fopen("sort1.dat", "w");
    for (i = 0; i < t; i++)
    {fwrite(&st[i], sizeof(struct student), 1, fp1);
        printf("\n %8s%8s", st[i].num, st[i].name);
        for (j = 0; j < 3; j++)
            printf("%8d", st[i].score[j]);
        printf("%10.2f", st[i].ave);
    }
    fwrite(&s, sizeof(struct student), 1, fp1);
    printf("\n %8s %7s %7d %7d %7d %10.2f", s.num, s.name, s.score[0], s.score[1], s.score[2], s.ave);
    for (i = t; i < n; i++)
    {fwrite(&st[i], sizeof(struct student), 1, fp1);
        printf("\n %8s%8s", st[i].num, st[i].name);
        for (j = 0; j < 3; j++)
            printf("%8d", st[i].score[j]);
        printf("%10.2f", st[i].ave);
    }
    printf("\n");
    fclose(fp);
    fclose(fp1);
    return 0;
}

运行后果:

题目 9:有一磁盘文件 employee,内寄存职工的数据。每个职工的数据包含职工姓名、职工号、性别、年龄、住址、工资、健康状况、文化水平。今要求将职工名、工资的信息独自抽出来另建一个扼要的职工工资文件。

解:N- S 图如图 10.5 所示。

答案代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct employee
{char num[6];
    char name[10];
    char sex[2];
    int age;
    char addr[20];
    int salary;
    char health[8];
    char class[10];
} em[10];

struct emp
{char name[10];
    int salary;
} em_case[10];

int main()
{
    FILE *fp1, *fp2;
    int i, j;
    if ((fp1 = fopen("employee", "r")) == NULL)
    {printf("can not open file.\n");
        exit(0);
    }
    printf("\n NO. name sex age addr salary health class\n");
    for (i = 0; fread(&em[i], sizeof(struct employee), 1, fp1) != 0; i++)
    {printf("\n%4s%8s%4s%6d%10s%6d%10s%8s", em[i].num, em[i].name, em[i].sex, em[i].age, em[i].addr, em[i].salary, em[i].health, em[i].class);
        strcpy(em_case[i].name, em[i].name);
        em_case[i].salary = em[i].salary;
    }
    printf("\n\n**************************************************");
    if ((fp2 = fopen("emp_salary", "wb")) == NULL)
    {printf("can not open file\n");
        exit(0);
    }
    for (j = 0; j < i; j++)
    {if (fwrite(&em_case[j], sizeof(struct emp), 1, fp2) != 1)
            printf("error!");
        printf("\n %12s%10d", em_case[j].name, em_case[j].salary);
    }
    printf("\n\n**************************************************");
    fclose(fp1);
    fclose(fp2);
    return 0;
}

运行后果:

阐明:数据文件 employee 是当时建设好的,其中已有职工数据,而 emp_salary 文件则是由程序建设的。

建设 employee 文件的程序如下:

#include <stdio.h>
#include <stdlib.h>
struct employee
{char num[6];
    char name[10];
    char sex[2];
    int age;
    char addr[20];
    int salary;
    char health[8];
    char class[10];
} em[10];

int main()
{
    FILE *fp;
    int i;
    printf("input NO.,name,sex,age,addr,salary,health,class\n");
    for (i = 0; i < 4; i++)
        scanf("%s %s %s %d %s %d %s %s", em[i].num, em[i].name, em[i].sex, &em[i].age, em[i].addr, &em[i].salary, em[i].health, em[i].class);

    // 将数据写入文件
    if ((fp = fopen("employee", "w")) == NULL)
    {printf("can not open file.");
        exit(0);
    }
    for (i = 0; i < 4; i++)
        if (fwrite(&em[i], sizeof(struct employee), 1, fp) != 1)
            printf("error\n");
    fclose(fp);
    return 0;
}

在运行此程序时从键盘输入 4 个职工的数据,程序将它们写入 employee 文件。在运行后面一个程序时从 employee 文件中读出数据并输入到屏幕,而后建设一个扼要文件,同时在屏幕上输入。

题目 10:从第 9 题的 ” 职工工资文件 ” 中删去一个职工的数据,再存回原文件。

解:N- S 图如图 10.6 所示。

答案代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct employee
{char name[10];
    int salary;
} emp[20];

int main()
{
    FILE *fp;
    int i, j, n, flag;
    char name[10];
    if ((fp = fopen("emp_salary", "rb")) == NULL)
    {printf("can not open file.\n");
        exit(0);
    }

    printf("\noriginal data:\n");
    for (i = 0; fread(&emp[i], sizeof(struct employee), 1, fp) != 0; i++)
        printf("\n %8s %7d", emp[i].name, emp[i].salary);
    fclose(fp);
    n = i;
    printf("\ninput name deleted:\n");
    scanf("%s", name);
    for (flag = 1, i = 0; flag && i < n; i++)
    {if (strcmp(name, emp[i].name) == 0)
        {for (j = i; j < n - 1; j++)
            {strcpy(emp[i].name, emp[+1].name);
                emp[j].salary = emp[j + 1].salary;
            }
            flag = 0;
        }
    }
    if (!flag)
        n = n - 1;
    else
        printf("\nnot found!");
    printf("\nNow,The content of file:\n");
    if ((fp = fopen("emp_salary", "wb")) == NULL)
    {printf("can not open file\n");
        exit(0);
    }
    for (i = 0; i < n; i++)
        fwrite(&emp[i], sizeof(struct employee), 1, fp);
    fclose(fp);
    fp = fopen("emp_salary", "r");
    for (i = 0; fread(&emp[i], sizeof(struct employee), 1, fp) != 0; i++)
        printf("\n%8s %7d", emp[i].name, emp[i].salary);
    printf("\n");
    fclose(fp);
    return 0;
}

运行后果:

题目 11:从键盘输入若干行字符(每行长度不等),输出后把它们存储到一磁盘文件中。再从该文件中读入这些数据,将其中小写字母转换成大写字母后在显示屏上输入。

解:N- S 图如图 10.7 所示。

答案代码:

#include <stdio.h>
int main()
{
    int i, flag;
    char str[80], c;
    FILE *fp;
    fp = fopen("text", "w");
    flag = 1;
    while (flag == 1)
    {printf("input string:\n");
        gets(str);
        fprintf(fp, "%s\n", str);
        printf("continue?");
        c = getchar();
        if ((c == 'N') || (c == 'n'))
            flag = 0;
        getchar();}
    fclose(fp);
    fp = fopen("text", "r");
    while (fscanf(fp, "%s", str) != EOF)
    {for (i = 0; str[i] != '\0'; i++)
            if ((str[i] >= 'a') && (str[i] <= 'z'))
                str[i] -= 32;
        printf("%s\n", str);
    }
    fclose(fp);
    return 0;
}

运行后果:

此程序运行后果是正确的,然而如果输出的字符串中蕴含了空格,就会产生一些问题,例如输出:

inut string:

i am a student.

失去的后果是:

I

AM

A

STUDENT.

把一行分成几行输入。这是因为用 fscanf 函数从文件读入字符串时,把空格作为一个字符串的完结标记,因而把该行作为 4 个字符串来解决,别离输入在 4 行上。请读者思考怎么解决这个问题。

正文完
 0