0

我真的被这个难住了。

我在 c 中编写了一个简单的程序,用于从用户键盘输入中检索名字、姓氏和 YOB(出生年份)(我还没有时间将年龄解析为整数)并且我设置了最大字符数为输入。

但是,每当我允许字段的最大字符数为 50 或更大时,返回值始终为空白。

这是代码(60 行),输出如下。引起问题的函数是倒数第二个函数getInputNoNewLine:

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

void flushBuffer();
char *getInput(int max, char message[]);
char *getInputNoNewline(int max, char message[]);

typedef struct Person {
    char *firstName;
    char *lastName;
    int yob;
} Person;

void flushBuffer() {
    int ch; 
    while ((ch = getchar()) != '\n' && ch != EOF); //flush the input buffer
}

char *getInput(int max, char message[]) {
    char in[max];
    char *input;
    do {
        printf("%s", message);
        input = fgets(in, max + 2, stdin); //max + 2 accounts for characters fgets adds
        if (input[strlen(input)-1] != '\n') {
            printf("Sorry, maximum %d characters\n", (max));
            flushBuffer();
        }
    } while (input[(strlen(input)-1)] != '\n');
    printf("input: %s", input); //debug
    return input;
}

//OFFENDING FUNCTION
char *getInputNoNewline(int max, char message[]) {
    char *input;
    input = getInput(max, message);
    printf("raw input : %s", input); //debug
    if (input[strlen(input) - 1] == '\n') { //strip new line character
        input[strlen(input) - 1] = '\0';
    }
    printf("final input: '%s'\n", input); //debug
    return input;
}

int main(int argc, char *argv[]) {
    int numPlayers = 3;
    char *intIn;
    int i = 0;
    Person players[numPlayers]; 
    printf("Hello world Game\n");
    for (i = 0; i < numPlayers; ++i) {
        players[i].firstName = getInputNoNewline(50, "What is your first name: "); //50 will return blank
        players[i].lastName = getInputNoNewline(49, "What is your last name: "); //49 will return fine
        intIn = getInputNoNewline(4, "What is your YOB: "); //TODO: convert number to integer with sscanf
        printf("-----------------------------------\n");
    }
    printf("Finished\n");
    return 0;
}

这是输出,您可以看到 jim 的第一个输入是从 fgets 接收的,但返回值为空白(原始输入:)。如果我要将最大值从 50 减少到 49,根据姓氏字段的情况,它工作得很好。有什么想法吗?

Hello world Game
What is your first name: jim
input: jim
raw input : final input: ''
What is your last name: smith
input: smith
raw input : smith
final input: 'smith'
What is your YOB: 1984
input: 1984
raw input : 1984
final input: '1984'
-----------------------------------
4

3 回答 3

3

您的代码具有未定义的行为
您正在返回一个指向本地分配数组的指针。

char *getInput(int max, char message[])
{
    char in[max];
    ....
    ....
    return input;
}

in是函数局部的数组,并且保证仅在函数作用域之前有效{``}。为了能够在函数范围之外访问此数组的内容,您需要通过以下方式增加数组的生命周期:

  • malloc使用或动态分配它
  • 使其static或全球

如果您使用malloc,请不要忘记在使用后通过调用释放数组,free否则最终会导致内存泄漏。

于 2013-02-11T04:07:45.923 回答
2

既然你分配in了 50 个字符的长度,而你允许读取 52 个字符,你就会遇到麻烦!你想用

static char* in;
if(in!=NULL) free(in);
in = (char*)malloc(max + 2);

这既解决了 Alok 提出的问题(关于函数返回后未定义本地范围指针),也解决了您的函数允许fgetsmax+2字符写入缓冲区的事实in

于 2013-02-11T04:08:27.813 回答
0

您遇到了许多内存管理问题。fgets 调用请求崩溃,因为您传递的长度比分配的内存大 2 个字节。您还将返回从 fgets 返回的 char * 并将其视为分配的内存。

您应该复制从 fgets 返回的缓冲区并将其存储在您的 Person 结构中。

真的,我认为你应该回顾一下基本的 C 内存分配和销毁。

于 2013-02-11T04:13:07.870 回答