C语言——通讯录的实现

来源:互联网 发布:网络自制综艺节目 编辑:程序博客网 时间:2024/05/16 16:58
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>


#define T 1
#define F 0


struct address
{
int id;
char name[20];
char telephone[20];
char home_phone[20];
struct address *next;//节点指针
};


typedef struct address * Address;//重命名节点指针
typedef int Status;


Status menu(Address p);//主菜单
Status add(Address p);//添加
Status delete(Address p);//删除
Status search(Address p);//搜索
Status modify(Address p);//修改
Status length(Address p);//个数
void paixu(Address p);//排序
void swap(Address arr[], int i, int j);
void quicksort1(Address arr[], int low, int high);//快速排序
Status pivotkey1(Address arr[], int low, int high);
void quicksort2(Address arr[], int low, int high);
Status pivotkey2(Address arr[], int low, int high);
void heapadjust(Address arr[], int n, int m);
void dui_name(Address arr[], Address p);//堆排序
void heapadjust2(Address arr[], int n, int m);
void dui_tel(Address arr[], Address p);
void paixu_print(Address arr[], Address p);


Status init(Address *p)//初始化链表
{
Address newnode = (Address)malloc(sizeof(struct address)); //申请空间
if(NULL == newnode)
{
return F;
}


newnode->next = NULL;
*p = newnode;


return T;
}


Status updata(Address p)//将文件中的信息传到链表里
{
FILE *file = fopen("./address.txt", "r");//打开当前目录下的address.txt,只写的方式
if(NULL == file)
{
perror("fopen");
exit(1);
}


Address newnode = (Address)malloc(sizeof(struct address));
if(NULL == newnode)
{
return F;
}
while(fscanf(file, "%d ", &newnode->id) != EOF)
{
fscanf(file, "name : %s   telephone : %s   home_phone : %s", 
  newnode->name, newnode->telephone, newnode->home_phone);//从参数file的文件流中读取字符串


newnode->next = NULL;
p->next = newnode;
p = p->next;


newnode = (Address)malloc(sizeof(struct address));
if(NULL == newnode)
{
return F;
}
}
fclose(file);
}


void write(Address p)//将链表信息写入文件
{
Address head = p;


FILE *file = fopen("./address.txt", "w+");//打开当前目录下的address.txt,只读的方式
if(NULL == file)
{
perror("fopen");
exit(1);
}


int i = 1;
while(p->next != NULL)
{
fprintf(file, "%d name : %-20s    telephone : %-11s    home_phone : %-11s ", 
   i, p->next->name, p->next->telephone, p->next->home_phone);//将字符串输出到文件中
fprintf(file,"\r\n");
p = p->next;
i++;
}


fclose(file);
}


void read(Address p)//把文件信息打印到终端
{
FILE *file = fopen("./address.txt", "r");
if(NULL == file)
{
perror("fopen");
exit(1);
}
char ch;
while(1)
{
ch = fgetc(file);//从文件中读取一个字符
if(ch == EOF)
break;
fputc(ch, stdout);
}


}


int main()//主函数、、、、、、、、、、、、、、
{
Address head;
init(&head);
updata(head);


menu(head);


return 0;
}


Status menu(Address p)//主菜单界面
{ printf("\n\n\n\n");
printf("\t    ********************************************************\n");
printf("\t    *                          欢迎来到通讯录!            *\n");
printf("\t    *                                                      *\n");
printf("\t    *          (A)             列出好友信息                *\n");//排序后列出信息
printf("\t    *                                                      *\n");
printf("\t    *          (B)             搜索好友信息                *\n");
printf("\t    *                                                      *\n");
printf("\t    *          (C)             添加好友信息                *\n");
printf("\t    *                                                      *\n");
printf("\t    *          (D)             修改好友信息                *\n");
printf("\t    *                                                      *\n");
printf("\t    *          (E)             删除好友信息                *\n");
printf("\t    *                                                      *\n");
printf("\t    *          (F)             显示好友信息                *\n");
printf("\t    *                                                      *\n");
printf("\t    ********************************************************\n\n\n\n\n\n");
printf("\t    **************************请输入您的选择:***************\n");
char a;
scanf("%c", &a);
switch(a)
{
case 'A':
read(p);
break;
case 'B':
search(p);
break;
case 'C':
add(p);
break;
case 'D':
modify(p);
break;
case 'E':
delete(p);
break;
case 'F':
paixu(p);
break;
}


printf("是否返回主菜单?是:Y 否:N \n");//选择“否”则退出程序
getchar();
char t;
scanf("%c", &t);
if(t == 'Y')
{
menu(p);
}
else
//ext();
return T;

}


Status add(Address p)//使用尾插的方式来添加用户信息
{
Address head = p;
Address newnode = (Address)malloc(sizeof(struct address));//申请空间
if(NULL == newnode)
{
return F;
};

printf("请输入新用户的姓名:");
scanf("%s", newnode->name);
int flag = 0;
while(p->next != NULL)
{
if(strcmp(p->next->name, newnode->name) == 0)//首先判断该用户是否存在
{
flag = 1;
printf("该用户已存在:%d %s:%s\n", p->next->id, p->next->name, p->next->telephone);
printf("新建该用户还是继续添加在当前用户的信息下? 是:1 否:2\n");
int i;
scanf("%d", &i);
if(i == 1)//选择新建用户时,退出当前循环,进入flag==0时添加用户的循环
{
flag = 0;
break;
}


printf("请输入该用户的新信息:");//选择将信息添加在已有用户之下时
scanf("%s", p->next->home_phone);//将新输入的信息添加在当前用户下


while(1)
{
int j = 0;
while(p->next->home_phone[j] >= '0' && p->next->home_phone[j] <= '9')//号码由数字组成,其他则报错
{
j++;
}
if(j == 11)//最多不超过11位
break;
else
{
printf("请输入正确的手机号:\n");//手机号超出11位报错
scanf("%s", p->next->home_phone);
}
}


printf("已添加 : %d name : %s : telephone : %s,home_phone : %s\n", 
p->next->id, p->next->name, p->next->telephone, p->next->home_phone);//添加完毕后显示当前用户的完整信息
}
p = p->next;
}
if(flag == 1)
{
free(newnode);//不需要添加新用户,则释放申请的空间
}
if(flag == 0)//添加新用户
{
newnode->id = length(head) + 1;//链表长度加1,id号加1
printf("请输入该用户的手机号:");
scanf("%s", newnode->telephone);
while(1)
{
int j = 0;
while(newnode->telephone[j] >= '0' && newnode->telephone[j] <= '9')//号码由数字组成,其他则报错
{
j++;
}
if(j == 11)
break;
else
{
printf("请输入正确的手机号:\n");//手机号超出11位或不足11位报错
scanf("%s", newnode->telephone);
}
}


newnode->home_phone[0] = 'N';////////////???????
printf("已添加 : %d name : %s : telephone : %s\n", newnode->id, newnode->name, newnode->telephone);

p = head;
while(p->next != NULL)//尾插的方式添加
{
p = p->next;
}
newnode->next = NULL;
p->next = newnode;
}




write(head);//写入文件中
}


Status delete(Address p)//删除用户
{
Address head = p;
printf("请输入删除方式:1:按id删除,2:按姓名删除,3:按手机号删除\n");
int i;
int flag;
scanf("%d", &i);
switch(i)
{
case 1:
printf("输入要删除用户的id : ");
int delete_id;
scanf("%d", &delete_id);//输入要删除的用户id
if(delete_id > length(p))//输入的id超出范围报错
{
printf("请输入正确的id号\n");
return F;
}
while(p->next->id != delete_id)//通过while循环找到要删除的用户
{
p = p->next;
}
Address temp = p->next;
p->next = temp->next;
free(temp);
printf("已删除\n");


break;


case 2:
printf("输入要删除用户的姓名 : ");
char delete_name[20];
scanf("%s", delete_name);
flag = 0;//设立一个flag,假如没有找到用户,进入内层循环,则flag一直等于0
while(p->next != NULL)
{
if(strcmp(p->next->name, delete_name) == 0)//通过while循环找到要删除的用户,用strcmp比较
{
flag = 1;
Address temp = p->next;
p->next = temp->next;
free(temp);
printf("已删除\n");
}
p = p->next;
}
if(flag == 0)
{
printf("查无此人\n");
return T;
}
break;


case 3:
printf("输入要删除用户的手机号: ");
char delete_tel[20];
scanf("%s", delete_tel);
while(1)
{
int t = 0;
while(delete_tel[t] >= '0' && delete_tel[t] <= '9')
{
t++;
}
if(t == 11)
break;
else
{
printf("请输入正确的手机号:\n");
scanf("%s", delete_tel);
}
}


flag = 0;//若进入内层循环,flag=1,若flag=0,则说明输入的手机号,固话不存在
while(p->next != NULL)
{
if(strcmp(p->next->telephone, delete_tel) == 0 || strcmp(p->next->home_phone, delete_tel) == 0)
{
flag = 1;
Address temp = p->next;
p->next = temp->next;
free(temp);
printf("已删除\n");
}
p = p->next;
}
if(flag == 0)
{
printf("没有这个号码\n");
return T;
}
break;
}


write(head);
updata(head);
}


Status search(Address p)//查询用户信息
{
printf("请输入搜索方式:1:按id搜索,2:按姓名搜索,3:按手机号搜索\n");
int i;
scanf("%d", &i);
int flag;
switch(i)
{
case 1:
printf("输入要搜索用户的id:");
int search_id;
scanf("%d", &search_id);
if(search_id > length(p))//判断id是否超出范围
{
printf("请输入正确的id\n");
return F;
}
while(p->next->id != search_id)//通过while循环找到要查询的用户
{
p = p->next;
}
printf("%d name : %s : telephone : %s,home_phone : %s\n", 
p->next->id, p->next->name, p->next->telephone, p->next->home_phone);
break;
case 2:
printf("输入要搜索用户的姓名:");
char search_name[20];
scanf("%s", search_name);
flag = 0;//设立一个flag,假如没有找到用户,进入内层循环,则flag一直等于0
while(p->next != NULL)
{
if(strcmp(p->next->name, search_name) == 0)
{
flag = 1;
printf("%d name : %s : telephone : %s,home_phone : %s\n", 
  p->next->id, p->next->name, p->next->telephone, p->next->home_phone);
}
p = p->next;
}
if(flag == 0)
{
printf("搜索不到 %s\n", search_name);
}
break;
case 3:
printf("输入要搜索用户的手机号:");
char search_tel[20];
scanf("%s", search_tel);
while(1)
{
int t = 0;
while(search_tel[t] >= '0' && search_tel[t] <= '9')
{
t++;
}
if(t == 11)
break;
else
{
printf("请输入正确的手机号:\n");
scanf("%s", search_tel);
}
}


flag = 0;//假如没有找到用户,进入内层循环,则flag一直等于0,说明搜索不到该用户不存在
while(p->next != NULL)
{
if(strcmp(p->next->telephone, search_tel) == 0 || strcmp(p->next->home_phone, search_tel) == 0)//通过比较号码找到用户
{
flag = 1;
printf("%d name : %s : telephone : %s,home_phone : %s\n", 
  p->next->id, p->next->name, p->next->telephone, p->next->home_phone);
}
p = p->next;
}
if(flag == 0)
{
printf("搜索不到 %s\n", search_name);
}
break;
}
}


Status modify(Address p)//修改用户信息
{
Address head = p;
printf("输入要修改用户的姓名:");
char modify_name[20];
scanf("%s", modify_name);
printf("请选择修改手机号还是固话 : 1 or 2\n");
int i;
scanf("%d", &i);
printf("请输入修改后的号码:");
char modify_tel[20] = {0};
scanf("%s", modify_tel);
while(1)
{
int t = 0;
while(modify_tel[t] >= '0' && modify_tel[t] <= '9')
{
t++;
}
if(t == 11)
break;
else
{
printf("请输入正确的手机号:\n");
scanf("%s", modify_tel);
}
}


while(strcmp(p->next->name, modify_name) != 0)//while循环找到该用户
{
p = p->next;
}
if(p->next == NULL)
{
printf("找不到名为 %s 的用户\n", modify_name);
return F;
}


if(i == 1)
{
strcpy(p->next->telephone, modify_tel);//修改手机号
}
if(i == 2)
{
strcpy(p->next->home_phone, modify_tel);//修改固话
}

printf("after modify : %d name : %s : telephone : %s,home_phone : %s\n", 
p->next->id, p->next->name, p->next->telephone, p->next->home_phone);


write(head);
}


Status length(Address p)//链表长度统计函数
{
int len = 0;
while(NULL != p->next)
{
len++;
p = p->next;
}
return len;
}


void paixu(Address p)//排序
{
printf("************************************************\n");
printf("****************选择排序方式********************\n");
printf("**************A 按名字快速排序******************\n");
printf("**************B 按名字堆排序********************\n");
printf("**************C 按手机号快速排序****************\n");
printf("**************D 按手机号堆排序******************\n");
    printf("************************************************\n");


Address head = p;
int high = length(head) - 1;


Address arr[length(head)];
int i = 0;
while(i < length(head))
{
arr[i] = p->next;
p = p->next;
i++;
}


char a;
scanf("%c", &a);


switch(a)
{
case 'A':
quicksort1(arr, 0, high);//按名字快速排序
paixu_print(arr, head);
read(head);
break;
case 'B':
dui_name(arr, head);//按名字堆排序
paixu_print(arr, head);
read(head);
break;
case 'C':
quicksort2(arr, 0, high);//按手机号快速排序
paixu_print(arr, head);
read(head);
break;
case 'D':
dui_tel(arr, head);//按手机号堆排序
paixu_print(arr, head);
read(head);
break;
}


}
void swap(Address arr[], int i, int j)//交换函数
{
Address temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}


void quicksort1(Address arr[], int low, int high)//快速排序(名字)
{
if(low < high)
{
int pivotkey = pivotkey1(arr, low, high);//pivotkey为枢轴的位置
quicksort1(arr, low, pivotkey - 1);//对低子表进行快排
quicksort1(arr, pivotkey + 1, high);//对高子表进行快排
}
}


Status pivotkey1(Address arr[], int low, int high)
{
char pivot[20];
strcpy(pivot, arr[low]->name);//把数组的第一个元素作为枢轴
while(low < high)
{
while(low < high && strcmp(arr[high]->name, pivot) >= 0)
high--;//high指针前移
swap(arr, low, high);//arr[low] = arr[high];
while(low < high && strcmp(arr[low]->name, pivot) <= 0)
low++;//low指针后移
swap(arr, low, high);//arr[high] = arr[low];
}
return low;
}


void quicksort2(Address arr[], int low, int high)//快速排序(号码)
{
if(low < high)
{
int pivotkey = pivotkey2(arr, low, high);//pivotkey为枢轴的位置
quicksort2(arr, low, pivotkey - 1);//对低子表进行快排
quicksort2(arr, pivotkey + 1, high);//对高子表进行快排
}
}


Status pivotkey2(Address arr[], int low, int high)
{
char pivot[20];
strcpy(pivot, arr[low]->telephone);//把数组的第一个元素作为枢轴


while(low < high)
{
while(low < high && strcmp(arr[high]->telephone, pivot) > 0)
high--;
swap(arr, low, high);//arr[low] = arr[high];
while(low < high && strcmp(arr[low]->telephone, pivot) < 0)
low++;
swap(arr, low, high);//arr[high] = arr[low];
}
return low;
}


void heapadjust(Address arr[], int n, int m)//将数组调成大顶堆
{
int i;
Address temp = arr[n];
for(i = 2*n+1; i <= m; i = 2*i+1)
{
if(i < m && strcmp(arr[i]->name, arr[i+1]->name) < 0)
i++;
if(strcmp(arr[i]->name, temp->name) < 0)
break;
arr[n] = arr[i];
n = i;
}
arr[n] = temp;
}


void dui_name(Address arr[], Address p) //堆排序(名字)
{
int len = length(p);


int i;
for(i = (len - 1) / 2; i >= 0; i--)
heapadjust(arr, i, len - 1);//首先将数组调成大顶堆
for(i = len - 1; i >= 0; i--)
{
swap(arr, 0, i);//交换堆顶和第i个元素后,继续将其调成大顶堆
heapadjust(arr, 0, i - 1);
}
}


void heapadjust2(Address arr[], int n, int m)
{
int i;
Address temp = arr[n];
for(i = 2*n+1; i <= m; i = 2*i+1)
{
if(i < m && strcmp(arr[i]->telephone, arr[i + 1]->telephone) < 0)
i++;
if(strcmp(arr[i]->telephone, temp->telephone) < 0)
break;
arr[n] = arr[i];
n = i;
}
arr[n] = temp;
}


void dui_tel(Address arr[], Address p)//堆排序(号码)
{
int len = length(p);


int i;
for(i = (len-1) / 2; i >= 0; i--)//首先将数组调成大顶堆
heapadjust2(arr, i, len-1);
for(i = len-1; i >= 0; i--)
{
swap(arr, 0, i);//交换堆顶和第i个元素后,继续将其调成大顶堆
heapadjust2(arr, 0, i-1);
}
}


void paixu_print(Address arr[], Address p)//打印排序后的用户信息
{
Address head = p;


FILE *file = fopen("./address.txt", "w+");
if(NULL == file)
{
perror("fopen");
exit(1);
}


int len = length(p);
int i = 0;
int n = 1;
for(i = 0; i < len; i++)
{
fprintf(file, "%d name : %-20s    telephone : %-11s    home_phone : %-11s ", 
   n, arr[i]->name, arr[i]->telephone, arr[i]->home_phone);
fprintf(file,"\r\n");
n++;
}


fclose(file);
}
原创粉丝点击