【C语言】图书录入程序设计

首先要知道我们所期望的程序有什么功能?

1.录入图书

2.保存录入图书的数据

3.在下次打开文件时加载已经导入的图书数据

 

首相我们建立一下程序的大致框架

1.创建一个图书的模板,并创建图书数组。相信这个并不难

struct book {
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
};

 

2.创建一个输入的函数,要求将换行符换成 “\0” 如果不正常输入返回NULL值

3.若已存在数据,则输出已有数据

4.创建循环:持续录入信息

5.将所有结构写入数据到文件

 

 

现在开始设计一个输入的函数s_gets()

我们要将内容从stdin存入数组之中,那么参数应该写:

char* s_gets(char* st, int n)

然后开始获取内容

fgets(st, n, stdin);

如果用户不输入值,我们想让函数返回null值,那么实际就是fgets返回的null值。考虑到我们要在函数中对数组进行去回车的处理,所以要用一个变量存储fgets的返回值(fgets返回的是一个指针)

char* s_gets(char* st, int n) {
    char* ret_val;
    ret_val = fgets(st, n, stdin);
    return ret_val;
}

接着进行去换行符的操作,我们可以用到 strchr() 函数,strchr可以返回匹配指定符号内容的指针。用法为strchr(处理的数组,匹配的内容),我们可以创建一个变量find去接收它,然后替换\n

char* s_gets(char* st, int n) {
    char* ret_val;
    char* find;
    ret_val = fgets(st, n, stdin);
    if (ret_val)
    {
        find=strchr(st, '\n');
        if (find)
            *find = '\0';
    }
    return ret_val;
}    

 

接下来我们来实现录入数据并储存

首先创建一个book的数组,以count进行编号,每录入一次就有count++

录入就会用到循环,那么循环的条件改是什么呢?

1.用户不输入新的书名,既书名时‘\n’时退出循环

2.书本书超过设定的大小

那么条件应该为

    while (count<MAXBKS && s_gets(lib[count].title, MAXTITL)!=NULL&&lib[count].title[0]!='\0')
    {、、、}

注意s_gets函数会将\n替换为\0

然后就是录入

    puts("enter the book");

    while (count<MAXBKS&& s_gets(lib[count].title, MAXTITL)!=NULL&&lib[count].title[0]!='\0')
    {
        puts("Enter the auther");
        s_gets(lib[count].author, MAXAUTL);
        puts("Enter the value");
        fscanf(stdin, "%f", &lib[count++].value);     //书本书加一
        while (getchar() != '\n')continue;
        if (count<MAXBKS)puts("enter the book");
    }

递增书本的时候可以将count++单独写出来,也可以直接在数组内执行

然后就是录入:录入条件肯定是输入了书本书,既count>0,然后用fwrite写入

 if (count>0)
    {
        puts("here is your book");
        for (size_t i = 0; i < count; i++)printf("%s ,%s, %f\n", lib[i].title, lib[i].author, lib[i].value);
        fwrite(&lib, sizeof(struct book), count, pbooks);
    }

 

 

最后我们来实现从文件中读取数据:

1.将文件中的数据读取并打印出来

我们要解决判断文件中有没有数据的问题,再就是将数据写入数组后才能输出的问题

如何判断有没有数据,既通过fread返回值来判断:有数据则返回1

既然我们设置了图书总量的限制,那么我们也要统计已有图书的个数,那么每次就读入1本图书的数据,然后用count进行统计

    while (count<MAXBKS&&fread(&lib[count],sizeof(struct book),1,pbooks)==1)
    {
        if (count==0)puts("currents books"); //只需要让这个显示1次
        printf("%s ,%s, %f\n", lib[count].title, lib[count].author, lib[count].value);
        count++;
    }

于是程序有了新的变动,因为改变了count的初始值。之前我们设置的将书本写入文件的数量就用到了count,那么就需要减去文件中的count数,最终结果为

/* booksave.c -- saves structure contents in a file */
#pragma warning(disable:4996)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXTITL  40
#define MAXAUTL  40
#define MAXBKS   10
char* s_gets(char* st, int n);
//创建图书信息模板
struct book { char title[MAXTITL]; char author[MAXAUTL]; float value; }; int main(void) { struct book lib[MAXBKS]; FILE* pbooks; int count=0; //打开文件 if ((pbooks = fopen("book.txt", "a+")) == NULL) { printf("erro!"); exit(1); } //判断并打印文件中已有的图书数据 while (count<MAXBKS&&fread(&lib[count],sizeof(struct book),1,pbooks)==1) { if (count==0)puts("currents books"); printf("%s ,%s, %f\n", lib[count].title, lib[count].author, lib[count].value); count++; } //获取已存在图书数量 int fcount = count;

//录入图书 puts(
"enter the book"); while (count<MAXBKS&& s_gets(lib[count].title, MAXTITL)!=NULL&&lib[count].title[0]!='\0') { puts("Enter the auther"); s_gets(lib[count].author, MAXAUTL); puts("Enter the value"); fscanf(stdin, "%f", &lib[count++].value); while (getchar() != '\n')continue; if (count<MAXBKS)puts("enter the book"); }

//储存图书
if (count>0) { puts("here is your book"); for (size_t i = 0; i < count; i++)printf("%s ,%s, %f\n", lib[i].title, lib[i].author, lib[i].value); fwrite(&lib, sizeof(struct book), count-fcount, pbooks); //减去已有数量 fclose(pbooks); } return 0; } char* s_gets(char* st, int n) { char* ret_val; char* find; ret_val = fgets(st, n, stdin); if (ret_val) { find=strchr(st, '\n'); if (find){*find = '\0';} } return ret_val; }

 

posted @ 2022-11-01 20:28  kitcat  阅读(417)  评论(0)    收藏  举报