簡體   English   中英

為什么 scanf 可以使用 for 循環讀取一行中的多個輸入?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM