[英]Why can scanf read multiple inputs in a line with a for loop?
我想將給定的 n 個值(n 已知)存儲在一個數組中,但我不知道該怎么做,所以我查看並找到了這篇文章: C, reading multiple numbers from single input line (scanf?)和這個回答:
int main()
{
int i, size, *v;
scanf("%d", &size);
v = malloc(size * sizeof(int));
for (i=0; i<size; i++)
scanf("%d", &v[i]);
printf("%d %d %d", v[0], v[1], v[2]);
}
我不明白為什么 scanf 可以做到這一點,函數不應該在循環的每次迭代中要求另一個輸入嗎? 只要它們用空格分隔,它如何讀取一個 int,然后讀取另一個等等? scanf 怎么會這樣呢? 因為它似乎不應該。
PS:為簡單起見,我只用 3 個值編寫了最終打印語句,在“我的情況”中,大小為 3。
先感謝您!
當您在控制台上輸入一些數字並按 ENTER 時,您將通過標准輸入向您的代碼提供輸入流。 您輸入的全部內容都保存在該輸入流中。 所以如果你輸入
2 4 6 8
然后回車,輸入流包含:2 4 6 8
現在,您的每個 scanfs 僅從該輸入流中讀取(和刪除)一個整數,因此在單個 scanf 之后,stdin 輸入流現在包含: 4 6 8
額外的輸入不會被丟棄,它仍然在輸入流中可用,所以你的下一個 scanf 可以出現並從流中獲取下一個整數,下一個,下一個......直到輸入中的數據流已用盡。
這是scanf
令人驚訝的事情之一。
如果我寫
scanf("%d %d %d", &a, &b, &c);
看起來我希望閱讀一行包含三個數字的行。 但是如果用戶實際輸入的是
1
2
3
(也就是說,在三個單獨的行上),它會“工作”得很好。 scanf
想要三個整數,它找到了它們,但它必須讀取三行才能這樣做。
相反,如果我寫
scanf("%d", &a);
scanf("%d", &b);
scanf("%d", &c);
和用戶輸入
4 5 6
再一次,在一行上,這會“工作”得很好,有三個scanf
調用要求總共三個整數,並且那里有三個整數——盡管它們恰好在一行上。
在您的情況下,您在循環中的scanf
調用與幾個單獨的scanf
調用的效果大致相同。
底線是scanf
不是基於行的。 對scanf
的調用和預期的輸入行之間沒有一一對應的關系。 scanf
不會特別處理換行符——它們只是被視為空格,分隔其他輸入字段。
(相比之下, printf
也不是基於行的,盡管它至少會特別處理\n
字符。但輸出之間沒有區別
printf("one ");
printf("two ");
printf("three\n");
和
printf("one two three\n");
.)
閱讀原始問題后,我想我明白你在問什么。
所以在另一個問題中,輸入是:
5<ENTER>
1 2 3 4 99<ENTER>
scanf
是一個讀取格式化輸入的函數設計(名稱來自scan formatted),它不是讀取隨機用戶輸入的設計。
引用 scanf 的手冊頁:
#include <stdio.h> int scanf(const char *format, ...);
描述
scanf()
系列函數根據如下所述的format
掃描輸入。 此格式可能包含conversion specifications
; 此類轉換的結果(如果有)存儲在遵循格式的指針參數所指向的位置。 每個指針參數的類型必須適合相應轉換規范返回的值。
這意味着 scanf 根據提供的格式掃描輸入。 轉換說明符%d
匹配可選帶符號的十進制整數。 如果您的格式僅包含"%d"
,它將消耗任何空白字符並嘗試將下一個非空白字符序列轉換為帶signed int
。 如果可能, scanf
會將轉換后的整數存儲在傳遞參數指向的內存中。 如果轉換失敗,它將停止掃描,輸入緩沖區中的任何其他字符都將保留在輸入緩沖區中。
所以讓我們這樣做:您輸入 3 個這樣的數字:
3空格空格4空格選項卡5 ENTER
您的輸入緩沖區將如下所示:
+---+---+---+---+---+----+---+----+
| 3 | █ | █ | 4 | █ | \t | 5 | \n |
+---+---+---+---+---+----+---+----+
在第一次迭代中scanf
消耗任何空白字符,現在沒有,所以它將讀取 3 並繼續下一個字符,即空格。 此時它停止並轉換 3 並將其存儲在&v[i]
中。 輸入緩沖區將如下所示:
+---+---+---+---+----+---+----+
| █ | █ | 4 | █ | \t | 5 | \n |
+---+---+---+---+----+---+----+
在第二次迭代中,它將消耗任何空白字符。 那里有兩個空間,它們只是被消耗掉了。 然后它將讀取 4,然后是一個空白字符。 scanf
停止並轉換 4 並將其存儲在&v[i]
中。 輸入緩沖區將如下所示:
+---+----+---+----+
| █ | \t | 5 | \n |
+---+----+---+----+
如您所見,在每次迭代中, scanf
都沒有等待塊並等待用戶輸入某些內容,因為之前的迭代中字符都留在了輸入緩沖區中。
這就是為什么您可以在循環中使用scanf("%d", &v[i])
以獲取像這樣的輸入"1 2 3 4 5"
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.