1. 程式人生 > >scanf函數用法小記

scanf函數用法小記

lur 忽略 match 過濾 std 12個 可用 cte turn

By francis_hao Aug 26,2017

scanf – 輸入格式轉換

概述

#include <stdio.h>
int scanf(const char *format, ...);

描述

該函數通過format掃描標準輸入stdin, format包含轉換描述說明,如果需要轉換,那麽轉換後的結果存儲在format之後的指針參數中,每個指針參數類型必須要正確對應轉換說明。如果format中轉換說明符的個數,超過了後面的指針參數,那麽結果將是未定義的。反過來,如果指針參數的數量超過了轉換符的數量,那麽多余的指針參數將被忽略。

format字符串包含一串指令,這些指令描述了該如何處理輸入的字符,如果一個指令處理失敗,那麽之後的輸入將不再讀取,而且函數返回。處理失敗可以是以下幾種:
1、輸入失敗,意味著輸入的字符串不可用。
2、匹配失敗,意味著輸入不相稱。

一個指令可以是下面幾種:
1、一串空白符(空格,tab,新行等),此指令匹配任何數量的空白符,也可以匹配none。
2、普通的字符(既不是空白字符也不是‘%‘)。這種字符必須準確的匹配輸入的字符。
3、以‘%‘開頭的轉換說明,通過此說明將輸入的字符串進行轉換,結果會放在對應的指針參數中,如果輸入的項與轉換說明不匹配,那麽轉換就會失敗,這就是上面提到的匹配失敗。

format中的轉換說明以‘%‘或"%n$"開始,後面(按順序)跟著以下內容:
1、一個可選的‘*‘分配抑制符,scanf()像普通的轉換符那樣從輸入讀取,但是之後會丟棄該輸入,不會將該輸入存入指針參數,而且不會作為scanf()返回的成功分配項的數量。
2、一個可選的‘m‘字符。此項用於轉換符%s,%c和%[,使調用者無需申請存放輸入的緩沖,而是由scanf()去申請緩存,並將緩存的地址賦給指針參數,該參數應該是一個指向char *

變量(該變量在調用前無需初始化,但是建議仍舊初始化一下)的指針。調用者需要在之後不再需要該緩沖的時候進行free(3)。
3、一個可選的十進制整數,用來指定字段最大寬度。此項表示當讀取到了指定的最大寬度或讀取到不匹配的字符後就會停止,。大部分的轉換符會跳過前面的空白字符(例外情況在下面介紹),而且那些跳過的字符不計入最大字段寬度,字符串輸入轉換符包含一個終止字節‘\0‘以表示輸入的結束,字段最大寬度也不包括此項。
4、一個可選的,類型修飾符,例如,修飾符l用於轉換符%d表示其對應的指針參數指向一個long int類型而不是一個int類型。
5、轉換說明符,用以指定輸入需要轉換的類型。

format中的轉換說明有兩種形式,要麽以‘%‘開始,要麽以"%n$"開始。兩種形式不能在同一個format

中混用,但是有"%n$"的轉換說明可以包含%%和%*。如果format包含‘%‘說明,那麽參數會按順序,一個個的進行賦值。但是在"%n$"形式中(此形式是POSIX.1-2001指定的,不是C99),其中n是一個十進制整數,用以指定被轉換後的輸入應該存放在第n個指針參數處。

類型修飾符

類型修飾符

說明

h

表明轉換符將是d,i,o,u,x,X或n的其中一個,而且其後的參數是一個指向short int或unsigned short int(而不是int)的指針。

hh

類似h,但是其後的參數是一個指向signed char 或 unsigned char的指針

j

類似h,但是其後的參數是一個指向intmax_t 或 uintmax_t的指針

t

類似h,但是其後的參數是一個指向ptrdiff_t的指針

z

類似h,但是其後的參數是一個指向size_t的指針

l

1、表明轉換符將是d,i,o,u,x,X或n的其中一個,而且其後的參數是一個指向long int或unsigned long int(而不是int)的指針

2、表明轉換符將是e, f,或g的其中一個,而且其後的參數是一個指向double(而不是float)的指針

3、指定兩個l,和L一致。

L

1、表明轉換符將是e, f, 或 g的其中一個,而且其後的參數是一個指向long double的指針

2、表明轉換符是d, i, o, u,或x的其中一個,而且其後的參數是一個指向long double的指針

轉換符

轉換符

說明

d

匹配一個有符號的十進制整數,後面的指針參數必須是一個指向int的指針

i

匹配一個有符號的十進制整數,後面的指針參數必須是一個指向int的指針

輸入如果是以0x或0X開頭,就以16進制讀入

輸入如果是以0開頭,就以8進制讀入

其他形式就以10進制讀入

o

匹配一個無符號八進制整數,後面的指針參數必須是指向unsigned int的指針

u

匹配一個無符號十進制整數,後面的指針參數必須是指向unsigned int的指針

x

匹配一個無符號十六進制整數,後面的指針參數必須是指向unsigned int的指針

f,e,E,g,a

匹配一個有符號的浮點數,後面的指針參數必須是指向float的指針

s

匹配一個沒有空白字符的字符串序列,其後的指針參數必須是指向字符數組的指針,而且大小要足夠大以容納輸入的序列和終止符null字節。當遇到輸入的空白字符或者最大字段寬度時即停止。

c

匹配一個字符序列,其長度由最大字段寬度指定(默認是1),其後的指針參數必須是指向char的指針,而且要有足夠長的空間存儲所有的字符(結尾不會自動添加null字節)。如果開頭有空白字符不會跳過,如果想要跳過開頭的空白字符,需要在format中使用一個確實的空格。

[

從指定的接受字符集合中匹配一個非空字符序列,後面的指針參數必須是指向char的參數,而且,必須有足夠的空間已存放所有匹配的字符和一個終止的null字節。此項中,如果開頭有空白字符不會跳過。

[]中的字符組成了一個集合,表示只匹配[]裏的字符,如果是開頭的字符是^,則表示除了[]內的字符其余的字符集合,如果想包含一個],需要將]放在[或[^後的第一個位置,在其他位置則表示集合終止。-是有特殊含義的,表示一個字符範圍,如果想包含-則需要放在[]的最後一個位置。比如

[^]0-9-]:表示除了],0,1,2,3,4,5,6,7,8,9,-這12個字符以外的所有字符。

p

匹配一個指針數值,後面的指針參數必須是指向void的指針

n

不需要輸入,而是將截止到該項為止,之前輸入的字符數存儲在其後對應的指針中,指針參數必須是指向int類型的指針。此項不屬於轉換符,盡管它可以被*抑制(抑制之後就什麽作用都沒有了)

返回值

返回函數成功匹配和分配的項數,有可能少於提供的參數,如果最早匹配時發生錯誤甚至會返回0。

如果在成功轉換完成或者匹配失敗之前,遇到了輸入的結尾,那麽就會返回EOF。如果讀取失敗同樣也會返回EOF,並且errno會被置為相應的值。

示例

1、

技術分享

結果為

技術分享技術分享

本示例主要說明了分配抑制符*的使用,可以用來過濾掉不需要的輸入,因為帶*的轉換說明不會給其後的參數賦值,因此也不需要給定存儲的參數。

而n主要是記錄到此前位置共有多少個字符被輸入(包含空格),並將該值分配給其後的參數

2、man手冊上的一個例子,添加了一些註釋

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

int main(void)
{
char *p;
int n;

errno = 0;
n = scanf("%m[a-z]", &p);
if (n == 1) {/*number of input items successfully matched and assigned*/
printf("read: %s\n", p);
free(p);
} else if (errno != 0) {/*EOF must be returned*/
perror("scanf");
} else {/*matching failure n may be zero*/
fprintf(stderr, "No matching characters.n is %d\n",n);
}

return 0;
}

結果為

技術分享

技術分享
本文由 劉英皓 創作,采用 知識共享 署名-非商業性使用-相同方式共享 3.0 中國大陸 許可協議進行許可。歡迎轉載,請註明出處:
轉載自:http://www.cnblogs.com/yinghao1991/p/7436582.html

參考

【1】man scanf

scanf函數用法小記