1. 程式人生 > >scanf與printf用法詳解

scanf與printf用法詳解

一、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時都要加上限定符。若未加上將導致一個較長的變數只有一部分被初始化,一個較短的變數的鄰近變數也被修改。這些取決於機器中型別的長度。
格式碼\限定符 h l L
d,i,n short long
o,u,x unsigned short unsigned long
e,f,g double long double
例如:short var_a; scanf("%hd",&var_a);      (4)格式碼:單個字元,表示輸入字元如何被解釋,以及指標列表指標的指向型別。
程式碼 對應的指標引數型別 含義
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 * 處理字元的個數
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)標誌字元:
標誌 含義
- 左對齊;預設右對齊
0 右對齊時,用0填充左邊未使用的列;預設用空格填充
+ 當一個數為正數時,前面加上一個+號,預設不顯示
空格 當一個數為正數時,前面加上一個空格,預設不顯示
(2)欄位寬度:指定輸出的最小字元數,若輸出的小於欄位寬度。則根據標誌字元進行相應的修改輸出 (3)精度: 作用於%s:指定要被轉換的最多字元數 作用於%f:指定出現在小數點後的數字位數 (4)修改符:
修改符 作用物件 表示型別
h d,i,o,u,x short型整數
l d,i,o,u,x long型整數
l e,f,g long double型資料
(5)格式程式碼
程式碼 引數 含義
c int 引數被裁剪為unsigned char型別並作為字元列印
d
i
int 作為一個十進位制整數列印
o
u
x
unsigned int 引數作為一個無符號值列印,u使用十進位制,o使用八進位制,x使用十六進位制
e、f、g double 引數按照浮點數列印,精度缺少為6位
s char * 列印一個字串
n int * 列印字元的個數
(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的位數。