[英]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
不能確保buf
以nul終止的字符串,因此請確保processBuffer
不會將buf
傳遞給需要字符串的函數,或者對buf
進行迭代以期望在末尾找到以nul終止的字符。)
仔細檢查一下,如果您還有其他問題,請告訴我。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.