實現一個通訊錄; 通訊錄可以用來存儲1000個人的信息,每個人的信息包括: 姓名、性別、年齡、電話、住址
提供方法1.添加聯繫人信息 2.刪除指定聯繫人信息 3.查找指定聯繫人信息 4.修改指定聯繫人信息 5.顯示所有聯繫人信息 6.清空所有聯繫人 7.以名字排序所有聯繫人 8. 保存聯繫人到文件 9. 加載聯繫人
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#define PERSON_INFO_MAX_SIZE 1024
typedef struct PersonInfo{
char name[1024];
char phone[1024];
}PersonInfo;
typedef struct AddressBook{//結構體數組
PersonInfo infos[PERSON_INFO_MAX_SIZE];
int size;//描述數組中前多少個元素是被使用的,有效元素區間[0,size)
}AddressBook;
//我們將生活中的常識抽象成計算機中的語言
AddressBook g_address_book;
void Init(AddressBook* addr_book){
assert(addr_book != NULL);
addr_book-> size = 0;
}
void AddPersonInfo(AddressBook* addr_book){
assert(addr_book != NULL);
printf("插入一個聯繫人!\n");
if(addr_book->size >= PERSON_INFO_MAX_SIZE){
printf("當前通訊已滿,插入失敗!\n");
return;
}
//每次都把新的聯繫人放到有效數組的最後一個元素上
PersonInfo *p = &addr_book->infos[addr_book->size];
printf("請輸入新增的聯繫人姓名:");
scanf("%s",p->name);
printf("請輸入新增的聯繫人的電話:");
scanf("%s",p->phone);
//新增完成後,需要更新size
++addr_book->size;
printf("插入聯繫人成功!\n");
}
void DelPersonInfo(AddressBook* addr_book){
assert(addr_book != NULL);
printf("刪除聯繫人!\n");
//根據用戶輸入的下標來刪除聯繫人
printf("請輸入要刪除的聯繫人符號:");
int id = 0;
scanf("%d",&id);
if(id < 0 || id >= addr_book->size){
printf("您輸入的序號有誤!刪除失敗!\n");
return;
}
PersonInfo *p = &addr_book->infos[id];
printf("您要刪除的聯繫人爲[%d] %s,確認請輸入Y:",id,p->name);
char cmd[1024] = {0};
scanf("%s",cmd);
if(strcmp(cmd, "Y") != 0){
printf("刪除操作已經取消!\n");
return;
}
PersonInfo* from = &aaddr_book->infos[addr_book->size - 1];
PersonInfo* to = p;
*to = *from;
--addr_book->size;
printf("刪除成功!\n");
}
void ModifyPersonInfo(AddressBook* addr_book){
assert(addr_book != NULL);
printf("修改聯繫人\n");
printf("請輸入需要修改的聯繫人序號:");
int id = 0;
scanf("%d",&id);
if(id < 0 || id >= addr_book->size){
printf("您輸入的序號錯誤");
return;
}
PersonInfo *p = &addr_book->infos[id];
char input[1024] = {0};
printf("請輸入要修改的姓名:");
scanf("%s",input);
if(strcmp(input,"#") != 0){
strcpy(p->name,input);
}
printf("請輸入要修改的電話:");
scanf("%s",input);
if(strcmp(input,"#") != 0){
strcpy(p->phone,input);
}
printf("修改成功!\n");
}
void FindPersonInfo(AddressBook* addr_book){
assert(addr_book != NULL);
printf("開始進行查找!\n");
printf("請輸入要查找的姓名:");
char name[1024] = {0};
scanf("%s",name);
int count = 0;
for(int i = 0;i < addr_book->size;++i){
PersonInfo* p = &addr_book->infos[i];
if(strcmp(name,p->name) == 0){
printf("[%d] %s\t%s\n",i,p->name,p->phone);
++count;
}
}
printf("查找完畢!共找到 %d 條記錄!\n",count);
}
void SortPersonInfo(AddressBook* addr_book){//只適用於英文名字的排序
assert(addr_book != NULL);
int i = 0;
int j = 0;
for(i = 0;i < addr_book->size;++i){
for(j = 0;j < addr_book->size - 1 - i;j++){
if(strcmp(addr_book->infos[j].name,addr_book->infos[j + 1].name) > 0){
PersonInfo tmp;
tmp = addr_book->infos[j];
addr_book->infos[j] = addr_book->infos[j + 1];
addr_book->infos[j + 1] = tmp;
}
}
}
}
void PrintAllPersonInfo(AddressBook* addr_book){
assert(addr_book != NULL);
for(int i = 0;i < addr_book->size;++i){
PersonInfo* p = &addr_book->infos[i];
printf("[%d] %s\t%s\n",i ,p->name,p-phone);
}
}
void ClearPersonInfo(AddressBook* addr_book){
assert(addr_book != NULL);
printf("清空所有記錄!\n");
printf("您確認要清空所有記錄嗎?輸入 Y 表示確定");
char cmd[1024] = {0};
scanf("%s",&cmd);
if(strcmp(cmd,"Y") != 0){
printf("清空操作取消");
return;
}
addr_book->size = 0;
printf("清空操作成功!\n");
}
int Menu(){
printf("=================");
printf("1.新增\n");
printf("2.刪除\n");
printf("3.修改\n");
printf("4.查找\n");
printf("5.排序\n");
printf("6.顯示全部\n");
printf("7.清空全部\n");
printf("0.退出\n");
printf("=================");
int choice = 0;
scanf("%d",&choice);
return choice;
}
int main(){
//1.對通訊錄進行初始化
Init(&g_address_book);
typedef void(*pfunc_t)(AddressBook*);
pfunc_t table[] = {
AddPersonInfo,
DelPersonInfo,
ModifyPersonInfo,
FindPersonInfo,
SortPersonInfo,
PrintAllPersonInfo,
ClearPersonInfo
}
while(1){
int choice = Menu();
if(choice < 0 || choice > (int)(sizeof(table) / sizeof(table[0]))){
printf("您的輸入有誤!\n")
}
if(choice == 0){
printf("goodbye!\n");
break;
}
table[choice - 1](&g_address_book);
}
return 0;
}
這個通訊錄只是一個靜態的,此時還可以進行一些改版,將其變爲動態結合的,這時候可利用到malloc函數
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#define PERSON_INFO_MAX_SIZE 1024
typedef struct PersonInfo{
char name[1024];
char phone[1024];
}PersonInfo;
typedef struct AddressBook{//結構體數組
PersonInfo* infos;
int capacity;//容量,infos指針指向的動態數組的長度(元素個數)
int size;//描述數組中前多少個元素是被使用的,有效元素區間[0,size)
}AddressBook;
//我們將生活中的常識抽象成計算機中的語言
AddressBook g_address_book;
void Init(AddressBook* addr_book){
assert(addr_book != NULL);
addr_book-> size = 0;
addr_book->capacity = 10;
addr_book->infos = (PersonInfo*)malloc(sizeof(PersonInfo) * addr_book->capacity);
}
void Realloc(AddressBook* addr_book){
assert(addr_book != NULL);
//此處每次擴容多少,這樣的策略完全是我們自定製的
//1.擴大capacity的取值
addr_book->capacity *= 2;
//2.申請一個更大的內存
PersonInfo* old_infos = addr_book->infos;
addr_book->infos = (PersonInfo*)malloc(addr_book->capacity * sizeof(PersonInfo));
//3.把原有的內存中的數據複製過來
for(int i = 0;i < addr_book->size;++i){
addr_book->infos[i] = old_infos[i];
}
//4.釋放原有的內存
free(old_infos);
}
void AddPersonInfo(AddressBook* addr_book){
assert(addr_book != NULL);
printf("插入一個聯繫人!\n");
if(addr_book->size >= addr_book->capacity){
printf("當前通訊已滿,插入失敗!進行擴容!\n");
Realloc(addr_book);
}
//每次都把新的聯繫人放到有效數組的最後一個元素上
PersonInfo *p = &addr_book->infos[addr_book->size];
printf("請輸入新增的聯繫人姓名:");
scanf("%s",p->name);
printf("請輸入新增的聯繫人的電話:");
scanf("%s",p->phone);
//新增完成後,需要更新size
++addr_book->size;
printf("插入聯繫人成功!\n");
}
void DelPersonInfo(AddressBook* addr_book){
assert(addr_book != NULL);
printf("刪除聯繫人!\n");
//根據用戶輸入的下標來刪除聯繫人
printf("請輸入要刪除的聯繫人符號:");
int id = 0;
scanf("%d",&id);
if(id < 0 || id >= addr_book->size){
printf("您輸入的序號有誤!刪除失敗!\n");
return;
}
PersonInfo *p = &addr_book->infos[id];
printf("您要刪除的聯繫人爲[%d] %s,確認請輸入Y:",id,p->name);
char cmd[1024] = {0};
scanf("%s",cmd);
if(strcmp(cmd, "Y") != 0){
printf("刪除操作已經取消!\n");
return;
}
PersonInfo* from = &aaddr_book->infos[addr_book->size - 1];
PersonInfo* to = p;
*to = *from;
--addr_book->size;
printf("刪除成功!\n");
}
void ModifyPersonInfo(AddressBook* addr_book){
assert(addr_book != NULL);
printf("修改聯繫人\n");
printf("請輸入需要修改的聯繫人序號:");
int id = 0;
scanf("%d",&id);
if(id < 0 || id >= addr_book->size){
printf("您輸入的序號錯誤");
return;
}
PersonInfo *p = &addr_book->infos[id];
char input[1024] = {0};
printf("請輸入要修改的姓名:");
scanf("%s",input);
if(strcmp(input,"#") != 0){
strcpy(p->name,input);
}
printf("請輸入要修改的電話:");
scanf("%s",input);
if(strcmp(input,"#") != 0){
strcpy(p->phone,input);
}
printf("修改成功!\n");
}
void FindPersonInfo(AddressBook* addr_book){
assert(addr_book != NULL);
printf("開始進行查找!\n");
printf("請輸入要查找的姓名:");
char name[1024] = {0};
scanf("%s",name);
int count = 0;
for(int i = 0;i < addr_book->size;++i){
PersonInfo* p = &addr_book->infos[i];
if(strcmp(name,p->name) == 0){
printf("[%d] %s\t%s\n",i,p->name,p->phone);
++count;
}
}
printf("查找完畢!共找到 %d 條記錄!\n",count);
}
void SortPersonInfo(AddressBook* addr_book){//只適用於英文名字的排序
assert(addr_book != NULL);
int i = 0;
int j = 0;
for(i = 0;i < addr_book->size;++i){
for(j = 0;j < addr_book->size - 1 - i;j++){
if(strcmp(addr_book->infos[j].name,addr_book->infos[j + 1].name) > 0){
PersonInfo tmp;
tmp = addr_book->infos[j];
addr_book->infos[j] = addr_book->infos[j + 1];
addr_book->infos[j + 1] = tmp;
}
}
}
}
void PrintAllPersonInfo(AddressBook* addr_book){
assert(addr_book != NULL);
for(int i = 0;i < addr_book->size;++i){
PersonInfo* p = &addr_book->infos[i];
printf("[%d] %s\t%s\n",i ,p->name,p-phone);
}
}
void ClearPersonInfo(AddressBook* addr_book){
assert(addr_book != NULL);
printf("清空所有記錄!\n");
printf("您確認要清空所有記錄嗎?輸入 Y 表示確定");
char cmd[1024] = {0};
scanf("%s",&cmd);
if(strcmp(cmd,"Y") != 0){
printf("清空操作取消");
return;
}
addr_book->size = 0;
printf("清空操作成功!\n");
}
int Menu(){
printf("=================");
printf("1.新增\n");
printf("2.刪除\n");
printf("3.修改\n");
printf("4.查找\n");
printf("5.排序\n");
printf("6.顯示全部\n");
printf("7.清空全部\n");
printf("0.退出\n");
printf("=================");
int choice = 0;
scanf("%d",&choice);
return choice;
}
int main(){
//1.對通訊錄進行初始化
Init(&g_address_book);
typedef void(*pfunc_t)(AddressBook*);
pfunc_t table[] = {
AddPersonInfo,
DelPersonInfo,
ModifyPersonInfo,
FindPersonInfo,
SortPersonInfo,
PrintAllPersonInfo,
ClearPersonInfo
}
while(1){
int choice = Menu();
if(choice < 0 || choice > (int)(sizeof(table) / sizeof(table[0]))){
printf("您的輸入有誤!\n")
}
if(choice == 0){
printf("goodbye!\n");
break;
}
table[choice - 1](&g_address_book);
}
return 0;
}
在擴容過程中,我們經過分析之後,當內存不夠時,考慮到只有添加才需要開闢新的空間。
所以在第一個靜態的版本之上,又加入了動態開闢,這樣當添加不夠時,我們的程序會自動開闢新的空間,爲了當前能夠使用。
在代碼中有註釋,關於開闢的關鍵。
內存中原先保存的位置我們也要管理,否則會造成內存泄漏。