關于標準庫函數scanf
論壇上很多人對scanf的不太了解,導致程序出錯,我想把scanf的具體用法貼出來,希望大家可以共同進步,有什么不對的地方可以提出來。
int scanf(char *format,...);
這應該是scanf的標準形式。先說說關于他的返回值的問題。
庫函數幾乎都是有返回值的,有些人可能很奇怪,怎么很少人用過scanf的返回值呢?
scanf會返回成功接收到的變量數量的值。比如scanf("%d",&j"),與scanf("%d=",&j),如果接受成功的話返回值都是1
我用如下語句作了測試
#include <stdio.h>
int main (){
????int j;
????printf ("%d",scanf("%d\n",&j));
????return 0;
}
如果你開始就輸入回車,程序會繼續等待你輸入,因為在輸入數字的時候,scanf會跳過空白字符。(the c programming language 上說,scanf實際上是用getchar()接受由數字組成的字符串,再轉換成數字)
如果我輸入ctrl-z(unix上是ctrl-d)則會返回-1(隨編譯器而定).這實際上就是常量EOF的值,也就是所謂的返回eof
如果我鍵入的不是數字返回值就是0。但是如果我輸入浮點數,又會怎么樣呢?
我舉的例子中同樣會返回1,但是緩沖區會留下垃圾,如果是scanf("%d%d",&a,&b);則會出錯。
這是可以使用一個庫函數fflush(stdin)來清除緩沖。不過貌似雨中飛燕大姐說這個用法是非標準的。K&R,只是說行為沒有定義,但我們可以使用while((c=getchar())!='\n'&&c!=EOF);同樣可以清除后面的垃圾
scanf的格式匹配還是比較簡單,一定要記住的就是普通變量一定要加上&,否則編譯器無法檢測錯誤,但運行肯定會段錯誤。
??? ┏━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
??? ┃ 代??碼 │???????????? 意??????????????????????????義???????????? ┃
??? ┠────┼────────────────────────────┨
??? ┃???%a???│讀浮點值(僅適用于 C99)????????????????????????????????? ┃
??? ┃???%A???│讀浮點值(僅適用于 C99)????????????????????????????????? ┃
??? ┃???%c???│讀單字符????????????????????????????????????????????????┃
??? ┃???%d???│讀十進制整數????????????????????????????????????????????┃
??? ┃???%i???│讀十進制、八進制、十六進制整數??????????????????????????┃
??? ┃???%e???│讀浮點數????????????????????????????????????????????????┃
??? ┃???%E???│讀浮點數????????????????????????????????????????????????┃
??? ┃???%f???│讀浮點數????????????????????????????????????????????????┃
??? ┃???%F???│讀浮點數(僅適用于 C99)????????????????????????????????? ┃
??? ┃???%g???│讀浮點數????????????????????????????????????????????????┃
??? ┃???%G???│讀浮點數????????????????????????????????????????????????┃
??? ┃???%o???│讀八進制數????????????????????????????????????????????? ┃
??? ┃???%s???│讀字符串????????????????????????????????????????????????┃
??? ┃???%x???│讀十六進制數????????????????????????????????????????????┃
??? ┃???%X???│讀十六進制數????????????????????????????????????????????┃
??? ┃???%p???│讀指針值????????????????????????????????????????????????┃
??? ┃???%n???│至此已讀入值的等價字符數????????????????????????????????┃
??? ┃???%u???│讀無符號十進制整數??????????????????????????????????????┃
??? ┃??%[ ]??│掃描字符集合????????????????????????????????????????????┃
??? ┃???%%???│讀 % 符號(百分號)???????????????????????????????????????┃
??? ┗━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
前面都很簡單,%p,%n很少用到,跳過。要輸入%必須要在前面再加一個%,
重點來談談%s和%[]。%s是讀入一個數組,他與gets的區別就在于%s會以任何的空字符結束,而gets是回車結束。
同樣%s前可以加數字,表示只讀多少個。
ANSI C 標準向 scanf() 增加了一種新特性,稱為掃描集(scanset)。 掃描集定義一個字符集合,可由 scanf() 讀入其中允許的字符并賦給對應字符數組。 掃描集合由一對方括號中的一串字符定義,左方括號前必須綴以百分號。 例如,以下的掃描集使 scanf() 讀入字符 A、B 和 C:
??? %[ABC]
使用掃描集時,scanf() 連續吃進集合中的字符并放入對應的字符數組,直到發現不在集合中的字符為止(即掃描集僅讀匹配的字符)。返回時,數組中放置以 null 結尾、由讀入字符組成的字符串。
對于許多實現來說,用連字符可以說明一個范圍。 例如,以下掃描集使 scanf() 接受字母 A 到 Z:
%[A-Z]
重要的是要注意掃描集是區分大小寫的。因此,希望掃描大、小寫字符時,應該分別說明大、小寫字母。
對于%[]還可以用^+任意字符(包括eof)來結束字符串的輸入。比如%[^EOF]就是直到有EOF輸入,字符串才中止。
但一定要記住就是c語言是緩沖輸入,即使你%[^a],再你輸入回車之前輸入多少的a都是不可能結束的。
%s的輸入會跳過空白字符,但是%c則不會。
這也就是
scanf("%d",&h);
scanf("%c",&c);
如果這寫的話,變量c放的一定是回車。
如果想實現這種輸入,可以在兩個語句之間加入一個getchar(),他可以吃掉這個回車,
也可用scanf("%d %c",&h,&c);來做,再輸入數字后加一個空格。就可以了
但千萬別用scanf("%d\n",&h)!!!!!!!!k&r說的十分清楚,任何非格式化的字符都需要完全匹配。
意味著,只有輸入數字后面再加\n才是合法的。
還有就是*加在任何項的前面表示該項不符值,別的就沒什么好說的了
Read formatted data from the standard input stream.
int scanf(
???const char* format [,argument]...
);
int wscanf(
???const wchar_t* format [,argument]...
);
Parameters
format
Format control string.
argument
Optional arguments.
Return Values
Both scanf and wscanf return the number of fields converted and assigned; the return value does not include fields that were read but not assigned.
A return value of 0 indicates that no fields were assigned.
The return value is EOF for an error or if the end-of-file character or the end-of-string character is encountered in the first attempt to read a character.
Remarks
The scanf function reads data from the standard input stream stdin and writes the data into the location given by argument.
Each argument must be a pointer to a variable of a type that corresponds to a type specifier in format.
If copying takes place between strings that overlap, the behavior is undefined.
The information here applies to the entire scanf family of functions, including the secure versions and describes the symbols used to tell the scanf functions how to parse the input stream, such as the input stream stdin for scanf, into values that are inserted into program variables.
A format specification has the following form:
% [width] [{h | l | ll | I64 | L}]type
The format argument specifies the interpretation of the input and can contain one or more of the following:
White-space characters: blank (' '); tab ('\t'); or newline ('\n'). A white-space character causes scanf to read, but not store, all consecutive white-space characters in the input up to the next non–white-space character. One white-space character in the format matches any number (including 0) and combination of white-space characters in the input.
Non–white-space characters, except for the percent sign (%). A non–white-space character causes scanf to read, but not store, a matching non–white-space character. If the next character in the input stream does not match, scanf terminates.
Format specifications, introduced by the percent sign (%). A format specification causes scanf to read and convert characters in the input into values of a specified type. The value is assigned to an argument in the argument list.
The format is read from left to right. Characters outside format specifications are expected to match the sequence of characters in the input stream; the matching characters in the input stream are scanned but not stored. If a character in the input stream conflicts with the format specification, scanf terminates, and the character is left in the input stream as if it had not been read.
When the first format specification is encountered, the value of the first input field is converted according to this specification and stored in the location that is specified by the first argument. The second format specification causes the second input field to be converted and stored in the second argument, and so on through the end of the format string.
An input field is defined as all characters up to the first white-space character (space, tab, or newline), or up to the first character that cannot be converted according to the format specification, or until the field width (if specified) is reached. If there are too many arguments for the given specifications, the extra arguments are evaluated but ignored. The results are unpredictable if there are not enough arguments for the format specification.
Each field of the format specification is a single character or a number signifying a particular format option. The type character, which appears after the last optional format field, determines whether the input field is interpreted as a character, a string, or a number.
The simplest format specification contains only the percent sign and a type character (for example, %s). If a percent sign (%) is followed by a character that has no meaning as a format-control character, that character and the following characters (up to the next percent sign) are treated as an ordinary sequence of characters, that is, a sequence of characters that must match the input. For example, to specify that a percent-sign character is to be input, use %%.
An asterisk (*) following the percent sign suppresses assignment of the next input field, which is interpreted as a field of the specified type. The field is scanned but not stored.
function
scanf
<cstdio>
int scanf ( const char * format, ... );
Read formatted data from stdin
Reads data from
stdin and stores them according to the parameter
format into the locations pointed by the additional arguments. The additional arguments should point to already allocated objects of the type specified by their corresponding format tag within the
format string.
Parameters
format- C string that contains one or more of the following items:
- Whitespace character: the function will read and ignore any whitespace characters (this includes blank spaces and the newline and tab characters) which are encountered before the next non-whitespace character. This includes any quantity of whitespace characters, or none.
- Non-whitespace character, except percentage signs (%): Any character that is not either a whitespace character (blank, newline or tab) or part of a format specifier (which begin with a% character) causes the function to read the next character from stdin, compare it to this non-whitespace character and if it matches, it is discarded and the function continues with the next character offormat. If the character does not match, the function fails, returning and leaving subsequent characters ofstdin unread.
- Format specifiers: A sequence formed by an initial percentage sign (%) indicates a format specifier, which is used to specify the type and format of the data to be retrieved fromstdin and stored in the locations pointed by the additional arguments. A format specifier follows this prototype:
%[*][width][modifiers]type
where:
* | An optional starting asterisk indicates that the data is to be retrieved fromstdin but ignored, i.e. it is not stored in the corresponding argument. |
width | Specifies the maximum number of characters to be read in the current reading operation |
modifiers | Specifies a size different from int (in the case of d, i and n), unsigned int (in the case of o, u andx) or float (in the case of e, f and g) for the data pointed by the corresponding additional argument: h : short int (for d, i and n), orunsigned short int (for o, u and x) l : long int (for d, i and n), orunsigned long int (for o, u and x), or double (fore, f and g) L : long double (for e, f and g) |
type | A character specifying the type of data to be read and how it is expected to be read. See next table. |
scanf type specifiers: type | Qualifying Input | Type of argument |
---|
c | Single character: Reads the next character. If a width different from 1 is specified, the function readswidth characters and stores them in the successive locations of the array passed as argument. No null character is appended at the end. | char * |
d | Decimal integer: Number optionally preceded with a + or- sign. | int * |
e,E,f,g,G | Floating point: Decimal number containing a decimal point, optionally preceded by a+ or - sign and optionally folowed by the e or E character and a decimal number. Two examples of valid entries are -732.103 and 7.12e4 | float * |
o | Octal integer. | int * |
s | String of characters. This will read subsequent characters until a whitespace is found (whitespace characters are considered to be blank, newline and tab). | char * |
u | Unsigned decimal integer. | unsigned int * |
x,X | Hexadecimal integer. | int * |
additional arguments- The function expects a sequence of references as additional arguments, each one pointing to an object of the type specified by their corresponding%-tag within the format string, in the same order.
For each format specifier in the format string that retrieves data, an additional argument should be specified.
These arguments are expected to be references (pointers): if you want to store the result of afscanf operation on a regular variable you should precede its identifier with thereference operator, i.e. an ampersand sign (&), like in:
int n;
scanf ("%d",&n);
Return Value
On success, the function returns the number of items successfully read. This count can match the expected number of readings or fewer, even zero, if a matching failure happens.
In the case of an input failure before any data could be successfully read, EOF is returned.
Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| /* scanf example */
#include <stdio.h>int main ()
{char str [80];int i;printf ("Enter your family name: ");scanf ("%s",str); printf ("Enter your age: ");scanf ("%d",&i);printf ("Mr. %s , %d years old.\n",str,i);printf ("Enter a hexadecimal number: ");scanf ("%x",&i);printf ("You have entered %#x (%d).\n",i,i);return 0;
} |
This example demonstrates some of the types that can be read with
scanf:
Enter your family name: Soulie
Enter your age: 29
Mr. Soulie , 29 years old.
Enter a hexadecimal number: ff
You have entered 0xff (255).
scanf函數,與printf函數一樣,都被定義在stdio.h里,因此在使用scanf函數時要加上#include<stdio.h>。它是格式輸入函數,即按用戶指定的格式從鍵盤上把數據輸入到指定的變量之中,其關鍵字最末一個字母f即為“格式”(format)之意。
[編輯本段]scanf函數的一般形式
scanf(格式控制,地址表列)
int scanf(char *format[,argument,...]);
“格式控制”的含義同printf函數;“地址表列”是由若干個地址組成的表列,可以是變量的地址,或字符串首地址。
scanf()函數返回成功賦值的數據項數,出錯時則返回EOF。
例:使用scanf函數輸入數據。
#include<stdio.h>
void main()
{
int a,b,c;
printf("input a,b,c/n");
scanf("%d%d%d",&a,&b,&c);
printf("a=%d,b=%d,c=%d",a,b,c);
}
格式字符說明
%a,%A 讀入一個浮點值(僅C99有效)
%c 讀入一個字符
%d 讀入十進制整數
%i 讀入十進制,八進制,十六進制整數
%o 讀入八進制整數
%x,%X 讀入十六進制整數
%c 讀入一個字符
%s 讀入一個字符串,遇空格、制表符或換行符結束。
%f,%F,%e,%E,%g,%G 用來輸入實數,可以用小數形式或指數形式輸入。
%p 讀入一個指針
%u 讀入一個無符號十進制整數
%n 至此已讀入值的等價字符數
%[] 掃描字符集合
%% 讀%符號
附加格式說明字符表修飾符說明
L/l 長度修飾符 輸入"長"數據
h 長度修飾符 輸入"短"數據
W 整型常數 指定輸入數據所占寬度
* 表示本輸入項在讀入后不賦值給相應的變量
scanf的返回值
scanf的返回值有后面的參數決定
scanf("%d%d", &a, &b);
如果a和b都被成功讀入,那么scanf的返回值就是2
如果只有a被成功讀入,返回值為1
如果a和b都未被成功讀入,返回值為0
如果遇到錯誤或遇到end of file,返回值為EOF。
且返回值為int型.
使用scanf函數時應該注意的問題
1、sacnf()中的變量必須使用地址。
2、scanf()的格式控制串可以使用其它非空白字符,但在輸入時必須輸入這些字符。
3、在用"%c"輸入時,空格和“轉義字符”均作為有效字符。
問題一:scanf()函數不能正確接受有空格的字符串?如: I love you!
#include <stdio.h>
int main()
{
char str[80];
scanf("%s",str);
printf("%s",str);
return 0;
}
輸入:I love you!
輸出:scanf()函數接收輸入數據時,遇以下情況結束一個數據的輸入:(不是結束該scanf函數,scanf函數僅在每一個數據域均有數據,并按回車后結束)。
① 遇空格、“回車”、“跳格”鍵。
② 遇寬度結束。
③ 遇非法輸入。
所以,上述程序并不能達到預期目的,scanf()掃描到"I"后面的空格就認為對str的賦值結束,并忽略后面的"love you!".這里要注意是"love you!"還在鍵盤緩沖區(關于這個問題,網上我所見的說法都是如此,但是,我經過調試發現,其實這時緩沖區字符串首尾指針已經相等了,也就是說緩沖區清空了,scanf()函數應該只是掃描stdin流,這個殘存信息是在stdin中)。我們改動一下上面的程序來驗證一下:
#include <stdio.h>
int main()
{
char str[80];
char str1[80];
char str2[80];
scanf("%s",str);/*此處輸入:I love you! */
printf("%s",str);
sleep(5);/*這里等待5秒,告訴你程序運行到什么地方*/
scanf("%s",str1);/*這兩句無需你再輸入,是對鍵盤盤緩沖區再掃描 */
scanf("%s",str2);/*這兩句無需你再輸入,是對鍵盤盤緩沖區再掃描 */
printf("/n%s",str1);
printf("/n%s",str2);
return 0;
}
輸入:I love you!
輸出:
I
love
you!
好了,原因知道了,那么scanf()函數能不能完成這個任務?回答是:能!別忘了scanf()函數還有一個 %[] 格式控制符(如果對%[]不了解的請查看本文的上篇),請看下面的程序:
#include "stdio.h"
int main()
{
char string[50];/*scanf("%s",string);不能接收空格符*/
scanf("%[^/n]",string);
printf("%s/n",string);
return 0;
}
問題二:鍵盤緩沖區殘余信息問題
#include <stdio.h>
int main()
{
int a;
char c; do
{
scanf("%d",&a);
scanf("%c",&c);
printf("a=%d c=%c/n",a,c);/*printf("c=%d/n",c);*/
}while(c!='N');
}
scanf("%c",&c);這句不能正常接收字符,什么原因呢?我們用printf("c=%d/n",c);將C用int表示出來,啟用printf("c=%d/n",c);這一句,看看scanf()函數賦給C到底是什么,結果是c=10 ,ASCII值為10是什么?換行即/n.對了,我們每擊打一下"Enter"鍵,向鍵盤緩沖區發去一個“回車”(/r),一個“換行"(/n),在這里/r被scanf()函數處理掉了(姑且這么認為吧^_^),而/n被scanf()函數“錯誤”地賦給了c.解決辦法:可以在兩個scanf()函數之后加個fflush(stdin);,還有加getch() , getchar()也可以,但是要視具體scanf()語句加那個,這里就不分析了,讀者自己去摸索吧。但是加fflush(stdin);不管什么情況都可行。
(
函數名: fflush
功 能: 清除一個流
用 法: int fflush(FILE *stream);
)
#include <stdio.h>
int main()
{
int a;
char c; do
{
scanf("%d",&a);
fflush(stdin);
scanf("%c",&c);
fflush(stdin);
printf("a=%d c=%c/n",a,c); }while(c!='N');
}
這里再給一個用“空格符”來處理緩沖區殘余信息的示例:運行出錯的程序:
#include <stdio.h>
int main()
{
int i;
char j;
for(i = 0;i < 10;i++)
{
scanf("%c",&j);/*這里%前沒有空格*/
}
}
使用了空格控制符后:
#include <stdio.h>
int main()
{
int i;
char j;
for(i = 0;i < 10;i++)
{
scanf(" %c",&j);/*注意這里%前有個空格*/
}
}
可以運行看看兩個程序有什么不同。
問題三: 如何處理scanf()函數誤輸入造成程序死鎖或出錯?
#include <stdio.h>
int main()
{
int a,b,c; /*計算a+b*/
scanf("%d,%d",&a,&b);
c=a+b;
printf("%d+%d=%d",a,b,c);
}
如上程序,如果正確輸入a,b的值,那么沒什么問題,但是,你不能保證使用者每一次都能正確輸入,一旦輸入了錯誤的類型,你的程序不是死鎖,就是得到一個錯誤的結果,呵呵,這可能所有人都遇到過的問題吧?解決方法:scanf()函數執行成功時的返回值是成功讀取的變量數,也就是說,你這個scanf()函數有幾個變量,如果scanf()函數全部正常讀取,它就返回幾。但這里還要注意另一個問題,如果輸入了非法數據,鍵盤緩沖區就可能還個有殘余信息問題。正確的例程:
#include <stdio.h>
int main()
{
int a,b,c; /*計算a+b*/
while(scanf("%d,%d",&a,&b)!=2)fflush(stdin);
c=a+b;
printf("%d+%d=%d",a,b,c);
}
補充: fflush(stdin)這個方法在GCC下不可用。(在VC6.0下可以)
以下是 C99 對 fflush 函數的定義:
int fflush(FILE *stream);
如果stream指向輸出流或者更新流(update stream),并且這個更新流
最近執行的操作不是輸入,那么fflush函數將把任何未被寫入的數據寫入stream
指向的文件(如標準輸出文件stdout)。否則,fflush函數的行為是不確定的。
fflush(NULL)清空所有輸出流和上面提到的更新流。如果發生寫錯誤,fflush
函數會給那些流打上錯誤標記,并且返回EOF,否則返回0。
由此可知,如果 stream 指向輸入流(如 stdin),那么 fflush 函數的行為是不確定的。故而使用
fflush(stdin) 是不正確的,至少是移植性不好的。
可采用如下方法:
/* 此函數可以和scanf函數一起使用,但使用%c輸入時要注意,即此函數只能用于緩沖區非空的情況 */
void flush()
{
char c;
while ((c=getchar()) != '/n'&&c!=EOF) ;
}
#include <stdio.h>
int main()
{
int a,b,c; /*計算a+b*/
while(scanf("%d,%d",&a,&b)!=2) flush();
c=a+b;
printf("%d+%d=%d",a,b,c);
}
- scanf 原型:
- # include <stdio.h>;
- int scanf( const char *format, ... );
- ? ? 函數 scanf() 是從標準輸入流 stdin 中讀內容的通用子程序,可以讀入全部固有類型的數據并自動轉換成機內形式。scanf() 是 printf() 的補函數。
- ? ? 在 C99 中,format 用 restrict 修飾。
- ? ? format 指向的控制串由以下三類字符組成:
- ? ?? ? ● 格式說明符
- ? ?? ? ● 空白符
- ? ?? ? ● 非空白符
- ? ? 輸入格式說明符前綴為百分號(%),告訴 scanf() 下次讀入何種數據類型。這些格式說明符的清單如下表所示:
- ? ? ┏━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
- ? ? ┃ 代??碼 │? ?? ?? ?? ? 意? ?? ?? ?? ?? ?? ?? ?? ???義? ?? ?? ?? ? ┃
- ? ? ┠────┼────────────────────────────┨
- ? ? ┃? ?%a? ?│讀浮點值(僅適用于 C99)? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? ┃
- ? ? ┃? ?%A? ?│讀浮點值(僅適用于 C99)? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? ┃
- ? ? ┃? ?%c? ?│讀單字符? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?┃
- ? ? ┃? ?%d? ?│讀十進制整數? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???┃
- ? ? ┃? ?%i? ?│讀十進制、八進制、十六進制整數? ?? ?? ?? ?? ?? ?? ?? ???┃
- ? ? ┃? ?%e? ?│讀浮點數? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?┃
- ? ? ┃? ?%E? ?│讀浮點數? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?┃
- ? ? ┃? ?%f? ?│讀浮點數? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?┃
- ? ? ┃? ?%F? ?│讀浮點數(僅適用于 C99)? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? ┃
- ? ? ┃? ?%g? ?│讀浮點數? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?┃
- ? ? ┃? ?%G? ?│讀浮點數? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?┃
- ? ? ┃? ?%o? ?│讀八進制數? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? ┃
- ? ? ┃? ?%s? ?│讀字符串? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?┃
- ? ? ┃? ?%x? ?│讀十六進制數? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???┃
- ? ? ┃? ?%X? ?│讀十六進制數? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???┃
- ? ? ┃? ?%p? ?│讀指針值? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?┃
- ? ? ┃? ?%n? ?│至此已讀入值的等價字符數? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???┃
- ? ? ┃? ?%u? ?│讀無符號十進制整數? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???┃
- ? ? ┃??%[ ]??│掃描字符集合? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???┃
- ? ? ┃? ?%%? ?│讀 % 符號(百分號)? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?┃
- ? ? ┗━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
- ? ? 例如: %s 表示讀串而 %d 表示讀整數。格式串的處理順序為從左到右,格式說明符逐一與變元表中的變元匹配。為了讀取長整數,可以將 l(ell) 放在格式說明符的前面;為了讀取短整數,可以將 h 放在格式說明符的前面。這些修飾符可以與 d、i、o、u 和 x 格式代碼一起使用。
- ? ? 默認情況下,a、f、e 和 g 告訴 scanf() 為 float 分配數據。 如果將 l(ell) 放在這些修飾符的前面,則 scanf() 為 double 分配數據。使用 L 就是告訴 scanf(),接收數據的變量是 long double 型變量。
- ? ? 如果使用的現代編譯器程序支持 1995 年增加的寬字符特性, 則可以與 c 格式代碼一起,用 l 修飾符說明類型 wchar_t 的寬字符指針;也可以與 s 格式代碼一起,用 l 修飾符說明寬字符串的指針。l 修飾符也可以用于修飾掃描集,以說明寬字符。
- ? ? 控制串中的空白符使 scanf() 在輸入流中跳過一個或多個空白行。空白符可以是空格(space)、制表符(tab)和新行符(newline)。 本質上,控制串中的空白符使 scanf() 在輸入流中讀,但不保存結果,直到發現非空白字符為止。
- ? ? 非空白符使 scanf() 在流中讀一個匹配的字符并忽略之。例如,"%d,%d" 使 scanf() 先讀入一個整數,讀入中放棄逗號,然后讀另一個整數。如未發現匹配,scanf() 返回。
- ? ? scanf() 中用于保存讀入值的變元必須都是變量指針,即相應變量的地址。
- ? ? 在輸入流中,數據項必須由空格、制表符和新行符分割。逗號和分號等不是分隔符,比如以下代碼:
- ? ? scanf( "%d %d", &r, &c );
- 將接受輸入 10 20,但遇到 10,20 則失敗。
- ? ? 百分號(%)與格式符之間的星號(*)表示讀指定類型的數據但不保存。因此,
- ? ? scanf( "%d %*c %d", &x, &y );
- 對 10/20 的讀入操作中,10 放入變量 x,20 放入 y。
- ? ? 格式命令可以說明最大域寬。 在百分號(%)與格式碼之間的整數用于限制從對應域讀入的最大字符數。例如,希望向 address 讀入不多于 20 個字符時,可以書寫成如下形式:
- ? ? scanf( "%20s", address );
- ? ? 如果輸入流的內容多于 20 個字符,則下次 scanf() 從此次停止處開始讀入。 若達到最大域寬前已遇到空白符,則對該域的讀立即停止;此時,scanf() 跳到下一個域。
- ? ? 雖然空格、制表符和新行符都用做域分割符號,但讀單字符操作中卻按一般字符處理。例如,對輸入流 "x y" 調用:
- ? ? scanf( "%c%c%c", &a, &b, &c );
- 返回后,x 在變量 a 中,空格在變量 b 中,y 在變量 c 中。
- ? ? 注意,控制串中的其它字符,包括空格、制表符和新行符,都用于從輸入流中匹配并放棄字符,被匹配的字符都放棄。例如,給定輸入流 "10t20",調用:
- ? ? scanf( "%dt%d", &x, &y );
- 將把 10 和 20 分別放到 x 和 y 中,t 被放棄,因為 t 在控制串中。
- ? ? ANSI C 標準向 scanf() 增加了一種新特性,稱為掃描集(scanset)。 掃描集定義一個字符集合,可由 scanf() 讀入其中允許的字符并賦給對應字符數組。 掃描集合由一對方括號中的一串字符定義,左方括號前必須綴以百分號。 例如,以下的掃描集使 scanf() 讀入字符 A、B 和 C:
- ? ? %[ABC]
- ? ? 使用掃描集時,scanf() 連續吃進集合中的字符并放入對應的字符數組,直到發現不在集合中的字符為止(即掃描集僅讀匹配的字符)。返回時,數組中放置以 null 結尾、由讀入字符組成的字符串。
- ? ? 用字符 ^ 可以說明補集。把 ^ 字符放為掃描集的第一字符時,構成其它字符組成的命令的補集合,指示 scanf() 只接受未說明的其它字符。
- ? ? 對于許多實現來說,用連字符可以說明一個范圍。 例如,以下掃描集使 scanf() 接受字母 A 到 Z:
- ? ? %[A-Z]
- ? ? 重要的是要注意掃描集是區分大小寫的。因此,希望掃描大、小寫字符時,應該分別說明大、小寫字母。
- ? ? scanf() 返回等于成功賦值的域數的值,但由于星號修飾符而讀入未賦值的域不計算在內。給第一個域賦值前已出錯時,返回 EOF。
- ? ? C99 為 scanf() 增加了幾個格式修飾符:hh、ll、j、z 和 t。hh 修飾符可用于 d、i、o、u、x、X 或 n。它說明相應的變元是 signed 或 unsigned char 值,或用于 n 時, 相應的變元是指向 long char 型變量的指針。ll 修飾符也可用于 d、i、o、u、x、X 或 n。它說明相應的變元是 signed 或者 unsigned long long int 值。
- ? ? j 格式修飾符應用于 d、i、o、u、x、X 或 n,說明匹配的變元是類型 intmax_t 或 uintmax_t。這些類型在 <stdint.h>; 中聲明,并說明最大寬度的整數。
- ? ? z 格式修飾符應用于 d、i、o、u、x、X 或 n,說明匹配的變元是指向 size_t 類型對象的指針。該類型在 <stddef.h>; 中聲明,并說明 sizeof 的結構。
- ? ? t 格式修飾符應用于 d、i、o、u、x、X 或 n,說明匹配的變元是指向 ptrdiff_t??類型對象的指針。該類型在 <stddef.h>; 中聲明,并說明兩個指針之間的差別。
- 例子:
- # include <stdio.h>;
- int main( void )
- {
- ? ? char str[80], str2[80];
- ? ? int i;
- ? ? /* read a string and a integer */
- ? ? scanf( "%s%d", str, &i );
- ? ? /* read up to 79 chars into str */
- ? ? scanf( "%79s", str );
- ? ? /* skip the integer between the two strings */
- ? ? scanf( "%s%*d%s", str, str2 );
- ? ? return 0;
- }
- 相關函數:
- printf() 及 fscanf()。
復制代碼
down votefavorite 1 share [g+]share [fb] share [tw] | Consider the following code: #include <stdio.h>int main (void)
{char str1[128], str2[128], str3[128];printf ("\nEnter str1: ");scanf ("%[^\n]", str1);printf ("\nstr1 = %s", str1);printf ("\nEnter str2: ");scanf ("%[^\n]", str2);printf ("\nstr2 = %s", str2);printf ("\nEnter str3: ");scanf ("%[^\n]", str3);printf ("\nstr2 = %s", str3);printf ("\n");return 0;
}
When it is executed only the first scanf stops for the prompt. The program does not stop for the nextscanf s. But if the format string is changed from "%[^\n]" to" %[^\n]" (note the blank space before % ), then it works okay. Does some existing newline character from the previous input buffer is automatically accepted ? But flushingstdin does not solve this. What is the cause of this. |