2

我想知道为什么下面的代码如下所示。我第一次打印变量“account_name”时它工作正常。第二次和第三次,它根本不起作用,而是打印乱码。我是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*/
4

2 回答 2

4

您正在从 中返回局部变量的loc_account_name地址get_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++)都有更好的内置方法来处理字符串。

于 2012-07-16T02:08:34.343 回答
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;
}

要清除输入缓冲区,您应该使用符合标准的方式。

于 2012-07-16T09:29:31.277 回答