首页 > 代码库 > C语言复习——指针 链表 与 文件操作

C语言复习——指针 链表 与 文件操作

     刚刚进入大二,准备开始学习C++,对大一所学的C语言一次练习,正好也是赶上老师布置的任务,用C语言写一个  销售管理系统  ,就尽可能的把所学的都用上,也就是结构,指针,文件操作,还有数据结构,本次加入了链表。

     用两个函数 Load_LinkList() 和 Save_LinkList() 让链表与文件操作结合,除了打印函数,其他都是在内存中操作链表,这样写更有条理,在创建链表时没有采用书上的用一个中间变量引导,并插入到结点前面,而是直接在链表尾的next申请内存,便于理解,操作也方便。

 

/*首先是文件包含,这里就不使用 ifndef 那样常规写一个头文件*/#include <stdio.h>#include <string.h>#include <windows.h>#include <stdlib.h>#include <conio.h>
/*接下来就是结构体*//*每一种商品对应一个结点,用链表连接起来,统一写入文件,或者从文件中读取*/typedef struct commodity{    int data;               //头结点data统计个数,其余为商品编号    char name[20];          //名称    double price;           //价格    int count;              //数量    double sum;             //总计,头结点sum为所有商品总计    struct commodity *next;} *LinkList, LNode;
/*定义全局变量,方便使用*//*链表头指针*/LinkList H = NULL;/*文件指针*/FILE *fp = NULL;

 

/*函数声明*//***************显示函数****************///欢迎界面void welcome();//显示菜单void menu();
//打印表格头
void printf_header();
//显示单个结点信息
void printf_linklist_info(LinkList pTemp);//延时函数void delay();/***********链表文件操作函数*****************///从文件中读取到链表中void Load_LinkList(LinkList H);//将链表保存到文件中void Save_LinkList(LinkList H);/***************链表函数**********************///建立头结点void Creat_LinkList();//添加结点到链表尾部LinkList Add_LinkList(LinkList H);//输入结点数据void Scanf_LinkList(LinkList pTemp);//找到符合要求的结点的前驱LinkList Find_LinkList_Pos(LinkList H,int index);//找到符合要求的结点的地址LinkList Find_LinkList_Val(LinkList H, char *name);//删除指定结点void Del_LinkList(LinkList H, char *name);//修改结点内容void Modify_LinkList(LinkList H, int index, int data);//顺序输出void Printf_LinkList(LinkList H);//释放内存void Free_LinkList(LinkList H);

 

/*main函数,没什么说的,除了getch函数用的时候会方便一些*/int main(){    LinkList pTemp = NULL;    char name[20] = {0};    system("color A");    //welcome();    Creat_LinkList();    Load_LinkList(H);    while(1)    {        system("cls");        menu();        switch(getch())        {            case 1:                pTemp = Add_LinkList(H);                Scanf_LinkList(pTemp);                getch();                break;            case 2:                printf_header();                Printf_LinkList(H);                getch();                break;            case 3:                printf("\n输入名称查找:");                scanf("%s", name);                pTemp = Find_LinkList_Val(H, name);                printf_linklist_info(pTemp);                getch();                break;            case 4:                printf("\n请先输入名称查找:");                scanf("%s", name);                pTemp = Find_LinkList_Val(H, name);                Scanf_LinkList(pTemp);                getch();                break;            case 5:                printf("\n请先输入名称查找:");                scanf("%s", name);                Del_LinkList(H, name);                getch();                break;            case 6:                Save_LinkList(H);                printf("\n成功保存%d条信息!\n", H->data);                getch();                break;            case 0:                printf("\n欢迎下次使用!\n");                exit(0);            default :                printf("错误输入!");                getch();        }    }    return 0;}

////////////////////下面是显示函数实现内容

/*欢迎界面,其实不要也可以*/void welcome(){    int i;    for(i=1 ; i<=100 ; i++)    {        printf("*******************欢迎使用本系统*************************");        printf("\n\n\n\n\n\n\n");        printf("                                                 加载中");        printf("...\n");        printf("                                                      %3d%%\n",i);        printf("**********************************************************");        system("cls");    }    return ;}

 

/*菜单函数*/void menu(){    system("cls");    printf("                        欢迎进入本系统                     \n");    printf("\n");    printf("-------------------------------------------------------------------\n");    printf("|                 1 添加商品                                      |\n");    printf("|                 2 显示商品                                      |\n");    printf("|                 3 查找商品                                      |\n");    printf("|                 4 修改商品                                      |\n");    printf("|                 5 删除商品                                      |\n");    printf("|                 6 保存修改                                      |\n");    printf("|                 0 退出系统                                      |\n");    printf("-------------------------------------------------------------------\n");    printf("                                               提示:退出前请先保存!");    printf("\nchoose(0-8):");}

 

/*以表格的形式打印所有商品信息*/void printf_header(){    system("cls");    printf("-------------------------您的所有库存-------------------------------------\n");    printf("|   编号   |      名称     |    价格       |       数量     |    总计    |\n");    printf("|----------|---------------|---------------|----------------|------------|\n");}

 

/*显示单个结点信息*/void printf_linklist_info(LinkList pTemp){    if(pTemp == NULL)    {        return ;    }    printf_header();    pTemp->sum = pTemp->price * pTemp->count;    printf("|%10d|%15s| %lf  |%20d|  %lf   |\n",pTemp->data, pTemp->name, pTemp->price, pTemp->count, pTemp->sum);    printf("|----------|---------------|---------------|----------------|------------|\n");    return ;}

 

/*延时函数,写完了发现我一直用的是getch等待按键*/void delay(){    long int i,j;    for(i=500000 ; i>0 ; i--)    {        for(j=0 ; j<=2000 ; j++);    }}

 

/*创建头结点*/void Creat_LinkList(){    H = (LinkList)malloc(sizeof(LNode));    if(H)    {        H->next = NULL;        H->data = http://www.mamicode.com/0;    }    return ;}

 

/*添加结点,这里是直接用最后一个节点的next申请内存*/LinkList Add_LinkList(LinkList H){    LinkList q = H;    while(q->next != NULL)        q = q->next;    q->next = (LinkList)malloc(sizeof(LNode));    q->next->sum = 0;    q->next->next = NULL;    H->data++;    return q->next;}

 

/*用于添加结点时输入结点信息,或者修改时输入*/void Scanf_LinkList(LinkList pTemp){    if(pTemp == NULL)    {        return ;    }    printf("\n输入编号:");    scanf("%d", &pTemp->data);    printf("输入名称:");    scanf("%s", pTemp->name);    printf("输入价格:");    scanf("%lf", &pTemp->price);    printf("输入数量:");    scanf("%d", &pTemp->count);    pTemp->sum = pTemp->price * pTemp->count;}

 

/*从文件中读取并加载到链表中,和Save函数一样,是最关键的两个函数*/void Load_LinkList(LinkList H){    LinkList p = NULL, pTemp = NULL;    pTemp = (LinkList)malloc(sizeof(LNode));    pTemp->next = NULL;    fp = fopen("D:/a.txt", "rb");    while(1)    {        /*这里用一个中间结点,临时储存,fread读一次才能决定是否添加结点,直接用p添加结点会错误,本身就是空文件时会多出一个结点,存的垃圾值,而fread必须有一块内存才能读*/        if((fread(pTemp, sizeof(LNode), 1, fp)) != 0)        {            p = Add_LinkList(H);            p->data = http://www.mamicode.com/pTemp->data;            strcpy(p->name, pTemp->name);            p->price = pTemp->price;            p->count = pTemp->count;            H->data++;        }        else            break;    }    free(pTemp);    fclose(fp);    return ;}    

 

/*将链表保存到文件中*/void Save_LinkList(LinkList H){    LinkList p = H->next;    if(p == NULL)    {        /*这里是清空一下,假如链表中保存的有数据,调用删除完之后,不能用fwrite,只是这种情况下用wb清空文件*/        fp = fopen("D:/a.txt", "wb");        H->data = http://www.mamicode.com/0;        fclose(fp);        getch();        return ;    }    fp = fopen("D:/a.txt", "wb");    while(p != NULL)    {        fwrite(p, sizeof(LNode), 1, fp);        p = p->next;    }    fclose(fp);    return ;}

 

///////////////接下来的函数就是只在内存里面操作链表

/*通过位置查找,返回结点  前驱结点  地址,计划是有这个查找的,后来写菜单也不想用了,就放这里没动过*/LinkList Find_LinkList_Pos(LinkList H,int index){    LinkList p = H;    index--;    while(index--)    {        p = p->next;    }    return p;}

 

/*通过字符串匹配查找,返回结点地址*/LinkList Find_LinkList_Val(LinkList H, char *name){    LinkList p = H;    while(strcmp(p->name, name) != 0  &&  p->next != NULL)    {        p = p->next;    }    if(p->next == NULL)    {        printf("没有此商品!");        return NULL;        getch();    }    return p;}

 

/*删除一个结点,pre是前驱结点,p是要找的结点*/void Del_LinkList(LinkList H, char *name){    int flag = 0;    LinkList p = H->next, pre = H;    while(p != NULL)    {        if(strcmp(p->name, name) == 0)        {            flag = 1;            break;        }        pre = p;        p = p->next;    }    if(flag == 0)    {        printf("没有此商品!\n");        return ;    }    p = pre->next;    pre->next = p->next;    free(p);    return ;}

 

/*修改结点信息,也是也可以实现的,和Find_LinkList_Pos()一样,没有用过*/void Modify_LinkList(LinkList H, int index, int data){    LinkList p = Find_LinkList_Pos(H, index+1);    if(p)        p->data =http://www.mamicode.com/ data;    return ;}

 

/*顺序输出,表格没有对太齐,应该用 %xd 这样的,后来也不想改了*/void Printf_LinkList(LinkList H){    LinkList p = NULL;    p = H->next;    if(p == NULL)    {        printf("当前没有任何商品!");        getch();        return ;    }    while(p != NULL)    {        p->sum = p->price * p->count;        printf("|%10d|%15s|   %lf   |   %15d  |  %lf   |\n",p->data, p->name, p->price, p->count, p->sum);        printf("-------------------------------------------------------------------------------\n");        p = p->next;    }    printf("                                                                           %lf\n", H->sum);    return ;}

 

/*内存总是要释放的*/void Free_LinkList(LinkList H){    LinkList pre = NULL, p = H->next;    while(pre != NULL)    {        pre = p->next;        free(p);        p = p->next;    }    H->next = NULL;    return ;}

 

C语言复习——指针 链表 与 文件操作