# C Language / Fromatted Input & Output ## 概述 C 語言中,所有輸入和輸出操作都是透過串流(stream) 進行,串流是一序列的位元組(bytes)。在輸入操作中,位元組從裝置(如鍵盤、磁碟機、網路連線等)流向主記憶體。在輸出操作中,位元組從主記憶體流向裝置(如顯示器螢幕、印表機、磁碟機、網路連線等)。 當程式執行開始時,會自動連接三個串流: - 標準輸入串流連接到鍵盤 - 標準輸出串流連接到螢幕 - 第三個串流(標準錯誤串流)也連接到螢幕 好其實這章節就是在說 scanf 和 printf 函數的格式化功能,然後要包含標頭檔`<stdio.h>`。不能說是枯燥乏味,~~只能說是無聊至極~~。 ## Ch01 / printf 函數 printf 可以精確地格式化輸出。每一次呼叫printf都需要一個格式控制字串(format control string),描述輸出格式。格式控制字串包含了轉換字元、旗標、欄位寬度、精度和文字字元。這些元素與百分號(%)組合而成轉換規範(conversion specification)。 printf 函數具有以下格式化能力: - 將浮點數四捨五入到指定的小數位數 - 將輸出右對齊和左對齊 - 以指數格式表示浮點數 - 以八進制和十六進制格式表示無號整數 - 以固定的欄位寬度和精度顯示所有類型的資料 printf 函數的格式為: ```c printf(格式控制字串, 其他參數); ``` 格式控制字串描述輸出格式,而其他參數(可選)對應於格式控制字串中的每個轉換規範。每個轉換規範以百分號開頭,並以轉換字元結尾。一個格式控制字串可以包含多個轉換規範。 ### 1. 整數轉換規範 整數是不含小數點的整數,可以用幾種不同的格式顯示,以下程式範例使用每個整數轉換字元印出一個整數: ```c= #include <stdio.h> int main(void) { int x = 459; printf("%d\n", x); /* 459 */ printf("%i\n", x); /* 459 */ printf("%o\n", x); /* 713 */ printf("%u\n", x); /* 459 */ printf("%x\n", x); /* 1cb */ printf("%X\n", x); /* 1CB */ /* 僅減號會被印出,加號通常會被隱藏 */ printf("%d\n", -x); /* -459 */ /* 將-455視為無號整數時,其值為4294966841 */ printf("%u\n", -x); /* 4294966841 */ return 0; } ``` | 格式控制符 | 說明 | |-------|------| | `%d`和`%i` | 印出十進制整數 | | `%o` | 八進制整數 | | `%u` | 印出無號十進制整數 | | `%x` | 印出小寫十六進制整數 | | `%X` | 印出大寫十六進制整數 | > note:當將負數以`%u`無號整數格式印出時,會得到一個大於等於2^32的值 ### 2. 浮點數轉換規範 浮點數包含小數點,程式中通常會使用指數表示法 + 轉換字元`e`和`E`來顯示浮點數,這相當於數學中使用的科學記號法。 例如,150.4582可以用科學記號法表示為1.504582 * 10^2,或用指數記號法表示為1.504582E+02。這表示1.504582乘以10的2次方(E+02),E代表"指數"。 使用轉換字元`e`、`E`和`f`時,預設顯示小數點右側有6位數的精度。`f`會確保在小數點左側至少有一位數字,而`e`和`E`則會在指數前分別印出小寫e和大寫E,並且在小數點左側只會有一位數字。 轉換字元`g`(或`G`)會根據數值大小,自動選擇使用`e`(或`E`)或`f`格式,且不會印出尾隨的0(如1.234000會被印為1.234)。 說了這麼多密密麻麻的一大堆,還是直接看程式範例比較快: ```c= #include <stdio.h> int main(void) { float x = 459.683; printf("%e\n", x); /* 4.596830e+02 */ printf("%E\n", x); /* 4.596830E+02 */ printf("%f\n", x); /* 459.683000 */ printf("%g\n", x); /* 459.683 */ printf("%G\n", x); /* 459.683 */ /* 根據指數的值,決定使用e或f格式 */ printf("%g\n", 0.0000875); /* 8.75e-05 */ printf("%g\n", 8750000.0); /* 8.75e+06 */ printf("%g\n", 8.75); /* 8.75 */ printf("%g\n", 87.5); /* 87.5 */ /* 精度表示最多顯示幾位有效數字(包含整數部分) */ printf("%g\n", 1234567.0); /* 1.23457e+06 */ return 0; } ``` | 格式控制符 | 說明 | |-------|------| | `%e`和`%E` | 分別使用小寫e和大寫E印出指數格式的浮點數 | | `%f` | 以定點表示法印出浮點數,不會四捨五入 | | `%g`和`%G` | 根據數值大小自動選擇`e`(或`E`)或`f`格式,並移除尾隨的0,其精度控制預設為6 | ## Ch02 / scanf函數 scanf函數可以精確格式化輸入。每一次呼叫 scanf 都需要一個格式控制字串,描述要讀入的資料格式。格式控制字串包含了轉換字元和文字字元。 scanf函數具有以下輸入格式化能力: - 讀入所有類型的資料 - 從輸入串流讀取特定字元 - 在輸入串流中跳過特定字元 scanf函數的格式為: ```c scanf(格式控制字串, 其他參數); ``` 格式控制字串描述輸入格式,而其他參數是將要存放輸入資料的變數位址。 以下是常用的轉換字元: | 轉換字元 | 說明 | |-------|------| | `%c` | 讀取一個字元 | | `%d` | 讀取一個十進制整數 | | `%i` | 讀取一個整數(十進制、八進制或十六進制) | | `%f` | 讀取一個浮點數 | | `%lf` | 讀取一個double型浮點數 | | `%s` | 讀取一個字串 | | `%x` | 讀取一個十六進制整數 | ## Ch03 / 程式範例 ### 範例1:讀取並印出整數 ```c= #include <stdio.h> int main(void) { int x, y, z; printf("請輸入三個整數(用空白隔開):"); scanf("%d %d %d", &x, &y, &z); // 使用 %d 轉換字元讀取三個十進制整數到變數x、y和z printf("你輸入的三個整數為: %d, %d, %d\n", x, y, z); return 0; } ``` ### 範例2:計算圓面積 ```c= #include <stdio.h> #include <math.h> int main(void) { const double PI = 3.14159265358979323846; double radius, area; printf("請輸入圓的半徑: "); scanf("%lf", &radius); // 使用 %lf 轉換字元讀取一個double型浮點數到radius變數 area = PI * radius * radius; printf("圓的面積為: %.2f\n", area); // 使用`%.2f`印出圓面積到小數點後兩位 return 0; } ``` ### 範例3:讀取並反轉字串 ```c= #include <stdio.h> #include <string.h> void reverseString(char str[]); int main(void) { char str[100]; printf("請輸入一個字串: "); scanf("%s", str); printf("原始字串: %s\n", str); reverseString(str); printf("反轉後字串: %s\n", str); return 0; } void reverseString(char str[]) { int length = strlen(str); int i, j; char temp; for (i = 0, j = length - 1; i < j; i++, j--) { temp = str[i]; str[i] = str[j]; str[j] = temp; } // 不斷交換首尾字元,直到遇到中間 } ``` --- *註: 部分內容截自於網路,此筆記非完全原創。* ***Latest Updated On:2024.05.31, published with the of LICENSE of WTFPL Author:Qaron(呱呱)***