最近一直在码项目。直到今天,终于正式的完成了一个属于自己的第一个项目。虽然可能有些不足,有些地方确实也需要修改,但是大体功能是实现了的,对我来说也是一个挑战和突破,再写的过程中,我也逐渐认清楚自己是要走项目还是要走算法的道路。下面我就对于这次项目做一个总结。
这一次我写了一个简单的通讯录。其核心就是链表和对文件的处理。可能有些功能并不完善,如果有好的建议,请写在评论区,我会及时修改或者改进。刚开始我对于链表并不熟悉,只能说看得懂但远远没到会用,会写的程度。于是我只能边学边写,进度很缓慢。
首先是主程序:
int x;
? ? link();//把文件内容导入链表
? ? menu();//打印菜单
? ? printf("请输入你的选择\n");
? ? scanf("%d", &x);
? ? while (x)
? ? {
? ? ? ? switch (x)
? ? ? ? {
? ? ? ? case 1:
? ? ? ? ? ? add();
? ? ? ? ? ? break;
? ? ? ? case 2:
? ? ? ? ? ? del();
? ? ? ? ? ? break;
? ? ? ? case 3:
? ? ? ? ? ? update();
? ? ? ? ? ? break;
? ? ? ? case 4:
? ? ? ? ? ? search();
? ? ? ? ? ? break;
? ? ? ? case 5:
? ? ? ? ? ? save();
? ? ? ? ? ? break;
? ? ? ? case 6:
? ? ? ? ? ? display();
? ? ? ? ? ? break;
? ? ? ? case 7:
? ? ? ? ? ? delall();
? ? ? ? ? ? break;
? ? ? ? case 8:
? ? ? ? ? ? Count();
? ? ? ? ? ? break;
? ? ? ? default:
? ? ? ? ? ? printf("输入错误,请重新输入!");
? ? ? ? ? ? break;
? ? ? ? }
? ? ? ? menu();
? ? ? ? scanf("%d", &x);
? ? ? ? if (x == 0)
? ? ? ? {
? ? ? ? ? ? break;
? ? ? ? }
? ? }
这里我写了一个link函数,因为我要对文件里边的内容进行导入到链表。所以在程序执行前会调用它,后面没什么好说的,就是简单的用switch来调用不同函数功能。
接着是第一个功能,添加联系人,先上代码:
void add()
{
? ? char s;
? ? while (1)
? ? {
? ? ? ? p1 = (struct node *)malloc(LEN);
? ? ? ? p2->next = p1;
? ? ? ? p2 = p1;
? ? ? ? printf("请输入联系人姓名:");
? ? ? ? scanf("%s", p2->content.name);
? ? ? ? printf("请输入联系人地址:");
? ? ? ? scanf("%s", p2->content.adress);
? ? ? ? printf("请输入联系人电话号码:");
? ? ? ? scanf("%s", p2->content.number);
? ? ? ? printf("请输入联系人邮箱:");
? ? ? ? scanf("%s", p2->content.email);
? ? ? ? getchar();
? ? ? ? printf("添加联系人成功!\n你是否想继续存储?(Y ?or ?N):");
? ? ? ? scanf("%c", &s);
? ? ? ? if (s == 'Y')
? ? ? ? ? ? continue;
? ? ? ? else
? ? ? ? ? ? break;
? ? }
? ? p2->next = NULL;
? ? printf("\n");
}
这里因为我先调用了link函数把文件里面的内容导入链表,所以现在我就不需要再一次创建链表,只需要在节点后面继续开辟新空间就行。这里我当时因为找不准节点的接入,一直出错,debug好久。。。。。
然后就是删除联系人:
void del()
{
? ? char m[100];
? ? char k;
? ? p = q = head;
? ? printf("请输入你想要删除的联系人姓名:");
? ? scanf("%s", m);
? ? getchar();
? ? struct node *h = head;
? ? while (q != NULL)
? ? {
? ? ? ? if (strcmp(q->content.name, m) == 0 && q == head)
? ? ? ? {
? ? ? ? ? ? head = head->next;
? ? ? ? ? ? printf("删除成功!\n");
? ? ? ? }
? ? ? ? else if (strcmp(q->content.name, m) == 0)
? ? ? ? {
? ? ? ? ? ? p->next = q->next;
? ? ? ? ? ? free(q);
? ? ? ? ? ? printf("删除成功!\n");
? ? ? ? }
? ? ? ? else
? ? ? ? {
? ? ? ? ? ? p = q;
? ? ? ? ? ? q = q->next;
? ? ? ? ? ? continue;
? ? ? ? }
? ? ? ? printf("你是否要继续删除?\n继续输入'Y'否则输入'N':");
? ? ? ? scanf("%c", &k);
? ? ? ? getchar();
? ? ? ? if (k == 'Y')
? ? ? ? {
? ? ? ? ? ? printf("请输入你想要删除的联系人姓名:");
? ? ? ? ? ? scanf("%s", m);
? ? ? ? ? ? getchar();
? ? ? ? ? ? q = p = head;
? ? ? ? ? ? continue;
? ? ? ? }
? ? ? ? else if (k == 'N')
? ? ? ? ? ? break;
? ? }
}
这个就很简单了,就是对链表进行删除,就是对链表进行遍历,找出我们先要删除的联系人,如果是第一个节点,我们就让头指针往下移一个。如果不是,我们就用双指针进行删除。
下一个是修改联系人:
void update()
{
? ? char k;
? ? p2 = p1 = head;
? ? char m[100], n[100];
? ? if (head == NULL)
? ? ? ? printf("通讯录中无可修改的联系人!\n");
? ? while (p1 != NULL)
? ? {
? ? ? ? printf("请输入你想修改的联系人名字:");
? ? ? ? scanf("%s", m);
? ? ? ? getchar();
? ? ? ? if (strcmp(p1->content.name, m) == 0)
? ? ? ? {
? ? ? ? ? ? printf("请输入联系人新的姓名:");
? ? ? ? ? ? scanf("%s", p1->content.name);
? ? ? ? ? ? printf("请输入联系人新的地址:");
? ? ? ? ? ? scanf("%s", p1->content.adress);
? ? ? ? ? ? printf("请输入联系人新的电话:");
? ? ? ? ? ? scanf("%s", p1->content.number);
? ? ? ? ? ? printf("请输入联系人新的邮箱:");
? ? ? ? ? ? scanf("%s", p1->content.email);
? ? ? ? ? ? printf("修改成功!");
? ? ? ? ? ? p1 = head;
? ? ? ? }
? ? ? ? else
? ? ? ? {
? ? ? ? ? ? p1 = p1->next;
? ? ? ? ? ? continue;
? ? ? ? }
? ? ? ? getchar();
? ? ? ? printf("你是否想继续修改?继续输入'Y'否则输入'N':");
? ? ? ? scanf("%c", &k);
? ? ? ? if (k == 'Y')
? ? ? ? ? ? continue;
? ? ? ? else if (k == 'N')
? ? ? ? ? ? break;
? ? }
}
修改联系人,就是对结构体进行重新赋值,这个没什么可说的。
接着是查找联系人:
void search()
{
? ? char m[100], k;
? ? p1 = head;
? ? printf("请输入你想要查询的联系人姓名 ?:");
? ? scanf("%s", m);
? ? getchar();
? ? if (head == NULL)
? ? ? ? printf("通讯录中无可查询的联系人!\n");
? ? while (p1 != NULL)
? ? {
? ? ? ? if (strcmp(p1->content.name, m) == 0)
? ? ? ? ? ? Printf(m);
? ? ? ? else
? ? ? ? {
? ? ? ? ? ? p1 = p1->next;
? ? ? ? ? ? continue;
? ? ? ? }
? ? ? ? printf("你想继续查询联系人吗?\n继续输入'Y'否则输入'N':");
? ? ? ? scanf("%c", &k);
? ? ? ? getchar();
? ? ? ? if (k == 'Y')
? ? ? ? {
? ? ? ? ? ? p1 = head;
? ? ? ? ? ? printf("请输入你想查询的联系人姓名:");
? ? ? ? ? ? scanf("%s,m");
? ? ? ? ? ? continue;
? ? ? ? }
? ? ? ? else if (k == 'N')
? ? ? ? ? ? break;
? ? }
}
这里我用了一个函数进行封装,每次只需要在链表中找到对应联系人,在调用函数就行了。
还有就是存储数据,也就是把链表内容导入文件:
void save()
{
? ? q = head;
? ? FILE *fp = fopen("C:\\Users\\JY\\Desktop\\通讯录.txt", "w+");
//这里要把打开文件改成自己电脑里的路径!
? ? while (q != NULL)
? ? {
? ? ? ? fprintf(fp, "%s\n", q->content.name);
? ? ? ? fprintf(fp, "%s\n", q->content.adress);
? ? ? ? fprintf(fp, "%s\n", q->content.number);
? ? ? ? fprintf(fp, "%s\n", q->content.email);
? ? ? ? q = q->next;
? ? }
? ? printf("保存成功!\n");
? ? fclose(fp);
}
因为刚学的C,对于文件这一块可以说是完全不懂,甚至没接触过,只知道这里一个小小的w+,让我找了三天没找来,还差点把代码修改炸了。其实文件会用也不难,如果要涉及底层原理,比如说是如何把文本文件与程序进行互相导入导出,如何导入到二进制文件中,以及缓冲区和输出流等等的原理,要理解起来是要费点时间的。因为时间紧迫,我就没能一一深入了解。总归来说,FILE* fp=fopen(“文件路径”,“打开方式”)是打开文件的必要条件,结束之后要记得关闭文件,但是好像程序结束也能关闭。
最后一个就是打印链表。这个也挺简单的:
void display()
{
? ? p1 = head;
? ? if (head == NULL)
? ? ? ? printf("此文件中无联系人!\n");
? ? else
? ? {
? ? ? ? while (p1 != NULL)
? ? ? ? {
? ? ? ? ? ? printf("=============================\n");
? ? ? ? ? ? printf("姓名:%s\t", p1->content.name);
? ? ? ? ? ? printf("地址:%s\t", p1->content.adress);
? ? ? ? ? ? printf("电话号码:%s\t", p1->content.number);
? ? ? ? ? ? printf("电子邮箱:%s\t\n", p1->content.email);
? ? ? ? ? ? printf("=============================\n");
? ? ? ? ? ? p1 = p1->next;
? ? ? ? ? ? printf("\n");
? ? ? ? }
? ? }
? ? printf("\n");
}
这里没什么好说的,完全就是对链表进行打印。
对于这一次的项目,我深深的感受到了什么叫做debug的痛苦,因为对与链表和文件的不熟练,导致我花费在改代码的时间比我写代码的时间还要长,让我一度很痛苦,不过好在今天终于把bug全部改完了。就希望自己以后能多注意点细节处理,然后把底层原理给弄懂,这样处理代码的时候就能够简单一些吧。
|