实验项目名称:
电话号码查询系统的设计与实现
实验目的与要求:
1.基础知识:
(1)掌握数据结构中的查找、排序等算法相关知识。
(2)掌握 C 或 C++语言中程序设计的方法。
2.程序功能:
(1)自选存储结构(顺序表或哈希表)实现电话号码表的初始化创建。
(2)编写一个电话号码查询系统,要求有电话号码记录的录入(插入)存储、查 询、删除、打印、排序(顺序表存储结构必须有排序功能,哈希表结构则可以无此功能) 等模块。
这里用的是哈希表的方式书写的,献丑了
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <io.h>
#include<fcntl.h>#define Hash_Length 16
typedef struct {char* str;int length;
} String;typedef struct {String Name;String mobile_phone_number_one;String mobile_phone_number_two;String QQ_number;String dateTime;
} Contact;typedef struct {Contact contact;struct HashNode* next;
} HashNode;typedef struct HashTable {int length[Hash_Length];HashNode* table[Hash_Length];
} HashTable;//判断QQ号格式
bool isTrue_QQ_number(String str);
//判断手机号格式
bool isTrue_Mobile_phone_number(String str);
//判断格式是否正确
bool is_true(Contact contact);
//判断内容是否未空
bool isEmpty(char* str, int length);
//计算哈希值
int hashCode(String str);
//初始化
void CreateTable(HashTable* table);
//对比字符串的方法
bool equals(String str1, String str2);
//判断主要数据是否重复
bool is_Have(Contact contact, HashTable table);
//修改信息
void change_data(HashNode* node);
//输入信息
Contact* Scanf(Contact* contact);
Contact* Scanf_chance(Contact* contact);
//打印
void Print(Contact contact);
void ReadData(HashTable* table);
void InsertTable(HashTable* table, Contact contact);//判断QQ号格式
bool isTrue_QQ_number(String str) {if (str.length == 1) {return true;}if (str.length < 5 || str.length > 15) {printf("QQ号格式错误!\n");return false;}for (int i = 0; i < str.length; i++) {if (str.str[i] < '0' || str.str[i] > '9') {printf("QQ号格式错误!\n");return false;}}return true;
}//判断手机号格式
bool isTrue_Mobile_phone_number(String str) {if (str.length != 11 && str.length != 1) {printf("手机号格式错误!\n");return false;}for (int i = 0; i < str.length; i++) {if (str.str[i] < '0' || str.str[i] > '9') {printf("手机号格式错误!\n");return false;}}return true;
}//判断格式是否正确
bool is_true(Contact contact) {if (!isTrue_Mobile_phone_number(contact.mobile_phone_number_one) || !isTrue_Mobile_phone_number(contact.mobile_phone_number_two)) {return false;}if (!isTrue_QQ_number(contact.QQ_number)) {return false;}return true;
}//判断内容是否未空
bool isEmpty(char* str, int length) {if (length == 1 && str[0] == '0') {return true;}return false;
}//计算哈希值
int hashCode(String str) {int sum = 0;for (int i = str.length - 1; i > str.length - 5; i--) {sum += str.str[i];}return sum & (Hash_Length - 1);
}//初始化
void CreateTable(HashTable* table) {for (int i = 0; i < Hash_Length; i++) {table->table[i] = NULL;table->length[i] = 0;}ReadData(table);
}//对比字符串的方法
bool equals(String str1, String str2) {int num_str1 = 0;int num_str2 = 0;if (str1.length != str2.length) {return false;}if (str1.length >= 4) {for (int i = str1.length - 1; i > str1.length - 5; i--) {num_str1 += str1.str[i];num_str2 += str2.str[i];if (num_str1 != num_str2) {return false;}}}for (int i = 0; i < str1.length; i++) {if (str1.str[i] != str2.str[i]) {return false;}}return true;
}//判断主要数据是否重复
bool is_Have(Contact contact, HashTable table) {int index = hashCode(contact.mobile_phone_number_one);HashNode* temp = table.table[index];for (int i = 0; i < table.length[index]; i++) {if (equals(temp->contact.mobile_phone_number_one, contact.mobile_phone_number_one)) {return true;}temp = temp->next;}return false;
}//修改信息
void change_data(HashNode* node) {Contact* new_con = (Contact*)malloc(sizeof(Contact));new_con->mobile_phone_number_one.str = node->contact.mobile_phone_number_one.str;new_con->mobile_phone_number_one.length = strlen(new_con->mobile_phone_number_one.str);new_con = Scanf_chance(new_con);if (!is_true(*new_con)) {printf("输入记录有误!\n");return;}node->contact = *new_con;
}//输入信息
Contact* Scanf(Contact* contact) {contact->Name.str = (char*)malloc(50 * sizeof(char));printf("输入姓名:");scanf("%s", contact->Name.str);getchar();contact->Name.length = strlen(contact->Name.str);contact->mobile_phone_number_one.str = (char*)malloc(50 * sizeof(char));printf("输入号码1:");scanf("%s", contact->mobile_phone_number_one.str);getchar();contact->mobile_phone_number_one.length = strlen(contact->mobile_phone_number_one.str);contact->mobile_phone_number_two.str = (char*)malloc(50 * sizeof(char));printf("输入号码2:");scanf("%s", contact->mobile_phone_number_two.str);getchar();contact->mobile_phone_number_two.length = strlen(contact->mobile_phone_number_two.str);contact->QQ_number.str = (char*)malloc(50 * sizeof(char));printf("输入QQ号:");scanf("%s", contact->QQ_number.str);getchar();contact->QQ_number.length = strlen(contact->QQ_number.str);time_t rawtime;struct tm* timeinfo;time(&rawtime);timeinfo = localtime(&rawtime);contact->dateTime.str = _strdup(asctime(timeinfo));return contact;
}Contact* Scanf_chance(Contact* contact) {contact->Name.str = (char*)malloc(50 * sizeof(char));printf("输入姓名:");scanf("%s", contact->Name.str);getchar();contact->Name.length = strlen(contact->Name.str);contact->mobile_phone_number_two.str = (char*)malloc(50 * sizeof(char));printf("输入号码2:");scanf("%s", contact->mobile_phone_number_two.str);getchar();contact->mobile_phone_number_two.length = strlen(contact->mobile_phone_number_two.str);contact->QQ_number.str = (char*)malloc(50 * sizeof(char));printf("输入QQ号:");scanf("%s", contact->QQ_number.str);getchar();contact->QQ_number.length = strlen(contact->QQ_number.str);time_t rawtime;struct tm* timeinfo;time(&rawtime);timeinfo = localtime(&rawtime);contact->dateTime.str = _strdup(asctime(timeinfo));return contact;
}//打印
void Print(Contact contact) {printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");printf("姓名:%10s\n", contact.Name.str);printf("电话一:%s\n", contact.mobile_phone_number_one.str);printf("电话二:");if (contact.mobile_phone_number_two.length == 1) {printf("未填写\n");}else {printf("%s\n", contact.mobile_phone_number_two.str);}printf("QQ号:");if (contact.QQ_number.length == 1) {printf("未填写\n");}else {printf("%s\n", contact.QQ_number.str);}printf("记录时间:%s\n", contact.dateTime.str);
}
//txt保存
//存入txt
void Input(Contact contact) {FILE* file_out = fopen("output.txt", "a");if (file_out == NULL) {printf("无法打开文件,尝试创建新文件\n");file_out = fopen("output.txt", "w+");if (file_out == NULL) {printf("无法创建新文件\n");return 1;}}fprintf(file_out, contact.Name.str);fprintf(file_out, "|"); fprintf(file_out, contact.mobile_phone_number_one.str);fprintf(file_out, "|");fprintf(file_out, contact.mobile_phone_number_two.str);fprintf(file_out, "|");fprintf(file_out, contact.QQ_number.str);fprintf(file_out, "|");fprintf(file_out, contact.dateTime.str);fclose(file_out);
}
void writeData(HashTable table) {FILE* file_out = fopen("output.txt", "w");if (file_out == NULL) {printf("无法打开文件,尝试创建新文件\n");file_out = fopen("output.txt", "w+");if (file_out == NULL) {printf("无法创建新文件\n");return 1;}}fclose(file_out);for (int i = 0; i < Hash_Length; i++) {if (table.length[i] == 0) {continue;}HashNode* temp = table.table[i];for (int j = 0; j < table.length[i]; j++) {Input(temp->contact);temp = temp->next;}}
}
void ReadData(HashTable* table) {FILE* file_in = fopen("output.txt", "r");if (file_in == NULL) {printf("无法打开文件\n");return 1;}char line[100];const char delimiter[2] = "|";while (fgets(line, sizeof(line), file_in) != NULL) {char* token;int index = 0;Contact* con = (Contact*)malloc(sizeof(Contact));// 获取第一个子字符串token = strtok(line, delimiter);// 通过循环获取其他子字符串while (token != NULL) {switch (index){case 0:con->Name.str = (char*)malloc(strlen(token) + 1);strcpy(con->Name.str, token);con->Name.length = strlen(con->Name.str);break;case 1:con->mobile_phone_number_one.str = (char*)malloc(strlen(token) + 1);strcpy(con->mobile_phone_number_one.str, token);con->mobile_phone_number_one.length = strlen(con->mobile_phone_number_one.str);break;case 2:con->mobile_phone_number_two.str = (char*)malloc(strlen(token) + 1);strcpy(con->mobile_phone_number_two.str, token);con->mobile_phone_number_two.length = strlen(con->mobile_phone_number_two.str);break;case 3:con->QQ_number.str = (char*)malloc(strlen(token) + 1);strcpy(con->QQ_number.str, token);con->QQ_number.length = strlen(con->QQ_number.str);break;case 4:con->dateTime.str = (char*)malloc(strlen(token) + 1);strcpy(con->dateTime.str, token);con->dateTime.length = strlen(con->dateTime.str);break;}token = strtok(NULL, delimiter);index++;}InsertTable(table,*con);}fclose(file_in);
}//1.插入数据
void InsertTable(HashTable* table, Contact contact) {int index = hashCode(contact.mobile_phone_number_one);HashNode* newNode = (HashNode*)malloc(sizeof(HashNode));newNode->contact = contact;newNode->next = NULL;if (table->table[index] == NULL) {table->table[index] = newNode;}else {HashNode* current = table->table[index];while (current->next != NULL) {current = current->next;}current->next = newNode;}table->length[index]++;
}//2.修改数据
void change(HashTable* table, String contact) {int index = hashCode(contact);HashNode* temp = table->table[index];for (int i = 0; i < table->length[index]; i++) {if (equals(temp->contact.mobile_phone_number_one, contact)) {printf("请输入电话号所属人姓名:");String tempstr;char tempchar[20];scanf("%s", tempchar);tempstr.str = tempchar;tempstr.length = strlen(tempstr.str);if (equals(tempstr, temp->contact.Name)) {change_data(temp);return;}break;}temp = temp->next;}printf("未找到该条记录!\n");
}//3.删除操作
void deleteNode(HashTable* table, String contact) {int index = hashCode(contact);HashNode* temp = table->table[index];HashNode* tempbefore = (HashNode*)malloc(sizeof(HashNode));tempbefore->next = table->table[index];for (int i = 0; i < table->length[index]; i++) {if (equals(temp->contact.mobile_phone_number_one, contact)) {printf("请输入电话号所属人姓名:");String tempstr;char tempchar[20];scanf("%s", tempchar);getchar();tempstr.str = tempchar;tempstr.length = strlen(tempstr.str);if (equals(tempstr, temp->contact.Name)) {if (table->length[index] == 1) {table->table[index] = NULL;table->length[index]--;return;}table->length[index]--;HashNode* tempnode = temp->next;temp = NULL;tempbefore->next = tempnode;return;}break;}temp = temp->next;tempbefore = tempbefore->next;}printf("未找到该条记录!\n");
}//4.遍历显示数据
void display(HashTable table) {for (int i = 0; i < Hash_Length; i++) {if (table.length[i] == 0) {continue;}HashNode* temp = table.table[i];for (int j = 0; j < table.length[i]; j++) {Print(temp->contact);temp = temp->next;}}
}
//界面
void Face(HashTable* table) {char Options = 0;do{Contact contact;String str;printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");printf("联系方式查询系统\n");printf("1.插入数据\n");printf("2.修改数据\n");printf("3.删除数据\n");printf("4.显示数据\n");printf("请进行操作:");scanf("%c", &Options);getchar();printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");switch (Options){case '0':break;case '1':printf("请输入数据:\n");Scanf(&contact);if (!is_true(contact)||contact.mobile_phone_number_one.length!=11) {printf("数据输入有误!\n");continue;}InsertTable(table, contact);break;case '2':printf("请输入想修改的记录的手机号:\n");str.str = (char*)malloc(20 * sizeof(char));scanf("%s", str.str);str.length = strlen(str.str);change(table, str);break;case '3':printf("请输入想删除的记录的手机号:\n");str.str = (char*)malloc(20 * sizeof(char));scanf("%s", str.str);getchar();str.length = strlen(str.str);deleteNode(table, str);break;case '4':display(*table);break;default:printf("输入错误,请重新输入!\n");break;}} while (Options != '0');writeData(*table);
}int main() {HashTable table;CreateTable(&table);Face(&table);return 0;
}