2008年12月5日 星期五

C/C++:scanf 格式控制介紹

scanf格式控制的完整格式:
%  *  m  l或h  格式字符
① 格式字符與printf函數中的使用方式相同,以%d、%o、%x、%c、%s、%f、%e,無%u格式、%g格式。

② 可以指定輸入數據所佔列寬,系統自動按它截取所需數據。如:
scanf(「%3d%3d」,&a,&b);
輸入:123456
系統自動將123賦給a,456賦給b。

③ %後的「*」附加說明符,用來表示跳過它相應的數據。例如:
scanf(「%2d%*3d%2d」,&a,&b);
如果輸入如下信息:1234567。將12賦給a,67賦給b。第二個數據」345」被跳過不賦給任何變量。


④ 輸入數據時不能規定精度,例如:
scanf(「%7.2f」,&a);
是不合法的,不能企圖輸入:12345.67而使a的值為12345.67。

輸入數據流分隔
① 根據格式字符的含義從輸入流中取得數據,當輸入流中數據類型與格式字符要求不符時,就認為這一項結束。如:
scanf(「%d%c%f」,&a,&b,&c);
如果輸入如下信息:
1234r1234.567
則scanf函數在接收數據時發現」r」類型不匹配,於是把」1234」轉換成整型賦值給a,把」r」賦給變量b,最後把」1234.567」轉換成實型數據賦給c。

② 根據格式項中指定的域寬分隔出數據項。如語句:scanf(「%2d%3f%4f」,&a,&b,&c);
如果輸入如下信息:
123456789012345
   則scanf函數在接收數據時根據域寬把12賦值給a,345賦值給b,6789賦值給c。

③ 隱示分隔符。空格、跳格符(』\t')、換行符(』\n')都是C語言認定的數據分隔符。

④ 顯示分隔符。在scanf函數的兩個格式說明項間有一個或多個普通字符,那麼在輸入數據時,在兩個數據之間也必須以這一個或多個字符分隔。如語句:
scanf(「a=%d,b=%f,c=%f」,&a,&b,&c);
則輸入數據應該為:
   a=1234,b=67.8,c=98.123

關於scanf函數的進一步說明:
① scanf函數中的「格式控制」後面應當是變量地址,而不應是變量名。例如,如果a、b為整型變量,則
scanf(「%d,%d」,a,b);
是不對的,應將」a,b」改為」&a,&b」。

② 如果在「格式控制」字符串中除了格式說明以外還有其它字符,則在輸入數據時應輸入與這些字符相同的字符。例如:
scanf(「%d,%d」,&a,&b);
輸入時應輸入:3,4。3與4之間的逗號應與scanf函數中的「格式控制」中的逗號相對應,輸入其它符號是不對的。

③ 在用「%c」格式輸入字符時,空格字符和轉義字符都作為有效字符輸入。
scanf(「%c%c%c」,&c1,&c2,&c3);
如輸入:a b c 。字符』a'賦給c1,字符(空格)』 』賦給c2,字符』b' 賦給c3。

④ scanf  中不使用U說明符.對unsigned型數據用d、o、x說明符輸入

[Reading Undelimited strings]
*To read strings not delimited by whitespace characters, a set of characters in brackets ([ ]) can be substituted for the s (string) type character. The set of characters in brackets is referred to as a control string. The corresponding input field is read up to the first character that does not appear in the control string. If the first character in the set is a caret (^), the effect is reversed: The input field is read up to the first character that does appear in the rest of the character set.
*Note that %[a-z] and %[z-a] are interpreted as equivalent to %[abcde...z]. This is a common scanf function extension, but note that the ANSI standard does not require it.

舉一些例子:
對於 const char* p = "12232114687ABC12356";
sscanf(p,"%[123]",buf); // 就把是'1'或'2'或'3'的字讀讀到buf中,直到遇到一個不是'1'且不是'2'且不是'3'的字符,於是執行後buf應該是"1223211";
%[123]等同於%[231],等同於%[321]……,列表中的順序是無所謂的;
%[123]也等同於%[1-3]或%[3-1],也就是「1至3」,對於連續的字符列表這樣寫就很簡單,比如%[a-z]等同%[abc…省略…z];
想想看,%[3-14]應該等同於什麼?是「3至14」嗎?當然不是,因為[]中的是字符,而不是數字,所以%[3-14]應該等同於%[3214],等同於%[1234];
同理,想只取字母,那就可以寫成%[A-Za-z];
如果列表的第一個字母是^,那麼正好相反,比如%[^A-Za-z]的意思就是取字母之外的所有字符。
對於字符串"abDEc123"如果想按照字母和數字讀到兩個字符串中就應該是 "%[a-zA-Z]%[0-9]",buf1,buf2 ;
假 如我想取一行字符,該怎麼辦?"%s"是不行的,因為%s遇到空白字符(空格、製表符、\r、\n)就結束了,所以可以寫成 "%[^\n]%*c",% [^\n]的作用剛才講過了,就是讀\n之外的所有字符,也就是說讀到\n為止,%*c的作用就是把\n去掉,否則再次讀的時候一直遇到的都是\n;
所有對%s起作用的控制,都可以用於%[],比如"%*[^\n]%*c"就表示跳過一行,"%-20[^\n]"就表示讀取\n前20個字符。

※以上並非完整格式介紹,但我想應該算蠻多的了。

沒有留言:

張貼留言