标题:这代码写完,我差不多就已经不认识了。
取消只看楼主
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
结帖率:95.65%
已结贴  问题点数:20 回复次数:13 
这代码写完,我差不多就已经不认识了。
题目:写一个图书管理程序,要求可以增加记录,读取记录,删除记录,修改记录。

我从11点半写到1点半,然后越写越觉得这代码写的可真蠢。

程序代码:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
                 char title[50];
                 char author[50];
                 float value;
                 int del_tag;
               }BOOKS;
void menu(void);
void f_read(void);
void data_add(void);
void data_delete(void);
FILE * f_open(void);
void f_write(BOOKS a[], int arrays);
long int datas = 0;

int main(void)
{
    typedef void(*P_FUN)(void);
    P_FUN fun_M[3] = { f_read,data_delete,data_add };
    int option = 0;
    FILE *p_file;

    p_file = f_open();
    fclose(p_file);

    while (menu(), scanf("%d", &option) == 1)
    {
        if (option >= 3)
            printf("该选项不存在\n");
        else if (option < 0)
            printf("该选项不存在\n");
        else if (!datas && option != 2)
            printf("文件中没有记录。\n");
        else
            fun_M[option]();
    }
    return 0;
}

void menu(void)
{
    printf("0) 读取文件\n");
    printf("1) 删除/修改记录\n");
    printf("2) 增加记录\n");
    printf("q) 退出\n");
}

void f_read(void)
{
    FILE * p_file;
    long int data_in = 0;
    int st_size = sizeof(BOOKS);
    BOOKS book;

    p_file = f_open();
    for (data_in = 0; data_in < datas; data_in += st_size)
    {
        fseek(p_file, data_in, SEEK_SET);
        fread(&book, sizeof(BOOKS), 1, p_file);
        printf("%-25s %s  ¥%.2f\n", book.title, book.author, book.value);
    }

    fseek(p_file, 0, SEEK_END);
    datas = ftell(p_file);
    fclose(p_file);
}

void data_add(void)
{
    BOOKS a;
    FILE * p_file;
    p_file = f_open();

    while (getchar() != '\n');
    while (printf("输入书名(空行结束):"), gets(a.title) != NULL && a.title[0] != '\0')
    {
        while (printf("输入作者:"), gets(a.author) == NULL || a.author[0] == '\0');
        printf("输入单价:");
        scanf("%f", &a.value);
        a.del_tag = 1;
        while (getchar() != '\n');
        fwrite(&a, sizeof(BOOKS), 1, p_file);
    }
    fseek(p_file, 0, SEEK_END);
    datas = ftell(p_file);
    fclose(p_file);
}

void data_delete(void)
{
    int arrays = datas / sizeof(BOOKS);
    BOOKS a[arrays];
    int n, array_in;
    FILE * p_file;

    p_file = f_open();

    for (n = 0, array_in = 0; n < datas && array_in < arrays; array_in++, n += sizeof(BOOKS))
    {
        fseek(p_file, n, SEEK_SET);
        fread(&a[array_in], sizeof(BOOKS), 1, p_file);
    }
    fclose(p_file);

    while (printf("0.删除\n1.修改\n2.返回主菜单\n"), scanf("%d", &n) == 1 && n != 2)
    {
        if (!n)
        {
            for (array_in = 0; array_in < arrays; array_in++)
                printf("%d %s %s: %.2f\n", array_in, a[array_in].title, a[array_in].author, a[array_in].value);
            while (printf("输入要删除的记录的编号,可选范围0-%d(q退出):", arrays - 1), scanf("%d", &array_in) == 1)
            {

                if (array_in > arrays)
                    printf("记录不存在.\n");
                else if (!a[array_in].del_tag)
                    printf("记录不存在.\n");
                else
                    a[array_in].del_tag = 0;
            }
            while (getchar() != '\n');
        }
        else if (n == 1)
        {
            for (array_in = 0; array_in < arrays; array_in++)
                printf("%d %s %s: %.2f\n", array_in, a[array_in].title, a[array_in].author, a[array_in].value);
            while (printf("输入要修改的记录的编号,可选范围0-%d(q退出):", arrays - 1), scanf("%d", &array_in) == 1)
            {

                if (array_in > arrays)
                    printf("记录不存在\n");
                else if (!a[array_in].del_tag)
                    printf("该记录已经被删除\n");
                else
                {
                    while (getchar() != '\n');
                    while (printf("输入新的书名:"), gets(a[array_in].title) == NULL || a[array_in].title[0] == '\0');
                    while (printf("输入新的作者名:"), gets(a[array_in].author) == NULL || a[array_in].author[0] == '\0');
                    printf("输入新的价格:");
                    scanf("%f", &a[array_in].value);
                }
            }
            while (getchar() != '\n');
        }
    }
    f_write(a, arrays);
}

FILE * f_open(void)
{
    FILE *p_file;
    if ((p_file = fopen("books_s.dat", "a+b")) == NULL)
    {
        fprintf(stderr, "无法打开文件");
        exit(EXIT_FAILURE);
    }
    fseek(p_file, 0, SEEK_END);
    datas = ftell(p_file);

    return p_file;
}

void f_write(BOOKS a[], int arrays)
{
    FILE * p_file;
    int array_in;

    if ((p_file = fopen("books_s.dat", "w+b")) == NULL)
    {
        fprintf(stderr, "无法打开文件");
        exit(EXIT_FAILURE);
    }
    for (array_in = 0; array_in < arrays; array_in++)
        if (a[array_in].del_tag)
            fwrite(&a[array_in], sizeof(BOOKS), 1, p_file);
    datas = ftell(p_file);
    fclose(p_file);
}


[此贴子已经被作者于2017-1-31 15:20编辑过]

搜索更多相关主题的帖子: 管理程序 记录 
2017-01-30 01:51
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
得分:0 
回复 2楼 九转星河
你说多出来的哪行以及变量n都是应该被删除的,我写来给我自己看的。
竟然留在那里了。

a+b是二进制打开文件,这样方便用结构体或者数组读取。
stderr是I/O标准错误,如果无法打开文件,就显示,好吧,其实在那里就跟printf差不多,不过对于打开文件的话,我习惯用fprintf,然后带上stderr.


[此贴子已经被作者于2017-1-30 02:12编辑过]


09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-01-30 02:07
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
得分:0 
回复 2楼 九转星河
很多重复的代码,完全可以写另一个打开文件将数据复制到结构数组的函数来省掉不少,但是写的有点累了,后面的修改记录那个函数,直接复制的删除函数,稍加修改了一下。

[此贴子已经被作者于2017-1-30 02:56编辑过]


09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-01-30 02:09
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
得分:0 
回复 5楼 linlulu001
我知道,但是写的当时,完全没考虑,只想快点而弄完,以至于修改记录的函数完全就是复制的删除记录(只做了一点点修改)!这代码有很多地方可以精简。



[此贴子已经被作者于2017-1-30 13:21编辑过]


09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-01-30 12:11
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
得分:0 
回复 7楼 书生牛犊
其实就是顺手。
将函数将参数传递在后续的修改中会更方便,你可以直接修改函数就行,而不用修改其他。
比如说我定义的两个函数,xieru()和duqu(),如果在后面我要修改他们,我只需要直接修改这两个函数的定义,而不需要修改其他部分。



[此贴子已经被作者于2017-1-30 16:49编辑过]


09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-01-30 16:48
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
得分:0 
回复 7楼 书生牛犊
嗯……精简想不到,没有什么思路,但是有扩展的思路,总觉得有些地方不够完善,比如早上的时候就发现没有检查越界,后来加上了。

所以……导致,我修改了几次之后,代码量依旧没有减少。

09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-01-30 16:51
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
得分:0 
回复 9楼 书生牛犊
不太清楚封装,我是超级新手来的,接触编程不到2个月。
收到的鲜花
  • 书生牛犊2017-01-30 17:00 送鲜花  20朵   附言:我也是新手刚学没多久

09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-01-30 16:52
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
得分:0 
回复 11楼 书生牛犊
是这样的,只要函数的返回值和参量不变,那么就不需要修改别的地方。但是以我的代码为例,我想不到那两个函数的返回值或参量有变化的可能。

09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-01-30 16:53
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
得分:0 
回复 11楼 书生牛犊
我个人的理解,需要用到函数指针的地方,都是这个函数跟其他函数有很亲密的联系。

还是拿我自己的为例,如果要修改那两个函数的返回值或参量,那么我的代码就需要大改。

09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-01-30 16:56
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
得分:0 
回复 16楼 书生牛犊
所以……我们又回到了最初的话题。

我没有思路………………
收到的鲜花
  • 书生牛犊2017-01-30 17:14 送鲜花  20朵   附言:好吧,谢谢

09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-01-30 17:01



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-473884-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.080405 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved