[英]fgets from stdin with unpredictable input size
我正在嘗試從stdin
讀取一行,但是我不知道如何正確處理輸入大小至少等於限制的情況。 示例代碼:
void myfun() {
char buf[5];
char somethingElse;
printf("\nInsert string (max 4 characters): ");
fgets (buf, 5, stdin);
...
printf("\nInsert char: ");
somethingElse = getchar();
}
現在,用戶可以做三件事:
getchar()
正確等待用戶輸入; getchar()
讀取它; getchar()
讀取該字符,並至少留了一個換行符。 情況2和3需要使用while(getchar() != '\\n')
類的東西來清空stdin
,而情況1則不需要任何其他操作。 當我從閱讀的答案類似的問題和c-FAQ了解,有了解實際的情況是1或沒有描述的一個沒有標准/可移植的方法。
我做得好嗎? 還是實際上有一種便攜式的方法? 還是完全不同的方法?
如果有空間, fgets
函數會將換行符存儲在緩沖區中。 因此,如果字符串中的最后一個字符不是換行符,則說明您需要刷新緩沖區。
fgets (buf, 5, stdin);
if (strrchr(buf, '\n') == NULL) {
// flush buffer
int c;
while ((c = getchar()) != '\n') && (c != EOF));
}
如果有人假設永遠不會讀取空字符 '\\0'
,那么@dbush答案將起作用。
如果讀取了空字符 ,則strrchr(buf, '\\n')
找不到可能已經讀取的任何'\\n'
。
代碼可以預先設置緩沖區,以查看最后是否讀取了'\\n'
。
buf[sizeof buf - 2] = '\n';
if (fgets (buf, sizeof buf, stdin)) {
if (strrchr(buf, '\n') == NULL) {
// incomplete line read. (the usual detection)
} else if (buf[sizeof buf - 2] != '\n') {
// incomplete line read with prior null character (see below note).
}
}
然而,C標准並未指定在buf[]
讀取的數據是否保持不變,因此用某種模式預填充緩沖區不足以檢測是否讀取了空字符 '\\0'
。
是一種便攜式方法嗎?
最可移植的方法是使用重復調用fgetc()
或類似方法代替fgets()
。
也許是完全不同的方法?
我建議使用fgetc()
或通用但不符合C標准的getline()
另一種選擇:使用scanf("%4[^\\n]%n", buf, &n)
:這很麻煩 ,但是可以使用一種便攜式方法。 即使某些字符為空字符,它也會跟蹤在'\\n'
之前讀取的字符數 。
int n = 0;
cnt = scanf("%4[^\n]%n", buf, &n); // Cumbersome to get that 4 here.
// Lots of TBD code now needed:
// Handle if cnt != 1 (\n to be read or EOF condition)
// Handle if n == sizeof buf - 1, (0 or more to read)
// Handle if n < sizeof buf - 1, (done, now get \n)
// A \n may still need to be consumed
// Handle EOF conditions
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.