1. 程式人生 > >通訊錄編譯過程遇到的經典問題,新手必看

通訊錄編譯過程遇到的經典問題,新手必看

先上程式碼:

#include <stdio.h>

#include <string.h>

#define NAMELEN 22

#define TELNO 12

#define N 100

//定義person結構體

typedefstruct{

   char name[NAMELEN];

   char tel[TELNO];

} Person;

//記錄聯絡人個數和人編號

int contactCount =0,fno =0;

//建立檔案的名稱,這樣便於修改

char *filePath ="dadada.data";

//用巨集定義方便修改

Person person[N

];

void doAdd();

void doDelete();

void doUpdate();

void doSearch();

void doList();

void doWrite();

void doInit();

int verify(int,int,int);

int main(int argc,constchar * argv[]) {

//初始化

   doInit();

   int flag =1;

printf("請輸入你的選擇\n");

   while (flag) {

printf("**************************\n");

printf

("******歡迎使用通訊錄 ******\n");

printf("****** 1、新增聯絡人  ******\n");

printf("****** 2、刪除聯絡人  ******\n");

printf("****** 3、修改聯絡人  ******\n");

printf("****** 4、檢視所有聯絡人 ****\n");

printf("****** 5、搜尋聯絡人  ******\n");

printf("****** 6、退出系統    ******\n");

printf("**************************\n\n");

//定義變數接受使用者輸入的選擇

       int no ;

//接受非數字字元

       getchar();

printf("請再次輸入你的選擇\n");

//鍵盤輸入no的值

       scanf("%d",&no);

       //功能選擇

       switch (no) {

           case1:

               doAdd();

               break;

           case2:

               doDelete();

               break;

           case3:

               doUpdate();

               break;

           case4:

              doList();

               break;

           case5:

               doSearch();

               break;

           case6:

               printf("您正在推出程式...\n");

               return0;

           default:

               break;

        }

    }

   return0;

}

/**

 *  刪除聯絡人

 */

void doDelete(){

   int pno;

   FILE *fp =fopen(filePath,"w");

   if (fp !=NULL) {

       if(contactCount !=0) {

           doList();

           printf("請輸入要刪除人的編號\n");

           scanf("%d",&pno);

           while (!(verify(pno,1,contactCount))) {

               printf("請輸入要修改人的編號\n");

               scanf("%d",&pno);

            }

           for (int i = pno; i <contactCount; i++) {

               person[pno-1] =person[pno];

            }

           contactCount--;

           doWrite();

        }

    }

   fclose(fp);

}

/**

 *  更新聯絡人

 */

void doUpdate(){

   FILE *fp =fopen(filePath,"w");

   if (fp !=NULL) {

       if (contactCount !=0) {

           int flag1,pno;

printf("修改姓名請按1\n修改號碼請按2\n全部修改請按3\n");

           scanf("%d",&flag1);

           while (!(verify(flag1,1,3))) {

printf("操作有誤,修改姓名請按1\n修改號碼請按2\n全部修改請按3\n");

               scanf("%d",&flag1);

            }

           doList();

           printf("請輸入要修改人的編號\n");

           scanf("%d",&pno);

           while (!(verify(pno,1,contactCount))) {

printf("無此編號,請重新輸入要修改人的編號\n");

               scanf("%d",&pno);

            }

           switch (flag1) {

               case1:

                   printf("請輸入新的姓名\n");

                   scanf("%s",person[pno-1].name);

                   doWrite();

                   break;

               case2:

                   printf("請輸入新的號碼\n");

                   scanf("%s",person[pno-1].tel);

                   doWrite();

                   break;

               case3:

                   printf("請輸入新的姓名\n");

                   scanf("%s",person[pno-1].name);

                   printf("請輸入新的號碼\n");

                   scanf("%s",person[pno-1].tel);

                   doWrite();

                   break;

               default:

                   break;

            }

        }

    }

   fclose(fp);

}

/**

 *  增加聯絡人

 */

void doAdd(){

   FILE *fp =fopen(filePath,"w");

   if (fp !=NULL) {

       printf("請輸入姓名\n");

scanf("%s",person[contactCount].name);

       printf("請輸入電話\n");

scanf("%s",person[contactCount].tel);

contactCount++;

       doWrite();

    }

   fclose(fp);

}

/**

 *  按姓名查詢人

 */

void doSearch(){

   FILE *fp =fopen(filePath,"r");

   if (fp !=NULL) {

printf("請輸入你需要查詢人的姓名\n");

       char goal[NAMELEN];

       fgets(goal,NAMELEN,stdin);

       int i =0;

       for (; i <contactCount; i++) {

           if (!(strcmp(goal,person[i].name))) {

               printf("姓名:%s電話:%s",person[i].name,person[i].tel);

               break;

            }

        }

       if (i ==contactCount) {

           printf("這個人你查不到\n");

        }

    }

   fclose(fp);

}

/**

 *  顯示所有人

 */

void doList(){

   FILE *fp =fopen(filePath,"r");

   if (fp !=NULL) {

printf("編號\t姓名\t電話\t\n");

       for (int i =0; i <contactCount; i++) {

            printf("%d\t%s\t%s\t\n",i+1,person[i].name,person[i].tel);

        }

    }

   fclose(fp);

}

/**

 *  初始化

 */

void doInit(){

   FILE *fp =fopen(filePath,"r");

   if (fp !=NULL) {

fread(&contactCount,sizeof(contactCount),1, fp);

       printf("%d\n",contactCount);

       for (int i =0; i <contactCount; i++) {

           fread(&person[i],sizeof(Person),1, fp);

        }

    }else {

        fp =fopen(filePath,"wb");

       if (fp !=NULL) {

           fwrite(&contactCount,sizeof(contactCount),1, fp);

        }

    }

   fclose(fp);

}

/**

 *  person中的資料寫入檔案

 */

void doWrite(){

   FILE *fp =fopen(filePath,"w");

   if (fp !=NULL) {

       for (int i =0; i <contactCount; i++) {

           fwrite(&person[i],sizeof(Person),1, fp);

        }

    }

   fclose(fp);

}

/**

 *  判定只是否合法

 *

 *  @param useNo 使用者輸入的值

 *  @param min   合法最小的值

 *  @param max   合法最大的值

 *

 *  @return ;

 */

int verify(int useNo,int min,int max){

   if (useNo > max || useNo < min) {

       return0;

    }

   return 1;

}

問題1:啟動後,做任意選擇,先以選擇1為例;

先按要求輸入來

請輸入你的選擇 

1

請再次輸入你的選擇

1

請輸入姓名

xiaoPengYou

請輸入電話

110

請再次輸入你的選擇      到了這步不按要求來啦,這麼搞

daNanHai

請輸入姓名

請輸入電話

120

請再次輸入你的選擇

4

你會發現通訊錄裡面顯示有兩個人,一個是xiaoPengYou 110  一個是 daNanHai120,

原因,因為scanf("%d",&pno);是要接受int型別的,你給個字串,此時快取裡面是存的‘d’ 'a' 'N' 'a' 'n'  'H' 'a' 'i' ‘\n’

所以會跳過這幾個字元不讀取,而pno裡面原本就存著上次輸入的1,故選擇了swich  1:的語句,當進入doAdd的

printf("請輸入姓名\n");   這句後,遇到下句時,scanf會直接從記憶體中將‘d’ 'a' 'N' 'a' 'n'  'H' 'a' 'i' '\n',讀入  person[contactCount].name  中,故姓名中就存了  “daNanHai”

scanf("%s",person[contactCount].name);

printf("請輸入電話\n");

scanf("%s",person[contactCount].tel);

問題2  程式退出後,再次執行程式會卡住,後來用打斷點的方式發現,原來程式在 doInit()這裡個函式裡一直迴圈著

void doInit(){

    FILE *fp = fopen(filePath"r");

    if (fp != NULL) {

fread(&contactCountsizeof(contactCount), 1, fp);

        printf("%d\n",contactCount); //---->  此處打印發現,contactCount的值很大很大

        for (int i = 0; i < contactCount; i++) {

            fread(&person[i], sizeof(Person), 1, fp);

        }

    }else {

        fp = fopen(filePath"wb");

        if (fp != NULL) {

            fwrite(&contactCountsizeof(contactCount), 1, fp);

        }

    }

    fclose(fp);

}

最終發現原來在doWrite() 函式中

void doWrite(){

    FILE *fp = fopen(filePath"w");

    if (fp != NULL) {

----->  這裡沒有講contactCount的值寫入檔案中,而直接寫入Person 了

----->  這就導致在去出contactCount時,是取的person[0].name 的第前4個位元組,故數很大

        for (int i = 0; i < contactCount; i++) {

            fwrite(&person[i], sizeof(Person), 1, fp);

        }

    }

    fclose(fp);

}