学生消费记账系统,大学c语言课程设计大作业

小组团队合作完成,在最初基础(即增删查改基础上再做更新)

设计一个学生消费管理系统,消费信息包括消费的时间,消费的种类以及消费的金额等,其中时间不重复,该系统能实现以下几个功能

  1. 消费信息录入功能:将所录入的数据储存在文件中;
  2. 消费信息统计功能:从文件中将信息读取,显示在显示器上;
  3. 消费信息查询功能:包括消费时间查询;
  4. 消费信息删除功能:按照消费时间进行删除操作
  5. 消费信息修改功能:按时间修改;
  6. 消费信息排序功能:按金额大小排序;
  7. 文件的保存:将数据写入后对文件的保存;
  8. 文件的加载:在访问数据时对文件的加载;
  9. 对系统的美化:调用颜色函数来美化系统

具体描述如下:

1消费信息录入功能

对消费信息进行管理,首先要把消费信息储存在文件里,因此,该系统应具备录入消费信息的功能。

关于c语言所对文件能进行的文件储存按照二进制或者asccii码的形式,在消费系统中包含消费时间,消费种类,消费金额,又因为消费信息为结构体,因此我们考虑用二进制形式进行储存,将文件打开关闭调用了fopen和fread函数,当我们输入完信息后我们将文件关闭,此时我们已经将输入的数据储存在了文件中,对文件的读写调用系统函数fread和fwrite,并判断文件是否结束,此时可以调用feof函数来进行判断。

生成数据文件,当我们从键盘键入数据的时候,将所有的数据建立成一个结构体链表,当我们发出键入结束的指令时,一次性得将这些结点信息写入数据文件中,这样就节省了由于来回读写文件所占用的时间,降低了程序的时间复杂度,本系统我们建立链表时采用的时头插法。

2消费信息统计功能

对我们存入文件的数据进行读取统计,这就需要调用fopen函数来打开文件,fread来读取文件中所储存的数据,然后用fclose来将文件关闭,此时便将数据完全读取了,然后执行循环,将我们所输入的每一条信息全部打印出来,这部分我们调用了简单的printf函数进行数据输出打印,直到文件读空时循环结束,停止打印,此时显示器上是所有我们输入的数据

我们定义一个指向Node类型的指针head作为参数。这个指针代表链表的头部,定义了一个整数变量count并初始化为0,这个变量用于存储学生的消费总金额。这段代码遍历链表中的每个结点,并累加每个学生的消费金额,每当遍历到一个结点时,它将该结点的消费金额加到count变量上,然后移动到下一个结点,一旦遍历完链表,它打印出消费的总金额count,同时我们调用了系统命令pause,使得程序暂停并等待用户按键继续。这是一种常见的在Windows系统上暂停程序的方法

3消费信息查查询功能

我们采用在链表中查找具有特定日期的学生消费记录,函数名为findstudent,我们定义了一个Node的类型的指针head作为参数,该指针就指向链表的头部,同时我们定义了一个整数变量a并将其初始化为0,该变量用来计数与输入日期匹配的记录的数量,我们在定义结构体的时候定义了一个字符数组date,因为本系统是通过查找日期来实现查找消费记录功能,首先,提示用户输入要查找的消费的时间,然后接着使用scanf函数从用户处获取输入的日期并存储在date中,然后是一个while循环,它遍历链表中的每个结点,直到找到与输入日期匹配的记录或到达链表的末尾,使用strcmp函数比较当前节点的日期与输入的日期。如果它们相同,则打印出该节点的所有信息并将a增加1。执行完这一部分后将指针移动到链表中的下一个结点,在循环结束后,检查是否找到了任何匹配的记录。如果没有找到匹配的记录,则打印一个消息告诉用户没有找到消费信息

4消费信息删除功能

我们定义了一个名为deletStudent的函数,它的目的是从链表中删除具有特定日期的学生消费记录,它接受一个指向Node类型的指针head作为参数,这个指针代表链表的头部,定义了一个字符数组date用于存储用户输入的日期,以及一个指向Node的指针move初始化为链表的头部,首先,它提示用户输入要删除的消费时间。然后,使用scanf函数从用户处获取输入的日期并存储在date变量中,并执行一个while循环,它遍历链表中的每个节点,直到找到与输入日期匹配的记录或到达链表的末尾,在循环内部:

使用strcmp函数比较当前节点的下一个节点的日期与输入的日期,如果它们相同,则执行以下操作:

保存当前节点的下一个节点到变量lin

将当前节点的next指针指向当前节点的下一个节点的下一个节点,从而跳过当前节点的下一个节点。

使用free函数释放已删除结点(即lin)的内存。

调用saveStudent(head)函数,对剩余数据进行保存

使用系统命令pause暂停程序。

使用系统命令cls清空控制台屏幕。

返回,结束函数。如果循环结束后仍未找到匹配的日期,则打印“未找到消费信息”。

最后,再次使用系统命令pausecls来暂停程序和清空屏幕。这是在提示用户输入日期后进行的操作,但如果找到日期并成功删除后也会执行。这部分代码放在了循环外,因此只会在没有找到日期时执行

5消费信息修改功能

我们定义了一个名为modifyStudent的函数,它的目的是修改链表中具有特定消费时间的学生的消费记录,这是一个名为 modifyStudent的函数,是一个指向Node类型的指针head作为参数,这个指针代表链表的头部,在初始结构体中我们定义了一个字符数组date用于存储用户输入的日期,以及一个指向Node的指针move初始化为链表的第二个节点(即头节点的下一个节点)。首先,它提示用户输入要修改的消费时间。然后,它使用scanf函数从用户处获取输入的日期并存储在date变量中,然后执行一个while循环,它遍历链表中的每个结点,直到找到与输入日期匹配的记录或到达链表的末尾,在while循环内部:

使用strcmp函数比较当前节点的日期与输入的日期。如果它们相同,则执行以下操作:

提示用户输入新的消费种类和金额。

使用scanf函数从用户处获取新的消费种类和金额,并存储在节点的相应字段中。

打印“修改成功”。

调用saveStudent(head)函数,这是我们所定义的储存数据的函数

使用系统命令pause暂停程序。

使用系统命令cls清空控制台屏幕。

返回,结束函数。如果循环结束后仍未找到匹配的日期,则打印“未找到消费信息”

最后,再次使用系统命令pausecls来暂停程序和清空屏幕。这是在提示用户输入日期后进行的操作,但如果找到日期并成功修改后也会执行。这部分代码放在了循环外,因此只会在没有找到日期时执行

6消费信息排序功能

这是一个名为sortStudent的函数,它接受一个指向Node类型的指针head作为参数,表示链表的头部,我们定义了两个指向Node的指针ab。这是用于遍历链表并比较结点中的学生消费金额的双重循环,外层循环变量a遍历链表,内层循环变量b遍历与a相邻的结点,如果当前结点a的学生消费金额大于其相邻结点b的学生消费金额,则交换这两个节点的学生信息。Student是我们所定义的结构体,代表学生的信息(消费日期、消费种类、消费金额),在排序完成后,调用一个名为printStudent的函数,将我们排序后的消费记录打印出来,这是为了验证排序结果并将其显示给用户,这段代码完成了对学生消费金额的排序,但未修改链表本身的结构

7文件的保存

我们定义了一个名为saveStudent的函数,它的目的是将学生消费信息保存到一个文件中,它接受一个指向Node类型的指针head作为参数,表示链表的头部,使用fopen函数打开一个名为Consumption.txt的文件,以写入模式("w")打开,如果文件不存在,它会被创建,如果文件已存在,它的内容会被清空,使用一个指针move从链表的第二个节点开始遍历整个链表,使用fwrite函数将当前结点(即move所指向的结点)中的学生信息写入文件,如果写入失败(例如由于磁盘空间不足或磁盘错误等一些问题),则会打印“保存失败”并返回,当执行完所有写入操作后,使用fclose函数关闭文件

8文件的加载

我们定义了一个名为loadStudent的函数,它的目的是从文件中加载学生消费信息并重新构建一个链表,这个函数接受一个指向Node类型的指针head作为参数,表示链表的头部,使用fopen函数打开一个名为Consumption.txt的文件,以只读模式("r")打开。为新结点分配内存,如果文件不存在,则打印一条消息并返回,这里使用了循环来读取文件中的每个学生的消费信息:在每次循环中:

使用fread函数从文件中读取一个学生的消费信息。

将当前节点(move所指向的节点)的下一个结点设置为新结点(fresh

move指针移动到新节点

为新结点分配内存。

在循环结束后,释放最后一结点的内存,使用fclose函数关闭文件,使用系统命令cls清空控制台屏幕,然后打印“读取成功”的消息,这是在提示用户输入日期后进行的操作,但如果找到日期并成功修改后也会执行。这部分代码放在了循环外,因此只会在没有找到日期时执行

9对系统的美化

我们定义了一个名为 color 的函数,该函数用于设置控制台文本的颜色,它接受一个类型为 short 的参数 x,我们先检查 x 是否在 0 到 15 的范围内,控制台文本的颜色通常使用一个 16 色的调色板,其中 0 到 15 对应不同的颜色,当x 在允许的范围内,则使用 SetConsoleTextAttribute 函数来设置控制台文本的颜色,这个函数需要两个参数,如果 x 不在允许的范围内,仍然会尝试设置控制台文本颜色,但实际上这可能不会产生预期的效果,因为 x 可能超出了 SetConsoleTextAttribute 函数所支持的颜色范围。代码中存在一个小问题。当 x 不在 0 到 15 的范围内时,虽然调用了 SetConsoleTextAttribute 函数,但传递给它的参数 x 可能超出了有效颜色的范围,这可能导致不可预测的行为。为了避免这种情况,应该确保在所有情况下都只传递有效的颜色值                  给 SetConsoleTextAttribute 函数

三、详细设计

void inputStudent(Node* head)

{

   Node* move = head;

   Node* fresh = (Node*)malloc(sizeof(Node));

   fresh->next = NULL;

   color(7);

   printf("请输入消费消费的时间,种类,金额\n");

   color(11);

   scanf("%s%s%d", fresh->student.date, fresh->student.name, &fresh->student.price);

   while (move->next != NULL)

   {

       move = move->next;

   }

   move->next = fresh;

   saveStudent(head);

   system("pause");

   system("cls");

}

Node* move = head;:定义一个指针move并初始化为指向链表的头部(头结点)。

Node* fresh = (Node*)malloc(sizeof(Node));:动态分配一个新的节点,并初始化其next指针为NULLprintf("请输入消费消费的时间,种类,金额\n");:提示用户输入消费的时间、种类和金额。scanf("%s%s%d", fresh->student.date, fresh->student.name, &fresh->student.price);:从标准输入读取用户输入的时间、种类和金额,并存储在新的节点中。while (move->next != NULL):循环遍历链表,直到到达链表的末尾。move = move->next;:移动指针到链表的下一个节点。move->next = fresh;:在链表的末尾添加新的节点。

saveStudent(head);:调用一个名为saveStudent的函数,并传递头结点作为参数。这个函数是用于将链表中的数据保存到文件。system("pause");和system("cls");:这两个函数调用是系统命令,用于暂停程序执行和清空控制台窗口

void printStudent(Node* head)//将储存的信息全部打印出来

{

     Node* move = head->next;

     while (move != NULL)

     {

           color(7);

           printf("时间:%s 种类:%s 金额:%d\n", move->student.date, move->student.name, move->student.price);

           move = move->next;

     }

     system("pause");

     system("cls");

}

Node* move = head->next;:定义一个指针move并初始化为指向链表的第二个节点。while (move != NULL):开始一个循环,只要指针move不为空(即链表还有节点),就继续循环。printf("时间:%s 种类:%s 金额:%d\n", move->student.date, move->student.name, move->student.price);:打印消费记录的时间、种类和金额。

move = move->next;:将指针move移动到链表的下一个节点。system("pause");:调用系统命令pause,暂停程序执行,等待用户按键。system("cls");:调用系统命令cls,清空控制台窗口。

countStudent(Node* head)函数这个函数的目的是计算并打印出链表中所有学生的消费总金额。1.初始化计数器:初始化一个变量count为0,用于累计消费总金额。2.遍历链表:同样使用while循环遍历链表,直到move指针变为NULL。在循环体中,将当前节点的消费金额加到count上。3.打印总金额:在遍历结束后,打印出消费的总金额。4.清空控制台:同样使用system("cls")来清空控制台。

void findStudent(Node* head)

{

   Node* move = head->next;

   char date[20];

   color(7);

   printf("请输入要查找的消费的时间:");

   color(11);

   scanf("%s", date);

   while (move != NULL)

   {

       if (strcmp(date, move->student.date) == 0)

       {

          color(7);

          printf("时间:%s 种类:%s 金额:%d\n", move->student.date, move->student.name, move->student.price);

          system("pause");

          system("cls");

          return;}

       move = move->next;

   }color(7);

   printf("未找到消费信息\n");

   system("pause");

   system("cls");}

Node* move = head->next;: 定义一个指针move,并初始化为指向链表的第二个节点。char date[20];: 定义一个字符数组date,用于存储用户输入的时间。printf("请输入要查找的消费的时间:"): 打印提示信息,要求用户输入要查找的消费时间。scanf("%s", date);: 从标准输入读取一个字符串,并存储在变量date中。while (move != NULL): 开始一个循环,只要指针move不为空(即链表还有节点),就继续循环。

if (strcmp(date, move->student.date) == 0): 使用strcmp函数比较用户输入的日期与当前节点的学生日期是否相同。如果相同,执行以下操作:

    • 打印消费记录的时间、种类和金额。
    • system("pause");: 调用系统命令pause,暂停程序执行,等待用户按键。
    • system("cls");: 调用系统命令cls,清空控制台窗口。
    • return;: 结束函数执行。

move = move->next;: 将指针move移动到链表的下一个节点。

printf("未找到消费信息\n");: 如果循环结束还没有找到匹配的记录,打印提示信息表示没有找到消费信息。

system("pause");: 暂停程序执行。

system("cls");: 清空控制台窗口。

查询函数:

该模块用void modifyStudent(Node *head)和savestudent(head)两个函数实现,其中modifystudent(Node *head)函数的功能是输入要修改的消费时间,其参数为指向Node类型指针变量。在链表中查找与输入的消费信息相同的节点,如果找到就删除当前节点。使用While循环来历遍链表,如果未找到,则输出未找到消费信息。删除完毕后,调用saveStudent(head),是更改后的信息存储到文件中。

排序:

该模块使用void sortStudent(Node *head)和printStudent(head)两个函数实现的。在sotrStudent(Node *head)函数中定义两个指针ab,用于遍历链表中的节点。使用两个嵌套的for循环遍历链表中的所有节点。外层循环变量a从链表的头节点开始,内层循环变量ba的下一个节点开始。在内层循环中,比较节点a和节点b中的学生价格。如果节点a中的学生价格大于节点b中的学生价格,则交换这两个节点的学生信息。这是通过临时变量temp来实现的。在排序完成后,调用printStudent(head)函数来打印排序后的学生链表。这假定有一个名为printStudent的函数,它能够遍历并打印链表中的学生信息。

#include<stdio.h>

#include<stdlib.h>

#include<conio.h>

#include<string.h>

#define _CRT_SECURE_NO_WARNINGS 1

#pragma warning(disable:4996)

#include<Windows.h>

void color(short x)

{

      if (x >= 0 && x <= 15)

         SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), x);

      else

         SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), x);

}

typedef struct Student

{

      char date[10];

      char name[10];

      int price;

}Student;

typedef struct _Node

{

      Student student;

      struct _Node* next;

}Node;

void welcome();

void inputStudent(Node* head);//输入

void printStudent(Node* head);//输出

void countStudent(Node* head);//统计

void findStudent(Node* head);//查询

void saveStudent(Node* head);//存储

void loadStudent(Node* head);//读取

void modifyStudent(Node* head);//修改

void deletStudent(Node* head);//删除

void sortStudent(Node* head);//排序

//主函数

int main()

{

      char c;

      Node* head = (Node*)malloc(sizeof(Node));

      head->next = NULL;

      loadStudent(head);

      while (1)

      {

            welcome();

            c = _getch();

            switch (c)

            {

            case '1'//录入消费信息

                  inputStudent(head);

                  break;

            case '2'//打印消费信息

                  printStudent(head);

                  break;

            case '3'//统计消费金额

                  countStudent(head);

                  break;

            case '4'//查找消费信息

                  findStudent(head);

                  break;

            case '5'//修改消费信息

                  modifyStudent(head);

                  break;

            case '6'//删除消费信息

                  deletStudent(head);

                  break;

            case'7'://将消费信息排序

                  sortStudent(head);

                  break;

            case '8'//退出系统

                  system("cls");

                  color(7);

                  printf("感谢使用!\n");

                  break;

            default:

                  color(7);

                  printf("请重新选择功能!\n");

                  break;

            }

      }

      return 0;

}//主函数

//页面

void welcome()

{

      color(11);

      printf("                *********************************\n");

      color(14);

      printf("                *\t消费信息管理系统\t*\n");

      color(11);

      printf("                *********************************\n");

      color(14);

      printf("                *\t请选择功能列表\t        *\n");

      color(11);

      printf("                *********************************\n");

      color(14);

      printf("                *\t  1.录入消费信息\t*\n");

      color(14);

      printf("                *\t  2.打印消费信息\t*\n");

      color(14);

      printf("                *\t  3.统计消费金额\t*\n");

      color(14);

      printf("                *\t  4.查找消费信息\t*\n");

      color(14);

      printf("                *\t  5.修改消费信息\t*\n");

      color(14);

      printf("                *\t  6.删除消费信息\t*\n");

      color(14);

      printf("                *\t  7.整理消费信息\t*\n");

      color(14);

      printf("                *\t  8.退出系统\t        *\n");

      color(11);

      printf("                *********************************\n");

}

//录入消费信息

void inputStudent(Node* head)

{

      Node* move = head;

      Node* fresh = (Node*)malloc(sizeof(Node));

      fresh->next = NULL;

      color(7);

      printf("请输入消费消费的时间,种类,金额\n");

      color(11);

      scanf("%s%s%d", fresh->student.date, fresh->student.name, &fresh->student.price);

      while (move->next != NULL)

      {

            move = move->next;

      }

      move->next = fresh;

      saveStudent(head);

      system("pause");

      system("cls");

}

//打印所储存的所有信息

void printStudent(Node* head)

{

      Node* move = head->next;

      while (move != NULL)

      {

            color(7);

            printf("时间:%s 种类:%s 金额:%d\n", move->student.date, move->student.name, move->student.price);

            move = move->next;

      }

      system("pause");

      system("cls");

}

//统计所有消费次数

void countStudent(Node* head)

{

      int count = 0;

      Node* move = head->next;

      while (move != NULL)

      {

            count += move->student.price;

            move = move->next;

      }

      printf("消费的总金额为%d\n", count);

      system("pause");

      system("cls");

}

//查找消费记录

void findStudent(Node* head)

{

      int a;

      a = 0;

      Node* move = head->next;

      char date[20];

      color(7);

      printf("请输入要查找的消费的时间:");

      color(11);

      scanf("%s", date);

      while (move != NULL)

      {

            if (strcmp(date, move->student.date) == 0)

            {

                  color(7);

                  printf("时间:%s 种类:%s 金额:%d\n", move->student.date, move->student.name, move->student.price);

                  a++;

            }

            move = move->next;

            if (move == NULL && a == 0)

            {

                  printf("未找到消费信息\n");

                  break;

            }

      }color(7);

      system("pause");

      system("cls");

      return;

}

//保存消费信息

void saveStudent(Node* head)

{

      FILE* file = fopen("./Consumption.txt", "w");

      Node* move = head->next;

      while (move != NULL)

      {

            if (fwrite(&move->student, sizeof(Student), 1, file) != 1)

            {

                  color(7);

                  printf("保存失败\n");

                  return;

            }

            move = move->next;

      }

      fclose(file);

}

//加载消费数据信息

void loadStudent(Node* head)

{

      FILE* file = fopen("./Consumption.txt", "r");

      Node* fresh = (Node*)malloc(sizeof(Node));

      Node* move = head;

      fresh->next = NULL;

      if (!file)

      {

            color(7);

            printf("没有查询到消费文件,跳过读取\n");

            return;

      }

      while (fread(&fresh->student, sizeof(Student), 1, file) == 1)

      {

            move->next = fresh;

            move = fresh;

            fresh = (Node*)malloc(sizeof(Node));

            fresh->next = NULL;

      }

      free(fresh);

      fclose(file);

      color(7);

      printf("读取成功\n");

      system("cls");

}

//修改消费数据信息

void modifyStudent(Node* head)

{

      char date[20];

      Node* move = head->next;

      color(7);

      printf("请输入要修改的消费的时间:");

      color(11);

      scanf("%s", date);

      while (move != NULL)

      {

            if (strcmp(move->student.date, date) == 0)

            {

                  color(7);

                  printf("请输入更改的消费种类,金额\n");

                  color(11);

                  scanf("%s%d", move->student.name, &(move->student.price));

                  color(7);

                  printf("修改成功\n");

                  saveStudent(head);

                  system("pause");

                  system("cls");

                  return;

            }

            move = move->next;

      }

      color(7);

      printf("未找到消费信息。\n");

      system("pause");

      system("cls");

}

//删除信息

void deletStudent(Node* head)

{

      char date[20];

      Node* move = head;

      color(7);

      printf("请输入要删除的消费时间:");

      color(11);

      scanf("%s", date);

      while (move != NULL)

      {

            if (strcmp(date, move->next->student.date) == 0)

            {

                  Node* lin = move->next;

                  move->next = move->next->next;

                  free(lin);

                  saveStudent(head);

                  system("pause");

                  system("cls");

                  return;

            }

            move = move->next;

      }color(7);

      printf("未找到消费信息。\n");

      system("pause");

      system("cls");

}

//排序

void sortStudent(Node* head) {

      Node* a, * b;

      for (a = head; a->next != NULL; a = a->next) {

            for (b = a->next; b != NULL; b = b->next) {

                  if (a->student.price > b->student.price) {

                        Student temp = a->student;

                        a->student = b->student;

                        b->student = temp;

                  }

            }

      }

      printStudent(head);

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Think m

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值