【寫在開頭:】
『UI界面習慣了,用一個命令行版的通訊錄也蠻好的...』
實現簡單計算器的計算功能,用命令行的方式選擇具體的操作
歡迎界面:

1)添加聯系人:

2)刪除聯系人:

3)修改聯系人:

4)查看聯系人:

5)搜索聯系人:

數據庫文件:

按照原型編寫相應的流程功能。
/**
分析:
0、初始化
初始化方法,用於初始化數據
思路:
1)嘗試性的讀取文件
2)如果成功了,說明文件存在,則讀取文件內容
3)不成功,說明文件不存在
1)創建文件
2)寫入聯系人數量
1、添加聯系人
思路:
1)提示用戶輸入姓名和電話號碼
2)接收用戶輸入的內容
3)保存到聯系人數組
4)寫入到文件中
2、刪除聯系人
思路:
1)讓用戶輸入要刪除的數據的編號
2)判斷編號是否合法
3)讓用戶再次確認刪除
4)開始刪除數組元素
5)刪除文件的內容
3、修改聯系人
更新聯系人信息
思路:
1)提示用戶輸入要刪除聯系人的編號
2)判斷編號是否合法
3)讓用戶再次確認修改
4)開始修改用戶信息
5)更新到文件中
4、查看聯系人
查看所有聯系人
思路:
1)先判斷聯系人是否為空
2)如果不為空,則遍歷數組,列出所有的聯系人
5、搜索聯系人
根據輸入的姓名查找聯系人
思路:
1)提示用戶要輸入查找的人的姓名
2)遍歷聯系人數組,查找是否有這個人
3)如果找到,就把電話號碼顯示出來
4)沒有找到,則顯示沒有該聯系人信息
6、退出系統
*/
用到的知識點:
常量、變量的使用;全局變量;數組;分支語句;函數;宏;循環語句;scanf和printf;數據;結構體;文件操作;指針*
難點:
數組元素的刪除(可變數組,使用鏈表會更優)
需定義的宏
//******宏定義 #define N 100 //聯系人數組的長度 #define NAMELEN 13 //姓名長度 #define NUMLEN 12 //手機號長度 //**********
全局變量
//******定義變量 int inputNum; //接收鍵盤輸入 int telCount; //聯系人個數 int flag; //接收確認標記 char *telBook = "telNumBook.data"; //數據庫文件 //****
函數聲明
//*****函數聲明 void doAdd(); void doDel(); void doEdit(); void doList(); void doSearch(); void startView(); int writeFile(); void init(); int validateInput(int num, int min, int max); //********
聯系人結構體
//******聯系人結構體
typedef struct{
char telName[NAMELEN];
char telNum[NUMLEN];
}Person;
Person contacts[N]; //聯系人數組
//*********
1)添加聯系人模塊
1 /**
2 * 添加聯系人
3 */
4 void doAdd(){
5 printf("您選擇了添加聯系人操作\n");
6 printf("請輸入要添加的聯系人的姓名:(*注意聯系人姓名中間不能有空格)\n");
7 scanf("%s", contacts[telCount].telName); //存入數組
8
9 printf("請輸入要添加的聯系人的電話號碼:(*注意聯系人電話號碼中間不能有空格)\n");
10 scanf("%s", contacts[telCount].telNum);
11
12 //提示確認
13 printf("是否確認添加\"%s\"聯系人? 1.確認 0.取消\n", contacts[telCount].telName);
14 scanf("%d", &flag);
15 if (flag) {
16 //聯系人個數+1
17 telCount++;
18 //寫入文件中
19 writeFile();
20
21 printf("\n");
22 }
23
24 }
2)刪除聯系人模塊
1 /**
2 * 刪除聯系人
3 */
4 void doDel(){
5 printf("您當前選擇的是刪除聯系人操作\n");
6 doList();
7 printf("請輸入要刪除的聯系人編號:\n");
8
9 scanf("%d", &inputNum);
10 if (validateInput(inputNum, 1, telCount)){
11 //非法輸入則返回
12 return;
13 } else{
14 printf("數據刪除後將不可恢復,您是否確認要刪除\"%s\"的信息? 1.確認 0.取消\n",
15 contacts[inputNum - 1].telName);
16 scanf("%d", &flag);
17 if (flag) {
18 if (inputNum == telCount){ //要刪除的是最後一個元素
19 telCount--;
20 } else{ //不是最後一個元素,則要移動數組元素的位置
21 for (int i = inputNum; i < telCount; i++){
22 contacts[inputNum - 1] = contacts[inputNum];
23 telCount--; //聯系人-1
24 }
25 }
26 //寫入文件
27 writeFile();
28 }
29 }
30
31 }
3)修改聯系人模塊
1 /**
2 * 編輯聯系人
3 */
4 void doEdit(){
5 printf("您選擇了修改聯系人操作\n");
6
7 doList();
8 printf("請輸入要修改的聯系人的編號:\n");
9 scanf("%d", &inputNum);
10
11 //定義臨時數組保存新聯系人的姓名和電話,不直接修改數組
12 char tempName[NAMELEN];
13 char tempTelNum[NUMLEN];
14 if (validateInput(inputNum, 1, telCount)) {
15 return;
16 } else{
17 printf("您是否確認要修改聯系人\"%s\"的信息? 1.確認 0.取消",
18 contacts[inputNum - 1].telName);
19 scanf("%d", &flag);
20
21 if (flag) {
22 printf("請輸入新的聯系人姓名:(*注意姓名中間不能有空格)\n");
23 scanf("%s", tempName);
24 printf("請輸入新的聯系人電話號碼:(*注意電話號碼中間不能有空格)\n");
25 scanf("%s", tempTelNum);
26
27 //更新數組信息
28 strcpy(contacts[inputNum - 1].telName, tempName);
29 strcpy(contacts[inputNum - 1].telNum, tempTelNum);
30
31 //保存入文件
32 writeFile();
33
34 }
35 }
36
37 }
4)查看聯系人模塊
1 /**
2 * 顯示聯系人
3 */
4 void doList(){
5 if (telCount == 0) {
6 printf("您的當前的聯系人為空,請先添加小伙伴喲~~\n");
7 return;
8 }
9 printf("當前聯系人列表:\n");
10 for (int i = 0; i < telCount; i++) {
11 printf("編號%d 姓名: %s, 電話號碼: %s\n", i + 1, contacts[i].telName, contacts[i].telNum);
12 }
13 }
5)搜索聯系人模塊
1 /**
2 * 搜索聯系人
3 */
4 void doSearch(){
5 printf("您當前選擇的是搜索聯系人操作\n");
6
7 doList();
8 char tempName[NAMELEN]; //臨時數組
9 printf("請輸入要查找的聯系人姓名:\n");
10 scanf("%s",tempName);
11
12 int i;
13 for (i = 0; i < telCount; i++) {
14 if (strcmp(tempName, contacts[i].telName) == 0){
15 printf("您搜索的聯系人\"%s\"的電話號碼是%s\n", contacts[i].telName, contacts[i].telNum);
16 break; //找到則循環終止
17 }
18 }
19 //循環一遍還沒有找到
20 if (i == telCount){
21 printf("抱歉!沒有找到\"%s\"的記錄信息\n", tempName);
22 }
23 }
6)自定義校驗非法數值及寫入文件函數
/**
* 將數組和聯系人個數寫入文件
*
* @return 1 異常 0 正常
*/
int writeFile(){
//打開文件
FILE *fp = fopen(telBook, "wb"); //以二進制寫入
if (fp != NULL) {
//將聯系人個數寫入文件
fwrite(&telCount, sizeof(telCount), 1, fp);
//數組寫入文件
for (int i = 0; i < telCount; i++) {
fwrite(&contacts[i], sizeof(Person), 1, fp);
}
printf("數據更新成功!\n");
} else{
printf("數據寫入失敗!\n");
return 1;
}
//關閉指針
fclose(fp);
return 0;
}
/**
* 驗證輸入是否合法
*
* @param num 待驗證的整數
* @param min 最小值
* @param max 最大值
*
* @return 0.合法 1.非法
*/
int validateInput(int num, int min, int max){
if (num >= min && num <= max) {
return 0;
} else{
printf("非法輸入!\n");
return 1;
}
}
分析:
此處為什麼一定要將聯系人的個數telCount持久化?
因為如果聯系人個數如果不持久化,那麼每次程序重啟後都讀取不到聯系人了,因為這裡使用的是變量數組的形式。所以注意此處一定要持久化個數。
7)自定義初始化函數
/**
初始化
從文件讀取聯系人和數組
*/
void init(){
FILE *fp = fopen(telBook, "r"); //打開文件
if (fp != NULL) {
//從文件中讀取聯系人
fread(&telCount, sizeof(telCount), 1, fp);
//讀取數組
for (int i = 0; i < telCount; i++) {
fread(&contacts[i], sizeof(Person), 1, fp);
}
} else{ //如果沒有文件,則創建
FILE *fp = fopen(telBook, "wr");
fwrite(telBook, sizeof(Person), 1, fp);
printf("通訊錄創建成功~\n");
}
//關閉指針
fclose(fp);
printf("通訊錄初始化成功!~~\n");
}
分析:
為什麼要有一個初始化的方法?
因為每次系統啟動時都必須從文件中讀取聯系人數組和聯系人個數,所以,要有一個初始化方法。
8)主界面和主函數
/**
* 主界面
*/
void startView(){
printf("********************************\n");
printf("******** 歡迎使用C通訊錄 ******\n");
printf("******** 1、添加聯系人 ******\n");
printf("******** 2、刪除聯系人 ******\n");
printf("******** 3、修改聯系人 ******\n");
printf("******** 4、查看所有聯系人 ******\n");
printf("******** 5、搜索聯系人 ******\n");
printf("******** 6、退出系統 ******\n");
printf("********************************\n");
printf("請選擇1-6之間您要進行的操作\n");
}
/**
* 主函數
*
* @param argc
* @param argv
*
* @return 0 程序正常退出
*/
int main(int argc, const char * argv[]) {
init();
while (1) {
startView();
scanf("%d", &inputNum);
switch (inputNum) {
case 1:
doAdd();
break;
case 2:
doDel();
break;
case 3:
doEdit();
break;
case 4:
doList();
break;
case 5:
doSearch();
break;
case 6:
printf("系統正在退出...\n");
printf("系統安全退出,感謝您再次使用\n");
return 0;
default:
break;
}
}
return 0;
}
【寫在結尾:】
『有那麼一個時候,真的好想說一聲,對不起,謝謝』