int N, n, i;
char t[1000], s[1000];
scanf("%d", &N);
while (N--) {
gets(t); // 讀取字串
scanf("%d", &n); // 讀取整數
for (i = 0; i < n; i++) s[i] = t[i];
s[n] = '\0';
puts(s);
}
現象:第一輪 `gets(t)` 讀到空行,後續邏輯錯亂。
`scanf("%d", &N)` 讀取整數後,**換行符 `\n` 殘留在標準輸入緩衝區**中。緊接著的 `gets(t)` 遇到此 `\n` 立即返回空字串(不包含換行符),導致實際要讀的字串被下一輪 `scanf("%d", &n)` 讀走,造成連鎖錯誤。
while (N--) {
fflush(stdin); // 清空輸入緩衝區(含殘留 \n)
gets(t);
scanf("%d", &n);
...
}
⚠️ C 標準規定 `fflush` 僅適用於輸出流,`stdin` 行為未定義。MSVC 實現了清空輸入緩衝區,但 GCC/Clang 等不支援,**不可移植**。
while (N--) {
int c;
while ((c = getchar()) != '\n' && c != EOF); // 吞掉殘留 \n
gets(t); // 仍不推薦,見下
scanf("%d", &n);
...
}
while (N--) {
if (fgets(t, sizeof(t), stdin) == NULL) break; // 讀取含 \n
t[strcspn(t, "\n")] = '\0'; // 移除末尾換行符(若有)
scanf("%d", &n);
// 清空 scanf 留下的 \n
int c;
while ((c = getchar()) != '\n' && c != EOF);
for (i = 0; i < n && i < (int)strlen(t); i++) s[i] = t[i];
s[n] = '\0';
puts(s);
}
優勢:`fgets` 限制讀取長度(防溢位)、標準 C、可移植、行緩衝行為可控。
#include <stdio.h>
#include <string.h>
int main() {
int N, n, i;
char t[1000], s[1000];
if (scanf("%d", &N) != 1) return 0;
// 吞掉首行 scanf 留下的換行符
int c;
while ((c = getchar()) != '\n' && c != EOF);
while (N--) {
if (fgets(t, sizeof(t), stdin) == NULL) break;
t[strcspn(t, "\n")] = '\0'; // 去除換行
if (scanf("%d", &n) != 1) break;
// 吞掉 scanf 留下的換行符
while ((c = getchar()) != '\n' && c != EOF);
for (i = 0; i < n && t[i]; i++) s[i] = t[i];
s[i] = '\0';
puts(s);
}
return 0;
}