scanf()函數總結

基本說明


  • 功能: 按用戶指定的格式從鍵盤上把數據輸入到指定的變量之中。
  • 頭文件:#include <stdio.h>
  • 標準格式:scanf("<控制串>",變量地址) 輸入一個整數:scanf("%d",&a);
  • 返回值:scanf()函數返回成功賦值的數據項數,讀到文件末尾出錯時則返回EOF。(後面詳解)

實例


返回值
scanf函數就是返回正確輸入的數據個數,返回值int型,以下代碼說明:

#include <stdio.h>
int main()
{
    int a,b,c;
    c=scanf("%d%d",&a,&b);
    printf("%d",c);
}
輸入 輸出
1 2 2
1 a 1
a b 0

如果遇到錯誤或遇到end of file,返回值爲EOF,所以經常見到

while(scanf("%d",&a)!=EOF)

控制串說明


控制串有三種類型:格式說明符(也是最常用的)、空白符,非空白符

1.經常使用的格式說明符就不多說了,比如輸入一個整數一個字符

scanf("%d%c",&a,&c);

比如鍵入 1x 那麼就將1賦值給變量a 將’x’賦值給變量c。


2.空白符


空白字符會使scanf()函數在讀操作中略去輸入中的一個或多個空白字符。
其中空白字符包括space,tab,newline等等。比如

 scanf("%d%d",&a,&b);
 printf("%d %d",a,b);

若輸入10 20 則就將10賦給a ,20 賦給b , 輸入時候的空格則忽略;
注:如果格式是字符 char的話,空格或者轉義字符會被當做普通字符:

int a;char c;
scanf("%d%c",&a,&c);
printf("%d%c",a,c);

若輸入10 a 輸出將會是10 而不是10 a 這是因爲空格賦值給了c
'a' 則繼續留在緩衝區內,如果再下面再加一句scanf("%c",&c) (不用再次輸入),那麼此時c的值就是'a'
本質上,控制串中的空白符使 scanf() 在輸入流中讀,但不保存結果,直到發現非空白字符爲止。

3.非空白符[過濾]


非空白字符會使scanf()函數在讀入時剔除掉與這個非空白字符相同的字符;這個在實際應用中挺常用的;
1,比如我想輸入的字符串是’a=2 b=3’,而且還需要將a,b賦值成2,3,,可以這樣實現。

scanf("a=%db=%d",&a,&b);

這樣輸入的時候直接輸入a=2b=3 scanf()就會自動剔除掉不需要的字符,而將2賦值給a,3賦值給b
這裏空格space,同樣可以使用

scanf("%d %d",&a,&b)

這樣同樣可以實現空格輸入:輸入10 20 同,space將相當於一個普通字符。
2, 寬度設置
在百分號(%)與格式碼之間的整數用於限制從對應域讀入的最大字符數。例如,希望向name 讀入不多於 10個字符時,可以書寫成如下形式:

scanf("%10s",name);

如果輸入流的內容多於 10 個字符,則下次 scanf() 從此次停止處開始讀入。 若達到最大域寬前已遇到空白符,則對該域的讀立即停止;此時,scanf() 跳到下一個域。

3,省略指定的數據類型*符號
比如

scanf("%d%*c%d",&a,&b); 

比如輸入10a20,得到的是a=10,b=20
再如

char c[20];
scanf("%*s%s",&c);
printf("%s",c);

若輸入"hello, world" 則會輸出world 因爲world之前的space終止了%*s.
注:%是選擇滿足條件的,%* 是過濾掉滿足條件的。可以配合下面所說的掃描集使用。


4.scanf的”正則表達式”—掃描集
掃描集定義一個字符集合,可由 scanf() 讀入其中允許的字符並賦給對應字符數組。 掃描集合由一對方括號中的一串字符定義,左方括號前必須綴以百分號。
遇到不屬於掃描集的結束;有點像正則表達式,其實用法也很類似。
比如 :

char s[10];
scanf("%[abc]",s);
輸入 輸出
abc abc
bc bc
abdf ab
abdcb ab

就類似一個過濾。
下面是一些常用符號:
- ^表示補集: %[^abc] 遇到abc停止
- ‘-‘表示區間: %[A-Z] A-Z範圍
- %[^\n] 表示可以吸收空格,回車結束;

char s[10];
scanf("%s",s);
printf("%s",s);

比如輸入的是'I love you'那麼輸出的s 是I, 而不是I love you
因爲空格作爲了分隔符。
而想要吸收空格可以用 掃描集

char s[10];
scanf("%[^\n]",s);
printf("%s",s);

表示只有輸入回車才結束
此時再輸入 I love you 將完整輸出 I love you

再看一個例子:
要去出一個郵箱的域名,經常用正則,那麼這裏用scanf的該怎麼使用呢?

char s[30];
scanf("%*[^@]@%[^\.]",s);
printf("%s",s);

這個可以 輸入[email protected] 輸出就會是 gmail;
首先分成三部分%*[^@]@%[^\.] ;
%*[^@] 表示過濾前面的不是@的部分,這部分讀取到了mymail 但是不保存到變量 s。第二部分@ 是指過濾掉 緩存區中的 @ 字符。 最後一部分%[^\.] 則表示選擇不是.的部分,對應字符串中的gmail部分,並且賦值給s。
注:
1. 在scanf()正則裏面 最多只能有一個%表示選擇。而過濾%*可以有多個
2. 上述所講的正則規則 與sscanf()函數完全適用。只不過是輸入方式不同。
其實 scanf()用正則比較少。sscanf()就比較常用了。很方便的處理字符串。


5.scanf()緩衝區問題總結

int a;
char c;
scanf("%d",&a);
scanf("%c",&c);
printf("a=%d  c=%c",a,c);

比如輸入20 a 那麼輸出將會是 20和一個空格[前面已經提到過]
如果打算想 輸入20之後 回車再輸入’a’ 結果會是輸入回車之後 就會輸出。這時候如果輸入c的ASCII碼值就會發現是 10 正好是\n
這樣就對了,\n被scanf()函數“錯誤”地賦給了c;
常見的解決方法:
1. 在第一個scanf()之後加入getchar()函數可以消掉回車。具體原理還不太懂。。
2. 還有就是利用fflush(stdin); 刷新或者清空緩衝區,這樣輸入一個20之後 按回車的話就可以,繼續輸入字符 賦值給c,如下:

#include <stdio.h>
int main()
{
    int a,b;
    char c;
    scanf("%d",&a);
    fflush(stdin);
    scanf("%c",&c);
    printf("a=%d c=%d\n",a,c);
}

這樣就可以了。

上面是學了以scanf的一些總結, 雖然平時使用的很簡單,但是總感覺不太踏實,因爲總時不時的出錯。這次記錄一下學習收穫挺大的。

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