如何处理C中的缓冲区

时间:2013-09-10 15:33:47

标签: c

我正在尝试使用一个返回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;
}

3 个答案:

答案 0 :(得分:2)

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

应该使用&&而不是||或者循环永远不会退出

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

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

答案 1 :(得分:1)

以下是我发现的问题:

  • 您无法在fflush()上致电stdin。它导致未定义的行为。 fflush()仅适用于输出流。
  • c的类型应为int。当没有更多输入时,getchar()将返回EOF,而EOF的值不等于unsigned char的任何有效值。这就是getchar()返回int的原因,因此接收getchar()返回值的变量应与该类型匹配。
  • while检查的意义不正确。如果c同时等于\n\0,则只会离开循环,这是不可能的。因此循环永远不会退出。如果你实际上结束了给你的程序的输入,你可能进入了一个无限循环,不断分配,直到你的系统内存不足。因此,如果c等于\n\0,您希望离开循环。
  • 如果cEOF,则应添加一项检查以离开循环。
  • 在分配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;
}

答案 2 :(得分: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;
}