簡體   English   中英

從標准輸入讀取並填充緩沖區,直到EOF

[英]Read from stdin and fill buffer until EOF

我需要從stdin讀取並填充_SC_PAGESIZE的緩沖區(來自sysconf()),直到stdin處於EOF為止。 該程序應該是wc克隆,因此我希望傳遞類似常規文件的內容。如果緩沖區不夠大,無法容納stdin,那么我必須繼續填充它,對其進行處理信息,然后清除它並繼續從stdin中的文件偏移再次填充緩沖區。 我只是在跟蹤stdin的EOF時遇到問題,並且遇到了無限循環。 這是我所擁有的:

int pSize = sysconf(_SC_PAGESIZE);
char *buf = calloc(pSize, sizeof(char));
assert(buf);
if (argc < 2) {
        int fd;
        while (!feof(stdin)) {
                fd = read(0, buf, pSize);
                if (fd == -1)
                        err_sys("Error reading from file\n");
                lseek(0, pSize, SEEK_CUR);
                if (fd == -1)
                        err_sys("Error reading from file\n");
                processBuffer(buf);
                buf = calloc(pSize, sizeof(char));
        }
        close(fd);
}

我假設問題與測試條件有關(while(!feof(stdin)),所以我想我需要的是正確的測試條件才能退出循環。

你可以這樣寫循環

int n;
do {
    n = read(0, buf, pSize);
    // process it
} while(n > 0);

請記住,EOF只是一個退出條件,在任何其他錯誤條件發生之前可能不會發生。 真正檢查運行循環的有效性是read的健康返回代碼。 另外,請注意, while(n > 0)是否足夠取決於您從何處讀取。 如果是stdin ,可能就足夠了。 但是例如對於套接字,條件可以這樣寫: while(n > 0 || errno == EAGAIN)

為什么要使用低級read而不是打開FILE *stream和使用fgets (或POSIX getline )? 此外,每次調用都會泄漏內存:

            buf = calloc(pSize, sizeof(char));

在循環中,因為您覆蓋了buf包含的地址,從而丟失了對前一個內存塊的引用,從而無法free它。

相反,分配一次緩沖區,然后連續填充緩沖區,將已填充的緩沖區傳遞給processBuffer 您甚至可以使用三元運算符來確定是打開文件還是僅從stdin讀取文件,例如

int pSize = sysconf(_SC_PAGESIZE);
char *buf = calloc(pSize, sizeof(char));
assert(buf);

FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) {
    perror ("fopen failed");
    return 1;
}

while (fgets (buf, pSize, fp))
    processBuffer(buf);     /* do not call calloc again -- memory leak */

if (fp != stdin) fclose (fp);   /* close file if not stdin */

注意:由於fgets讀取一行,因此您只需計數迭代次數即可獲得行數-只要您的_SC_PAGESIZE不超過_SC_PAGESIZE

如果要使用精確的pSize塊,則可以使用fread而不是fgets 唯一的效果是稍微減少對processBuffer的調用processBuffer ,但這完全取決於您。 您唯一需要做的就是將while (...)行更改為:

while (fread (buf, (size_t)pSize, 1, fp) == 1)
    processBuffer(buf);     /* do not call calloc again -- memory leak */

if (ferror(fp))     /* you can test ferror to insure loop exited on EOF */
    perror ("fread ended in error");

注意:read一樣, fread不能確保bufnul終止的字符串,因此請確保processBuffer不會將buf傳遞給需要字符串的函數,或者對buf進行迭代以期望在末尾找到以nul終止的字符。)

仔細檢查一下,如果您還有其他問題,請告訴我。

暫無
暫無

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

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