scanf函式和回車 空格 及其返回值

2021-10-07 05:29:56 字數 2817 閱讀 2457

scanf和回車的關係:

先看乙個我們經常使用的**:

char c;

scanf("%c", &c);

scanf 的各種格式中,%d、%c、%s三種最常用,通常都是以回車作為一次輸入的結束。由於對字元解析方式及字元特點不同(如數字中一般不會出現空格回車等特殊字元)不同,%d格式一般不會在連續輸入時,遇到問題。而%s和%c卻會出現各種各樣的問題,比如回車問題,空格問題等。

我們已經習慣了上面的**,再看下面存在連續輸入時的情況:

int i;

char c;

scanf("%d", &i);

scanf("%c", &c);

如果我們為i賦值為3,並以回車的方式結束對i的賦值。再按常規思路為c賦值時,就會發現並不能為c賦值,並且c自動賦值為十進位制的10,也就是回車鍵。why???

要回答這個問題,先看scanf函式的功能和工作原理:

scanf函式這個函式的作用是從標準輸入裝置獲取輸入值,並儲存到引數列表中指標所指向的記憶體單元,如果讀入成功,函式會返回讀入成功的資料的個數;scanf函式的結束通常有3種,遇到空格、回車或者tab鍵為常用的結束方式;或者按照格式控制符的指定來控制結束,如%5d類的格式;遇到非法輸入也會自動結束。

對常用的三種格式,結束符號分別如下:

%d格式輸入,預設分隔符是所有的 white-spaces(空格、回車、製表);

%c格式輸入,則按ascii字元考慮,無分隔符。可能會受到之前輸入的影響,必要時用fflush(stdin);清除緩衝區;

%s 是 字串格式,預設分隔符是所有的 white-spaces,輸入後自動加入結束符"\0"。

繼續上面的由於連續輸入帶來的問題,往深了說,就涉及到緩衝區了。scanf函式是以刪除的方式從緩衝區讀取資料(緩衝區中儲存來自標準輸入的資料)。如果緩衝區是空的,就阻塞之,等待從鍵盤輸入;並且scanf還能對數字輸入忽略先導的空白符,如\n\t和空格等(注意,對字元輸入並不忽略先導字元,這個也是很自然的道理,因為\n\t和空格在字元中都是合法的字元)。

scanf的緩衝機制和對字元的處理方式就造成了scanf對字元%c和字串%s的讀取時的各種意外。比如上面的例子,回頭分析這段**:

輸入了i的值為3然後按回車,當前緩衝區中資料為」3\n」,由回車的作用scanf開始從緩衝區中讀取乙個%d控制的資料,也就是3,此時緩衝區中還剩」\n」;對下乙個scanf函式的格式控制是%c,這個情況下並不忽略先導的空白字元\n,而是直接賦給字元c了。想要檢視緩衝區的內容,stdin[s1] ,如果想要檢視當前stdin中的內容,一般方法都比較忤逆,可以嘗試使用檔案操作freopen將stdin中的資料重定向到另外乙個file*中。這個另闢一文。

如何解決這個緩衝區和字元解析的問題呢?既然緩衝區有我們不需要的東西,那就清除緩衝區。微軟系統中是fflush(stdin)函式可以清除緩衝區,而有的編譯系統並沒有定義對stdin的fflush操作,就把stdin中的資料讀出來:

可以使用fgets()函式,這個函式沒有編譯器的限制;

或者把緩衝區中多餘的東西交給別的函式,如getchar(),具體**為 while( (c = getchar() ) != 『/n』 && c != eof );

上面的方法基於原理,但有點麻煩,尤其是遇到字元%c和字串%s對回車的處理時。c還提供了gets()函式解決了這個問題,gets()函式是不論中間有什麼字元,一律讀進來,直到遇到回車符;

c++中,還可以操作stdin的指標,stdin是乙個file*型別的資料結構,使stdin->_io_read_ptr = stdin->_io_read_end;。但是c中不可以。

scanf和空格鍵

前面就有說,scanf函式,根據格式的不同,對空白字元的處理也不同。%d格式下,對空白字元不敏感,通常都是作為結束符的;對%c來說,對回車符比較敏感,空格的做為乙個普通字元處理的;對%s來說,回車和空格都是當前函式的結束字元,由於緩衝區stdin機制,這裡又要特別注意 空格和回車對%s的影響。

%s預設分隔符是所有的 white-spaces,輸入後自動加入結束符"\0",使其成為乙個字串(之所以加上\0,是和字元陣列char的結束符有關的,c中是沒有string這個型別的,是使用char結構實現字串)。值得注意的是,即使輸入字元的長度足夠,%s是寧願捨棄輸入字元,也要把/0加上去的,作為字串的結束。並且,scanf會忽略緩衝區開頭的空格,知道遇到乙個非空格字元,才開始向記憶體中讀取資料。

比如,我們想要輸入」the c programming language.\n」,中間的空格怎麼處理呢?

其中乙個解決方法是使用gets函式,這個函式是以回車符作為輸入結束的標誌的;還有一種解決方式是:scanf("%[^\n]", c):

char c[15];

scanf("%[^\n]", c[s2] );

只是scanf("%[^\n]", c);和gets這兩種處理方式都是不忽略所有的空格,包括緩衝區開頭的空格;這一點和scanf("%s",c);的處理方式不同,%s的方式,忽略緩衝區開頭的空格。

另:scanf的返回值

scanf()函式返回的值為:正確按指定格式輸入變數的個數;也即能正確接收到值的變數個數。在型別匹配錯誤的時候,以非正常的方式退出。可以利用scanf函式的返回值判斷輸入是否正確,並進行流程控制:

int i = 0;

char c1[15];

while((scanf("%c", &c1[i])!=eof) && i<14)

[s1]stdin是標準輸入,一般針對鍵盤,是個file* 型別的資料。

[s2]這裡注意使用c 還是 &c:

c是個陣列,陣列 即代表了陣列的首位址,所以可以使用c;

scanf(「%s」, c);

C語言中scanf函式與空格回車

1 scanf的返回值 scanf通常返回的是成功賦值 從標準輸入裝置賦值到引數列表所指定的記憶體區域 的資料項數,如果出錯或是遇到end of file 注意,如果想從鍵盤輸入eof,在windows的dos視窗用ctrl z 或f6 在unix系統上,用ctrl d。則返回eof,比如 scan...

C語言中scanf函式與空格回車

scanf 函式有返回值,且返回值是正確讀取的個數 scanf d d x,y scanf是從快取區讀取資料的 scanf對不同型別輸入的處理方式 前提 空格 回車 製表符table都是空白字元 原因是 scanf n s 接收非回車符,一旦碰到回車就停止,然後進入迴圈裡面執行。但是緩衝區裡面的 n...

ios NSString 去除空格和回車

去除兩端空格 nsstring temp textfield.text stringbytrimmingcharactersinset nscharacterset whitespacecharacterset 去除兩端空格和回車 nsstring text temp stringbytrimmin...