scanf與printf用法詳解
阿新 • • 發佈:2018-12-23
一、scanf家族
1、scanf家族的原型
int scanf(char const *format,...);
int fscanf(FILE *stream,char const *format,...);
int sscanf(char const *buffer,char const *format,...);
每個原型中的省略號表示一個可變長度的指標列表。從輸入轉換而來的值逐個儲存到這些指標指向的記憶體位置。由於C的引數傳遞都是傳值呼叫決定了可變引數都是指標列表。注意:若給的不是指標,而是變數值。scanf將把變數值當做指標,在進行解引用時或者導致程式終止,或者導致不可預料的記憶體位置的資料被改寫。
2、返回值
當格式化字串format到達末尾或者讀取的輸入不再匹配格式字串所指定的型別時,輸入就停止,並返回被轉換的輸入值的數目,若在任何輸入都沒被轉換之前檔案就到達尾部則返回EOF。
3、型別的匹配
由於scanf是採用可變引數的機制,所以函式無法驗證它們的指標引數是否為正確的型別,所以函式假定它們是正確的,(因此格式字元必須和後面的指標指向的型別保持一致)如果指標引數的型別和輸入資料的型別不匹配則結果值就是垃圾。而且鄰近的變數也有可能被改寫。例如:
float a;
scanf("%d",&a); //本來a是一個float資料,卻用一個整形指標指向變數a。
4、scanf格式程式碼
format字串中包括以下內容。
空白字元:他們與輸入中的零個或多個空白字元匹配,在處理過程中將被忽略。(常用於%c中)
格式程式碼:他們指定函式如何解釋接下來的輸入字元。
其他字元:若出現其他字元時,下一個輸入字元必須與之匹配。若匹配則該輸入字元丟棄,若不匹配,函式不再讀取,直接返回。
格式程式碼:以%開頭,後面接:一個可選的星號;一個可選的寬度;一個可選的限定符;格式程式碼
(1)星號:轉換後的值被丟棄而不進行儲存,跳過不需要的輸入字元。
(2)寬度:限制被讀取用於轉換的輸入字元的個數。若未給出寬度,函式讀入字元直到遇到空白字元。
(3)限定符:修改有些格式程式碼的含義。注意轉換所有的short、long、double、long double時都要加上限定符。若未加上將導致一個較長的變數只有一部分被初始化,一個較短的變數的鄰近變數也被修改。這些取決於機器中型別的長度。
例如:short var_a;
scanf("%hd",&var_a);
(4)格式碼:單個字元,表示輸入字元如何被解釋,以及指標列表指標的指向型別。
5、用scanf實現行定向的輸入。
由於scanf把回車也當做空白字元處理所以使用scanf保持行邊界的同步時很困難的。為了實現行定向。可以搭配fgets。先用fgets讀取一行,然後用sscanf對讀取的行處理。
6、使用sscanf處理可變格式的輸入。
int a,b,c;
fgets(buf,20,stdin);
char *p = strrchr(buf,'\n');
*p = '\0'; //去除回車符
if(sscanf(buf,"%d%d%d",&a,&b,&c) != 3)
{
a = 1; //defalut value of a
if(sscanf(buf,"%d%d",&b,&c) != 2)
{
b = 1; //default value of b
if(sscanf(buf,"%d",&c)!=1)
{
printf("input error\n ");
exit(1);
}
}
}
printf("a = %d\nb=%d\nc=%d\n",a,b,c); 二、printf家族 1、原型 int printf(char const *format,...); int fprintf(FILE *stream,char const *format,...); int sprintf(char *buffer,char const *format,...); 2、型別匹配 printf函式和scanf一樣,無法驗證一個值是否具有格式碼所表示的正確型別。所以保證他們相互匹配是程式設計師的責任。 3、printf格式碼 format字串包含格式碼,它使引數列表的下一個值根據指定的方式進行格式化,對於其他的字元則原樣輸出。 格式碼由一個%開頭,後邊可以跟: 標誌字元、欄位寬度、精度、修改符、#標誌、格式碼 (1)標誌字元:
(2)欄位寬度:指定輸出的最小字元數,若輸出的小於欄位寬度。則根據標誌字元進行相應的修改輸出
(3)精度:
作用於%s:指定要被轉換的最多字元數
作用於%f:指定出現在小數點後的數字位數
(4)修改符:
(5)格式程式碼
(6)#標誌
#標誌可以作用於格式程式碼:o,x,e,f,g 也就是無符號數和浮點數
o:產生的值以0開頭;x:以0x開頭;(這兩個很實用。)
e,f,g:確保結果始終包含一個小數點即使後面沒有數字。
long double a = 3.14;
printf("a = %08.3lf",a); //右對齊,開頭補零,字元寬度8位,精度3位,以long double型輸出。
三、利用sprintf和scanf實現字串和數值的相互轉換
利用sscanf可以實現字串向數值的轉換,而利用sprintf實現數值向字串的轉換
#include<stdio.h>
int main()
{
float a = 3.14;
double b; char buf[20]; sscanf("3.42","%lf",&b); //將字串轉換為數值double
sprintf(buf,"%.2f",a); //將double型數值轉換為字串
printf("b = %.2f\n",b);
printf("buf is:%s\n",buf);
} 另外標準庫提供的用於字串轉換為整型/浮點型的函式有: int atoi(char const *string); long int atol(char const *string); long int strtol(char const *string,char **unused,int base); long int strtoul(char const *string,char **unused,int base); double atof(char const *string); double strtod(char const *string,char **unused); 使用注意事項: 1、跳過前導空白字元,忽略非法綴尾字元 2、對於整型,當base=0時,根據string的字面確定string的進位制。(八進位制(以0開頭)、十進位制(預設)、十六進位制(以0x開頭)); 3、若不能轉換為相應型別則返回0 4、unused指向無法轉換的字元的指標的指標。 四、通過sprintf獲取一個整數的位數 通常對於一個整數data,我們需要獲得其位數的方法為:對其與10、100、1000、等相除來確定共有多少位。 下面程式提供了一個獲取data位數的一個好方法: int number,data;
data = 12345;
char buf[20];
sprintf(buf,"%d%n",data,&number); //利用snprintf防止訪問記憶體越界:snprintf(buf,20,"%d%n",data,&number);
printf("data is %d,has %d characters\n",data,number); 利用printf的%n格式符記錄列印字元的個數來統計data的位數。
格式碼\限定符 | h | l | L |
d,i,n | short | long | |
o,u,x | unsigned short | unsigned long | |
e,f,g | double | long double |
程式碼 | 對應的指標引數型別 | 含義 |
c | char * | 讀取和儲存單個字元,前導的空白字元不跳過(可以在格式字串中加入空格來跳過)。若給出寬度,就讀取和儲存這個數目的字元,後面不會新增NUL,必須保證足夠大的陣列空間 |
i d |
int * | 有符號整數被轉換。%d解釋為十進位制。%i根據第一個字元決定值的基數,和整型字元值常量的表示形式相同。10,034,0xa2 |
u o x |
unsigned * | 無符號整數被轉換。u:十進位制;o:八進位制;x:十六進位制 |
e f g |
float * | 期待一個浮點值。他的形式必須像一個浮點型字面值常量,但小數點並不必須 |
s | char * | 讀取一串非空白字元,當發現空白時則輸入停止。後面自動加上NUL。必須保證足夠大的陣列空間 |
n | int * | 處理字元的個數 |
char *p = strrchr(buf,'\n');
*p = '\0'; //去除回車符
if(sscanf(buf,"%d%d%d",&a,&b,&c) != 3)
{
a = 1; //defalut value of a
if(sscanf(buf,"%d%d",&b,&c) != 2)
{
b = 1; //default value of b
if(sscanf(buf,"%d",&c)!=1)
{
printf("input error\n ");
exit(1);
}
}
}
printf("a = %d\nb=%d\nc=%d\n",a,b,c); 二、printf家族 1、原型 int printf(char const *format,...); int fprintf(FILE *stream,char const *format,...); int sprintf(char *buffer,char const *format,...); 2、型別匹配 printf函式和scanf一樣,無法驗證一個值是否具有格式碼所表示的正確型別。所以保證他們相互匹配是程式設計師的責任。 3、printf格式碼 format字串包含格式碼,它使引數列表的下一個值根據指定的方式進行格式化,對於其他的字元則原樣輸出。 格式碼由一個%開頭,後邊可以跟: 標誌字元、欄位寬度、精度、修改符、#標誌、格式碼 (1)標誌字元:
標誌 | 含義 |
- | 左對齊;預設右對齊 |
0 | 右對齊時,用0填充左邊未使用的列;預設用空格填充 |
+ | 當一個數為正數時,前面加上一個+號,預設不顯示 |
空格 | 當一個數為正數時,前面加上一個空格,預設不顯示 |
修改符 | 作用物件 | 表示型別 |
h | d,i,o,u,x | short型整數 |
l | d,i,o,u,x | long型整數 |
l | e,f,g | long double型資料 |
程式碼 | 引數 | 含義 |
c | int | 引數被裁剪為unsigned char型別並作為字元列印 |
d i |
int | 作為一個十進位制整數列印 |
o u x |
unsigned int | 引數作為一個無符號值列印,u使用十進位制,o使用八進位制,x使用十六進位制 |
e、f、g | double | 引數按照浮點數列印,精度缺少為6位 |
s | char * | 列印一個字串 |
n | int * | 列印字元的個數 |
int main()
{
float a = 3.14;
double b; char buf[20]; sscanf("3.42","%lf",&b); //將字串轉換為數值double
sprintf(buf,"%.2f",a); //將double型數值轉換為字串
printf("b = %.2f\n",b);
printf("buf is:%s\n",buf);
} 另外標準庫提供的用於字串轉換為整型/浮點型的函式有: int atoi(char const *string); long int atol(char const *string); long int strtol(char const *string,char **unused,int base); long int strtoul(char const *string,char **unused,int base); double atof(char const *string); double strtod(char const *string,char **unused); 使用注意事項: 1、跳過前導空白字元,忽略非法綴尾字元 2、對於整型,當base=0時,根據string的字面確定string的進位制。(八進位制(以0開頭)、十進位制(預設)、十六進位制(以0x開頭)); 3、若不能轉換為相應型別則返回0 4、unused指向無法轉換的字元的指標的指標。 四、通過sprintf獲取一個整數的位數 通常對於一個整數data,我們需要獲得其位數的方法為:對其與10、100、1000、等相除來確定共有多少位。 下面程式提供了一個獲取data位數的一個好方法: int number,data;
data = 12345;
char buf[20];
sprintf(buf,"%d%n",data,&number); //利用snprintf防止訪問記憶體越界:snprintf(buf,20,"%d%n",data,&number);
printf("data is %d,has %d characters\n",data,number); 利用printf的%n格式符記錄列印字元的個數來統計data的位數。