2012-07-16 57 views
2

我想知道爲什麼下面的代碼行爲如下。我第一次打印變量「account_name」它可以正常工作。第二次和第三次,它根本不起作用,而是打印亂碼。我在C.C函數輸入字符串

const char * get_account_name(){ 

    char loc_account_name[255]; 

    printf ("Please enter the ledger Account name: "); 
    scanf ("%[^\n]", &loc_account_name); 
    fflush(stdin); 
    printf ("\n"); 
    return (loc_account_name); 
} 

void main (void) 
{ 

    /* Declare variables. We use the predefined "MAX_ENTRIES" definition to define how large the arrays will be */ 

    float credits[MAX_ENTRIES], debits [MAX_ENTRIES], starting_balance, ending_balance; 
    int  debit_amount, credit_amount, x; 
    char * account_name; 

    printf ("Welcome to the Sears Ledger System\n\n"); 

    /* Prompt the user to enter the name of the account, we allow for up to 255 characters and account for names with spaces as well */ 
    account_name = get_account_name(); 
    printf("%s",account_name); 
    printf("%s",account_name); 
    printf("%s",account_name); 


} /* end main*/ 

*更新

初學者我已刪除的get_account_name功能的scanf函數的符號。然後我發現它會不止一次地打印出正確的值,但是程序會在那之後永遠掛起。不幸的是,我被迫使用的編譯器沒有調試器,所以我仍然對發生的事情感到困惑。

char * get_account_name(){ 

    char * loc_account_name; 
    printf ("Please enter the ledger Account name: "); 
    scanf ("%[^\n]", loc_account_name); 
    fflush(stdin); 
    printf ("\n"); 

    return loc_account_name; 

} 

* *更新2

char *get_account_name() { 

    char loc_account_name[255]; 
    char *r; 

    printf ("Please enter the ledger Account name: "); 
    scanf ("%[^\n]", &loc_account_name); 
    fflush(stdin); 
    printf("%s\n", loc_account_name); 

    *r = malloc(strlen(loc_account_name) + 1); 
    strcpy(r, loc_account_name); 
    return r; 
} 

void main (void) 
{ 

    char  * account_name; 

    /* Prompt the user to enter the name of the account, we allow for up to 255 characters and account for names with spaces as well */ 
    account_name = get_account_name(); 
    printf("%s\n", account_name); 
    printf("%s\n", account_name); 
    printf("%s\n", account_name); 
    free(account_name); 


} /* end main*/ 
+0

'scanf(「%[^ \ n]」,...)'這是否工作? – Ashe 2012-07-16 02:14:23

+0

是的,迄今爲止我已經工作 – user1527739 2012-07-16 02:57:39

回答

4

您從get_account_name()返回一個局部變量loc_account_name的地址。該函數返回後,該內存不存在。 (嗯,它看起來像它仍然包含了很短的時間相同的數據,但你不使用它的第二次或第三次)

爲了解決這個問題,您可以:

  • 分配空間(使用malloc()或類似的)作爲get_account_name()函數中的字符串,並返回指向該空間的指針。調用者將負責釋放內存。

    char *get_account_name() { 
        char loc_account_name[255]; 
        // get user input into loc_account_name 
        char *r = malloc(strlen(loc_account_name) + 1); 
        strcpy(r, loc_account_name); 
        return r; 
    } 
    
    account_name = get_account_name(); 
    // use account_name 
    free(account_name); 
    

    注意,您可以使用strdup()代替malloc()/strcpy()如果你的運行時庫有其中的一個。

  • 具有呼叫者分配一些空間用於字符串的最大長度,以及緩衝液(和緩衝區的長度)通入get_account_name()函數爲它在繼續進行。

    void get_account_name(char *buffer, int buffer_size) { 
        // get user input into buffer 
        // but make sure the user can't type more than buffer_size characters! 
    } 
    
    char account_name[255]; 
    get_account_name(account_name, sizeof(account_name)); 
    // use account_name 
    

返回函數中的字符串在C中很笨拙和煩人。這就是爲什麼大多數現代語言(包括C++)具有更好的內置方式來處理字符串的原因。

+0

我已經刪除了&符號,以便它不再返回本地變量的地址。我不確定是否需要修復它,因爲儘管它現在確實不止一次地打印了正確的字符串,但它永遠掛起。 (我沒有調試功能)您能否使用您的一種方法發佈更詳細的響應,因爲我不熟悉這兩種方法。 – user1527739 2012-07-16 03:04:38

+0

您的更新代碼現在將用戶文本讀入由未初始化的'loc_account_name'指針指向的內存中的某個隨機位置。正如你所注意到的,這也是錯誤的。我將添加一些代碼示例。 – 2012-07-16 03:08:29

+0

我已經嘗試了上面的第一個解決方案,但結果與刪除&符號非常相似。系統連續寫出正確的文本3次,然後崩潰(我的簡單掛起而不是崩潰,但不是太不相似)它似乎與「免費(」聲明 – user1527739 2012-07-16 03:26:33

0

在單線程環境中,您可以簡單地使用一個靜態緩衝區,如:

const char *get_account_name(void) { 

    static char loc_account_name[255]; 
    int c; 

    printf ("Please enter the ledger Account name: "); 
    scanf ("%254[^\n]", loc_account_name); 
    while((c=getchar())!=EOF && c!='\n'); 
    printf("%s\n", loc_account_name); 

    return loc_account_name; 
} 

清除輸入緩衝區,你應該永遠使用一個符合標準的方式。