題目:通訊錄管理程序
問題描述
編寫一個簡單的通訊錄管理程序。通訊錄記錄有姓名,地址(省、市(縣)、街道),電話號碼,郵政編碼等四項。
基本要求
程序應提供的基本基本管理功能有:
1) 添加:即增加一個人的記錄到通信錄中
2) 顯示:即在屏幕上顯示所有通信錄中的人員信息,應能分屏顯示。
3) 存儲:即將通訊錄信息保存在一個文件中。
4) 裝入:即將文件中的信息讀入程序。
5) 查詢:可根據姓名查找某人的相關信息,若找到顯示其姓名、地址、電話號碼和郵政編碼。
6) 修改:可修改一個人的除姓名外其它信息。
測試數據
程序應輸入不少於10個人員的通訊錄信息,應考慮到人員可以同名的情況。
實現提示
程序可用一個結構體數組、單向鏈表或對象數組來管理人員信息,每個人員的姓名,地址,電話號碼和郵政編碼用一個結構體或類實現。
代碼:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define CHARMAX 30
typedef struct record {
char name[CHARMAX];
char phonenumber[11];
char address[3][CHARMAX]; //0-省 1-市 2-街道
char postcode[6];
struct record *next;
} RECORD;
void PrintMenu();
void AlterString(RECORD *head);
RECORD *InputRecord(RECORD *head, int *total);
void PrintAllRecords(RECORD *head, const int *total);
RECORD *DeleteRecord(RECORD *head,int *total);
RECORD *ReviseRecord(RECORD *head);
RECORD *SearchRecord(RECORD *head, int onlyOneRecord) ;
RECORD *ImportRecords(RECORD *head, int *total);
RECORD *ExportRecords(RECORD *head);
int main() {
int total = 0, selection;
RECORD *head = NULL;
printf("Welcome to Directory Management System!\n");
printf("By XZ&YYM\n");
printf("---------------------------------------------\n");
do {
PrintMenu();
scanf("%d", &selection);
system("cls");
switch (selection) {
case 0:
break;
case 1:
head = InputRecord(head, &total);
break;
case 2:
PrintAllRecords(head, &total);
break;
case 3:
head = DeleteRecord(head,&total);
break;
case 4:
head = ReviseRecord(head);
break;
case 5:
SearchRecord(head,0);
break;
case 6:
head = ImportRecords(head,&total);
break;
case 7:
ExportRecords(head);
break;
default:
printf("\n\n-- Sorry!Please input 0-10!\n");
};
} while (selection != 0);
return 0;
}
void PrintMenu() {
printf("\n");
printf("|1.Input record\n");
printf("|2.List all records\n");
printf("|3.Delete record\n");
printf("|4.Revise record\n");
printf("|5.Search record\n");
printf("|6.Import records from file\n");
printf("|7.Export records to file\n");
printf("|0.Exit\n");
printf("|Please input 0-7 to select function :");
}
//功能:將字符串后的回車刪掉
//入參:鏈表首地址
//出參:無
void AlterString(RECORD *head) {
int m;
RECORD *p1 = head;
while (p1 != NULL) {
for (m = 0; m < CHARMAX; m++) {
if (*((p1->name) + m) == '\n') {
*((p1->name) + m) = '\0';
}
}
for (m = 0; m < 11; m++) {
if (*((p1->phonenumber) + m) == '\n') {
*((p1->phonenumber) + m) = '\0';
}
}
for (m = 0; m < CHARMAX; m++) {
if (*((p1->address[0]) + m) == '\n') {
*((p1->address[0]) + m) = '\0';
}
}
for (m = 0; m < CHARMAX; m++) {
if (*((p1->address[1]) + m) == '\n') {
*((p1->address[1]) + m) = '\0';
}
}
for (m = 0; m < CHARMAX; m++) {
if (*((p1->address[2]) + m) == '\n') {
*((p1->address[2]) + m) = '\0';
}
}
for (m = 0; m < 6; m++) {
if (*((p1->postcode) + m) == '\n') {
*((p1->postcode) + m) = '\0';
}
}
p1 = p1->next;
}
}
//功能:連續輸入數據
//入參:鏈表首地址,數據總數地址
//出參:鏈表首地址
RECORD *InputRecord(RECORD *head, int *total) {
int i = *total;
char inputChar;
RECORD *p = head, *input = (RECORD *) malloc(sizeof(RECORD));
printf("\n-- Start to Input Record\n");
//如果擁有數據,則輸出現有數據總數
if (*total) {
printf("-- You have had %d records\n\n", *total);
}
do {
//輸入數據
printf("Input NO.%d Record`s Name:", i + 1);
fflush(stdin);
fgets(input->name, CHARMAX + 1, stdin);
printf("Input NO.%d Record`s Phone Number:", i + 1);
fflush(stdin);
fgets(input->phonenumber,CHARMAX + 1, stdin);
printf("Input NO.%d Record`s Address:\n", i + 1);
printf("- Input NO.%d Record`s Province:", i + 1);
fflush(stdin);
fgets(input->address[0], CHARMAX + 1, stdin);
printf("- Input NO.%d Record`s City:", i + 1);
fflush(stdin);
fgets(input->address[1], CHARMAX + 1, stdin);
printf("- Input NO.%d Record`s Street:", i + 1);
fflush(stdin);
fgets(input->address[2], CHARMAX + 1, stdin);
printf("- Input NO.%d Record`s Postcode:", i + 1);
fflush(stdin);
fgets(input->postcode, 7, stdin);
input->next = NULL; //插入時放於鏈表的最后
//插入數據,分為首數據和非首數據
if (head == NULL) {
head = input;
p = input;
} else {
while (p->next != NULL) {
p = p->next;
}
p->next = input;
}
//增加數據計數
(*total)++;
//詢問是否繼續
printf("\nDo you want to continue?(Y/N):");
scanf(" %c", &inputChar);
if (inputChar == 'Y' || inputChar == 'y') { //直接用getchar必須輸入大寫Y才能繼續
//創建新的空間
input = (RECORD *) malloc(sizeof(RECORD));
i++;
} else {
break;
}
} while (1);
//將字符串后面的回車刪除
AlterString(head);
return head;
}
//功能:打印全部數據
//入參:鏈表首地址,數據總數地址
//出參:無
void PrintAllRecords(RECORD *head, const int *total) {
int page = 1, firstIndex = 0, i, pageAmount = *total / 10 + 1;
RECORD *p = head;
do {
system("cls");
//處理輸入的數字過大或過小
if (page > pageAmount) {
printf("-- Sorry! The MAX of pages is %d\n", pageAmount);
} else if (page < 0) {
printf("-- Sorry! The number have to be positive\n");
} else {
//處理分頁
firstIndex = 10 * (page - 1);
printf("NO.\tName\tPhonenumber\tProvince\tCity\tStreet\tPostcode\t\n");
//處理前置數據
p = head;
for (i = 0; i < firstIndex; ++i) {
p = p->next;
}
i = 0;
//輸出數據
while (p != NULL && i < 10) { //todo 大量數據可能出現問題
i++;
printf("NO.%d\t%s\t%s\t\t%s\t\t%s\t%s\t%s\t\n", i+firstIndex,p->name, p->phonenumber, p->address[0], p->address[1],
p->address[2],
p->postcode);
p = p->next;
}
printf("-- Page %d (Total %d pages)\n ", page, pageAmount);
}
printf("-- Jump to page number (Input 0 to finish):");
scanf("%d", &page);
} while (page);
}
//功能:刪除某條數據
//入參:鏈表首地址
//出參:鏈表首地址
RECORD *DeleteRecord(RECORD *head,int *total) {
RECORD *p1 = head, *p2,*searchResult;
searchResult = SearchRecord(head, 1);
while (p1 != NULL && p1 != searchResult) {
p2 = p1; //p2上一個節點
p1 = p1->next; //p1下一個節點
}
if (p1 == head) {
head = p1->next;
free(p1);
(*total)--; //todo
printf("\n-- Success!\n");
} else if (p1 != NULL) {
p2->next = p1->next;
free(p1);
(*total)--;
printf("\n-- Success!\n");
} else {
printf("\n-- Do not find this id!\n");
}
return head;
}
//功能:輸出某條數據
//入參:數據地址
//出參:無
void PrintOneRecord(RECORD *p) {
printf("Name:%s\tPhonenumber:%s\tProvince:%s\tCity:%s\tStreet::%s\tPostcode:%s\t\n", p->name, p->phonenumber,
p->address[0], p->address[1], p->address[2], p->postcode);
}
//功能:更改數據
//入參:數據地址
//出參:無
RECORD *ReviseRecord(RECORD *head){
RECORD *p1 = head, *p2,*searchResult,*input = (RECORD *) malloc(sizeof(RECORD));
//返回需要更改的數組地址
searchResult = SearchRecord(head, 1);
if (!searchResult){
return head;
}
//輸入數據
printf("\nInput the newRecord`s Name:");
fflush(stdin);
fgets(input->name, CHARMAX + 1, stdin);
printf("Input the newRecord`s Phone Number:");
fflush(stdin);
fgets(input->phonenumber,CHARMAX + 1, stdin);
printf("Input the Record`s Address:\n");
printf("- Input the newRecord`s Province:");
fflush(stdin);
fgets(input->address[0], CHARMAX + 1, stdin);
printf("- Input the newRecord`s City:");
fflush(stdin);
fgets(input->address[1], CHARMAX + 1, stdin);
printf("- Input the newRecord`s Street:");
fflush(stdin);
fgets(input->address[2], CHARMAX + 1, stdin);
printf("- Input the newRecord`s Postcode:");
fflush(stdin);
fgets(input->postcode, 7, stdin);
//插入時放於鏈表的最后
input->next = NULL;
while (p1 != NULL && p1 != searchResult) {
p2 = p1; //p2上一個節點
p1 = p1->next; //p1下一個節點
}
if (p1 == head) {
head = input;
input->next = p1->next;
free(p1); //是否要釋放?
printf("\n-- Success the Revise!\n");
} else if (p1 != NULL) {
p2->next = input;
input->next = p1->next;
free(p1);
printf("\n-- Success Revise!\n");
} else {
printf("\n-- Do not find this id!\n");
}
AlterString(head);
return head;
}
//功能:搜索數據,並返回唯一搜索結果
//入參:鏈表首地址,是否要求返回唯一結果
//出參:數據地址
RECORD *SearchRecord(RECORD *head, int onlyOneRecord) {
int amount = 0, i = 0, selection = 0; //i,p1循環變量
char input[CHARMAX];
RECORD *p1 = head, *results[100] = {NULL}; //result是RECORD類型的指針數組
printf("\n-- Search the record:");
setbuf(stdin, NULL);
fgets(input, CHARMAX + 1, stdin);
//去除字符串回車
for (i = 0; i < CHARMAX; ++i) {
if (*((input) + i) == '\n') {
*((input) + i) = '\0';
}
}
//遍歷搜索
while (p1 != NULL) {
if (strstr(p1->name, input) || //strstr()判斷是否為子串
strstr(p1->phonenumber, input) ||
strstr(p1->address[0], input) ||
strstr(p1->address[1], input) ||
strstr(p1->address[2], input) ||
strstr(p1->postcode, input)) {
results[amount] = p1;
amount++;
}
p1 = p1->next;
}
//若有多個結果,提示用戶選擇
if (amount > 1) {
printf("\n-- Search Result:\n");
for (i = 0; i < amount; i++) {
printf("NO.%d\t", i + 1);
PrintOneRecord(results[i]);
}
if (!onlyOneRecord) {
return NULL; //如果不需要去重,則返回NULL
}
printf("\n-- Input the number you want to change: ");
scanf("%d", &selection);
//處理輸入數據不正確,默認返回第一個
if (selection - 1 > amount || selection < 0) {
printf("\n-- Wrong input (Choose the first record automatically)");
return results[0];
}
return results[selection - 1];
} else if (!amount) {
printf("\n-- Sorry! No result!");
return NULL;
} else {
printf("\n-- Search Result:\n");
PrintOneRecord(results[0]);
return results[0];
}
}
//功能:導入文件中的數據
//入參:鏈表首地址,總條數
//出參:數據地址
RECORD *ImportRecords(RECORD *head, int *total) {
int i = *total,m=3;
FILE *fpRead;
RECORD *p = head, *input;
fpRead = fopen("stu.txt","r");
if(fpRead==NULL){
printf("can't open file\n");
return 0;
}
do {
//輸入數據
input = (RECORD *) malloc(sizeof(RECORD));
fread(input, sizeof(struct record),1,fpRead);
input->next = NULL; //插入時放於鏈表的最后
//插入數據,分為首數據和非首數據
if (head == NULL) {
head = input;
p = input;
} else {
while (p->next != NULL) {
p = p->next;
}
p->next = input;
}
//增加數據計數
(*total)++;
m--;
} while (m);
return head;
}
//功能:搜索數據,並返回唯一搜索結果
//入參:鏈表首地址,是否要求返回唯一結果
//出參:數據地址
RECORD *ExportRecords(RECORD *head){
FILE *fp;
struct record *p=head;
if((fp=fopen("stu.txt","wb"))==NULL)
{
printf("Fail to open the stu.txt!\n");
exit(0);
}
while(p != NULL)
{
fwrite(p, sizeof(struct record),1,fp);
p=p->next;
}
fclose(fp);
printf("you have save correctly!\n");
return 0;
}