本人第一次写博客,也不知道该怎么写,只能按着自己能想到的思路来分享一下自己做的东西。
这个程序其实是我在大一下学期c++要求写的课程设计,奈何那时懂的不多,加上不好好学习,没能完整实现里面要求的功能。现在回过头来写,实在有不少感慨。这个课程设计要求编写代码实现校园学生消费信息记录,实现最基本的删除、修改、查询等功能,后来我添加了将信息保存到文件的功能。
说一下实现这个系统的思路吧。结构体是一个很好用的数据结构,将不同基本数据类型任意结合,是存储学生基本信息的最好结构。那么怎么对这个结构体进行管理呢?这时候用到一个叫单链表的数据结构,这时候就体现出指针的强大之处了。大家都知道程序是在内存中执行的,那么每个变量或者数据都会有一个地址,结构体也不例外。
为了让大家理解单链表,给大家举一个例子,把结构体比喻成一张纸条,那么单链表就是管理这张纸条的人。现在张三手里有一张纸条,纸条上写着李四住在101以及李四的一些基本信息;而李四手上也有一张纸条,上面写着王五住在211以及王五的一些基本信息;王五手上有一张纸条,上面写着赵六住在106以及赵六的一些基本信息,,,依次类推每个人手上只有一张纸条,所以他只能知道一个人的信息。
现在辅导员来了,她找到张三,问赵六在哪?张三肯定不知道,
张三说:”我只知道李四在101,你问一下李四,说不定他知道”。
然后辅导员按照张三指示到了101找到李四,问赵六在哪?
赵四说:“我只知道王五在211,他说不定知道赵六在哪”
辅导员有到了211找到王五,终于知道了赵六在106。
废话就不多说了,接下来到具体实现部分了。
先定义结构体存储学生信息
typedef struct node { char name[10]; //姓名 long number; //学号 char sex[4]; //性别 char info[10]; //消费信息 float ConsumeOut; //消费金额 struct node *next; }Info;
不知道有没有人对struct node *next不懂的,含义就是创建一个指向同类型的结构体;typedef类似于宏定义,这里是给struct node定义了一个别名Info,以后用到Info的时候相当于用了struct node。
接下来是创建单链表
void EnterInfo(Info *head,int n) { //录入学生信息 Info *p, *q = head; cout << "姓名\t学号\t 性别 金额\t消费信息" << endl; for (int i = 0; i < n; i++) { p = (Info *)malloc(sizeof(Info)); cin >> p->name >> p->number >> p->sex >>p->ConsumeOut>> p->info; p->next = NULL; q->next = p; q = p; } cout<<endl; }
创建单链表的核心在于给新建结点分配空间,并让单链表的最后一个结点的next指针为NULL,这点特别重要,上面的函数相当于在空链表的后面插入了一个p结点,那么p结点成为了单链表的最后一个结点,所以p->next = NULL;并修改头结点的next为p。
创建完单链表就可以往单链表里添加新信息了,那么接下来就可以对单链表进行查询、修改、删除等一系列操作了。先说怎么输出单链表吧。这个很简单,只需要找到头结点,只要结构体Info的next指针不为空就可以一直输出,输出完一个信息之后需要指向下一个结点,即p=p->next。
1 void PrintInfo(Info *head) { //输出消费信息表 3 Info *p; 4 p = head->next; 5 cout << "学生信息:" << endl; 6 cout<<"姓名\t 学号\t\t性别\t金额\t消费信息"<<endl; 7 while (p) { 8 cout << p->name<<"\t" <<p->number << "\t" << p->sex <<"\t"<<p->ConsumeOut<<"\t"<<p->info; 11 p = p->next;13 cout << endl; 14 } 15 cout << endl;17 }
接下来是查询单链表中的学生信息,这个相信大家都能看懂,就是从头结点开始遍历,一个一个结点地查下去,flag用来标志是否找到这个学生用的。
1 void FindNumber(Info *head){ //找出某个学号的学生 2 long num; 3 int flag=0; 4 Info *p; 5 p=head->next; 6 cout<<"请输入要查询的学号:"; 7 cin>>num; 8 while(p){ 9 if(p->number==num){ 10 cout<<"学生信息已找到"<<endl; 11 cout << p->name<<"\t\t" <<p->number << "\t" << p->sex <<"\t"<<p->ConsumeOut<<"\t"<< p->info<<endl; 12 flag=1; 13 } 14 p=p->next; 15 } 16 if(flag==0){ 17 cout<<"没有这个学生"<<endl; 18 } 19 cout<<endl; 20 }
接下来是插入操作,为了减少代码量,直接默认信息插在第一个位置,插入失败的情况很少发生,这个也不写了,只是一个if的代码,,,
1 void InsererInfo(Info *head){ //插入学生消费信息,默认插入位置为第一个位置 2 Info *p; 3 p=(Info *)malloc(sizeof(Info)); 4 cout << "请输入你想输入的学生消费信息"<<endl; 5 cout << "姓名 学号 性别 金额 消费信息 的次序依次输入" << endl; 6 cin>>p->name >> p->number >> p->sex >>p->ConsumeOut>> p->info; 7 p->next=head->next; /*注意指针的指向,必须是新生成的结点p->next=head->next,而不能是head->next=p->next,否则会发生内存访问错误*/ 10 head->next=p; 11 cout<<"插入成功!"<<endl; 12 }
接下来是删除操作,这个比较复杂,涉及到比较多的情况,首先需要查找这个学生的学号是否存在,定义了两个标志j和delet,每查找一个结点,如果没找到该学号delet就加1,这个delet标志很关键,因为要删除一个结点,必须将它的上一个结点的next指向要删除的结点的下一个结点,然后释放这个结点的空间。效果差不多就是这样
1 void DeletInfo(Info *head) { //删除在链表上的某个元素 2 Info *p = head; 3 Info *q; 4 int j = 1;int delet=0; 5 long num; 6 cout<<"请输入你想删除的学号:"; 7 cin>>num; 8 while(p->number!=num&&p->next!=NULL){ 9 p=p->next; 10 delet++; 11 } 12 if(!(p->number==num)){ 13 cout<<"您想删除的学号不存在,不能删除!"<<endl; 14 } 15 if(p->number==num){ 16 p=head; 17 while (p->next!=NULL&&j < delet) { 18 p = p->next; 19 j++; 20 } 21 if (p->next != NULL) { 22 q = p->next; 23 p->next = q->next; 24 free(q); 25 } 26 } 27 28 }
修改操作就比删除操作简单多了,只需要找到这个结点,修改指针p指向的内容就行了
1 void ExchangeInfo(Info *head){ //修改学生信息 2 Info *p=head->next; 3 long num; 4 cout<<"请输入你想修改信息的学号:"; 5 cin>>num; 6 while(p->number!=num&&p->next!=NULL){ 7 p=p->next; 8 } 9 if(!(p->number==num)){ 10 cout<<"这个学号的学生不存在!"<<endl; 11 } 12 if(p->number==num){ 13 cout<<"输入修改后的信息:"<<endl; 14 cin>>p->name>>p->number>>p->sex>>p->ConsumeOut>>p->info; 15 cout<<"修改成功,请注意保存!"<<endl; 16 } 17 }
到此整个程序的基本功能就实现了,下面还有文件操作功能和整个程序的代码
1 #include "iostream" 2 #include "string" 3 #include "fstream" 4 #include "iomanip" 5 #include "stdlib.h" 6 using namespace std; 7 8 typedef struct node { 9 char name[10]; //姓名 10 long number; //学号 11 char sex[4]; //性别 12 char info[10]; //消费信息 13 float ConsumeOut; //消费金额 14 struct node *next; 15 }Info; 16 17 void EnterInfo(Info *head,int n) { //录入学生信息 18 Info *p, *q = head; 19 cout << "姓名\t学号\t 性别 金额\t消费信息" << endl; 20 for (int i = 0; i < n; i++) { 21 p = (Info *)malloc(sizeof(Info)); 22 cin >> p->name >> p->number >> p->sex >>p->ConsumeOut>> p->info; 23 p->next = NULL; /* 注意,在结构体中声明的char name[10],输出的时候只能用 cout<<name,要不然会发生错误*/ 24 q->next = p; /*结构体声明的info如果是string类型的话会输出不了,程序异常*/ 25 q = p; 26 } 27 cout<<endl; 28 } 29 30 void PrintInfo(Info *head) { //输出消费信息表 31 Info *p; 32 p = head->next; 33 cout << "学生信息:" << endl; 34 cout<<"姓名\t 学号\t\t性别\t金额\t消费信息"<<endl; 35 while (p) { 36 cout << p->name<<"\t" <<p->number << "\t" << p->sex <<"\t"<<p->ConsumeOut<<"\t"<< p->info; 37 p = p->next; 38 cout << endl; 39 } 40 cout << endl; 41 } 42 43 int CountInfo(Info *head){ //统计表中学生个数 44 int count=0; 45 Info *p; 46 p=head->next; 47 while(p){ 48 p=p->next; 49 count++; 50 } 51 cout<<endl; 52 return count; 53 } 54 55 void FindNumber(Info *head){ //找出某个学号的学生 56 long num; 57 int flag=0; 58 Info *p; 59 p=head->next; 60 cout<<"请输入要查询的学号:"; 61 cin>>num; 62 while(p){ 63 if(p->number==num){ 64 cout<<"学生信息已找到"<<endl; 65 cout << p->name<<"\t\t" <<p->number << "\t" << p->sex <<"\t"<<p->ConsumeOut<<"\t"<< p->info<<endl; 66 flag=1; 67 } 68 p=p->next; 69 } 70 if(flag==0){ 71 cout<<"没有这个学生"<<endl; 72 } 73 cout<<endl; 74 } 75 76 void InsererInfo(Info *head){ //插入学生消费信息,默认插入位置为第一个位置 77 Info *p; 78 p=(Info *)malloc(sizeof(Info)); 79 cout << "请输入你想输入的学生消费信息"<<endl; 80 cout << "姓名 学号 性别 金额 消费信息 的次序依次输入" << endl; 81 cin>>p->name >> p->number >> p->sex >>p->ConsumeOut>> p->info; 82 p->next=head->next; /*注意指针的指向,必须是新生成的结点p->next=head->next,而不能是head->next=p->next,否则会发生内存访问错误*/ 83 head->next=p; 84 cout<<"插入成功!"<<endl; 85 } 86 87 void DeletInfo(Info *head) { //删除在链表上的某个元素 88 Info *p = head; 89 Info *q; 90 int j = 1;int delet=0; 91 long num; 92 cout<<"请输入你想删除的学号:"; 93 cin>>num; 94 while(p->number!=num&&p->next!=NULL){ 95 p=p->next; 96 delet++; 97 } 98 if(!(p->number==num)){ 99 cout<<"您想删除的学号不存在,不能删除!"<<endl; 100 } 101 if(p->number==num){ 102 p=head; 103 while (p->next!=NULL&&j < delet) { 104 p = p->next; 105 j++; 106 } 107 if (p->next != NULL) { 108 q = p->next; 109 p->next = q->next; 110 free(q); 111 } 112 } 113 114 } 115 116 void ExchangeInfo(Info *head){ //修改学生信息 117 Info *p=head->next; 118 long num; 119 cout<<"请输入你想修改信息的学号:"; 120 cin>>num; 121 while(p->number!=num&&p->next!=NULL){ 122 p=p->next; 123 } 124 if(!(p->number==num)){ 125 cout<<"这个学号的学生不存在!"<<endl; 126 } 127 if(p->number==num){ 128 cout<<"输入修改后的信息:"<<endl; 129 cin>>p->name>>p->number>>p->sex>>p->ConsumeOut>>p->info; 130 cout<<"修改成功,请注意保存!"<<endl; 131 } 132 } 133 void SaveInfo(Info *head){ //将学生消费信息表保存到文件中 134 ofstream save("e:\\StudentInfo.txt"); //将信息保存到e:\1\StudentInfo.txt,如果没有StudentInfo.txt就创建 135 Info *p=head->next; 136 while(p!=NULL){ 137 save<<p->name<<" "<<p->number<<" "<<p->sex<<" "<<p->ConsumeOut<<" "<<p->info<<endl; 138 p=p->next; 139 } 140 save.close(); 141 cout<<"学生消费信息成功保存到文件中"<<endl; 142 } 143 144 void InfoToMemory(Info *head){ //将文件中的信息导入到内存的链表中 145 char str[10],c; 146 Info *p,*q; 147 long num; 148 float con; 149 int line=0; 150 q=head; 151 ifstream in("e:\\StudentInfo.txt"); 152 if(!in){ 153 cout<<"文件不存在,请创建信息表,保存之后再读取!"<<endl; 154 in.close(); 155 } 156 else{ 157 cout<<"文件读取成功!"<<endl; 158 while (in.get(c)){ 159 if(c==‘\n‘){ 160 line++; 161 } 162 } 163 in.close(); 164 } 165 166 ifstream input("e:\\StudentInfo.txt"); 167 for(int i=0;i<line;i++) { 168 p=(Info *)malloc(sizeof(Info)); 169 input>>str; 170 strcpy(p->name,str); 171 input>>num; 172 p->number=num; 173 input>>str; 174 strcpy(p->sex,str); 175 input>>con; 176 p->ConsumeOut=con; 177 input>>str; 178 strcpy(p->info,str); 179 p->next=NULL; 180 q->next=p; 181 q=p; 182 } 183 input.close(); 184 } 185 186 void tips() { 187 cout<<"\t\t\t###################################\n"; 188 cout<<"\t\t\t##\t <1> 录入学生信息\t ##\n"; 189 cout<<"\t\t\t##\t <2> 输出学生信息\t ##\n"; 190 cout<<"\t\t\t##\t <3> 查找学号信息\t ##\n"; 191 cout<<"\t\t\t##\t <4> 插入学生信息\t ##\n"; 192 cout<<"\t\t\t##\t <5> 删除学生信息\t ##\n"; 193 cout<<"\t\t\t##\t <6> 修改学生信息\t ##\n"; 194 cout<<"\t\t\t##\t <7> 信息导入内存\t ##\n"; 195 cout<<"\t\t\t##\t <8> 保存信息文件\t ##\n"; 196 cout<<"\t\t\t##\t <0> 退出信息系统\t ##\n"; 197 cout<<"\t\t\t###################################\n"; 198 } 199 200 201 int main() { 202 int a,choice; 203 Info *list = (Info *)malloc(sizeof(Info)); 204 list->next = NULL; 205 tips(); 206 cin>>choice; 207 while(choice){ 208 switch(choice){ 209 case 1: 210 cout << "你想输入学生的数量:"; 211 cin >> a; 212 EnterInfo(list,a);break; 213 case 2: 214 PrintInfo(list);break; 215 case 3: 216 FindNumber(list);break; 217 case 4: 218 InsererInfo(list);break; 219 case 5: 220 DeletInfo(list);break; 221 case 6: 222 ExchangeInfo(list);break; 223 case 7: 224 InfoToMemory(list);break; 225 case 8: 226 SaveInfo(list);break; 227 case 0: 228 exit(0); 229 default: 230 cout<<"请输入在0-6之间的数字"<<endl;break; 231 } 232 tips(); 233 cin>>choice; 234 } 235 236 return 1; 237 }
花了两三个小时写这篇随笔,,,上面的程序肯定不是最好的,希望能借此给大家一点帮助吧,同时有什么问题希望大家提出来让我改正。