第4章 輸入/輸出
本章重點
· 語句和語句塊
· printf函數
· scanf函數
在C語言編程中,經常需要通過輸入設備(如鍵盤)向程序錄入信息,或者将信息顯示在輸出設備(如屏幕),這時,可以使用輸入輸出語句來完成。輸入輸出語句是用戶與程序交互的唯一途徑,掌握好輸入輸出語句對後面的學習至關重要。本章将針對輸入輸出進行詳細地講解。
4.1 語句
4.1.1 語句
正如一棟樓是由一塊塊磚組成,C語言編寫的程序主要由語句組成的。因此,要想寫出正确的C程序,首先要學會寫出正确的語句。
C語言中的多條語句也可組成一個語句塊,語句塊指的是用花括号{}括起來的多條語句。合理地使用語句塊可以讓程序的邏輯更加清晰。本小節将重點介紹什麼是語句和語句塊。
在C語言中,程序是由語句組成的,它是程序最基本的執行單元。先來看幾個簡單的例子,具體如下:
1、 用于向控制台輸出Hello world中的printf語句,具體示例如下:
printf("Hello world!\n");
2、 用于跳出當前函數的返回語句,具體示例如下:
return 0;
3、 用于定義變量的語句,具體示例如下:
int i = 10;
4、 用于執行簡單運算的語句,具體示例如下:
sum = 1.7f 2.5f;
需要特别注意的是,在書寫語句時,語句的末尾要有英文分号。
為了幫助大家更好地學習語句,接下來,通過一個案例來演示,如例4-1所示:
例4-1 語句
1 #include <stdio.h>
2 int main()
3 {
4 float sum = 0.0f;//定義了一個變量sum
5 sum = 1.2f 3.5f;//将sum重新賦值
6 printf("%f\n", sum);//輸出語句:輸出浮點數sum的值
7 printf("Hello world\n");//輸出語句:輸出Hello world
8 return 0;//返回語句
9 }
程序的運行結果如圖4-1所示:
圖 4‑1語句
在例4-1中,main()函數中包含了5條語句,這5條語句的作用如下所示:
第4行:定義了一個浮點數變量sum,并将浮點數的初值設為0.0;
第5行:将1.2和3.5兩個浮點數相加,并将加法運算的結果賦值給sum;
第6行:利用printf輸出語句打印sum的值;
第7行:利用printf輸出語句輸出Hello world
第8行:返回語句,跳出整個main函數,程序結束。
4.1.2 語句塊
在C程序中,使用"{}"包含的多條語句稱為一個語句塊,具體示例如下:
{
float sum = 0.0f;
sum = 3.5f;
printf("%f", sum);
}
上面的示例就是一個語句塊,它包含了三條語句,整個語句塊定義了一個變量sum并打印它的值。除了在形式上将一些語句組織在一起之外,語句塊還有一個顯著的作用就是它可以改變變量的作用域。所謂作用域就是在程序中可以正确使用這個變量的範圍。定義在語句塊内的變量隻能在語句塊内使用。為了大家更好地理解語句塊變量的作用域,接下來,通過一個案例來演示,如例程4-2所示:
例4-2 語句塊
10 #include <stdio.h>
11 int main()
12 {
13 int sum = 3;//定義了一個語句塊外的變量sum
14 {
15 int sum = 5;//在語句塊内定義了一個新的變量sum
16 printf("%d\n", sum);//在語句塊之内輸出sum的值
17 }
18 printf("%d\n", sum);//在語句塊之外輸出sum的值
19 return 0;
20 }
程序的運行結果如圖4-2所示:
圖 4‑2 語句塊
從上面的運行結果中可以看出:第一次調用printf的時候,輸出的sum是語句塊内的sum值,這說明了在語句塊内外出現重名變量時,在塊内使用的還是塊内的變量;第二次調用printf的時候輸出的是語句塊之外的sum,這說明了出了語句塊之後,語句塊内定義的sum就失效了,這從側面證明了塊内定義的sum作用域隻在塊内。
4.2 printf語句
printf是C語言中最基本的輸出語句,它負責向控制台中輸出内容。完整的printf用法非常龐雜,本節隻針對printf最常用的幾種用法進行講解,包括利用printf輸出字符串,輸出字符,輸出整數,輸出浮點數等等。
4.2.1 printf輸出字符串
printf最簡單的用法是直接輸出一串字符串,其語法格式如下所示:
printf("字符串");
需要注意的是,字符串要用英文雙引号括起來。例如,之前出現過的Hello world程序,如例程4-3所示:
例4-3 printf輸出字符串
21 #include <stdio.h>
22 int main()
23 {
24 printf("Hello, world!\n");
25 return 0;
26 }
程序的運行結果如圖4-3所示:
圖 4‑3 printf輸出字符串
除了直接将字符串寫在printf之中,printf還支持用下面的方式輸出一個字符串,具體格式如下所示:
printf("%s", "字符串");
在上述語法格式中, %s表示printf要輸出一個字符串,字符串則是用戶真正想要輸出的内容。
對例4-3進行修改,修改後的代碼如例4-4所示:
例4-4 printf格式化輸出字符串
27 #include <stdio.h>
28 int main()
29 {
30 printf("%s", "Hello, world!\n");
31 return 0;
32 }
程序的運行結果如圖4-4所示:
圖 4‑4 printf格式化輸出字符串
通過圖4-3和圖4-4的比較,發現使用兩種printf語句輸出字符串的效果是一緻的。
如果字符串太長,也可以将它拆成多個字符串分别輸出:
printf("%s %s", "字符串", "字符串");
和此前的例子一樣,這裡printf的第一個參數表示真正要輸出在控制台的内容。%s表示輸出一個字符串,這裡有兩個"%s"表示要輸出兩個字符串,并且兩個字符串之間存在一個空格。例4-5展示了如何利用printf輸出多個字符串:
例4-5 printf輸出多個字符串
33 #include <stdio.h>
34 int main()
35 {
36 printf("%s %s", "Hello", "world!\n");
37 return 0;
38 }
程序的運行結果如圖4-5所示:
圖 4‑5 printf輸出多個字符串
需要說明的是,在上面的語法中兩個%s之間不一定非要用空格來連接,第一個%s之前和第二個%s之後也可以有其他的内容,輸出的格式完全是由用戶自己控制的,比如下面的語句:
printf("%s%s\n", "Hello", " world!");
這條printf語句輸出了緊挨着的兩個字符串,在第二個字符串之後還輸出了一個\n,但是它的效果和前面是完全一樣的:原來兩個字符串之間的空格被放進了要輸出的第二個字符串,而第二個字符串原本的\n被單獨提出來放在了第一個參數中。
4.2.2 printf輸出字符
printf除了可以輸出字符串外,還可以輸出字符,使用printf輸出單個字符的語法格式如下所示:
printf("%c", 字符);
使用printf一次輸出多個字符的語法格式如下所示:
printf("%c %c", 字符, 字符);
接下來,通過一個案例來演示如何利用printf輸出字符的形式打印出Hello world,如例4-6所示:
例4-6 printf輸出字符
39 #include <stdio.h>
40 int main()
41 {
42 printf("%c%c%c%c%c%c%c%c%c%c%c%c%c",
43 'H', 'e', 'l', 'l', 'o', ' ',
44 'w', 'o', 'r', 'l', 'd', '!', '\n');
45 return 0;
46 }
程序的運行結果如圖4-6所示:
圖 4‑6 printf輸出字符
4.2.3 printf輸出整數
printf的第三個用法是輸出整數。整數類型有很多種,其中,用于輸出一個有符号整數的語法格式如下所示:
printf("%d", 有符号整數);
如果需要輸出多個整數,隻需要在printf中放入多個%d。接下來,通過一個案例來演示使用printf輸出三個int類型有符号整數值的情況,如例4-7所示。
例4-7 printf輸出有符号整數
47 #include <stdio.h>
48 int main()
49 {
50 int a = 15, b = -22, c = 123456;//定義三個int類型變量
51 printf("%d %d %d\n", a, b, c);
52 return 0;
53 }
程序的運行結果如圖4-7所示:
圖 4‑7 printf輸出有符号整數
在例4-7中,首先定義了三個int類型的變量a,b,c,并且它們都有初始值,然後使用printf輸出這三個變量的值。
除了輸出有符号整數,printf還可以輸出無符号整數,語法格式如下所示:
printf("%u", 無符号整數);
其中%u表示要輸出一個無符号整數。需要注意的是,如果在%u後面給出的是一個有符号整數,那麼printf會首先将該整數轉為無符号類型,然後再輸出它的值。接下來,通過一個案例來演示如何使用printf輸出兩個無符号整數,如例4-8所示:
例4-8 printf輸出無符号整數
54 #include <stdio.h>
55 int main()
56 {
57 unsigned short u = 456;//定義一個無符号類型整數u
58 int i = -1;//定義一個有符号類型整數i,初值為-1
59 printf("%u %u\n", u, i);
60 return 0;
61 }
程序的輸出結果如圖4-8所示:
圖 4‑8 printf輸出無符号整數
在上面的程序中,首先定義了一個無符号整數u,并初始化它的值為456;然後定義了一個有符号類型的int整數i,并初始化為-1。當使用printf輸出無符号整數u和i時,由于i是一個有符号的整數,因此,它首先會被轉換為無符号類型,然後再輸出,這也是輸出的i值為4294967295的原因。
除了上述幾種用法,printf還可以用來輸出八進制和十六進制整數。printf輸出八進制的語法如下:
printf("%o", 八進制整數);
其中%o表示輸出的是一個八進制整數。
printf輸出十六進制整數的語法如下:
printf("%x", 十六進制整數);
或者是:
printf("%X", 十六進制整數);
兩者的區别在于%x輸出的十六進制整數中所有字母都是小寫,而%X輸出的字母都是大寫。
接下來,通過一個案例來演示如何使用printf輸出八進制和十六進制整數,如例4-9所示。
例4-9 printf輸出其他進制
62 #include <stdio.h>
63 int main()
64 {
65 int a = 0123;//定義了一個八進制整數0123
66 int b = 0x1a2b3c4d;//定義了一個十六進制整數0x1a2b3c4d
67 printf("%o %x %X\n", a, b, b);
68 return 0;
69 }
運行
圖 4‑9 printf輸出其他進制
4.2.4 在上述程序中,首先定義了一個八進制的整數a,并賦值為0123;然後定義了一個十六進制的整數b并進行賦值。最後使用printf将a以八進制的形式,b以小寫十六進制和大寫十六進制的形式打印出來,結果如圖4-9所示。printf輸出浮點數
printf不僅可以輸出整數,還可以輸出浮點數,使用printf輸出浮點數的語法格式如下所示:
printf("%f", 浮點數);
其中%f表示以十進制的形式輸出一個浮點數。看一個使用printf輸出浮點數的例子,如例4-10所示
例4-10 printf輸出浮點數
70 #include <stdio.h>
71 int main()
72 {
73 double e = 2.718;//自然對數
74 float pi = 3.1416f;//圓周率
75 printf("%f %f\n", e, pi);
76 return 0;
77 }
程序的運行結果如圖4-10所示:
圖 4‑10 printf輸出浮點數
在這個例子中,程序裡首先定義了兩個浮點數e和pi,随後利用printf來輸出這兩個浮點數的值。需要注意的是,printf中的%f默認對應的浮點數是double類型,因此上面例子中的e會被首先轉為double類型的浮點數随後再輸出。
浮點數除了可以利用十進制表示之外,也可以利用科學計數法來表示。printf也支持利用科學計數法輸出一個浮點數。其語法格式如下所示:
printf("%e", 浮點數);
或者是
printf("%E", 浮點數);
兩者唯一的區别是在科學計數法的輸出中指數符号e是小寫還是大寫。%e表示小寫,而%E表示大寫。下面的例子展示了如何利用科學計數法的形式輸出一個浮點數,如例4-11所示:
例4-11 printf輸出浮點數
78 #include <stdio.h>
79 int main()
80 {
81 double e = 2.718;//自然對數
82 float pi = 3.1416f;//圓周率
83 printf("%e %E\n", e, pi);
84 return 0;
85 }
程序的運行結果如圖4-11所示:
圖 4‑11 printf輸出浮點數
在例4-11中,首先定義了兩個浮點數e和pi,然後分别以小寫和大寫的形式輸出了兩個以科學計數法表示的浮點數的值。
printf還可以控制浮點數的輸出長度。默認情況下,printf會輸出小數點後六位的數。 printf還允許程序員自己設定輸出小數的長度。它的語法如下所示:
printf("%.小數位數f", 浮點數);
其中小數位數指定了需要輸出的小數長度。下面的例子展示了printf的這種用法,如例4-12所示:
例4-12 printf輸出定長小數
86 #include <stdio.h>
87 int main()
88 {
89 float pi = 3.1416f;//圓周率
90 printf("%.0f %.2f %.4f\n", pi, pi, pi);
91 return 0;
92 }
程序的運行結果如圖4-12所示:
圖 4‑12 printf輸出定長小數
在例4-12中,程序首先定義了圓周率pi的值3.1416,随後使用printf分别輸出pi值的整數部分,pi值帶兩位小數的值,pi值帶四位小數的值。
4.2.5 printf格式控制字符
通過前面的學習,發現要想熟練使用printf函數,關鍵在于掌握printf中經常使用的格式控制字符,它們控制了printf輸出的具體類型。表4-1整理了4.2節中提到的所用常用格式控制字符。
表4-1 常用printf格式字符
最好對表中的内容有個簡單的介紹
4.3 scanf語句
scanf是C語言中最基本的輸入函數。它負責從控制台上接受用戶的輸入。和printf類似,scanf也可以靈活接受各種類型的輸入,包括字符串,字符,整型,浮點數等等。本節将逐一介紹如何利用scanf從控制台上獲取用戶的輸入。
4.3.1 scanf讀入字符串
本節中首先介紹如何利用scanf獲得用戶輸入的字符串。由于scanf需要從控制台中獲取輸入,因此在使用scanf獲取字符串之前首先要定義一個字符數組來保存獲得的字符串:
char str[256];
上面的語句定義了一個字符數組str,它的大小為256,目前可以将它理解為由連續256個字符組成的一段連續的内存。
利用scanf獲得字符串輸入的語法如下:
scanf("%s", 字符串地址);
和printf類似,這裡也用%s來表示數據的類型是一個字符串,scanf的第二個參數字符串地址指明了需要将字符串保存在什麼地方。在字符數組中,數組的名稱指示了字符數組的地址,因此可以直接用數組名作為scanf的第二個參數。
需要注意的是,scanf用來從控制台接受用戶輸入的字符串,隻要用戶的輸入中包含了以下任意一種字符,scanf就認定用戶想要輸入的字符串已經完畢了。這些字符包括:
表4-2 scanf輸入字符串的終止符
從上面的表格可以看出,如果用戶輸入後按下了空格、回車、tab等鍵,scanf都會認為輸入字符串已經終止。接下來,通過一個案例來演示如何使用scanf讀入字符串,如例4-13所示。
例4-13 scanf讀入字符串
93 #include <stdio.h>
94 int main()
95 {
96 char str[256];//字符數組保存得到的字符串
97 scanf("%s", str);
98 printf("%s\n", str);
99 return 0;
100 }
程序的運行結果如圖4-13所示:
圖 4‑13 scanf讀入字符串
在例4-13中,首先定義了一個長度為256個字符的字符數組str,随後利用scanf獲得用戶從控制台的輸入;接下來利用printf将得到的字符串打印在控制台上,例如,用戶從控制台上輸入了Hello world。
這從圖4-13可以看出,盡管輸入的字符串是Hello world,但是程序隻打印了Hello。這是因為在Hello world中包含了一個空格,因此scanf隻能讀到之前的Hello而無視了空格之後的world。相應地,假設輸入是不含空格的Helloworld,那麼上述程序的運行結果如圖4-14所示:
圖 4‑14 scanf輸入字符串
這時從圖4-14看出,輸入的Helloworld被完整地輸出在控制台上。由于輸入的Helloworld中不包含空格,因此輸入完成後的回車鍵就被scanf認為是字符串終止的标志,整個Helloworld都被scanf讀進了str數組中。
4.3.2 scanf讀入字符
利用scanf還可以讀入單個字符,其語法格式如下所示:
scanf("%c", 字符地址);
在上述語法格式中,%c用來表示獲取單個字符,字符地址用于告訴scanf獲得的字符保存在哪個變量中。與scanf讀取字符串不同的是,字符地址需要通過"&字符名稱"的方式獲取。
下面的例子中展示了如何從scanf獲得用戶輸入的一個字符,如例4-14所示:
例4-14 scanf讀入字符
101 #include <stdio.h>
102 int main()
103 {
104 char c;//保存用戶讀入的字符
105 scanf("%c", &c);
106 printf("%c\n", c);
107 return 0;
108 }
程序的運行結果如圖4-15所示:
圖 4‑15 scanf讀入字符
在例4-14中,首先讀入一個字符,然後将字符在控制台上輸出,用以驗證scanf讀入的字符是否正确。假設用戶輸入了一個英文字母e。
需要注意的是,scanf還可以讀入一些特殊字符。假設用戶輸入的是一個回車,程序運行後的結果如圖4-16所示:
圖 4‑16 scanf讀入字符
在圖4-16所示的結果中,程序一共打印出三個回車,具體如下:
第一個回車:用戶輸入的回車;
第二個回車:printf打印的字符變量c;
第三個回車:printf輸出變量c之後末尾的回車。
上面的運行結果證明了特殊字符回車被scanf以%c的形式正确地讀入到了字符變量c當中。
4.3.3 scanf讀入整數
同printf輸出整數類似,scanf讀入整數時,也需要用到格式控制符%d,具體語法格式如下:
scanf("%d", 整數地址);
在上述語法格式中,%d表示scanf要讀入的是一個十進制有符号整數,并将這個整數存放在第二個參數所指示的地址當中。當利用scanf讀入整數時,輸入的整數可以包括正負号。下面是一個利用scanf讀入十進制整數的例子,如例4-15所示。
例4-15 scanf讀入整數
109 #include <stdio.h>
110 int main()
111 {
112 int i;//用來保存讀入的十進制整數:
113 scanf("%d", &i);
114 printf("%d\n", i);
115 return 0;
116 }
在例4-15中,首先定義了一個int類型的變量i,然後使用scanf從控制台讀入一個整數,最後使用printf将讀入的整數輸出在控制台上。假設用戶輸入的整數是1234,程序的運行結果如圖4-17所示:
圖 4‑17 scanf讀入整數
為了驗證scanf能否接受帶正負号的輸入,假設用戶輸入的是 1234,程序的運行結果如題4-18所示。
圖 4‑18 scanf讀入整數
如果用戶輸入的是-1234,程序的運行結果如圖4-19所示。
圖 4‑19 scanf讀入整數
除了接受十進制輸入,scanf也可以接受八進制或者十六進制的輸入。scanf讀入八進制整數的語法是:
scanf("%o", 整數地址);
其中%o表示scanf等待輸入的是一個八進制整數,輸入的整數也可以包括正負号。下面的例程展示了如何利用scanf讀入一個八進制整數,如例4-16所示。
例4-16 scanf讀入八進制數
117 #include <stdio.h>
118 int main()
119 {
120 int i;//保存讀入的整數
121 scanf("%o", &i);
122 printf("%o\n", i);
123 return;
124 }
需要說明的是:在程序中定義一個八進制常量時必須要在開頭寫0,但是在scanf讀入八進制整數的時候這個0可以忽略不寫。這是因為scanf會自動将用戶的輸入視為一個八進制整數。例如,不管輸入123還是0123,scanf得到的都是相同的八進制整數,具體如圖4-20、圖4-21所示。
圖 4‑20 scanf讀入八進制整數
圖 4‑21 scanf讀入八進制整數
scanf讀入十六進制整數的語法格式如下所示:
scanf("%x", 整數地址);
其中%x表示scanf等待的是一個十六進制整數,這個十六進制整數可以以0x或者0X開頭,可以包括正負号,也可以混雜a到f的大小寫。先來看一個例子,如例4-17所示。
例4-17 scanf讀入十六進制數
125 #include <stdio.h>
126 int main()
127 {
128 int i;//保存讀入的整數
129 scanf("%x", &i);
130 printf("%x\n", i);
131 printf("%X\n", i);
132 return 0;
133 }
在例4-17中,首先定義了一個int類型的變量i,用來保存scanf讀入的結果。接下來,利用scanf将輸入的十六進制數保存在i中,并用大小寫兩種方式将i的值打印在控制台上。假設用戶的輸入是0x1a2b3c4d,程序的運行結果如圖4-22所示:
圖 4‑22 scanf讀入十六進制整數
也可以省略最開頭的0x,直接輸入十六進制數字。假設用戶的輸入是1a2b3c4d,則程序的運行結果如圖4-23所示。
圖 4‑23 scanf讀入十六進制整數
還可以在輸入的十六進制數當中混雜大小寫,比如用于輸入1a2B3c4D,程序的運行結果如圖4-24所示。
圖 4‑24 scanf讀入十六進制整數
由此可見,雖然使用scanf讀取的十六進制形式不同,但最後讀入的十六進制整數結果相同。
4.3.4 scanf讀入浮點數
使用scanf還可以讀入浮點數,其基本的語法格式如下所示:
scanf("%f", 浮點數地址);
在上述語法格式中,%f表示要輸入的是一個十進制小數,輸入當中可以包含小數點和正負号,輸入的結果保存在第二個參數浮點數地址指示的位置上。需要注意的是,在printf中%f默認對應的數據類型是double,而在scanf中%f對應的數據類型為float,因此如果要用%f來讀入一個浮點數的話,需要聲明一個float類型的變量。先來看一個例子,如例4-18所示。
例4-18 scanf讀入浮點數
134 #include <stdio.h>
135 int main()
136 {
137 float f;//保存讀入的浮點數
138 scanf("%f", &f);
139 printf("%f\n", f);
140 return 0;
141 }
在例4-18中,首先定義了一個浮點數變量d,然後利用scanf從控制台上讀入了一個浮點數,最後将浮點數的值打印出來。假設用戶的輸入是 123.45,程序的運行結果如圖4-25所示:
圖 4‑25 scanf讀入浮點數
這裡用戶輸入的 123.45在輸出的時候變成了123.449997。上面的運行結果表明float的精度不足以準确保存123.45的值。想要得到更加精确的結果隻能使用double。如果想要用double來保存從scanf讀入的浮點數,需要将scanf中的%f改為%lf,具體格式如下:
scanf("%lf", 浮點數地址);
%lf默認對應的數據類型是double,第二個參數中的浮點數地址也必須是double變量的地址。下面的例程展示了如何利用%lf讀入一個浮點數保存在double中,如例4-19所示。
例4-19 scanf讀入浮點數
142 #include <stdio.h>
143 int main()
144 {
145 double d;//保存讀入的浮點數
146 scanf("%lf", &d);
147 printf("%f\n", d);
148 return 0;
149 }
上面的程序使用double類型的變量來保存讀入的浮點數,提高了浮點數的精度。假設用戶輸入的依然是 123.456,這一次程序的運行結果如圖4-26所示。
圖 4‑26 scanf讀入浮點數
通過圖4-25和圖4-26的比較,發現使用讀入的浮點數精度明顯提高了。
scanf同樣接受以科學計數法表示的浮點數。當利用scanf讀入一個用科學計數法表示的浮點數時,它的語法格式如下所示。
scanf("%e", 浮點數地址);
在上述語法格式中,e表示讀入的是一個科學計數法形式的浮點數,并将它保存在第二個參數所對應的浮點數當中。這裡%e默認使用的數據類型也是float。下面的例子展示了%e的用法,如例4-20所示。
例4-20 scanf讀入科學計數法
150 #include <stdio.h>
151 int main()
152 {
153 float e;//保存讀入的浮點數
154 scanf("%e", &e);
155 printf("%e\n", e);
156 return 0;
157 }
在例4-20中,首先定義了一個浮點數e,随後利用scanf讀入一個科學計數法表示的浮點數,最後将e的值打印在控制台上。假設用戶的輸入是12.3e4,程序最後的運行結果如圖4-27所示。
圖 4‑27 scanf讀入科學計數法
同樣的,要想将讀入的浮點數保存在double中的話,需要将%e換成%le,其語法格式如下所示:
scanf("%le", 浮點數地址);
需要注意的是,%le默認對應的數據類型是double,因此,第二個參數"浮點數地址"的數據類型也必須是double類型。下面的例程展示了%le的使用效果,如例4-21所示。
例4-21 scanf讀入科學計數法
158 #include <stdio.h>
159 int main()
160 {
161 double d;//保存讀入的浮點數
162 scanf("%le", &d);
163 printf("%e\n", d);
164 return 0;
165 }
假設用戶輸入了12345.6789e10,上述程序的輸出結果如圖4-28所示。
圖 4‑28 scanf讀入科學計數法
注意:
在printf中,%e默認對應的數據類型就是double,而在scanf中%e對應的是float,%le對應的才是double。
4.3.5 scanf格式控制字符
和printf類似,要想熟練使用scanf函數,也需要充分掌握scanf中經常使用的格式控制字符,它們控制了scanf輸入的具體類型。表4-3列舉了4.3節中提到的所用常用格式控制字符。
表4-3 常用scanf格式字符
4.4 輸入輸出實例
scanf和printf的基本使用方法已經全部介紹完畢。本節中将要介紹一些scanf和printf共同配合使用的實例。scanf和printf構成了程序中一對完整的輸入輸出語句,在兩者之間,程序可以對scanf獲得的數據進行一定的處理,并使用printf将處理的結果輸出到控制台上。
4.4.1 大小寫轉換
下面的這個程序實現了一個很小的功能:從控制台接受用戶輸入的小寫英文字母,并将它轉化為大寫英文字母輸出:
例4-22 大小寫轉換
166 #include <stdio.h>
167 int main()
168 {
169 char ch;//保存用戶輸入的字符
170 scanf("%c", &ch);
171 ch = 'A' - 'a';
172 printf("%c\n", ch);
173 return 0;
174 }
這裡來逐行分析上述程序的作用:
第4行:定義了一個字符類型的變量ch,用來保存用戶輸入的字符;
第5行:從控制台接受用戶輸入的小寫英文字母;
第6行:将小寫英文字母轉換為大寫英文字母。由于在ASCII碼中大寫英文字母是連續編号的,小寫英文字母也是連續編号的,因此任何一對大小寫英文字母之間的差是相同的,這就是為什麼在第6行中可以直接用大寫A和小寫a之間的差來将小寫英文字母轉換為大寫英文字母。
第7行:将轉換之後的字符打印在控制台上。
假設用戶輸入的是f,程序運行後的輸出結果為:
圖 4‑29 大小寫轉換
需要注意:由于在程序中并沒有檢查輸入的範圍,因此如果輸入的字符不是小寫英文字母的話,程序會輸入未知的ASCII碼結果。比如當用戶輸入的是一個阿拉伯數字0的時候:
圖 4‑30 大小寫轉換
要想正确處理不合法的輸入,僅僅依靠輸入和輸出語句是完全不夠的。本書随後将要介紹的if判斷結構可以用來處理不合法的輸入或者其他異常情況,從而幫助程序員寫出更加健壯的程序。
4.4.2 計算課程得分
某所大學的C語言課程期末考試采用百分制,每個學生的期末考試分數會是一個在0到100(包含)之間的整數。然而這所大學的課程成績采用的是4分制,即學生在每門課的最終成績會是一個在0到4之間的浮點數。為此,C語言課程的老師決定按照如下的方式為學生登記課程分數:
課程分數=期末成績/25
這樣剛好可以将範圍在0到100之間的期末考試成績線性地轉換到0到4分的課程分數。現在請設計一個程序幫助老師自動完成上述轉換工作。
程序輸入:一個0到100之間(包含0和100)的整數,表示考生的期末成績
程序輸出:考生的課程得分,用浮點數表示。
分析:
這個程序的結構可以被非常清晰地分解成三個部分:
從控制台讀入一個整數;
計算考生的課程分數;
輸出考生的課程分數;
按照這個思路程序的整體框架如下:
175 #include <stdio.h>
176 int main()
177 {
178 int score;
179 float gpa;
180 //從控制台讀入一個整數
181 //計算考生課程分數
182 //輸出考生的課程分數
183 return 0;
184 }
其中,整數類型的score用來保存期末考試成績,浮點數gpa用來表示考生課程分數。
首先來看第一步:從控制台輸入一個整數。根據前面的知識,讀入一個整數可以用scanf來完成。score是一個整數變量,所以在這裡要使用的格式字符是%d。不要忘了在score前面加上&:
scanf("%d", &score);
接下來計算課程分數。計算公式非常直接:将score除以25即可:
gpa = score / 25;
最後一步輸出考生的課程得分:利用printf函數可以向屏幕上輸出考生的得分gpa。注意到gpa是一個浮點數, printf中的格式字符選擇%f:
printf("%f\n", gpa);
完整的程序如下:
例程 4‑23 計算課程得分
185 #include <stdio.h>
186 int main()
187 {
188 int score;
189 float gpa;
190 //從控制台讀入一個整數
191 scanf("%d", &score);
192 //計算考生得分
193 gpa = score / 25;
194 //輸出考生的得分
195 printf("%f\n", gpa);
196 return 0;
197 }
開始運行上述程序,假設現在考生的期末考試成績是90分,按照上述公式,該名考生的課程成績應該是3.6,然而程序的運行結果如下:
圖 4‑31 計算課程得分
輸出的考生課程得分是3.0,這意味着程序中存在錯誤。為了找出錯誤,可以從後向前一步一步地檢查:
首先,printf的用法是正确的:gpa是浮點數,選擇%f沒有錯,這說明此時gpa的值确實是4.5。
再向前看gpa是如何計算出來的:
gpa = score / 25;
由于score是90,而gpa是3,也就是說90/25的計算結果是3:原來錯誤在于程序在兩個整數之間使用了除法,得到的結果被向零取整了。
明白了錯誤在哪裡,程序就很好改了:隻需要把score強制轉換成浮點數,浮點數除以整數的時候會按照浮點數除法來運算,就可以得到正确的結果了:
例程 4‑24 計算課程得分
198 #include <stdio.h>
199 int main()
200 {
201 int score;
202 float gpa;
203 //從控制台讀入一個整數
204 scanf("%d", &score);
205 //計算考生得分
206 gpa = (float)score / 25;
207 //輸出考生的得分
208 printf("%f\n", gpa);
209 return 0;
210 }
運行程序,假設這次用戶輸入依然是90,程序的運行結果如圖4-32所示:
圖 4‑32 計算課程得分
從圖4-32可以看出輸入90分之後得到了期望的輸出3.6,這一次程序的運行結果正确。
這個例子不僅展示了如何利用scanf和printf完成基本的輸入輸出操作,還展示了當程序中出現問題時應該如何面對:隻要逐步縮小出錯的範圍,就一定能找到錯誤并改正它!
4.5 本章小結
本章首先介紹了C語言中語句和語句塊的用法,随後重點介紹了C語言中的輸入函數printf和輸出函數scanf的具體用法。printf和scanf是C語言中最基本的語句之一,在今後的學習和實踐中具有非常廣泛的應用。
18
1
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!