簡體   English   中英

在C中如何處理緩沖區

[英]What to do with buffer in C

我正在嘗試使用一個返回char * buffer的函數來捕獲來自標准輸入的隨機用戶輸入,並使用輸入返回char* (即字符串),直到檢測到'\\n''\\0'作為輸入為止。

但是,函數user_input()在第二次出現c = getchar();崩潰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;
}
while ( c != '\n' || c !='\0' ) {

應該使用&&代替|| 否則循環永遠不會退出

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

盡管代碼中還有其他錯誤,例如“ buffer [num_read] ='\\ 0';”,但我還是構建了它並起作用了。 如果數組中確實有buffer_size項,最后可能會使緩沖區溢出。

這是我發現的問題:

  • 您不能在stdin上調用fflush() 它導致未定義的行為。 fflush()僅用於輸出流。
  • c的類型應為int 當沒有更多輸入時, getchar()將返回EOF ,並且EOF是不等於unsigned char任何有效值的值。 這就是為什么getchar()返回int ,因此您的接收getchar()返回值的變量應該與該類型匹配。
  • while檢查的感覺不正確。 僅當c等於\\n\\0時,您才退出循環,這是不可能的。 因此,循環將永遠不會退出。 如果實際上結束了提供給程序的輸入,則可能進入了無限循環,不斷分配直到系統內存耗盡。 因此,如果c等於\\n\\0則要退出循環。
  • 如果cEOF則應添加檢查以退出循環。
  • 在分配\\0字符之前,應確保num_read小於buffer_size 這可以通過將realloc()代碼移動到while循環的底部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;
}

我在下面修改了您的代碼。 嘗試按原樣運行它,首先使用'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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM