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 = 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 = 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 = 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 = 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 ;
}
时间: 2024-11-25 16:50:22

C语言复习——指针 链表 与 文件操作的相关文章

C语言复习(一)文件操作

C语言—文件操作 1.1 fgets() + fputs(): 以字符串形式存取数据定义文件指针 #define _CRT_SECURE_NO_WARNINGS #include <cstdio> #include <cstdlib> using namespace std; /* 文件结束标志: EOF --- feof() 读写文件: fgetc: file get char 以字符形式获取 fputc: file put char 以字符形式写到文件 */ int main(

C语言第十二讲,文件操作.

C语言第十二讲,文件操作. 一丶文件操作概述 在操作系统中,我们的文档都称为文件.操作系统也为我们提供了接口进行操作.不同语言都是使用的相同的接口,只不过封装的上层接口不一样 操作文件的步骤 打开文件->读写文件->关闭文件. 二丶文件流的概述. 文件流称为 输入流和输出流.  其实就是从内存写数据到磁盘.和从磁盘读数据到内存. 内存->磁盘  称为输出流. 输出到磁盘 磁盘->内存 称为输入流.读取到内存. 三丶文件的打开和关闭. 1.操作原型. FILE *fopen(char

C语言的fopen函数(文件操作/读写)

头文件:#include <stdio.h> fopen()是一个常用的函数,用来以指定的方式打开文件,其原型为:     FILE * fopen(const char * path, const char * mode); [参数]path为包含了路径的文件名,mode为文件打开方式. mode有以下几种方式: 打开方式 说明 r 以只读方式打开文件,该文件必须存在. r+ 以读/写方式打开文件,该文件必须存在. rb+ 以读/写方式打开一个二进制文件,只允许读/写数据. rt+ 以读/写

C语言中数据输入输出到文件操作freopen()函数(1)

例题一.把短句 "Hello World!" 保存到磁盘文件f1.txt中. #include <stdio.h> #include <stdlib.h> int main() { FILE *fp; /* 定义文件指针*/ if( ( fp = fopen("f1.txt", "w") ) == NULL){ /* 打开文件 */ printf("File open error!\n"); exit(

Go语言入门(九) 文件操作

文件操作 文件的基本操作 读文件 func readFile(){ filename := "./aaa.log" file, err := os.Open(filename) if err != nil { fmt.Printf("open %s is error,error %v\n",filename,err) return } //关闭文件句柄 defer func() { file.Close() }() //读取文件 var buf[4096]byte

c语言基础学习10_关于文件操作的复习

=============================================================================如果一个程序只调用fopen,而不调用fclose.会导致两个结果: (1)一个程序同时可以打开的文件数量是有限的,如果超过系统限制,那么打开文件会失败.(2)一个fopen会占用一些内存,多个就会对内存消耗很大.所以记得fopen使用完文件后要及时的fclose.而且使用fclose后,能把缓冲区里面的数据同步到磁盘里面去.=========

函数指针|指针函数|C文件操作

数组指针(也称行指针)定义 int (*p)[n];()优先级高,首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,也可以说是p的步长.也就是说执行p+1时,p要跨过n个整型数据的长度. 如要将二维数组赋给一指针,应这样赋值:int a[3][4];int (*p)[4]; //该语句是定义一个数组指针,指向含4个元素的一维数组. p=a;        //将该二维数组的首地址赋给p,也就是a[0]或&a[0][0] p++;       //该语句执行过后,也就是p=p+

用C语言实现单链表的各种操作

#include<stdio.h> #include<stdlib.h> struct LinkList { int data; struct LinkList *next; }; /*初始化链表*/ void init_list(LinkList **head) { *head=(LinkList *)malloc(sizeof(LinkList)); (*head)->next=NULL; } /*添加节点*/ void add_node(LinkList *head)

【C语言】用C语言实现单链表的所有操作

建立源文件List.cpp #include"List.h" int main() {     Test();     system("pause");     return 0; } 建立头文件List.h #ifndef __LIST_H__ #define __LIST_H__ #include<stdio.h> #include<assert.h> #include<stdlib.h> typedef int DataTy