C語言進階篇 進階小專案【通訊錄】
技術標籤:C語言
目錄
//初始化通訊錄void InitContact(struct Contact* ps);
//查詢函式static int FindByName(const struct Contact* ps, char name[MAX_NAME])
//新增資訊void AddContact(struct Contact* ps);
//刪除指定的聯絡人void DelContact(struct Contact* ps);
//查詢指定的聯絡人void SearchContact(struct Contact* ps);
//更新指定的聯絡人void ModifyContact(struct Contact* ps);
//排序通訊錄void SortContact(struct Contact* ps);
//展示通訊錄void ShowContact(struct Contact* ps);
一、專案結構和專案說明
專案結構依然是標準三段式:
本程式需要完成以下功能:
1、初始化通訊錄
2、新增友人資訊
3、刪除指定聯絡人
4、查詢指定聯絡人
5、更新指定聯絡人資訊
6、對通訊錄按姓氏名字排序
7、展示通訊錄
二、具體實現
首先展示主函式:
int main()
int main() { int input = 0; //建立通訊錄 struct Contact con;//con就是通訊錄,裡面包含存放1000個人的資訊和size。 //初始化通訊錄 InitContact(&con); do { menu(); printf("請選擇:>"); scanf("%d", &input); switch (input) { case ADD: AddContact(&con); break; case DEL: DelContact(&con); break; case SEARCH: SearchContact(&con); break; case MODIFY: ModifyContact(&con); break; case SHOW: ShowContact(&con); break; case SORT: SortContact(&con); break; case EXIT: printf("退出通訊錄\n"); break; default: printf("選擇錯誤\n"); break; } } while (input); return 0; }
這裡使用了列舉變數,來一一對應0~6這7個數字,
增強了程式碼的可讀性。
然後我們來看一下標頭檔案:
struct PeoInfo
{
char name[MAX_NAME];
int age;
char sex[MAX_SEX];
char tele[MAX_TELE];
char addr[MAX_ADDR];
};
//通訊錄型別
struct Contact
{
struct PeoInfo data[MAX];//存放一個資訊
int size;//紀錄當前已經有的元素個數
};
我們用PeoInfo來表示個人,
然後用Contact這個結構體儲存個人資訊,將其用陣列儲存,
再新增一個計數器,用來計數已存放的人數。
接下來看函式實現:
//初始化通訊錄
void InitContact(struct Contact* ps);
void InitContact(struct Contact* ps)
{
memset(ps->data, 0, sizeof(ps->data));
ps->size = 0;
}
首先傳結構體的地址,這樣才能實際操作結構體。
然後使用記憶體設定函式,將這個結構體的資料域和大小域初始化。
//查詢函式
static int FindByName(const struct Contact* ps, char name[MAX_NAME])
//查詢函式
//找到返回名字所在元素的下標
//找不到返回 -1
//static修飾函式,使函式只能在該contact.cpp原始檔中使用,不暴露給外面。
static int FindByName(const struct Contact* ps, char name[MAX_NAME])
{
int i = 0;
for (i = 0; i < ps->size; i++)
{
if (0 == strcmp(ps->data[i].name, name))
{
return i;
}
}
return -1;//找不到的情況
}
我們先寫一個查詢函式,引數型別有兩個,一個是結構體地址,一個是字串。
通過for迴圈,如果找到了,就返回其下標;
如果沒找到,就返回-1.
這樣封裝起來減少了程式碼的冗餘,
並且不需要在標頭檔案裡宣告,
寫成static即可,在本函式下方便使用。
//新增資訊
void AddContact(struct Contact* ps);
void AddContact(struct Contact* ps)
{
if (ps->size == MAX)
{
printf("通訊錄已滿,無法增加\n");
}
else
{
printf("請輸入名字:>");
scanf("%s", ps->data[ps->size].name);
printf("請輸入年齡:>");
scanf("%d", &(ps->data[ps->size].age));
printf("請輸入性別:>");
scanf("%s", ps->data[ps->size].sex);
printf("請輸入電話:>");
scanf("%s", ps->data[ps->size].tele);
printf("請輸入地址:>");
scanf("%s", ps->data[ps->size].addr);
ps->size++;
printf("新增成功\n");
}
}
//刪除指定的聯絡人
void DelContact(struct Contact* ps);
void DelContact(struct Contact* ps)
{
char name[MAX_NAME];
printf("請輸入要刪除的人的名字:>");
scanf("%s", name);
//1.查詢要刪除的人在什麼位置
int pos = FindByName(ps, name);
//2.刪除
if (pos == -1)
{
printf("要刪除的人不存在\n");
}
else
{
//刪除資料,後面的元素往前覆蓋
int j = 0;
//注意這裡陣列的下標
for (j = pos; j < ps->size-1; j++)
{
ps->data[j] = ps->data[j + 1];
}
ps->size--;
}
}
這裡的刪除,我們用的方法是,先刪除該元素,然後依次將後面的元素往前挪。
注意陣列下標!
建議畫個草圖算一下。
//查詢指定的聯絡人
void SearchContact(struct Contact* ps);
void SearchContact(struct Contact* ps)
{
char name[MAX_NAME];
printf("請輸入要查詢的人的名字:>");
scanf("%s", name);
int pos = FindByName(ps, name);
if (pos == -1)
{
printf("要查詢的人不存在!\n");
}
else
{
printf("%-20s\t%-s\t%-5s\t%-12s\t%-20s\n", "名字", "年齡", "性別", "電話", "地址");
printf("%-20s\t%-4d\t%-5t\t%-12s\t%-20s\n",
ps->data[pos].name,
ps->data[pos].age,
ps->data[pos].sex,
ps->data[pos].tele,
ps->data[pos].addr);
}
}
這裡\t的意思是 橫向跳到下一製表符位置。
//更新指定的聯絡人
void ModifyContact(struct Contact* ps);
void ModifyContact(struct Contact* ps)
{
char name[MAX_NAME];
printf("請輸入要修改的人的名字:>");
scanf("%s", name);
int pos = FindByName(ps, name);
if (pos == -1)
{
printf("要修改的人不存在!\n");
}
else
{
printf("請輸入名字:>");
scanf("%s", ps->data[pos].name);
printf("請輸入年齡:>");
scanf("%d", &(ps->data[pos].age));
printf("請輸入性別:>");
scanf("%s", ps->data[pos].sex);
printf("請輸入電話:>");
scanf("%s", ps->data[pos].tele);
printf("請輸入地址:>");
scanf("%s", ps->data[pos].addr);
printf("修改完成\n");
}
}
//排序通訊錄
void SortContact(struct Contact* ps);
void SortContact(struct Contact* ps)
{
int i = 0;
for (i = 0; i < ps->size-1; i++)
{
int j = 0;
for (j = 0; j < ps->size - 1 - i; j++)
{
char cmp = strcmp(ps->data[j].name, ps->data[j+1].name);
if (cmp > 0)
{
struct Contact temp = { 0 };
temp.data[0] = ps->data[j + 1];
ps->data[j + 1] = ps->data[j];
ps->data[j] = temp.data[0];
}
}
}
printf("已按姓名排序\n");
}
//展示通訊錄
void ShowContact(struct Contact* ps);
void ShowContact(struct Contact* ps)
{
if (ps->size == 0)
{
printf("通訊錄為空!\n");
}
else
{
int i = 0;
printf("%-20s\t%-s\t%-5s\t%-12s\t%-20s\n", "名字", "年齡", "性別", "電話", "地址");
for (i = 0; i < ps->size; i++)
{
printf("%-20s\t%-4d\t%-5t\t%-12s\t%-20s\n",
ps->data[i].name,
ps->data[i].age,
ps->data[i].sex,
ps->data[i].tele,
ps->data[i].addr);
}
}
}
三、個人總結及GitHub地址
這個小專案實現了對資料的增刪改查,還有排序功能,已經是操作資料庫的雛形了。但是還有很多需要完善的地方,比如遇到同名怎麼辦?是否可以節約記憶體?是否可以實現用檔案的方式來處理通訊錄?我會再接下來的學習中改進這份通訊錄。