在典型的 scanf() 呼叫中不會使用換行符
當這個程式
#include <stdio.h>
#include <string.h>
int main(void) {
int num = 0;
char str[128], *lf;
scanf("%d", &num);
fgets(str, sizeof(str), stdin);
if ((lf = strchr(str, '\n')) != NULL) *lf = '\0';
printf("%d \"%s\"\n", num, str);
return 0;
}
使用此輸入執行
42
life
輸出將是 42 ""
而不是預期的 42 "life"
。
這是因為在 scanf()
的呼叫中沒有消耗 42
之後的換行符,並且在讀取 life
之前它被 fgets()
使用。然後,fgets()
在閱讀 life
之前停止閱讀。
為了避免這個問題,在知道線的最大長度 - 例如線上判斷系統中解決問題時 - 有用的一種方法是避免直接使用 scanf()
並通過 fgets()
讀取所有線。你可以使用 sscanf()
來解析讀取的行。
#include <stdio.h>
#include <string.h>
int main(void) {
int num = 0;
char line_buffer[128] = "", str[128], *lf;
fgets(line_buffer, sizeof(line_buffer), stdin);
sscanf(line_buffer, "%d", &num);
fgets(str, sizeof(str), stdin);
if ((lf = strchr(str, '\n')) != NULL) *lf = '\0';
printf("%d \"%s\"\n", num, str);
return 0;
}
另一種方法是在使用 scanf()
之後和使用 fgets()
之前讀取直到你擊中換行符。
#include <stdio.h>
#include <string.h>
int main(void) {
int num = 0;
char str[128], *lf;
int c;
scanf("%d", &num);
while ((c = getchar()) != '\n' && c != EOF);
fgets(str, sizeof(str), stdin);
if ((lf = strchr(str, '\n')) != NULL) *lf = '\0';
printf("%d \"%s\"\n", num, str);
return 0;
}