2011-12-08 25 views
0
#include <stdio.h> 

#define TRUE 1 
#define FALSE 0 

typedef struct contact {  
char firstname [40];  
char lastname [40]; 
char address [100]; 
char phone[10]; 
}contact; 


int main() 
{ FILE *pFile; 
    contact entry = {""}; 
    int choice, firstname_flag = TRUE, lastname_flag = TRUE, address_flag = TRUE, phone_flag = TRUE; 

    pFile = fopen("C:\\contacts.txt", "a+"); 

    if(!pFile){ 
     printf("File could not be open."); 
     return 1; 
     } 

    do{ 
    printf("Choose a selection:\n\n"); 
    printf("1. First name:\n"); 
    printf("2. Last name:\n"); 
    printf("3. Address:\n"); 
    printf("4. Phone number:\n\n"); 
    scanf("%d", &choice); 
    }while((choice < 1 || choice > 4)); 

    switch (choice){ 
    case 1: 
     firstname_flag = FALSE; 
     printf("Please enter first name: \n");  
     scanf("%s", &entry.firstname); 
     break; 
    case 2: 
     lastname_flag = FALSE; 
     printf("Please enter last name: \n");  
     scanf("%s", &entry.lastname); 
     break; 
    case 3: 
     address_flag = FALSE; 
     printf("Please enter address: \n"); 
     scanf("%s", &entry.address); 
     break; 
    case 4: 
     phone_flag = FALSE; 
     printf("Please enter phone number: \n");  
     scanf("%s", &entry.phone); 
     break; 
    default: 
     break; 
    } 

    printf("\nYou will now be asked to enter the other items. \n\n"); 

    if(firstname_flag){ 
     printf("Please enter first name: \n"); 
     scanf("%s", &entry.firstname); 
    }  
    if(lastname_flag){ 
    printf("Please enter last name: \n"); 
    scanf("%s", &entry.lastname); 
    } 
    if(address_flag){ 
     printf("Please enter address: \n"); 
     scanf("%s", &entry.address); 
    } 
    if(phone_flag){ 
     printf("Please enter phone number: \n"); 
     scanf("%s", &entry.phone); 
    } 

    fwrite (here) 

    fclose(pFile); 

    getchar(); 
    return 0; 
} 

這是我到目前爲止的代碼。首先是有什麼明目張膽的作爲無效或錯誤的練習等?第二我想寫名字,姓氏,地址和電話號碼到一個文件。我不確定是否需要寫入「輸入」。另外,我注意到當選擇Address時,它幾乎就像緩衝區不是空的,並且我在後面放置了123 Park,Park將被錯誤地用作第一個名字,並且我將放入的下一個條目將是Last名稱。任何有關代碼使用和任何建議的建議將不勝感激。再次感謝地址預訂和寫入文件

+0

兩個快速觀察。 'main'太長,將它分成單獨的函數。縮進不一致。看看和[astyle](http://astyle.sourceforge.net/)並觀察它對你的代碼有什麼作用。 – Jan

+0

大部分縮進問題可能是因爲我試圖讓它在這裏看起來合理。 – Questioneer

回答

1

N°1在迴應:「無效或者錯誤做法」有些是更有味道事項...

  • 如果你「必須」使用scanf,唐't指向一個字符串緩衝區與%s:指定緩衝區的長度,類似%32s減少(但可能不會消除)某人從打字太多和崩潰程序(或更糟糕......) - 但是,閱讀N°3下面更多關於這個問題...
    • 如果你開發的東西開源,或爲個人使用,GNU readline是一個非常不錯的選擇(但它是GPLLGPL,因此它不能在「非自由報」使用工作...)
  • 您的結構初始值設定項不包含所有元素。您可以使用{"", "", "", ""}
  • 您的意思是fwrite(entry)
  • 如果您在寫入文件之前檢查缺少的字段,則可能需要放置一組標誌,而是在「無效狀態」上循環。

    while ('\0' == entry.firstname[0]) { 
        printf("Please enter first name: \n"); 
        scanf("%40[^\r\n\0\04]", &entry.firstname[0]); 
    } 
    
  • 無需打開文件這麼早,並把它打開,而等待用戶交互。在a+模式下打開文件相當「危險」(請參閱​​man lockf),因爲其他人可能會嘗試在文件中寫入文件;長時間在此模式下打開它會增加風險。

  • 您應該使用strerror(errno)向用戶提供失敗系統調用的詳細信息,例如,在檢查fopen,fwritefclose的返回碼時。由於緩衝I/O的工作方式,fclose甚至可能在某些情況下報告fwrite發生的問題。
  • 使用fprintf (stderr, ... );,而不是輸出流...
  • 如果你要使用的標誌,以表明該數據是「有效的」打印您的錯誤消息stderr(或者,至少,它可能是),您應該在之後之後,用戶嘗試輸入它,而不是之前。
  • 功能是你的朋友...我可能會通過使用函數來收集用戶的輸入(類似於prompt_for_field ("first name", &entry.firstname);),一個函數來檢查缺少的記錄並提示它們,以及寫入記錄的函數至少...
  • 它通常被認爲是從main而不是returnexit的良好形式,例如通過使用exit(EXIT_SUCCESS)/exit(EXIT_FAILURE)。我認爲這個想法是支持誰可能比0治療一些值(S)等作爲一個成功的狀態碼深奧和可能的滅絕系統(VMS,也許?),但無論如何,它更易於閱讀:-)

和N°2,是的,你可以fwrite(entry),只要你永遠不會改變struct contact的定義,你應該可以正確地閱讀它。隨着時間的推移,您可能會希望切換到更爲「純文本」的格式(#include <json-xml-init-religious-war>),但在這個小例子中,並沒有迫切需要引入這種複雜性。

最後,N°3,你應該使用&entry.address[0]獲得char[]但最顯著的起始地址:scanf %s不讀的字符串。看起來像printf %s,但它不是...

s匹配的非空白字符的序列;下一個 指針必須是一個指向字符 的指針,該數組的長度足以容納輸入序列和終止空字符('\ 0'), ,該字符會自動添加。輸入字符串停留在空白處或最大字段寬度處,以先發生者爲準。

看到「非空白?」這就是你所擁有的。其餘的輸入(在第一個空格之後)留在鍵盤緩衝區中,等待另一個scanf來讀取它。從終端讀取並接受空格的好方法(012)是%40[^\r\n\0\04],用字符串緩衝區(char[])的大小替換。這意味着,只要它們不是:接受(最多)40個字符:回車符,換行符,空字節或文件結束碼(^D)。

總而言之,你看起來是在正確的軌道,但。祝你好運:-)