C語言printf()函數:格式化輸出函數
printf()函數是最常用的格式化輸出函數,其原型為:
int printf( char * format, ... );
printf()會根據參數 format 字串來轉換並格式化資料,然後將結果輸出到標準輸出裝置(顯示器),直到出現字串結束('\0')為止。
參數 format 字串可包含下列三種字元類型:
- 一般文本,將會直接輸出
- ASCII 控制字元,如\t、\n 等有特定含義
- 格式轉換字元
格式轉換為一個百分比符號(%)及其後的格式字元所組成。一般而言,每個%符號在其後都必需有一個參數與之相呼應(只有當%%轉換字元出現時會直接輸出%字元),而欲輸出的資料類型必須與其相對應的轉換字元類型相同。
printf()格式轉換的一般形式如下:
%(flags)(width)(. prec)type
以括弧括起來的參數為選擇性參數,而%與type 則是必要的,下面介紹 type 的幾種形式。
1) 整數
- %d 整數的參數會被轉成有符號的十進位數字
- %u 整數的參數會被轉成無符號的十進位數字
- %o 整數的參數會被轉成無符號的八位元字
- %x 整數的參數會被轉成無符號的十六進位數字,並以小寫abcdef 表示
- %X 整數的參數會被轉成無符號的十六進位數字,並以大寫ABCDEF 表示浮點型數
- %f double 型的參數會被轉成十進位數字,並取到小數點以下六位,四捨五入
- %e double 型的參數以指數形式列印,有一個數字會在小數點前,六位元字在小數點後,而在指數部分會以小寫e 來表示
- %E 與%e 作用相同,唯一區別是指數部分將以大寫的E 來表示
- %g double 型的參數會自動選擇以%f 或%e 的格式來列印,其標準是根據列印的數值及所設定的有效位元來決定。
- %G 與%g 作用相同,唯一區別在以指數形態列印時會選擇%E 格式。
2) 字元及字串
- %c 整型數的參數會被轉成unsigned char 型列印出
- %s 指向字串的參數會被逐字輸出,直到出現NULL 字元為止
- %p 如果是參數是"void *"型指標則使用十六進位格式顯示
prec 有幾種情況:
- 正整數的最小位元
- 在浮點型數中代表小數位元
- 格式代表有效位元的最大值
- 在%s 格式代表字串的最大長度
- 若為×符號則代表下個參數值為最大長度
width 為參數的最小長度,若此欄並非數值,而是*符號,則表示以下一個參數當做參數長度。
flags 有下列幾種情況
- + 一般在列印負數時,printf ()會加印一個負號,整數則不加任何負號,此旗標會使得在列印正數前多一個正號 (+)。
- # 此旗標會根據其後轉換字元的不同而有不同含義。當在類型為o 之前 (如%#o),則會在列印八位元值前多印一個o。而在類型為x 之前 (%#x)則會在列印十六進位數前多印'0x',在型態為e、E、f、g 或G 之前則會強迫數值列印小數點。在類型為g 或G 之前時則同時保留小數點及小數位元末尾的零。
- 0 當有指定參數時,無數位參數將補上0。預設是關閉此旗標,所以一般會列印出空白字元。
【傳回值】成功則返回寫入的字元數目。
如果發生寫入錯誤,將會設定檔案錯誤標誌(可通過 ferror() 檢測),並返回一個負數。
如果在寫入寬字元時一個多位元組的字元發生編碼錯誤,那麼 errno 將被設定為 EILSEQ,並返回一個負數。
printf( format, ... ) 等價於 fprintf(stdout, format, ...),更多資訊請參考 fprintf() 函數。
【執行個體】分別輸出整數、浮點數和字串。
#include<stdio.h>int main(void){ int a=1; float b=5.0; char str[100]= ""; scanf("%c %c %c",&a,&b,str); /*分別示範 整數*/ printf("int is:%d\n",a); /*分別示範 浮點數*/ printf("float is:%f\n",b); /*分別示範 字串*/ printf("char is:%s\n",str); return 0;}
輸出結果:
【運行結果】
1 4.4 fsint is:1float is:4.400000char is:fs
例子首先是等待使用者輸入整數浮點數和一個字串,然後調用函數printf()按照對應的格式輸出。
又如,輸出更多格式的資料。
#include <stdio.h>int main(){ printf ("Characters: %c %c \n", 'a', 65); printf ("Decimals: %d %ld\n", 1977, 650000L); printf ("Preceding with blanks: %10d \n", 1977); printf ("Preceding with zeros: %010d \n", 1977); printf ("Some different radices: %d %x %o %#x %#o \n", 100, 100, 100, 100, 100); printf ("floats: %4.2f %+.0e %E \n", 3.1416, 3.1416, 3.1416); printf ("Width trick: %*d \n", 5, 10); printf ("%s \n", "A string"); return 0;}
輸出結果:
Characters: a ADecimals: 1977 650000Preceding with blanks: 1977Preceding with zeros: 0000001977Some different radices: 100 64 144 0x64 0144floats: 3.14 +3e+000 3.141600E+000Width trick: 10A string
C語言fprintf()函數:輸出函數(格式化輸出資料至檔案)
標頭檔:
定義函數:
int fprintf(FILE * stream, const char * format, ...);
函數說明:fprintf()會根據參數format 字串來轉換並格式化資料, 然後將結果輸出到參數stream 指定的檔案中, 直到出現字串結束('\0')為止。
傳回值:關於參數format 字串的格式請參考printf(). 成功則返回實際輸出的字元數, 失敗則返回-1, 錯誤原因存於errno 中.
範例
#include <stdio.h>main(){ int i = 150; int j = -100; double k = 3.14159; fprintf(stdout, "%d %f %x \n", j, k, i); fprintf(stdout, "%2d %*d\n", i, 2, i);}
執行:
C語言sprintf()函數:將格式化的資料寫入字串
標頭檔:
sprintf()函數用於將格式化的資料寫入字串,其原型為:
int sprintf(char *str, char * format [, argument, ...]);
【參數】str為要寫入的字串;format為格式化字串,與printf()函數相同;argument為變數。
除了前兩個參數類型固定外,後面可以接任意多個參數。而它的精華,顯然就在第二個參數--格式化字串--上。 printf()和sprintf()都使用格式化字串來指定串的格式,在格式串內部使用一些以“%”開頭的格式說明符(format specifications)來佔據一個位置,在後邊的變參列表中提供相應的變數,最終函數就會用相應位置的變數來替代那個說明符,產生一個調用者想要的字串。
sprintf()最常見的應用之一莫過於把整數列印到字串中,如:
- sprintf(s, "%d", 123); //把整數123列印成一個字串儲存在s中
- sprintf(s, "%8x", 4567); //小寫16進位,寬度佔8個位置,靠右對齊
sprintf的作用是將一個格式化的字串輸出到一個目的字串中,而printf是將一個格式化的字串輸出到螢幕。sprintf的第一個參數應該是目的字串,如果不指定這個參數,執行過程中出現 "該程式產生非法操作,即將被關閉...."的提示。
sprintf()會根據參數format 字串來轉換並格式化資料,然後將結果複製到參數str 所指的字串數組,直到出現字串結束('\0')為止。關於參數format 字串的格式請參考printf()。
【傳回值】成功則返回參數str 字串長度,失敗則返回-1,錯誤原因存於errno 中。
注意:C語言對數組進行操作時並不檢測數組的長度,如果str的長度不夠,sprintf()很容易造成緩衝區溢位,帶來意想不到的後果,駭客經常利用這個弱點攻擊看上去安全的系統。請看下面的代碼:
#include <stdio.h>main(){ char buf[10]; sprintf(buf, "The length of the string is more than 10"); printf("%s", buf);}
編譯並運行,螢幕上輸出”The length of the string is more than 10“,同時系統提示程式已經停止。原因就是要寫入的字串的長度超過了buf的長度,造成緩衝區溢位。
使用snprintf()來代替sprintf()將能夠很好的解決這個問題。
【執行個體】列印字母a的ASCII值。
#include <stdio.h>main(){ char a = 'a'; char buf[80]; sprintf(buf, "The ASCII code of a is %d.", a); printf("%s", buf);}
運行結果:
The ASCII code of a is 97.
又如,產生10個100以內的隨機數並輸出。
#include<stdio.h>#include<stdlib.h>#include<time.h>int main(void){ char str[100]; int offset =0; int i=0; srand(time(0)); // *隨機種子 for(i = 0;i<10;i++) { offset+=sprintf(str+offset,"%d,",rand()%100); // 格式化的資料寫入字串 } str[offset-1]='\n'; printf(str); return 0;}
運行結果:
74,43,95,95,44,90,70,23,66,84
例子使用了一個新函數srand(),它能產生隨機數。例子中最複雜的部分是for迴圈中每次調用函數sprintf()往字元數組寫資料的時候,str+foffset為每次寫入資料的開始地址,最終的結果是所有產生的隨機資料都被以整數的形式存入數組中。