0

我正在尝试使用一个返回的函数char * buffer来捕获来自标准输入的随机用户输入,并返回一个char*带有输入的(即字符串),直到'\n'或被'\0'检测为输入。

但是,该函数在函数 末尾附近的user_input()第二次出现时崩溃(在注释处)。c = getchar();//Error Here

我究竟做错了什么?

char* user_input(){

    char *buffer=NULL;
    size_t num_read = 0;
    size_t buffer_size = 100;
    char c = '\0';
    char *new_buffer=NULL;
    buffer = malloc(buffer_size);
    fflush(stdin);
    c = getchar();

    while ( c != '\n' || c !='\0' ) {

           if (num_read >= buffer_size) {
           new_buffer=NULL;
           buffer_size *= 2; // try a buffer that's twice as big as before
           new_buffer = realloc(buffer, buffer_size);
           if (new_buffer == NULL) {
                free(buffer);
                return NULL;
                /* Abort - out of memory */
            }
            buffer = new_buffer;
        }
        buffer[num_read] = c;
        num_read++;
        c = getchar();  //Error Here
    }//while
    buffer[num_read] = '\0';
    return buffer;
}
4

3 回答 3

2
while ( c != '\n' || c !='\0' ) {

应该使用 && 而不是 || 否则循环将永远不会退出

while ( c != '\n' && c !='\0' ) {

我构建了它并且它可以工作,尽管代码中还有其他错误,例如“buffer[num_read] = '\0';” 如果数组中有确切的 buffer_size 项,最后可能会溢出缓冲区。

于 2013-09-10T15:47:11.523 回答
1

以下是我发现的问题:

  • 你不能打电话fflush()stdin它会导致未定义的行为。fflush()仅用于输出流。
  • for 的类型c应该是int. 将在没有更多输入时getchar()返回,并且该值不等于 的任何有效值。这就是为什么返回一个,所以你的变量接收的返回值应该匹配那个类型。EOFEOFunsigned chargetchar()intgetchar()
  • 检查的感觉while是不正确的。c只有同时等于两者时\n,您才会离开循环\0,这是不可能的。因此循环永远不会退出。如果你真的结束了给你的程序的输入,你可能进入了一个无限循环,不断地分配,直到你的系统内存不足。c所以,如果等于\n或,你想离开循环\0
  • c如果is ,您应该添加一个检查以离开循环EOF
  • 您应该确保num_read小于buffer_size分配\0字符之前的值。这可以通过将realloc()代码移动到循环底部while而不是顶部来完成。

通过这些更改,代码如下所示:

char *user_input() {
    char *buffer = NULL;
    size_t num_read = 0;
    size_t buffer_size = 100;
    int c = '\0';
    char *new_buffer = NULL;
    buffer = malloc(buffer_size);
    c = getchar();
    while (!(c == EOF || c == '\n' || c == '\0')) {
        assert(num_read < buffer_size);
        buffer[num_read++] = c;
        if (num_read >= buffer_size) {
            buffer_size *= 2;   // try a buffer that's twice as big as before
            new_buffer = realloc(buffer, buffer_size);
            if (new_buffer == NULL) {
                free(buffer);
                return NULL;
            }
            buffer = new_buffer;
        }
        c = getchar();
    }                           //while
    assert(num_read < buffer_size);
    buffer[num_read] = '\0';
    return buffer;
}
于 2013-09-10T16:14:15.273 回答
0

我在下面修改了您的代码。尝试按原样运行它,首先使用“q”字符,然后您可以稍后尝试其他退出条件。顺便说一句,您的代码无需修改即可工作,并且对我来说没有崩溃(除非发生缓冲区溢出,但否则它永远不会离开 while 循环(正如 Brian Walker 指出的那样)。无论如何,在任何 ANSI C 编译器中试试这个: (只是不要输入超过 1000 个条目:)

#include <ansi_c.h>
char* user_input(void);

int main(void)
{
    char *buf;

    buf = malloc(1000);
    //SearchDirectory("C:\\dev");
    sprintf(buf, "%s", user_input());
    printf("%s", buf);

    free(buf);
    return 0;   
}


char* user_input(void){

    char *buffer=NULL;
    size_t num_read = 0;
    size_t buffer_size = 100;
    char c = '\0';
    char *new_buffer=NULL;
    buffer = malloc(buffer_size);
    fflush(stdin);
    c = getchar();

    while ( c != 'q' ) {

           if (num_read >= buffer_size) {
           new_buffer=NULL;
           buffer_size *= 2; // try a buffer that's twice as big as before
           new_buffer = realloc(buffer, buffer_size);
           if (new_buffer == NULL) {
                free(buffer);
                return NULL;
                /* Abort - out of memory */
            }
            buffer = new_buffer;
        }
        buffer[num_read] = c;
        num_read++;
        c = getchar();
    }//while
    buffer[num_read] = '\0';
    return buffer;
}
于 2013-09-10T16:04:00.537 回答