zoukankan      html  css  js  c++  java
  • [链表] 对链表与文件的结合使用的一点看法

    概要:

         指针、链表和文件是C语言中比较重要的三块内容,经过一年的学习,我们大多人已经比较好的掌握了这三个方面的使用。但是将链表和文件结合使用,好像还没有哪道题中有过,或者还没有哪个人做过。于是,我写这篇论文——链表与文件的结合使用,并尽自己所能介绍一些比较方便易懂的方法和实例,将它们较好的呈献在大多人面前,以增加大家对链表、指针和文件的理解,提高大家学习C的兴趣。

    正文:

    用数组存放数据的时候,需要事先确定数组的长度,并分配连续的内存空间,其长度不能动态的改变,在面临实际的情况时,如对某公司的员工数据进行记录时,当员工数目变化时,数组很难相应变化。而使用链表,可以动态的分配空间,可以解决这些问题。谈到链表,就必须说到数据结构。链表是一种比较简单的线性数据结构,它可以实现对存储空间动态分配(首先要指明的是数组里的数据是连续存放,而链表里的数据是非连续存放的)。

    链表是由许许多多的链表节点串联起来的,且每一个节点都应是相同的结构体类型。

    对于链表的操作主要是:1.建立链表 2.数据的查找和输出 3.求链表节点的个数 4.插入和删除一个节点 3.链表的合并。

    首先建立链表(以学生信息管理为例):

    #include <malloc.h>   //建立链表是需要动态开辟空间,其函数属于malloc.h头文件

    #include <stdio.h>

    Int NUM = 0;         //NUM 记录链表的节点数,即学生的个数

    Struct stu {

    Long num;

    Float score;

    Struct stu *next;

    };

    Typedef  struct stu Stu_link;

    1.建立链表的方法有两种:尾插法和头插法,在此我就以尾插法为例。

    其函数模块为:

    Stu_link *cre_link () {

    //当前链表的头指针和为指针,表明链表的状态为空

    Stu_link *head = NULL, *last = NULL;

    Stu_link *p;

    P = (Stu_link *)malloc(sizeof(Stu_link));   //开辟节点

    Printf("input the number : ");

    Scanf("%d", &p->num);

    Printf("input the score : ");

    Scanf("%d", &p->score);

    While(p->num)

    {

    If(head == NULL)

    {

    Head = p;

    Last = p;

    }

    Else

    {

    Last->next = p;

    Last = p;

    }

    P = (Stu_link *)malloc(sizeof(Stu_link));   //重新开辟一个节点

    Printf("input the number : ");

    Scanf("%d", &p->num);

    If(p->num)

    {

    Printf("input the score : ");

    Scanf("%d", &p->score);

    P->next = NULL;

    }

    }

    Return head;

    }

    这个函数在主函数中被调用,会产生许多连接的链表节点,直到num输入0结束。

    此时就可以用文件操作了。在输入节点信息的时候就一同将学生信息存入到文件中去了。

    操作如下:

    void  cre_link () {

    //当前链表的头指针和为指针,表明链表的状态为空

    Stu_link *head = NULL, *last = NULL;

    FILE *stu;

    Stu_link *p;

    /*文件名应由用户自定义,可用下面注视语句,为了下面叙述方便,暂时由我来定义*/

    /*Char filename[30];

    Printf("input file path and name.dat : ");

    Gets(filename);*/

     

    /*以写的方式打开一个二进制文件*/

    If((stu = fopen("D:\\tc\\stuinfo.dat", "wb")) == NULL)

    {

    Printf("cannot open this file .");

    Exit(0);

    }

    P = (Stu_link *)malloc(sizeof(Stu_link));   //开辟节点

    Printf("input the number : ");

    Scanf("%d", &p->num);

    Printf("input the score : ");

    Scanf("%d", &p->score);

    While(p->num)

    {

    Fwrite(p, sizeof(Stu_link), 1, stu); 

    NUM++;        //记录链表的节点

    If(head == NULL)

    {

    Head = p;

    Last = p;

    }

    Else

    {

    Last->next = p;

    Last = p;

    }

    P = (Stu_link *)malloc(sizeof(Stu_link));   //重新开辟一个节点

    Printf("input the number : ");

    Scanf("%d", &p->num);

    If(p->num)

    {

    Printf("input the score : ");

    Scanf("%d", &p->score);

    P->next = NULL;

    }

    }

    Fclose(stu);

    }

    这样就实现了在建立链表并输入学生信息的时候,同时也将信息写入文件了。

    2.单链表元素的遍历:

    单链表元素的遍历,即将每个链表元素的内容都输出来。其函数模块比较简单,如下:

    Void print_link(Stu_link *head)

    {

    Stu_link *p;

    P = head;

    While(p)

    {

    Printf("num: %5d score:%5.1f\n", p->num, p->score);

    P = p->next;

    }

    Printf("\n");

    }

    因为上面已经对输入的学生信息写入了文件,所以链表的输出可以打开那个文件进行读操作。

    Void print_link()

    {

    Stu_link *p;

    FILE *fp;

    If((fp = fopen("D:\\tc\\stuinfo.dat", "rb")) == NULL)

    {
    printf("cannot open the file\n");

    Exit(0);

    }

    While(!feof(fp))   // 将文件中的内容读出并输出来

    {

    P = (Stu_link *)malloc(sizeof(Stu_link));

    Fseek(fp, 0, SEEK_CUR);               //保持文件内部指针在当前位置,下次

    Fread(p, sizeof(Stu_link), 1, fp);           //读出时的位置就从当前位置开始

    Printf("num: %5d score: %d5.1f", p->num, p->score);

    Free(p);                        //释放p的空间,以节省内存,方便下次开辟

    }

    Fclose(fp);

    }

    3.链表元素的查找

    具体思路是将文件中的数据读出来,然后一个个比较,若出现相等的,则找到结果。若没有出现则没有找到。

    其函数模块为:

    Stu_link *search(int num)   //其中num为要查找的学生的学号,在主函数中输出

    {

    Stu_link *p;

    FILE *fp;

    If((fp = (fopen("D:\\tc\\stuinfo.dat", "rb")) == NULL)

    {

    Printf("cannot open the file.");

    Exit(0);

    }

    While(!feof(fp))

    {

    P = (Stu_link *)malloc(sizeof(Stu_link));

    Fseek(fp, 0, SEEK_CUR);

    Fread(p, sizeof(Stu_link), 1, fp);

    If(p->num == num)

    {

    Printf("find the student .\n");

    Fclose(fp);

    Return p;

    }

    }

        printf("not find the student.\n");

    free (p);

    Fclose(fp);

    Return NULL;

    }

    4.链表的插入

    链表的插入有两种方法,节点前插入和节点后插入,在此我就以节点后插入为例,因为它比较符合习惯,简单易懂。

    Void  insert(Stu_link newstu)   //将新增加的信息插入到文件结尾   

    {

    FILE *fp;

    If((fp = fopen("D:\\tc\\stuinfo.dat", "ab")) == NULL)

    {

    Printf("cannot open the file.\n");

    Exit(0);

    }

    If(fwrite(&newstu, sizeof(Stu_link), 1, fp) == sizeof(Stu_link))

    {

    Printf("insert successfully!");

    NUM++;

    }

    Fclose(fp);

    Return;

    }

    5.链表的删除

    因为输入的数据都已经写入到文件中了,所以删除链表节点的基本思路是将文件中的节点一个个读出来,并与想删除的那个数据进行比较,若相同则可以删除,若没有相同的则没有该学生。

    其函数模块如下:

    //先把文件中的数据全部读出来,然后对信息进行删除,再将信息重新写入到文件中去

    Void delete(int stunum)

    {

    FILE *fp;

    Stu_link *stu, *p;

    Int i = 0, record;

    Stu = (Stu_link *)calloc(NUM, sizeof(Stu_link);

    If((fp = fopen("D:\\tc\\stuinfo.dat", "rb+")) == NULL)

    {

    Printf("cannot open the file.\n");

    Exit(0);

    }

    Fread(stu, sizeof(Stu_link), NUM, fp);

    For(i = 0; i < NUM; i++)

    {

    If(stu[i].num == stunum)

    {

    Record = i;

    Break;

    }

    Stu[record + 1].next = stu[record ].next;

    Free(stu[record]);

    Fclose(fp);

    If((fp = fopen("D:\\tc\\stuinfo.dat", "wb")) == NULL)

    {

    Printf("cannot open the file.\n");

    Exit(0);

    }

    Fwrite(stu, sizeof(Stu_link), NUM, fp);

    Fclose(fp);

    }

     

    结尾:

    上面所写内容只是链表与文件的结合使用的一部分,但却实现了我写这篇文章的初衷,即编写一个简单的学生成绩管理系统,可以实现简单的学生和学生成绩管理,对数据进行增删改查。大一尚未学过数据结构,所以只能以链表这个简单的数据结构来做此题。由于水平有限,对其解释仍有不够之处,还望海谅。

    参考资料:《C语言宝典》

    附:“自己用以上只是做的一个简单的学生管理系统”

    #include <stdio.h>

    #include <alloc.h>

    int NUM = 0;

     

    typedef struct stu

    {

    int  num;

    float score;

    struct stu *next;

    }Stu_link;

     

    void  cre_link()

    {

    Stu_link *head = NULL, *last = NULL;

    FILE *stu;

    Stu_link *p;

    float score;

     

    /*Char filename[30];   */

          /*printf("input file path and name.dat : ");     */

    /*gets(filename);*/

     

    if((stu = fopen("E:\\tc\\stuinfo.dat", "wb")) == NULL)

    {

    printf("cannot open this file .");

    getch();

    exit(0);

    }

    p = (Stu_link *)malloc(sizeof(Stu_link));

    printf("input the number : ");

    scanf("%d", &(p->num));

    if(!(p->num))

    {

    printf("NULL finished !\n");

    return ;

    }

    while(p->num)

    {

    printf("input the score : ");

    scanf("%f", &(p->score));

    fwrite(p, sizeof(Stu_link), 1, stu);

    NUM++;

    if(head == NULL)

    {

    head = p;

    last = p;

    }

    else

    {

    last->next = p;

    last = p;

    }

    p->next = NULL;

    p = (Stu_link *)malloc(sizeof(Stu_link));

    printf("input the number : ");

    scanf("%d", &(p->num));

    }

    printf("create successfully!\n");

    fclose(stu);

    }

     

    void print_link()

    {

    Stu_link *p;

    int i=0;

    FILE *fp;

    if((fp = fopen("E:\\tc\\stuinfo.dat", "rb")) == NULL)

    {

    printf("cannot open the file\n");

    getch();

    exit(0);

    }

    while(!feof(fp) && i < NUM)

    {

    p = (Stu_link *)malloc(sizeof(Stu_link));

    fread(p, sizeof(Stu_link), 1, fp);

    i++;

    printf("num: %d score: %.2f\n", p->num, p->score);

    free(p);

    }

    fclose(fp);

    }

     

    void  search(int num)

    {

    Stu_link *p;

    FILE *fp;

    if((fp = fopen("E:\\tc\\stuinfo.dat", "rb")) == NULL)

    {

    printf("cannot open the file.");

    getch();

    exit(0);

    }

    while(!feof(fp))

    {

    p = (Stu_link *)malloc(sizeof(Stu_link));

    fread(p, sizeof(Stu_link), 1, fp);

    if(p->num == num)

    {

    printf("find the student .\n");

    printf("num: %d  score: %.2f \n", p->num, p->score);

    fclose(fp);

    return;

    }

    }

    printf("not find the student.\n");

    free (p);

    fclose(fp);

    }

     

    void  insert(Stu_link newstu)

    {

    FILE *fp;

    if((fp = fopen("E:\\tc\\stuinfo.dat", "ab")) == NULL)

    {

    printf("cannot open the file.\n");

    getch();

    exit(0);

    }

    if(fwrite(&newstu, sizeof(Stu_link), 1, fp))

    {

    printf("insert successfully!\n");

    NUM++;

    }

    fclose(fp);

    return;

    }

     

    void delete(int stunum)

    {

    FILE *fp;

    Stu_link *stu, *p;

    int i = 0, record;

    stu = (Stu_link *)calloc(NUM, sizeof(Stu_link));

    if((fp = fopen("E:\\tc\\stuinfo.dat", "rb+")) == NULL)

    {

    printf("cannot open the file.\n");

    getch();

    exit(0);

    }

    fread(stu, sizeof(Stu_link), NUM, fp);

    for(i = 0; i < NUM; i++)

    {

    if(stu[i].num == stunum)

    {

    record = i;

    break;

    }

    }

    NUM--;

    fclose(fp);

    if((fp = fopen("E:\\tc\\stuinfo.dat", "wb")) == NULL)

    {

    printf("cannot open the file.\n");

    getch();

    exit(0);

    }

    for(i=0;i<NUM;i++)

    {

    if(i==record) continue;

    fwrite(stu+i, sizeof(Stu_link), 1, fp);

    }

    printf("Delete successfully!\n");

    free(stu);

    fclose(fp);

    }

    main()

    {

    int search_num, del_num, choice;

    Stu_link newstu;

    void cre_link();

    void print_link();

    void search(int);

    void delete(int);

    void insert(Stu_link);

    clrscr();

    while(1)

    {

    printf("-----Menu-----\n");

    printf("  1. start\n");

    printf("  2. search\n");

    printf("  3. print\n");

    printf("  4. amount of stu\n");

    printf("  5. insert \n");

    printf("  6. delete a stu\n");

    printf("  7. save and end \n");

    printf("\n");

    printf("choose : ");

    scanf("%d", &choice);

     

    switch(choice)

    {

     case 1:

    printf("input num 0 to stop.\n");

    cre_link();

    getch();

    break;

     case 2:

    printf("input the number of the student: ");

    scanf("%d", &search_num);

    search(search_num);

    getch();

    break;

     case 3:

    printf("all students : \n");

    print_link();

    getch();

    break;

     case 4:

    printf("All students are %d . \n", NUM);

    getch();

    break;

     case 5:

    printf("input the new student's number: ");

    scanf("%d", &newstu.num);

    printf("input the new student's score: ");

    scanf("%f", &newstu.score);

    insert(newstu);

    getch();

    break;

     case 6:

    printf("input the delete student's number: ");

    scanf("%d", &del_num);

    delete(del_num);

    getch();

    break;

     case 7:

    printf("save successfully !\n");

    getch();

    exit(0);

    break;

     default:

    printf("select error ! again ...\n");

    break;

    }

    }

    }

    该程序可以初始化学生的信息,查询学生的信息,打印学生的信息,查询学生总数,插入学生信息,删除学生信息。学生信息只需输入一次就可以多吃使用,因为它是从文件中读出学生信息。可见用文件将信息保存是个很好的方法。当然程序还有不完善的地方,比如,倘若学号输入相同,应进行提示,但这与我这篇文章的论题无关,而且进行修改很简单,在此不作赘述。

     

  • 相关阅读:
    Selenium生成Report的利器- ExtentReports
    学习使用monkey 测试
    charles 结合mocky 模拟数据
    Vue.use()源码分析且执行后干什么了
    commonjs 与 es6相关Module语法的区别
    vue函数化组件 functional
    html5细线表格制作
    移动端H5页面禁止长按复制和去掉点击时高亮
    javascript生成器
    promise和生成器的结合
  • 原文地址:https://www.cnblogs.com/xufeiyang/p/1760599.html
Copyright © 2011-2022 走看看