通訊錄編譯過程遇到的經典問題,新手必看
先上程式碼:
#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
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(&contactCount, sizeof(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(&contactCount, sizeof(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);
}