2014-03-05 40 views
0

典型的新手電話簿程序,試圖增加讀寫功能。這不是編譯,因爲讀寫功能c

1)它不會識別標籤ErrorHandler,無論身在何處,我把它

2)在這兩個功能:從兼容的指針類型傳遞的fprintf論據2 [默認啓用]

在文件

3)附帶.c文件,印刷在兩種功能:預期const char * __restrict__但參數的類型的用於整個事情struct pb *

代碼:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

typedef struct phonebook { 
    char cFirstName[20]; 
    char cLastName[20]; 
    char PhoNo[20]; 
} pb; 

//function prototypes 
void AddContact (pb *); 
void DeleteContact (pb *); 
void ShowContacts (pb *); 
void FindContact (pb *); 
void RandContact (pb *); 
void FindContact (pb *); 
void DeleteAll (pb *); 
void Read (pb *); 
void Write (pb *); 

char FileName[100]; 
FILE *pRead; 
FILE *pWrite; 

int counter = 0; 

main() 
{ 
    pb *phonebook; 
    phonebook = (pb*) malloc(sizeof(pb)*1); 
    int iChoice = 0; 

    while (iChoice <= 8) { 
     printf("\n-Choose an option- \n"); 
     printf("\n\t(1)\tAdd Contact"); 
     printf("\n\t(2)\tDelete Contact"); 
     printf("\n\t(3)\tShow All Contacts"); 
     printf("\n\t(4)\tSearch for a Contact"); 
     printf("\n\t(5)\tRandom Contact"); 
     printf("\n\t(6)\tDelete All Contacts"); 
     printf("\n\n\t(7)\tWrite contacts to file"); 
     printf("\n\t(8)\tRead contacts from file"); 
     printf("\n\n\t(9)\tExit\n\n\t"); 

     scanf("%d", &iChoice); 

     if (iChoice == 1) { 
      AddContact(phonebook); 
     } 

     if (iChoice == 2) { 
      DeleteContact (phonebook); 
     } 

     if (iChoice == 3) { 
      ShowContacts(phonebook); 
     } 

     if (iChoice == 4) { 
      FindContact(phonebook); 
     } 

     if (iChoice == 5) { 
      RandContact(phonebook); 
     } 

     if (iChoice == 6) { 
      DeleteAll(phonebook); 
     } 

     if (iChoice == 7) { 
      Write(phonebook); 
     } 

     if (iChoice == 8) { 
      Read(phonebook); 
     } 

     if (iChoice == 9) { 
      free(phonebook); 
      return 0; 
     }   
    } //end while 
} //end main 

//function definitions 

//add contact 
void AddContact (pb * phonebook) 
{ 
    counter++; //counter incremented for each entry 
    realloc(phonebook, sizeof(pb)); //realloc with every new contact 
    printf("\nFirst Name: "); 
    scanf("%s", phonebook[counter-1].cFirstName); 
    printf("Last Name: "); 
    scanf("%s", phonebook[counter-1].cLastName); 
    printf("Phone Number: "); 
    scanf("%s", phonebook[counter-1].PhoNo); 
    printf("\n\tContact added\n"); 
} 

//delete contact 
void DeleteContact (pb * phonebook) 
{ 
    int x = 0; 
    char scrapcFirstName[20]; //strings for deleting original strings 
    char scrapcLastName[20]; 
    char nullStr[20] = {"\0"}; 

    printf("\nFirst name: "); 
    scanf("%s", scrapcFirstName); 
    printf("Last name: "); 
    scanf("%s", scrapcLastName); 
    //compare strings 
    for (x = 0; x < counter; x++) { 
     if (strcmp(scrapcFirstName, phonebook[x].cFirstName) == 0) { 
      for (x = 0; x < counter; x++) { 
       if (strcmp(scrapcLastName, phonebook[x].cLastName) == 0) { 
        strcpy(phonebook[x].cFirstName, nullStr); 
        strcpy(phonebook[x].cLastName, nullStr); 
        strcpy(phonebook[x].PhoNo, nullStr); 
       }//end if 
       else { 
        printf("Invalid Input"); 
       } 
      }//end for 
     }//end if 
    }// end for 

    counter--; // Contact deleted, update counter 
    printf("Contact Deleted\n"); 
} 

//show phonebook 
void ShowContacts (pb * phonebook) 
{ 
    int x = 0; 
    printf("\nPhonebook:\n\n "); 
    for(x = 0; x < counter; x++) { 
     printf("\n(%d)\n", x+1); 
     printf("Name: %s %s\n", phonebook[x].cFirstName, phonebook[x].cLastName); 
     printf("Number: %s\n", phonebook[x].PhoNo); 
    } //end for 
} 

//Find a specific contact 
void FindContact (pb * phonebook) 
{ 
    int x = 0; 
    char TempFirstName[20]; 
    char TempLastName[20]; 

    printf("\nWho are you looking for?"); 
    printf("\n\nFirst Name: "); 
    scanf("%s", TempFirstName); 
    printf("Last Name: "); 
    scanf("%s", TempLastName); 

    for (x = 0; x < counter; x++) { 
     if (strcmp(TempFirstName, phonebook[x].cFirstName) == 0) { 
      if (strcmp(TempLastName, phonebook[x].cLastName) == 0) { 
       printf("\n%s %s \n%s\n", phonebook[x].cFirstName, 
             phonebook[x].cLastName, 
             phonebook[x].PhoNo); 
      } 
     } 
    }  
}  

//show a random contact 
void RandContact (pb * phonebook) 
{ 
    int iRand = 0; 
    srand(time(NULL)); 
    iRand = rand() % counter; 
    int x = iRand; 

    printf("\n%s %s\n", phonebook[x].cFirstName, phonebook[x].cLastName); 
    printf("%s\n", phonebook[x].PhoNo); 
}  

//delete all 
void DeleteAll (pb * phonebook) 
{ 
    int x = 0; 
    char nullStr[20] = {'\0'}; 

    for (x = 0; x < counter; x++) { 
     strcpy(phonebook[x].cFirstName, nullStr); 
     strcpy(phonebook[x].cLastName, nullStr); 
     strcpy(phonebook[x].PhoNo, nullStr); 
     --counter; 
    } 

    printf("Contacts have been wiped.\n");  
} 

void Read(pb * phonebook) 
{ 
    FILE *pRead; 
    char name[256]; 

    printf("File to read:"); 
    gets(name); 
    pWrite=fopen(name,"a"); 

    if(pWrite != NULL) { 
     printf("Contact List"); 
     while(!feof(pRead)) { 
      fprintf(pRead, phonebook,sizeof (struct phonebook)); 
      if (!feof(pRead)) { 
       fprintf(pRead, phonebook,sizeof (struct phonebook)); 
      } 
     } 
    } 
    else { 
     goto ErrorHandler; 
    } 

    exit(EXIT_SUCCESS); 

ErrorHandler: 
    perror("The folling error occured:"); 
    exit(EXIT_FAILURE); 
} 

void Write(pb * phonebook) 
{ 
    FILE *pWrite; 
    char name[256]; 

    printf("File to write:"); 
    gets(name); 
    pWrite=fopen(name,"a"); 

    if(pWrite != NULL) { 
     fprintf(pWrite, phonebook,sizeof (struct phonebook)); 
     fclose(pWrite); 
    } 
    else { 
     goto ErrorHandler; 
    } 

    exit(EXIT_SUCCESS); 

ErrorHandler: 
    perror("The folling error occured:"); 
    exit(EXIT_FAILURE); 
} 
+0

Waaa。去。 ...嗯,goto只能在函數內部工作,不能跨越函數......擺脫它並使用返回值工作 – deviantfan

+0

yea我的教授專門說過我們必須使用goto。地獄如果我知道。 –

+0

擺脫那個p ...哦不,最好不要。但是如果你必須在那些地方使用「goto」,那麼你就不能使用不同的功能(但主要做所有事情)。如果發生錯誤,那麼如何使用返回值,然後轉到main? – deviantfan

回答

-1

你應該投您的電話簿爲char *:

fprintf(pWrite, (char*)phonebook,sizeof (struct phonebook)); 

goto語句不能在不同功能之間跳躍。
您需要在每個函數中都有一個「ErrorHandler」標記。

也許更好的解決方案是Makro。第一季度銷售價格:

+0

他爲什麼要施放?宏如何提供幫助?他不應該首先打印這樣的東西...... – deviantfan

+0

@deviantfan:它至少會(嘗試)打印'cFirstname'。 – alk

+0

鑄造錯了。因爲只寫入字符串,所以你將無法寫出恰好包含'fprintf'的零字節的結構。另外,它會忽略'sizeof'參數。 – abligh

0

Q1。來自C標準的第6.8.6.1節:

goto語句中的標識符應該命名位於封閉函數某處的標籤。

A goto語句不應從具有不同修改類型的標識符的範圍之外跳轉到該標識符的範圍之內。

A goto語句導致無條件跳轉到由封閉函數中的指定標籤加前綴的語句。

你的教授是得到的是,你需要把每一個goto函數內的部分,在該處理相對清理該功能(關閉文件等),然後做了return底部。 goto(以及壞的)的使用示例如下:Examples of good gotos in C or C++

Q2。這意味着printf中的格式說明符與傳遞的參數類型不匹配。在這種情況下,你正在做的:

fprintf(pRead, phonebook, sizeof (struct phonebook)); 

fprintf採取char *爲指定格式字符串。你不應該直接將結構傳遞給它(想象一下如果你使用fprintf和電話簿條目登錄了%)會發生什麼。

在這種情況下,您希望將固定大小的對象寫入文件,而不是NULL終止的字符串。您應該在任何情況下使用fwrite而不是fprintf,例如

fwrite(phonebook, sizeof (struct phonebook), 1, pRead); 

你也應該考慮錯誤檢查和是否pRead是一個FILE *你正在寫一個好名字。

Q3。見Q2。

+0

感謝這麼多的細節,這樣可以修復它似乎只是一切,當我選擇的讀/寫功能,我的錯誤處理程序返回「無效的參數」 –

+0

這將意味着錯誤(即errnum'的'的值)從系統在錯誤發生之前立即調用EINVAL(文本表示是'Invalid argument'),找到哪個庫調用導致了這個問題,調出man page,你就會知道爲什麼了,你總是可以接受/接受答案如果它有用。 – abligh