基本說明
- 功能: 按用戶指定的格式從鍵盤上把數據輸入到指定的變量之中。
- 頭文件:
#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的一些總結, 雖然平時使用的很簡單,但是總感覺不太踏實,因爲總時不時的出錯。這次記錄一下學習收穫挺大的。