關於scanf的一點彙總

很多人對scanf的不太瞭解,導致程序出錯,我想把scanf的具體用法貼出來,希望大家可以共同進步,有什麼不對的地方可以提出來。
int scanf(char *format,...);
這應該是scanf的標準形式。先說說關於他的返回值的問題。
庫函數幾乎都是有返回值的,有些人可能很奇怪,怎麼很少人用過scanf的返回值呢?
scanf會返回成功接收到的變量數量的值。比如scanf("%d",&j"),與scanf("%d=",&j),如果接受成功的話返回值都是1
我用如下語句作了測試
#include <stdio.h>
int main (){
int j;
printf ("%d",scanf("%d\n",&j));
return 0;
}
如果你開始就輸入回車,程序會繼續等待你輸入,因爲在輸入數字的時候,scanf會跳過空白字符。(the c programming language 上說,scanf實際上是用getchar()接受由數字組成的字符串,再轉換成數字)
如果我輸入ctrl-z(unix上是ctrl-d)則會返回-1(隨編譯器而定).這實際上就是常量EOF的值,也就是所謂的返回eof
如果我鍵入的不是數字返回值就是0。但是如果我輸入浮點數,又會怎麼樣呢?
我舉的例子中同樣會返回1,但是緩衝區會留下垃圾,如果是scanf("%d%d",&a,&b);則會出錯。
這是可以使用一個庫函數fflush(stdin)來清除緩衝。不過貌似這個用法是非標準的。K&R,只是說行爲沒有定義,但我們可以使用while((c=getchar())!='\n'&&c!=EOF);同樣可以清除後面的垃圾
scanf的格式匹配還是比較簡單,一定要記住的就是普通變量一定要加上&,否則編譯器無法檢測錯誤,但運行肯定會段錯誤。
┏━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ 代 碼 │ 意 義 ┃
┠────┼────────────────────────────┨
┃ %a │讀浮點值(僅適用於 C99) ┃
┃ %A │讀浮點值(僅適用於 C99) ┃
┃ %c │讀單字符 ┃
┃ %d │讀十進制整數 ┃
┃ %i │讀十進制、八進制、十六進制整數 ┃
┃ %e │讀浮點數 ┃
┃ %E │讀浮點數 ┃
┃ %f │讀浮點數 ┃
┃ %F │讀浮點數(僅適用於 C99) ┃
┃ %g │讀浮點數 ┃
┃ %G │讀浮點數 ┃
┃ %o │讀八進制數 ┃
┃ %s │讀字符串 ┃
┃ %x │讀十六進制數 ┃
┃ %X │讀十六進制數 ┃
┃ %p │讀指針值 ┃
┃ %n │至此已讀入值的等價字符數 ┃
┃ %u │讀無符號十進制整數 ┃
┃ %[ ] │掃描字符集合 ┃
┃ %% │讀 % 符號(百分號) ┃
┗━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
前面都很簡單,%p,%n很少用到,跳過。要輸入%必須要在前面再加一個%,
重點來談談%s和%[]。%s是讀入一個數組,他與gets的區別就在於%s會以任何的空字符結束,而gets是回車結束。
同樣%s前可以加數字,表示只讀多少個。
ANSI C 標準向 scanf() 增加了一種新特性,稱爲掃描集(scanset)。 掃描集定義一個字符集合,可由 scanf() 讀入其中允許的字符並賦給對應字符數組。 掃描集合由一對方括號中的一串字符定義,左方括號前必須綴以百分號。 例如,以下的掃描集使 scanf() 讀入字符 A、B 和 C:
%[ABC]
使用掃描集時,scanf() 連續吃進集合中的字符並放入對應的字符數組,直到發現不在集合中的字符爲止(即掃描集僅讀匹配的字符)。返回時,數組中放置以 null 結尾、由讀入字符組成的字符串。
對於許多實現來說,用連字符可以說明一個範圍。 例如,以下掃描集使 scanf() 接受字母 A 到 Z:
%[A-Z]
重要的是要注意掃描集是區分大小寫的。因此,希望掃描大、小寫字符時,應該分別說明大、小寫字母。
對於%[]還可以用^+任意字符(包括eof)來結束字符串的輸入。比如%[^EOF]就是直到有EOF輸入,字符串才中止。
但一定要記住就是c語言是緩衝輸入,即使你%[^a],再你輸入回車之前輸入多少的a都是不可能結束的。
%s的輸入會跳過空白字符,但是%c則不會。往往在輸入多種類別的數值(整形,浮點,字符)%C很容易出問題。
這也就是
scanf("%d",&h);
scanf("%c",&c);
如果這寫的話,變量c放的一定是回車。
如果想實現這種輸入,可以在兩個語句之間加入一個getchar(),他可以吃掉這個回車,
也可用scanf("%d %c",&h,&c);來做,再輸入數字後加一個空格。就可以了
但千萬別用scanf("%d\n",&h)!!!!!!!!k&r說的十分清楚,任何非格式化的字符都需要完全匹配。
意味着,只有輸入數字後面再加\n纔是合法的。
還有就是*加在任何項的前面表示該項不符值。

如何讓scanf()函數正確接受有空格的字符串?如: I love you!

#include <stdio.h>

int main()

{

  char str[80];

  scanf("%s", str);

  printf("%s", str);

  return 0;

}  

輸入:I love you 

上述程序並不能達到預期目的,scanf()掃描到"I"後面的空格就認爲對str的賦值結束,並忽略後面的"love you".這裏要注意是"love you"還在鍵盤緩衝區(關於這個問題,網上我所見的說法都是如此,但是,我經過調試發現,其實這時緩衝區字符串首尾指針已經相等了,也就是說緩衝區清空了,scanf()函數應該只是掃描stdin流,這個殘存信息是在stdin中)。我們改動一下上面的程序來驗證一下:  

#include <stdio.h>  

#include<windows.h>  

int main()  

{

  char str[20], str1[20], str2[20];

  scanf("%s", str); /* 此處輸入:I love you */

  printf("%s\n", str);

  sleep(3); /* 這裏等待3秒,告訴你程序運行到什麼地方 */

  scanf("%s", str1); /* 這兩句無需你再輸入,是對stdin流再掃描 */

  scanf("%s", str2); /* 這兩句無需你再輸入,是對stdin流再掃描 */

  printf("%s\n", str1);

  printf("%s\n", str2);

  return 0;  

}  

輸入:I love you 

輸出:

I

love

you

  好了,原因知道了,所以結論是:殘留的信息love you是存在於stdin流中,而不是在鍵盤緩衝區中。那麼scanf()函數能不能完成這個任務?回答是:能!別忘了scanf()函數還有一個 %[ ] 格式控制符。請看下面的程序:  

#include <stdio.h>  

int main( )  

{

  char str[50];

  scanf("%[^\n]", str); //輸入I love you

  printf("%s\n", str);

  return 0;  

}

輸出

I love you

%[^\n]表示從stdin流中讀到'\n'才結束('\n'並沒有讀取到str中)

#include <stdio.h>  

int main( )  

{

  char str[50], c[50];

  scanf("%[^c]", str); // 輸入abcdefg

  printf("%s\n", str);

  scanf("%[^\n]",c); //這兩句無需再輸入,是對stdin流再掃描

  printf("%s\n",c);

  return 0;  

}

輸出

ab

cdefg

 

發佈了46 篇原創文章 · 獲贊 102 · 訪問量 47萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章