簡體   English   中英

scanf何時開始和停止掃描?

[英]When does scanf start and stop scanning?

當按下Enter鍵時, scanf似乎開始掃描輸入,我想用下面的代碼驗證這一點(為簡單起見,我省略了錯誤檢查和處理)。

#include <stdio.h>

int main(int argc, char **argv) {
    /* disable buffering */
    setvbuf(stdin, NULL, _IONBF, 0);
    int number;

    scanf("%d", &number);
    printf("number: %d\n", number);

    return 0;
}

這是另一個問題,在我禁用輸入緩沖之后(只是為了驗證結果;我知道我應該在實際中做到這一點,以防它干擾結果),輸出是(注意額外的提示):

$ ./ionbf
12(space)(enter)
number: 12
$
$

這與輸入緩沖啟用時的輸出不同(無額外提示):

$ ./iofbf
12(space)(enter)
number: 12
$

在啟用緩沖區時,似乎會消耗新的行字符。 我在兩台不同的機器上進行了測試,一台安裝了gcc 4.1.2和bash 3.2.25,另一台安裝了gcc 4.4.4和bash 4.1.5,結果兩者相同。

問題是:

  1. 如何在啟用和禁用輸入緩沖時解釋不同的行為?
  2. 回到原來的問題, scanf什么時候開始掃描用戶輸入? 角色進入的那一刻? 或者它是否緩沖直到一條線完成?

有趣的問題 - 冗長的回答。 如有疑問,我正在描述我認為在Unix上發生的事情; 我將Windows留給其他人。 我認為行為類似,但我不確定。

使用setvbuf(stdin, NULL, _IONBF, 0) ,使用read(0, buffer, 1)系統調用強制stdin流一次讀取一個字符。 當您使用_IOFBF_IOLBF運行時,管理流的代碼將嘗試一次讀取更多字節(如果使用setvbuf() ,則最多可讀取緩沖區的大小,如果不使用,則為BUFSIZ )。 這些觀察結果加上輸入中的空間是解釋所發生情況的關鍵。 我假設您的終端處於正常或規范輸入模式 - 請參閱Canonical與非規范終端輸入以進行討論。

在輸入return之前,終端驅動程序不會使任何字符可用是正確的。 這允許您在鍵入時使用退格等編輯行。

當你點擊返回時,內核有4個字符可供發送給任何想要讀取它們的程序: 1 2 空格 返回

使用_IONBF的情況下,通過調用read(0, buffer, BUFSIZ)將這4個字符一次性讀入stdin的標准I / O緩沖區。 scanf()然后收集1中 ,從所述緩沖器中的2空格字符,並提出回空間到緩沖器中。 (請注意,內核已將所有四個字符傳遞給程序。)程序打印其輸出並退出。 shell恢復,打印提示並等待更多輸入可用 - 但是在用戶鍵入另一個返回之前不會有任何輸入,可能(通常)前面有一些其他字符。

在你使用的情況下_IONBF ,程序讀取一個字符的時間。 它進行read()調用以獲取一個字符並獲得1 ; 它進行另一次read()調用並得到2 ; 它進行另一個read()調用並獲取空格字符。 (注意,內核仍然有返回就緒和等待。)它不需要空間來解釋數字,因此它將它放回到其后推緩沖區中(保證在后推中至少有一個字節的空間)緩沖區),准備好進行下一次標准I / O讀操作,並返回。 程序打印輸出並退出。 shell恢復,打印提示,並嘗試從終端讀取新命令。 內核要求返回正在等待的換行符,shell會說“哦,這是一個空命令”並給你另一個提示。

您可以通過輸入1 2 x p s 返回到您的( _IONBF )程序來證明這是發生的事情。 當你這樣做時,你的程序讀取值12和'x',留下'ps'和shell讀取換行符,然后執行ps命令(不回顯它讀取的字符),然后再次提示。

您還可以使用trussstrace或類似命令來跟蹤程序執行的系統調用,以查看我建議發生的真實性。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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