(1)簡介:
scanf函數是c語言當中非常重要的格式化輸入函數
其函數原型為:int scanf(const char *format, ...);
其函數返回值:成功格式化解析的個數
其調用格式為:scanf("<格式化字符串>", <參量表>);
(2)轉換說明:
轉換格式為:%[*][寬度][類型長度]類型
除了最后的類型之外都是可選的字段
修飾符 | 意義 |
* | 滯后賦值;示例:"%*d" |
digit(s) | z最大字段寬度;在達到最大字段寬度或者遇到第一個空白字符時(不管哪個先發生都一樣)停止對輸入項的讀取;示例:"%10s" |
hh | b把整數讀作signed char或unsigned char;示例:"%hhd" "%hhu" |
ll | b把整數讀作long long或unsigned long long(c99);示例:"%lld" "%llu" |
h,l或L | "%hd"和"%hi"指示該值將會儲存在一個short int中。"%ho"、"%hx"和"%hu"指示該值將會儲存在一個unsigned short int中。"%ld"和"%li"指示該值將會儲存在一個long中。"%lo"、"%lx"和"%lu"指示該值將會儲存在一個unsigned long中。"%le"、"%lf"和"%lg"指示該值以double類型儲存。將L(而非l)與e、f和g一起使用指示該值以long double類型儲存。如果沒有這些修飾符,d、i、o和x指示int類型,而e、f和g指示float類型; |
轉換說明符 | 意義 |
%c | 把輸入解釋稱一個字符 |
%d | 把輸入解釋稱一個有符號十進制整數 |
%e,%f,%g,%a | 把輸入解釋稱一個浮點數(%a是c99標准) |
%E,%F,%G,%A | 把輸入解釋稱一個浮點數(%A是c99標准) |
%i | 把輸入解釋稱一個有符號十進制整數 |
%o | 把輸入解釋稱一個有符號八進制整數 |
%p | 把輸入解釋稱一個指針(一個地址) |
%s | 把輸入解釋稱一個字符串,輸入內容以第一個非空白字符作為開始,並且包含直到下一個空白字符的全部字符 |
%u | 把輸入解釋稱一個無符號十進制整數 |
%x,%X | 把輸入解釋稱一個無符號十六進制整數 |
[] | 字符集合 |
(3)高級用法:
網上已經有很多博客將scanf的常用方法說的非常詳細了,本篇博客不再詳細介紹。
1。捕獲規則
在出現一個轉換說明符時,scanf函數會忽略前面的所有空白字符(除了%c),然后再捕獲相應的數據類型,一直到最大長度或者出現空白字符
scanf("%d,%d", &a, &b);
允許的輸入格式為:1,2\n;1, 2\n;1,\n2\n;
不允許的輸入格式:1 ,2\n; \n1,2\n; 1,2\n;
2。%[] 字符集合
這個算scanf函數中比較高級一點的用法
[]里面填寫需要捕獲的字符集合,例如
char buf[20];
scanf("%[abc]", buf); //輸入abcdabcd123, buf內容為abc
scanf函數匹配[]中的所有字符,直到找到一個非[]中的字符
[]中也可以填寫字符范圍,例如
[a-z] //捕獲包括字符從a到z的所有字符,直到找到一個非a-z的字符
[a-zA-Z] //捕獲所有字母
[0-9] //捕獲所有數字
[a-zA-Z0-9]捕獲所有字母和數字
[a-zA-Z0-9!]捕獲所有字母和數字並且捕獲!(感嘆號)
[]中如果第一字符為^符號則表示出現[]中的內容則停止捕獲,例如
[^a-zA-Z]捕獲非字母
[^0-9]捕獲非數字
3。scanf中的空格和\n
scanf中的空格的作用不僅僅是捕獲一個空格,它表示捕獲所有空白字符(空格,換行,制表符等)直到出現一個非空白字符(\n一樣),例如
我們想接受一個ip:端口的輸入
需要接受的輸入格式為:ip:端口,ip: 端口,ip : 端口,ip\n:\n端口
如果代碼為scanf("%d.%d.%d.%d:%d", &ip[0], &ip[1], &ip[2], &ip[3], &port);
則只能捕獲的格式:ip:端口,ip: 端口,ip:\n端口
如果我們將代碼改為scanf("%d.%d.%d.%d :%d", &ip[0], &ip[1], &ip[2], &ip[3], &port); // : 前面多了一個空格
則可以捕獲上述所有情況
4。scanf中的混合輸入字符和數字
在scanf當中混合輸入字符和數字是一個比較煩人的問題
如果我們直接編寫代碼為
1 #include <stdio.h> 2 3 int main() { 4 char ch; 5 int num; 6 7 while(scanf("%c%d", &ch, &num) == 2) { 8 printf("*%c*, *%d*\n", ch, num); 9 } 10 return 0; 11 }
第一次scanf("%c%d");沒有任何問題
第二次scanf("%c%d");字符會將上一次的\n給解析進來,就會出現了問題
解決方案1:
#include <stdio.h> int main() { char ch; int num; while(scanf("%c%d", &ch, &num) == 2) { printf("*%c*, *%d*\n", ch, num); while(getchar() != '\n'); //清除上次輸入殘留的\n } return 0; }
解決方案2:
#include <stdio.h> int main() { char ch; int num; while(scanf(" %c%d", &ch, &num) == 2) { //前面加一個空格忽略所有空白字符 printf("*%c*, *%d*\n", ch, num); } return 0; }
未定義的方案(官方文檔未定義,勿用):
#include <stdio.h> int main() { char ch; int num; while(scanf("%c%d", &ch, &num) == 2) { printf("*%c*, *%d*\n", ch, num); fflush(stdin); //flush標准輸入流 } return 0; }