纯新人,大北方某个c9就读(就一个吧,懂得都懂)
大一C语言大作业写了个通讯录,之前在csdn上查的总有这样那样的bug,把我自己的完成版发出来,感觉bug应该会少点,也算稍微有点参考价值吧。
链表
在代码里注释了。反正很多就对了,一个大作业总不能要求更多功能吧。
"contact.h"
# ifndef __CONTACT_H
# define __CONTACT_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#pragma comment(lib,"winmm.lib")
#define LEN sizeof(address_list) //开辟空间
int n=0;//记录通讯录人员人数
typedef struct A
{
char name[100];//名字
char sex[10];//性别
char age[10];//年纪
char phone[15];//电话
char addr[100];//地址
struct A *next;
} address_list;
void show_feature(void);//菜单函数
address_list * add(address_list *);//添加联系人
address_list * delete1(address_list *);//删除特定联系人
void show_list(address_list *);//显示所有联系人
void find_list(address_list *);//寻找特定联系人
address_list * sort(address_list *);//排序联系人
address_list * clear_list(address_list *);//清除所有联系人
address_list * revision_list(address_list *);//修改特定联系人特定信息
void save_list(address_list *);//保存所有联系人信息
void exit_list();//退出通讯录系统
address_list* read_list(address_list *head);//从文件中读取联系人信息
address_list *add_from_file(address_list *head, FILE *fp);//从文件中读取联系人信息
char *s_gets(char *st, int n);//读一个字符串儿
void search_by_type(address_list *head);//按类别搜索联系人
void ltrim(char *s);//去掉字符串左边儿的空格
void rtrim(char *s);//去掉字符串右边儿的空格
int changecolor(int c);//给字儿一个美丽的颜色
# endif // __CONTACT_H
"contact.c"
#include "contact.h"
int main()
{
char func[45];
address_list *p1;
p1 = (address_list *)malloc(LEN);
p1->next = NULL;
PlaySound(TEXT("Loading.wav"), NULL, SND_FILENAME|SND_ASYNC);
printf("\n");
printf("\n");
printf("\n");
printf("\n");
printf("\n");
printf("\n");
printf("\n");
printf("\n");
changecolor(14);
printf(" HELLO!\n");
changecolor(11);
printf(" CONTACT MANAGEMENT SYSTEM V1.14514\n");
printf(" by RepenX_0001, 5/29/2021\n");
printf(" Special Thanks to Uranus\n");
do
{
system("pause");
system("cls");
show_feature(); //显示菜单
printf("请选择您要进行的操作:");
scanf("%s", &func); //这里选择了读入%s,以避免scanf特性问题
fflush(stdin);
if (strlen(func) == 1)
{
switch(func[0]) //选择对联系人进行的操作
{
case '1':
p1=add(p1);
break; //添加联系人信息
case '2':
p1=delete1(p1);
break; //删除指定联系人信息
case '3':
find_list(p1);
break; //查找指定联系人信息
case '4':
revision_list(p1);
break; //修改指定联系人信息
case '5':
show_list(p1);
break; //显示全部联系人信息
case '6':
p1=clear_list(p1);
p1 = (address_list *)malloc(LEN);
break; //清除全部联系人信息
case '7':
p1=sort(p1);
break; //多种方式排序
case '8':
save_list(p1);
break; //保存到文件
case '9':
read_list(p1);
break; //从文件中读取
case '0':
search_by_type(p1);
break; //按指定类型查找
case 'E':
exit_list();
return 0; //退出系统
default:
printf("选择错误,请重新输入!\n");
break;
}
}
else
{
printf("选择错误,请重新输入!\n");
}
}
while(1);
return 0 ;
}
//修改选定联系人的信息
address_list * revision_list(address_list *head)
{
if(n==0)
{
printf("通讯录中没有信息,请添加或退出!\n");
return;
}
char j[100],q[100],p[100];
address_list *A1;
A1 = (address_list *)malloc(LEN);
printf("请输入你想要修改的人的姓名:");
s_gets(j,100);
A1 = head;
for (int i=1; i <= n; i++)
{
if(!(strcmp(j,A1->name)))
{
printf("成功找到 %s 的具体信息:\n", A1->name);
printf("名字:%s,性别:%s,年龄:%s,电话:%s,地址:%s\n",A1->name,A1->sex,A1->age,A1->phone,A1->addr);
printf("你想要修改%s的什么信息(name, sex, age, phone, addr):",j);
scanf("%s",q);
while((strcmp(q,"name"))&(strcmp(q,"sex"))&(strcmp(q,"age"))&(strcmp(q,"phone"))&(strcmp(q,"addr")))
{
printf("请输入正确的想要修改的信息!\n");
printf("你想要修改%s的什么信息(name, sex, age, phone, addr):",j);
scanf("%s",q);
}//判断想要修改的类型是否不存在
printf("你想要把 %s 的 %s 修改成:",j,q);
s_gets(p,100);
if(!(strcmp(q,"name")))
strcpy(A1->name, p);
if(!(strcmp(q,"sex")))
strcpy(A1->sex, p);
if(!(strcmp(q,"age")))
strcpy(A1->age, p);
if(!(strcmp(q,"phone")))
strcpy(A1->phone, p);
if(!(strcmp(q,"addr")))
strcpy(A1->addr, p);
printf("成功把 %s 的 %s 修改为 %s。\n", j,q,p);
break;
}
else
{
if(A1->next == NULL)
printf("没有找到%s的信息!\n",j);
A1 = A1->next;
}
}
return head;
}
//清除联系人信息
address_list * clear_list(address_list *head)
{
if(n==0)
{
printf("通讯录中没有信息,请添加或退出!\n");
}
else
{
head = NULL;
n = 0;
printf("已清除全部通讯录信息!!\n");
return head;
}
}
//寻找特定联系人信息
void find_list(address_list *head)
{
if(n==0)
{
printf("通讯录中没有信息,请添加或退出!\n");
}
else
{
char j[100];
address_list *A1;
A1 = (address_list *)malloc(LEN);
printf("请输入你要查找人的姓名:");
s_gets(j,100);
A1 = head;
int cnt = 0;
for (int i=1; i <= n; i++)
{
if( strstr(A1->name,j) != NULL )
{
cnt++;
if(cnt == 1)
{
printf("您查找的可能是以下联系人:\n");
}
printf("名字:%s,性别:%s,年龄:%s,电话:%s,地址:%s\n",A1->name, A1->sex,A1->age,A1->phone,A1->addr);
A1 = A1->next;
//break;
}
else
{
if(A1->next == NULL && cnt == 0)
printf("没有找到%s的信息\n",j);
A1 = A1->next;
}
}
}
//free(A1);
}
//删除某通讯录成员信息
address_list * delete1(address_list *head1)
{
char j[100];
int i;
address_list *p1,*p2,*p3,*p4;
p1=p2=p3=p4=(address_list *)malloc(LEN);
if (n == 0)
{
printf("通讯录中没有信息,请添加或退出!\n");
goto END;
}
else
{
p1=p2=head1;
p4=head1->next;//p4的作用:当删除的是链表第一个数据时候。
printf("Please enter the name that you want to delete:");
s_gets(j,100);
//遍历链表,寻找要删除的数据
if(!(strcmp(j,head1->name)))//删除数据是否为第一个链表
{
if(n==1)
{
head1 = NULL;
printf("删除成功!\n");
printf("现在通讯表没有任何信息,请添加或退出!\n");
}
else
{
head1=p4;
printf("删除成功!");
}
}
//遍历链表寻找要删除的信息(若p3在第一链,则p2在第二链,p1在第三链)
for (i=1; i<=n; i++)
{
p1=p1->next;
if(!(strcmp(j,p2->name)))
{
p3->next=p2->next;
printf("删除成功!");
n--;
goto END;
}
else
{
p3=p2;
p2=p1;
}
}
}
printf("遍历通讯录,并未发现想要删除的信息!");
END:
return head1;
}
//按首字母从小到大排序联系人信息
address_list * sort(address_list *head)
{
if(n == 0)
{
printf("没有数据,请添加!\n");
return head;
}
else//能进入下面程序的,n>=2
{
char j[100];
address_list *A1, *A2, *A3;
A1 = A2 = A3 =(address_list *)malloc(sizeof(address_list));//这里不开辟空间总会导致程序崩溃!
printf("请选择要排序的方式");
printf("(name, sex, age, phone, addr):");
scanf("%s",j);
if((strcmp(j,"name"))&(strcmp(j,"sex"))&(strcmp(j,"age"))&(strcmp(j,"phone"))&(strcmp(j,"addr")))
{
printf("输入有误!请输入正确的想要修改的信息!\n");
goto END;
}
//A1 = A2 = A3 = head;
if(head->next == NULL)//检测是否只有一组数据
{
printf("成功完成排序!\n");
//show_list(head);
return head;
}
else
{
for (int ii=1; ii<=n-1; ii++)
{
A1 = head->next;
A2 = head;
for (int jj=1; jj<=n-ii; jj++)
{
if(jj == 2)
{
A3 = head;
}
if(jj > 2)
{
A3 = A3->next;
}
if(!(strcmp(j,"name")))
{
if(strcmp(A2->name,A1->name)>0)
goto Loop;
else
goto Loop1;
}
if(!(strcmp(j,"sex")))
{
if(strcmp(A2->sex,A1->sex)>0)
goto Loop;
else
goto Loop1;
}
if(!(strcmp(j,"age")))
{
if(strcmp(A2->age,A1->age)>0)
goto Loop;
else
goto Loop1;
}
if(!(strcmp(j,"phone")))
{
if(strcmp(A2->phone,A1->phone)>0)
goto Loop;
else
goto Loop1;
}
if(!(strcmp(j,"addr")))
{
if(strcmp(A2->addr,A1->addr)>0)
goto Loop;
else
goto Loop1;
}
Loop:
{
if(jj == 1)
{
head = head->next;
}
if(jj >= 2)
{
A3->next = A1;
}
A2->next = A1->next;
A1->next = A2;
A1 = A1->next->next;
continue;
}
Loop1:
{
A2 = A1;
A1 = A1->next;
}
}
//show_list(head);
}
printf("成功完成排序!\n");
}
END:
return head;
}
}
//添加通讯录成员信息
address_list * add(address_list *head)
{
if(n==0)
{
printf("添加通讯录成员\n");
printf("请输入名字:");
s_gets(head->name,100);
printf("请输入性别:");
s_gets(head->sex,10);
printf("请输入年龄:");
s_gets(head->age,10);
printf("请输入电话:");
s_gets(head->phone,15);
printf("请输入地址:");
s_gets(head->addr,100);
printf("添加成功!\n");
head->next = NULL;
}
else
{
address_list *p = head;
while(p->next != NULL)
p = p->next;
address_list *A1;
A1 = (address_list *)malloc(sizeof(address_list));
printf("\n添加通讯录成员\n");
printf("请输入名字:");
s_gets(A1->name,100);
printf("请输入性别:");
s_gets(A1->sex,10);
printf("请输入年龄:");
s_gets(A1->age,10);
printf("请输入电话:");
s_gets(A1->phone,15);
printf("请输入地址:");
s_gets(A1->addr,100);
printf("添加成功!\n");
A1->next = NULL;
p->next = A1;
}
n++;
return head;
}
//显示已存在通讯表信息
void show_list(address_list *head)
{
int i;
address_list *A1;
A1 = (address_list *)malloc(sizeof(address_list));//这里不开辟空间总会导致程序崩溃!
A1 = head;
if (n == 0)
printf("没有数据,请添加!\n");
else
{
printf("\n现在通讯录中保存 %d 个人的信息!\n",n);
for (i=1; i<=n; i++)
{
printf("名字:%s,性别:%s,年龄:%s,电话:%s,地址:%s\n", A1->name, A1->sex, A1->age, A1->phone, A1->addr);
A1 = A1->next;
}
}
//free(A1);
}
//保存联系人信息
void save_list(address_list *head)
{
if(n==0)
{
printf("通讯录中没有信息,请添加或退出!\n");
}
else
{
address_list *A1;
A1 = (address_list *)malloc(sizeof(address_list));//这里不开辟空间总会导致程序崩溃!
A1 = head;
FILE *fp;//文件指针
/*文件的打开*/
char data_list[100];
printf("请输入想保存的文件名称(需带文件后缀):");
scanf("%s",data_list);
fp=fopen(data_list,"w");//fopen打开文件,这个文件可以是当前不存在的。“w”以写入的形式打开,“r”以读的形式打开
if(fp==NULL) //判断如果文件指针为空
{
printf("不能打开文件! " );
//exit(0);//在以0的形式退出,必须在文件开头有#include ,stdlib 头文件即standard library标准库头文件
}
//写入数据
else
{
for (int i=1; i<=n; i++)
{
fprintf(fp, "%s %s %s %s %s\n", A1->name, A1->sex, A1->age, A1->phone, A1->addr);
A1 = A1->next;
}
printf("通讯录信息成功保存至 %s 中!\n", data_list);
}
//关闭文件
fclose(fp);
free(A1);
}
}
address_list* read_list(address_list *head)
{
FILE *fp;
char j[100];
printf("请输入您想读取的文件(需带后缀):");
s_gets(j,100);
if ( (fp = fopen(j, "rt")) == NULL )
{
puts("找不到该文件!");
return;
}
else
{
head = add_from_file(head, fp);
puts("读取成功!");
}
return head;
}
//读取文件并读入信息
address_list *add_from_file(address_list *head, FILE *fp)
{
address_list *p = head;
while(p && p->next != NULL)
p = p->next;
address_list *A1;
A1 = (address_list *)malloc(sizeof(address_list));
if(fscanf(fp,"%s",A1->name) == EOF)
return head;
fscanf(fp,"%s",A1->sex);
fscanf(fp,"%s",A1->age);
fscanf(fp,"%s",A1->phone);
fscanf(fp,"%s",A1->addr);
A1->next = NULL;
if(n==0)
{
*p = *A1;
}
else
{
p->next = A1;
p = p->next;
}
n++;
A1 = (address_list *)malloc(sizeof(address_list));
while(fscanf(fp,"%s",A1->name) != EOF)
{
fscanf(fp,"%s",A1->sex);
fscanf(fp,"%s",A1->age);
fscanf(fp,"%s",A1->phone);
fscanf(fp,"%s",A1->addr);
A1->next = NULL;
p->next = A1;
p = p->next;
n++;
A1 = (address_list *)malloc(sizeof(address_list));
}
return head;
}
//按类别(性别或年龄)查找联系人
void search_by_type(address_list *head)
{
if(n==0)
{
printf("通讯录中没有信息,请添加或退出!\n");
}
else
{
char typee[100];
printf("请选择要搜索的信息");
printf("(sex, age):");
scanf("%s",typee);
if((strcmp(typee,"sex"))&(strcmp(typee,"age")))
{
printf("输入有误!请输入正确的想要修改的信息!\n");
return;
}
int flag = 0;
char j[100];
address_list *A1;
A1 = (address_list *)malloc(LEN);
A1 = head;
int cnt = 0;
if(!(strcmp(typee,"sex")))
{
printf("您想要查看哪一性别的信息:");
s_gets(j,100);
for (int i=1; i <= n; i++)
{
if(!(strcmp(j,A1->sex)))
{
flag = 1;
cnt++;
printf("名字:%s,性别:%s,年龄:%s,电话:%s,地址:%s\n",A1->name, A1->sex,A1->age,A1->phone,A1->addr);
A1 = A1->next;
}
else
{
if( A1->next == NULL && flag == 0)
printf("没有找到%s的信息\n",j);
A1 = A1->next;
}
}
printf("共找到%d条信息!\n", cnt);
}
if(!(strcmp(typee,"age")))
{
printf("您想要查看哪一年龄的信息:");
s_gets(j,100);
for (int i=1; i <= n; i++)
{
if(!(strcmp(j,A1->age)))
{
cnt++;
flag = 1;
printf("名字:%s,性别:%s,年龄:%s,电话:%s,地址:%s\n",A1->name, A1->sex,A1->age,A1->phone,A1->addr);
A1 = A1->next;
}
else
{
if( A1->next == NULL && flag == 0)
printf("没有找到%s的信息\n",j);
A1 = A1->next;
}
}
printf("共找到%d条信息!\n", cnt);
}
}
}
//显示功能
void show_feature(void)
{
printf("\n 现在通讯录中保存 %d 条信息!\n",n);
printf("---------------------------------------\n");
printf("| |\n");
printf("| 1. 添加 2. 删除 |\n");
printf("| 3. 查找 4. 修改 |\n");
printf("| 5. 显示 6. 清空 |\n");
printf("| 7. 排序 8. 保存 |\n");
printf("| 9. 读取 0. 分类 |\n");
printf("| |\n");
printf("| E.退出 |\n");
printf("---------------------------------------\n");
}
//退出通讯录系统
void exit_list()
{
printf("欢迎您再次使用!");
printf("\n已成功退出通讯录系统!\n");
}
//读一个字符串儿,并过滤非法字符
char *s_gets(char *st, int n)
{
char *ret_val;
char *find;
ret_val = fgets(st, n, stdin);
while(strlen(ret_val) == 1 && *ret_val == '\n')
{
ret_val = fgets(st, n, stdin);
}
ltrim(ret_val);
rtrim(ret_val);
return ret_val;
}
//去掉字符串左边儿的空格
void ltrim(char *s)
{
char *p;
p = s;
while(*p == ' ' || *p == '\t')
{
*p++;
}
strcpy(s,p);
}
//去掉字符串右边儿的空格
void rtrim(char *s)
{
int i;
i = strlen(s)-1;
while((s[i] == '\n' || s[i] == ' ') && i >= 0)
{
i--;
}
s[i+1] = '\0';
}
//改变文字颜色
int changecolor(int c)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c);
return 0;
}
照抄会被零分然后过程淘汰的哦。规格严格,功夫到家,懂得都懂。