前言
今天看到博友發了個有關scanf的使用的注意事項,就是討論緩沖區殘存數據的問題,用簡單的代碼示例復述一下:
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
int a;
char b;
scanf("%d", &a);
scanf("%c", &b);
printf("a = %d , b = %d\n", a, b);
system("pause");
return 0;
}
你或許碰到這個輸出:
5
a = 5 , b = 10
請按任意鍵繼續. . .
我明明想輸入個5,然后回車輸入下一個字符,但是,回車符也是個字符,會被scanf進去,絕大多數人的解決方案就是提前把這個字符讀取走,但是如果緩沖區的東西太多的話,需要加個循環,才能處理,下面我來介紹scanf的高級用法,之間研究過,忘記在哪里看到的,這個是我總結的,那些基礎用法自己看看書就行了。
清空緩存區
我先把清空緩沖區的代碼放上,因為后面的代碼都會用到,至於為什么后面會有詳細介紹:
scanf("%*[^\n]"); //清除到回車符的所有字符
scanf("%*c"); //清除回車符
指定輸入長度
我們都知道scanf可以指定小數位數和長度,如下是代碼示例:
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
int n;
float f;
char str1[23];
scanf("%2d", &n);
//清空緩沖區代碼{
scanf("%*[^\n]");
scanf("%*c");
//}
scanf("%5f", &f);
//清空緩沖區代碼{
scanf("%*[^\n]");
scanf("%*c");
//}
scanf("%5s", str1);
puts("執行后:");
printf("n=%d, f=%g, str=%s\n", n, f, str1);
system("pause");
return 0;
}
如下是輸入和輸出結果:
5653 12
2.56458452 2356.9999
helloworld
執行后:
n=56, f=2.564, str=hello
請按任意鍵繼續. . .
看到沒,清空緩沖區的代碼有效果了,如果沒有這行清空緩沖區的代碼,就會成這樣子:
5653 12
執行后:
n=56, f=53, str=12
請按任意鍵繼續. . .
這就是清除緩沖區的作用。
單范圍匹配
不要驚訝,scanf也是支持類似正則表達式的功能的,我們用如下代碼進行演示:
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
char str2[30];
scanf("%[abcd]", str2); //%[abcd]表示只要字符串只有 a,b,c,d 范圍內就匹配
puts("執行后:");
printf("%s\n", str2);
system("pause");
return 0;
}
如下是輸入和輸出結果:
babccbaxyz
執行后:
babccba
請按任意鍵繼續. . .
代碼中的注釋可能說的不明白,這里我長篇大論一下:字符串從開頭開始匹配,必須字符串只有abcd中這四個字符任意一個才有效,如果開頭沒有這四個字符,則匹配為空。
多范圍匹配
既然支持單范圍了,肯定也支持多范圍,什么是多范圍匹配可以先看看一些基礎示例,如果會正則表達式的話很容易懂:
- %[a-z]表示讀取 abc...xyz 范圍內的字符,也即小寫字母;
- %[A-Z]表示讀取 ABC...XYZ 范圍內的字符,也即大寫字母;
- %[0-9]表示讀取 012...789 范圍內的字符,也即十進制數字;
- %[a-zA-Z]表示讀取大寫字母和小寫字母,也即所有英文字母;
- %[a-z-A-Z0-9]表示讀取所有的英文字母和十進制數字;
- %[0-9a-f]表示讀取十六進制數字
如果經常使用的話也就這些類型,如下是代碼示例:
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
char str3[30];
scanf("%[a-zA-Z]", str3); //只讀取字母
puts("執行后:");
printf("%s\n", str3);
system("pause");
return 0;
}
如下是輸入和輸出結果:
abcXYZ123abcXYZ123
執行后:
abcXYZ
請按任意鍵繼續. . .
不匹配某些字符
既然有匹配的字符,肯定有不想匹配的字符。對於不匹配某些字符,scanf允許我們在%[ ]中直接指定某些不能匹配的字符,具體方法就是在不匹配的字符前面加上^,給幾個例子:
- %[^\n]表示匹配除換行符以外的所有字符,遇到換行符就停止讀取;
- %[^0-9]表示匹配除十進制數字以外的所有字符,遇到十進制數字就停止讀取。
如下是代碼示例:
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
char str11[30], str12[30];
scanf("%[^0-9]", str11);
scanf("%*[^\n]");
scanf("%*c"); //清空緩沖區
scanf("%[^\n]", str12); //等效為gets()
puts("執行后:");
printf("str1=%s \nstr2=%s\n", str11, str12);
system("pause");
return 0;
}
如下是輸入和輸出結果:
abcXYZ@#87edf
Cnblog wingsummer
執行后:
str1=abcXYZ@#
str2=Cnblog wingsummer
請按任意鍵繼續. . .
丟棄數據
scanf還允許把讀取到的數據直接丟棄,不往變量中存放,具體方法就是在%后面加一個*,如下是代碼示例:
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
int nn;
char str[30];
scanf("%*d %d", &nn);
scanf("%*[a-z]");
scanf("%[^\n]", str);
puts("執行后:");
printf("n=%d, str=%s\n", nn, str);
system("pause");
return 0;
}
如下是輸入和輸出結果:
100 999abcxyzABCXYZ
執行后:
n=999, str=ABCXYZ
請按任意鍵繼續. . .
