Professional Documents
Culture Documents
資料的輸出與輸入
資料的輸出
資料的輸入
可能的輸入問題與解決方法
字串的表達與使用
尊重智慧財產權,請勿任意複製或是轉載!
本章簡介
程式的首要工作
確保輸入的資料沒有錯誤
對輸入的資料進行加工與處理
轉變成有用的資訊
依照既定格式輸出這些資訊
輸入的媒介
程式中直接給、從檔案讀取
從鍵盤、滑鼠或是繪圖版讀取
資料的輸出
螢幕、印表機
或其他的裝置
螢幕與鍵盤為標準輸出入裝置
stdout (螢幕)
stdin (鍵盤)
尊重智慧財產權,請勿任意複製或是轉載!
資料的輸出
pinrtf 格式化輸出函式
puts/putchar 字串/字元輸出函式
尊重智慧財產權,請勿任意複製或是轉載!
資料的輸出
printf ()
將指定的內容以指定的格式(控制格式)輸出在螢幕上。
內容可以是 int、float、double、char(字元或是字串)
putchar ()
函數名稱取 put 以及 character 兩個字組成
函式的用途是輸出字元,一次只能輸出一個字元
不具備像 printf () 的格式化輸出功能
puts()
函數名稱取 put 以及 string 兩個字組成
函式的用途是輸出字串,一次只能輸出一個字串
不具備像 printf () 的格式化輸出功能
這些預設都是從螢幕 stdout 輸出
3
尊重智慧財產權,請勿任意複製或是轉載!
pinrtf 格式化輸出函式
printf(格式化字串[[,引數1][,引數2][,引數3]…]);
格式化字串(format string)
必須是字串,一定要寫在兩個雙引號 " " 之間
可包含文字或是控制格式,如:
%d(輸出整數)、%f(浮點數)、%c(字元),以 % 為開頭的就是控制格式
範例
單純的文字,如:"台北101"
包含一個控制字元輸出,如:"你購買 %d 杯紅茶"
包含兩個控制字元輸出,如:"購買 %d 杯可以打 %d 折"
[[,引數1][,引數2][引數3]…]
引數可以是變數、常數或是運算式,如:x*2-15
中括弧 [ ] 所包含的部分代表該選項是可有可無的
不同的引數之間一定要有逗號「,」來區隔
尊重智慧財產權,請勿任意複製或是轉載!
pinrtf 格式化輸出函式
[[,引數1][,引數2][引數3]…]
範例
沒有引數:printf("台北101");
一個引數:printf("你購買 %d 杯紅茶" ,Cups);
兩個引數:printf("購買 %d 杯可以打 %d 折",Cups, 85);
記住以下的兩個規則:
個數相同
引數的個數與格式化字串中所出現的控制格式的數量要相同
引數與引數之間一定要用逗號隔開(初學很容易忘記打逗號)
型別與控制格式相符
引數與控制格式的出現順序是一對一對應的,而且型別必須相
符,否則輸出的結果將無法預期
尊重智慧財產權,請勿任意複製或是轉載!
pinrtf 格式化輸出函式
範例 77 的一杯35元
購買 10 杯,共 131267028 元
購買 1073741824 杯,可以打 0.00 折
#include <stdio.h>
#include <stdlib.h> Prog3-1.c
int main(void)
{
int iCups = 10;
char cSize = 'M'; //中杯對應的英文字母,字元以整數輸出
float fDiscount = 0.85;
printf("%d 的一杯35元\n",cSize);// 給錯輸出格式
printf("購買 %d 杯,共 %d 元\n",iCups); //漏打了一個引數
printf("購買 %d 杯,可以打 %1.2f 折\n",fDiscount,iCups); //引數不小心放錯順序
system("pause"); return(0);
}
記得是一對一的對應關係
尊重智慧財產權,請勿任意複製或是轉載!
pinrtf 格式化輸出函式
%[flags] [width] [.precision] [l | h | L]type
%[輸出調整旗標] [最少輸出字元數] [.輸出位數] [資料型別修飾]輸出格式
type(輸出格式)
控制格式唯一必要的項目
指定輸出的資料型態,可使用的控制字元如下
x 與 e 有大小寫的選擇,差別在於輸出的英文字母顯示為大寫或小寫
g (或 G) 則是根據輸入浮點數的精確度,自動選擇 e (或自動選擇 E ) 或 f
來顯示浮點數 7
尊重智慧財產權,請勿任意複製或是轉載!
pinrtf 格式化輸出函式
flags(輸出調整旗標)
在輸出的數值之前,顯示正(+)、負(-)符號、空白、數字0、小數點(.)、八進
位(0)或十六進位(0x、0X)符號等
可使用的旗標與功能如下表所示:
flag 功能說明
- 輸出的數值靠左對齊。如:%-14.6f
+ 在輸出的數值前顯示該數的正(+)、負(-)符號
0 當輸出內容少於 width 欄位所指定的字元數時,不足的部分會在輸出的前面補零
空白 當輸出為正數時,前面補上一個空白(此方便對齊於負數前的負號)。
空白與 + 同時出現時,空白旗標的功能被忽略
# 與 o, x 或 X 控制字元一起使用時,數值的前面將會分別補上 0, 0x 與 0X,
其中 0 表示 8 進位,0x(0X) 表 16 進位數值
與 e, E 或 f 控制字元一起使用時,輸出的數值一定會包含小數點
與 g 或 G 控制字元一起使用時,會保留小數點後的 0 9
尊重智慧財產權,請勿任意複製或是轉載!
pinrtf 格式化輸出函式
控制輸出欄位的寬度
%[flags] [width] [.precision] [l | h | L]type
%[輸出調整旗標] [最少輸出字元數] [.輸出位數] [資料型別修飾]輸出格式
Width(最少的輸出字元數)
數值位數不到該字元數時,輸出時會向右對齊
前面不足的位置會以空白填補
輸出數值所伴隨顯示的符號都算在 width 內
如:正負號、0x、小數點、e 或 E 等
10
尊重智慧財產權,請勿任意複製或是轉載!
pinrtf 格式化輸出函式
控制輸出欄位的寬度
%[flags] [width] [.precision] [l | h | L]type
%[輸出調整旗標] [最少輸出字元數] [.輸出位數] [資料型別修飾]輸出格式
.precision(指定輸出的位數)
與不同的控制字元搭配效果如下:
d, u, o, x, X:precision 設定一定要輸出的字元數,如果數值
位數不足該字元數時前面補 0。例如
60 配合 %6.4d 的輸出結果為□□0060(□為空白)
e, E, f:precision 設定在小數點之後一定要輸出的位數
s:precision 設定字串一定要輸出的字元數。
11
尊重智慧財產權,請勿任意複製或是轉載!
pinrtf 格式化輸出函式
控制輸出欄位的寬度
%[flags] [width] [.precision] [l | h | L]type
%[輸出調整旗標] [最少輸出字元數] [.輸出位數] [資料型別修飾]輸出格式
l | h | L(指定的型別輸出資料)
l(小寫 L)代表 long,h 代表 short、L 代表 long double。
舉例來說
變數 x 為 int 型別,當 x 以 %hd 輸出時,x 的內容會被轉
成 short 然後再輸出
12
尊重智慧財產權,請勿任意複製或是轉載!
pinrtf 格式化輸出函式
整數的範例(開啟並執行 Prog3-3.c) Prog3-3.c
13
尊重智慧財產權,請勿任意複製或是轉載!
pinrtf 格式化輸出函式
浮點數的範例
#include <stdio.h>
#include <stdlib.h> Prog3-4.c
int main(void)
{
double dVal = 9453.59;
printf("123456789012345\n"); //顯示定位用 123456789012345
printf("%f\n",dVal); //全部輸出,小數點下固定6位 9453.590000
printf("%e\n",dVal); //全部輸出,小數點下固定6位 9.453590e+003
printf("%4.2f\n",dVal); //4個字元,小數點下2位 9453.59
printf("%10.1f\n",dVal); //10個字元,小數點下1位 9453.6
printf("%010.3f\n",dVal); //10個字元,小數點下3位,前面補0 009453.590
printf("%15.4e\n",dVal); //15個字元,小數點下4位 9.4536e+003
printf("%+10.2f\n",dVal); //輸出正負號,10個字元,小數點下2位 +9453.59
system("pause"); return(0);
}
硬是要去背誦這些控制方式會蠻花時間的,而且也不見得記得住
建議先記住一些常用的
14
尊重智慧財產權,請勿任意複製或是轉載!
puts/putchar 字串/字元輸出函式
puts 輸出字串,並在最後輸出一個換行字元('\n')
putchar
輸出一個字元
若引數是數字,則根據 ASCII 編碼將該數字轉換成字元後輸出
#include <stdio.h>
Prog3-5.c
#include <stdlib.h> a
int main(void) 上一行以 putchar(cNL) 輸出換行
A
{
char cNL = '\n'; int n = 97;
putchar(n); /* 輸出變數 n 的值, a 的 ASCII 編碼是 97 */
putchar(cNL);
puts("上一行以 putchar(cNL) 輸出換行");
putchar(65); /* 輸出 65 所對應的字元*/
putchar('\n'); /* 換行*/
system("pause"); return(0);
}
15
尊重智慧財產權,請勿任意複製或是轉載!
資料的輸入
scanf 格式化輸入函式
getchar/getche/getch 字元輸入函式
16
尊重智慧財產權,請勿任意複製或是轉載!
輸入函式簡介
scanf ()
函式名稱取 scan 以及 format 兩個字組成
使用者以鍵盤輸入資料後, 需按下 Enter 鍵,才會讀取資料
getchar ()
函式名稱取 get 以及 character 兩個字組成
輸入資料後按下 Enter 鍵, 會讀取資料的第 1 個字元進入程式
gets()
函式名稱取 get 以及 string 兩個字組成
在輸入資料後按下 Enter 鍵, 會讀取輸入的所有文字
getch() 與 getche() 非 ANSI C 所提供的函式
功能與 getchar 相同,無須按下 Enter 鍵,就會自動讀取第 1 個字元
getche():輸入的字元會顯示在螢幕上
getch() :輸入的字元不會顯示在螢幕上
17
尊重智慧財產權,請勿任意複製或是轉載!
scanf 格式化輸入函式
scanf () 函式:格式化輸入函式
最常用的鍵盤輸入函式
可配合各種輸入格式控制字元, 讀取任何型別的資料
18
尊重智慧財產權,請勿任意複製或是轉載!
scanf 格式化輸入函式
使用 scanf () 的格式如下:
scanf(格式化字串,引數1[[,引數2][,引數3]…]);
格式化字串:scanf 只負責輸入,所以格式化字串中所存放的都是
控制字元的組合,最多加上空白或是一些符號的組合。定義如下:
%[width] [l | h | L]type
type:與 printf 是相同
c (字元)、d (整數)、o (8進位整數)、u (無正負號整數)、x (16進位整數)、
s (字串)、f(浮點數,float) 與 lf (浮點數, double)
%f (浮點數,必須以 float 變數來接收)
%lf 則是配合 double 型別變數來接收使用輸入的浮點數
width最大可接受的字元數
輸入的字元數如果超過 width 的設定,超過的部分會直接忽略
l | h | L:轉換指定的型別
l (小寫 L)代表 long,h 代表 short、L 代表 long double
例如:%hd 必須以 short 型別變數來接收輸入的短整數
19
尊重智慧財產權,請勿任意複製或是轉載!
scanf 格式化輸入函式
範例
"%d" : 讀取一個整數
"%x" : 讀取一個 16 進位數值
"%f" : 讀取一個單倍精確度浮點數
"%lf" : 讀取一個雙倍精確度浮點數 (double)
“%4d” : 讀取輸入的前四個字元為輸入的整數,超過的將被忽略
20
尊重智慧財產權,請勿任意複製或是轉載!
scanf 格式化輸入函式
scanf(格式化字串,引數1[[,引數2][,引數3]…]);
[[,引數1][,引數2][引數3]…]:
使用規則:引數必須是儲存變數所對應的位址(左值)
變數前加上 & 符號,代表變數的位址(左值)
初學者最容易在這裡忽略了 &
使用注意事項
引數與格式化字串中控制字元必須
個數相同、型別與控制格式相符
21
尊重智慧財產權,請勿任意複製或是轉載!
scanf 格式化輸入函式
範例
#include <stdio.h>
#include <stdlib.h> Prog3-6.c
int main(void)
{
int iAge, iCode; short iId1, iId2;
float fWeight; char cH;
printf("輸入性別代碼(M:男,F:女):"); scanf("%c",&cH);
printf("輸入的是: %c\n",cH);
printf("輸入年齡:"); scanf("%d",&iAge);
printf("輸入的是: %d\n",iAge); 輸入性別代碼(M:男,F:女):F
printf("輸入體重(小數點下1位):"); 輸入的是: F
scanf("%f",&fWeight); 輸入年齡:23
printf("輸入的是: %3.1f\n",fWeight); 輸入的是: 23
printf("輸入兩個整數代碼:"); 輸入體重(小數點下1位):56.5
scanf("%hd%hd",&iId1,&iId2); 輸入的是: 56.5
printf("輸入的兩個數字: %d %d\n",iId1,iId2); 輸入兩個整數代碼:1234 45678
printf("輸入身份證後四碼:"); 輸入的兩個數字: 1234 -19858
scanf("%4d",&iCode); 輸入身份證後四碼:12345
printf("輸入的四碼是: %d\n",iCode); 輸入的四碼是: 1234
system("pause"); return(0);
輸入非預設格式所能接受的
22
}
尊重智慧財產權,請勿任意複製或是轉載!
scanf 格式化輸入函式
再次執行 Prog3-6.c,製造以下的錯誤
第7行
printf("輸入性別代碼(M:男,F:女):"); scanf("%c",&cH);
將 scanf 中的 &cH 改成 cH,產生引數格式錯誤
第9行
printf("輸入年齡:"); scanf("%d",&iAge);
程式執行時,故意輸入英文字母或是浮點數來代表年齡
製造輸入內容與所預期接受型別不符的錯誤(這種錯誤最常遇到)
第 15 行
scanf("%hd%hd",&iId1,&iId2);
將 scanf 中的 &hd 改成 &d,產生格式不相符的錯誤
上述的三種錯誤,是使用 scanf 時最容易發生的
23
尊重智慧財產權,請勿任意複製或是轉載!
scanf 格式化輸入函式
範例 ─ 多筆資料的輸入
格式化字串中放置多個控制格式即可
「,」、「@」、「#」等符號也可以當成是輸入的間隔。
應用時必須先在格式化字串中直接填入
如:“%d#%d”,輸入的內容也同樣必須使用相對應的符號才行
使用這樣的輸入方式,一定要有足夠的提示
尊重智慧財產權,請勿任意複製或是轉載!
變數內容的交換
範例:交換變數 x 與 y 的內容
直接寫 x = y 是不對的
那只是讓變數 x 的內容變成 y 而已
交換是有技巧的,需要借用另外一個變數來達成
#include <stdio.h>
#include <stdlib.h> Prog3-8.c
int main(void)
{
int x, y, t; // t 用於交換過程的暫存
printf("輸入兩個整數 x 與 y : ");
scanf("%d%d",&x,&y);
printf("交換前: x = %d, y = %d\n",x,y);
t = x; x = y; y = t; // 交換兩個變數內容
printf("交換後: x = %d, y = %d\n",x,y); 輸入兩個整數 x 與 y : 56 23
system("pause"); return(0); 交換前: x = 56, y = 23
} 交換後: x = 23, y = 56
25
尊重智慧財產權,請勿任意複製或是轉載!
程式技術講座
變數內容的交換
程式設計中經常會用到的技巧。
假設 x 與 y 是兩個變數,基本規則就是
再宣告一個相同型別的變數 (假設變數名稱為 t)
將 x 內容儲存到 t
指定 y 的內容給 x (x 內容已經保留在 t 中,所以內容可以被取代)
將 t 的內容給 y
程式碼就是寫成:t = x; x = y; y = t;
26
尊重智慧財產權,請勿任意複製或是轉載!
scanf 格式化輸入函式
範例 ─ 16 進位與 8 進位數值的輸入與輸出
%x 與 %o 接收
請輸入:16 進位數值 0x12、FF 或是 8 進位數值
0127 是否能如所預期的透過 scanf 正確的讀入
#include <stdio.h>
#include <stdlib.h> Prog3-9.c
輸入一個16進位數字:0xFa
int main(void)
fa(16進位) = 250(10進位) = 372(8進位)
{
輸入一個 8 進位數字:546
int iO,iH;
546(8進位) = 358(10進位) = 166(16進位)
printf("輸入一個16進位數字:");
scanf("%x",&iH);
printf("%x(16進位) = %d(10進位) = %o(8進位)\n",iH,iH,iH);
printf("輸入一個 8 進位數字:");
scanf("%o",&iO);
printf("%o(8進位) = %d(10進位) = %x(16進位)\n",iO,iO,iO);
system("pause"); return(0);
} 27
尊重智慧財產權,請勿任意複製或是轉載!
getchar/getche/getch 字元輸入函式
28
尊重智慧財產權,請勿任意複製或是轉載!
getchar/getche/getch 字元輸入函式
範例
#include <stdio.h>
#include <stdlib.h> Prog3-10.c
#include <conio.h>
int main(void)
{
char cx;
printf("輸入一個字元: "); cx = getchar(); 輸入一個字元: X
printf("輸入的字元是: %c\n",cx); 輸入的字元是: X
printf("輸入一個字元: "); cx = getche(); 輸入一個字元: y輸入的字元是: y
printf("輸入的字元是: %c\n",cx); 輸入一個字元: 輸入的字元是: Z
printf("輸入一個字元: "); cx = getch();
printf("輸入的字元是: %c\n",cx); 沒有顯示輸入的字元喔!執行結果
system("pause"); return(0);
}
getch 與 getche 只要一按下按鍵就會立刻處理
29
尊重智慧財產權,請勿任意複製或是轉載!
可能的輸入問題與解決方法
如何正確讀取/跳過空白字元
解決輸入緩衝區的問題--記得清除
輸入緩衝區
30
尊重智慧財產權,請勿任意複製或是轉載!
如何正確讀取/跳過空白字元
練習一
輸入:三個空白後再跟著200NTD
結果:讀取到 200
前面的空白並沒有被接受,後面的NTD也沒有被處理
#include <stdio.h>
#include <stdlib.h> Prog3-11.c
int main(void)
{
char ch = '\0'; int ix = 0;
printf("輸入一個整數:"); scanf("%d",&ix);
// printf("輸入一個字元:"); scanf("%c",&ch);
printf("ch = %d, ix = %d\n",ch,ix);
system("pause"); return(0);
}
31
尊重智慧財產權,請勿任意複製或是轉載!
如何正確讀取/跳過空白字元
練習二:
第 6 行前面輸入 // ,設定這一行是註解,然後刪除第 7 行前面的 //
輸入:一個空白鍵然後再輸入一個字元 A
結果:讀取到第一個空白字元
練習三:
scanf 中的 “%c” 改成 “ %c” ,也就是 % 與前面的 “ 之間多一個空白
輸入:三個空白字元後面跟者 A
結果:跳過前面的空白,讀取到字元 A
32
尊重智慧財產權,請勿任意複製或是轉載!
如何正確讀取/跳過空白字元
scanf 處理空白字元的規則
%d 格式接受整數
自動跳過遇到數字前的空白字元
遇到數字時就會開始讀取,遇到非數字字元時就會停止讀取
浮點數或其他整數資料的輸入時,採用相同的處理方式
%c 格式接受字元
因為空白也是字元,所以 scanf 並不會跳過會直接讀取
在控制格式前多一個空白字元
跳過所有遇到的空白字元,就算是使用 %c 格式也是
33
尊重智慧財產權,請勿任意複製或是轉載!
解決輸入緩衝區的問題--記得清除輸入緩衝區
認識輸入緩衝區
暫存使用者從鍵盤 (stdin) 輸入資料的地方
開啟並執行 Prog3-13.c
輸入:三個空白鍵後面跟著 310NTD
34
或許你會認為起因是輸入的資料不符合規範所導致的問題,與緩衝區的功能無關
尊重智慧財產權,請勿任意複製或是轉載!
解決輸入緩衝區的問題--記得清除輸入緩衝區
正常的輸入
#include <stdio.h>
Prog3-14.c
#include <stdlib.h>
int main(void)
{
char ch; int ix = 0;
printf("輸入一個整數:"); scanf("%d",&ix); 輸入一個整數:351
printf("輸入一個字元:"); ch = getchar(); 輸入一個字元:
printf("\nch = %d, ix = %d\n",ch, ix); ch = 10, ix = 351
system("pause"); return(0);
} LF 的 ASCII 編碼
35
尊重智慧財產權,請勿任意複製或是轉載!
解決輸入緩衝區的問題--記得清除輸入緩衝區
問題都是發生在輸入緩衝區中還有資料殘存
fflush 函式:清除指定區域的資料
fflush(stdin) :清除輸入緩衝區中的資料
#include <stdio.h>
#include <stdlib.h> Prog3-15.c
void main(void)
{
char ch; int ix = 0;
printf("輸入一個整數:"); scanf("%d",&ix);
輸入一個整數:351
fflush(stdin); // 清除輸入緩衝區的內容
輸入一個字元:Z
printf("輸入一個字元:"); ch = getchar();
ch = 90, ix = 351
printf("ch = %d, ix = %d\n",ch, ix);
system("pause");
}
36
尊重智慧財產權,請勿任意複製或是轉載!
字串的表達與使用
字串的宣告
字串的輸入與輸出函式
正確讀取輸入內容的技巧
為字串設定初始值--確保輸出/入結果正確
限制最大可讀取字元數
字串的長度
37
尊重智慧財產權,請勿任意複製或是轉載!
字串的宣告
字串是一個或是多個字元的組合
EX: "Zing went the strings of my heart!"
雙引號並非字串的一部份,只是告訴編譯器這是字串
單引號所包含住的字元。EX: 'A'
C 語言並沒有為字串的專屬型別名稱
必須利用陣列(Array)將一群字元組合在一起成為而成為字串
38
尊重智慧財產權,請勿任意複製或是轉載!
字串的宣告
從字元到字串
假設要儲存 “Einstein” 這個字串,那就需要 8 個
(c1~c8) 變數來儲存
如果能組合這些變數,而且只用一個名稱(如:cName)
就能代表這個字串,不就變得很方便
要達成這個目標,就必須使用陣列(Array)
39
尊重智慧財產權,請勿任意複製或是轉載!
字串的宣告
陣列
一群具有相同資料型別的儲存空間
宣告方式跟變數是相同的,只是必須指明需要的空間
陣列的宣告語法
資料型別 變數名稱[大小];
資料型別
這裡僅考慮字串,所以資料型別就是 char
以 char 型別所宣告的陣列又稱為字元陣列。
變數名稱[大小]
變數名稱就是陣列的名稱,命名的規則同變數命名
中括弧 [ ] 是必要的,這是陣列宣告的規定
陣列的大小一定要寫在中括弧 [ ] 內
40
尊重智慧財產權,請勿任意複製或是轉載!
字串的宣告
範例
char cName[9]; 這就是字元陣列,可以儲存 9 個字元
char strX[40]; 可以儲存 40 個字元
陣列可以看成是一個連續的記憶體單位 (memory
cell) 所組成的資料儲存方式
陣列中的每一個記憶體單位都是一樣的大小
以 char cName[9] 為例
每一個記憶體單位都是 1 byte
共佔用 9 個記憶體單位 共9個
cName
1 byte 41
尊重智慧財產權,請勿任意複製或是轉載!
字串的宣告
回到儲存 “Einstein” 這個字串的目標
將設定變數初始值的方法也融入陣列的宣告中
char cName[9] = "Einstein";
42
尊重智慧財產權,請勿任意複製或是轉載!
字串的宣告
字串的宣告與使用規則
‘\0’ 是字串的結尾字元或稱為 null 字元(character)
儲存 Einstein 這 8 個字母時,需要宣告 9 個位置,多要的
一個空間就是留給 null 字元
字串本身即包含了結尾字元
最後一個就是 null 字元,只是從程式的敘述中看不到而已
比較字串 "A" 與字元 ‘A’
字串 “A”包含了兩個字元 A 與 \0 ,字元 ‘A’ 就只有 A 而已
所以字串 "Einstein" 其實包含了 9 個字元,而不是 8 個
43
尊重智慧財產權,請勿任意複製或是轉載!
字串的宣告
字串的宣告與使用規則
「= "字串內容";」指定字串的初始值
例如:char strX[20] = "C與 C++";
陣列名稱就是左值
所以 cName 代表的意義就是左值(l-value)
這個觀念一定要記下來,稍後在字串的輸入與輸出函式就會用到
陣列儲存空間是從 0 開始編號
陣列所取的連續空間(抽屜),編號是從 0 開始
cName[0] 代表連續空間的第一個抽屜
cName[1] 是第二個
...依此類推
44
尊重智慧財產權,請勿任意複製或是轉載!
字串的輸入與輸出函式
printf 與 scanf 輸出入字串的範例
#include <stdio.h>
#include <stdlib.h> Prog3-16.c
int main(void)
{
char cName[16];
printf("輸入一段文字: ");
scanf("%s",cName); // 輸入姓名
輸入一段文字: Butterfly
printf("你輸入的是: %s\n",cName);
你輸入的是: Butterfly
system("pause");
return(0);
}
45
尊重智慧財產權,請勿任意複製或是轉載!
字串的輸入與輸出函式
printf 與 scanf 輸出入字串的規則
輸出字串時,使用字元陣列的名稱即可
字元陣列的名稱就是儲存位址的起點
46
尊重智慧財產權,請勿任意複製或是轉載!
程式技術講座
因為指寫陣列名稱就是陣列的起始位置(左值)
一定要記熟使用 scanf 時兩者的差異
一般變數要加上 &
陣列變數給名稱就行了
47
尊重智慧財產權,請勿任意複製或是轉載!
字串的輸入與輸出函式
gets 與 puts 函式
gets 讀取字串、 puts 輸出字串
使用時不需給 %s 控制格式,直接使用字元陣列的名稱即可,
語法的定義如下:
puts("輸出的字串") 或 puts(字串變數名稱);
gets(字串變數名稱);
48
尊重智慧財產權,請勿任意複製或是轉載!
字串的輸入與輸出函式
範例
#include <stdio.h>
Prog3-17.c
#include <stdlib.h>
int main(void)
{
char cAsk1[20] = "輸入你的姓名:";
字元陣列宣告設定初始值
char cAsk2[20] = "輸入你的學號:";
char cName[20];
char cId[20];
printf("%s",cAsk1);
scanf("%s",cName); // 輸入姓名 輸入你的姓名:Butterfly
fflush(stdin); 輸入你的學號:
puts(cAsk2); 123456
gets(cId); // 輸入學號 你的姓名: Butterfly 學號: 123456
printf("你的姓名: %s 學號: %s\n",cName,cId); 輸入你的姓名:Fly
printf("%s",cAsk1);
scanf("%s",cName); //瞭解字串的儲存內容
system("pause"); return(0); puts 函式在輸出字串後會動的換行
}
49
尊重智慧財產權,請勿任意複製或是轉載!
正確讀取輸入內容的技巧
練習一:執行 Prog3-17.c
在姓名處輸入:Bumble Bee
預期「Bumble Bee」應該出現在 cName 字串中
但 Bee 這幾個字卻不見了,印出來的文字只有 Bumble
練習二:再次執行 Prog3-17.c
在學號處輸入:Bumble Bee
如預期的「Bumble Bee」確實存入字元陣列 cId 中
50
尊重智慧財產權,請勿任意複製或是轉載!
正確讀取輸入內容的技巧
scanf 與 gets 在處理輸入的字串上差異:
gets
以 ‘\n’ 換行字元作為字串的結束字元
輸入「Bumble Bee」,整個字串都會儲存到 cId 字元陣列中
scanf
以空白(space)、跳格(tab) 或換行(\n)字元作為字串的結束字元
輸入「Bumble Bee」
空白字元讓 scanf 停止讀取,Bumble 就是目前的輸入結果並儲存到變
數 cName 中
字串輸入的第一個問題:輸入的內容並不如預期的都被
儲存到字串變數中
51
尊重智慧財產權,請勿任意複製或是轉載!
正確讀取輸入內容的技巧
以 scanf 來輸入,但要達到 gets 的輸入效果
必須使用 %[可接受字元] 的方式來取代 %s
規則
只要輸入字元沒有出現在中括弧 [ ] 中所指定的可接受字元
時,就會停止讀取
並將之前讀到的所有字元 (當然都是可接受字元的一份子)
當成是目前所輸入的字串
52
尊重智慧財產權,請勿任意複製或是轉載!
正確讀取輸入內容的技巧
範例
scanf(“%[a-z]”,cName)
代表的意義是小寫英文字母 a 到 z。
輸入的字元非小寫的 a 到 z,就會停止字元的讀取
如輸入:butterFly,則 cName 的內容將會是 butter。
scanf(“%[0-9]”,cId)
0-9 為可接受字元
53
尊重智慧財產權,請勿任意複製或是轉載!
正確讀取輸入內容的技巧
修改 Prog3-17.c 的第 10 行
scanf("%s",cName) 換成 scanf("%[A-Za-z0-9 ]",cName)
#include <stdio.h>
#include <stdlib.h> Prog3-18.c
int main(void)
{
char cAsk1[20] = "輸入你的姓名:";
char cAsk2[20] = "輸入你的學號:";
char cName[20];
char cId[20];
printf("%s",cAsk1);
scanf("%[A-Za-z0-9 ]",cName); // 輸入姓名
fflush(stdin);
puts(cAsk2);
gets(cId); // 輸入學號
printf("你的姓名: %s 學號: %s\n",cName,cId);
printf("%s",cAsk1);
scanf("%s",cName); //瞭解字串的儲存內容
system("pause");
return(0);
}
54
尊重智慧財產權,請勿任意複製或是轉載!
正確讀取輸入內容的技巧
以 Prog3-17.c 進
行偵錯與監看
55
尊重智慧財產權,請勿任意複製或是轉載!
為字串設定初始值--確保輸出/入結果正確
字串未設定初始值與輸入沒被接受所合併引發的問題
執行 Prog3-18.c
「輸入你的姓名」處,輸入「@Butterfly」
56
尊重智慧財產權,請勿任意複製或是轉載!
為字串設定初始值--確保輸出/入結果正確
字元陣列設定初始值
= ""; 就可以讓字元陣列都儲存 \0 null 字元
例如: char cName[20] = ""; 與 char cId[20] = "";,
#include <stdio.h>
#include <stdlib.h> Prog3-19.c
int main(void)
{
char cAsk1[20] = "輸入你的姓名:";
char cAsk2[20] = "輸入你的學號:";
char cName[20] = ""; // 設定初始值為 \0 字元
char cId[20] = ""; // 設定初始值為 \0 字元
printf("%s",cAsk1); 輸入你的姓名:@Butter
scanf("%[A-Za-z0-9 ]",cName); // 輸入姓名 輸入你的學號:
12345
fflush(stdin);
你的姓名: 學號: 12345
puts(cAsk2);
gets(cId); // 輸入學號
printf("你的姓名: %s 學號: %s\n",cName,cId);
system("pause"); return(0);
} 57
尊重智慧財產權,請勿任意複製或是轉載!
限制最大可讀取字元數
最後一個問題
使用者輸入的字元數超過字元陣列的儲存大小
執行 Prog3-19.c
姓名處,請輸入超過 20 個字元
輸入你的姓名:1234567890123456789012345
輸入你的學號:
A123
你的姓名: 1234567890123456789012345 學號: A123
結果就是發生執行上的錯誤
58
尊重智慧財產權,請勿任意複製或是轉載!
限制最大可讀取字元數
原因
scanf 並不會幫你檢查要寫入字元陣列的字元個數
當輸入超過所能儲存的容量時,就是造成執行錯誤
的原因
這是程式開發非常危險也是最常見的程式語意錯誤,
程式碼違反了對記憶體的存取規則。
59
尊重智慧財產權,請勿任意複製或是轉載!
限制最大可讀取字元數
解決的方法
在 %s 設定所能讀取的最大字元數
例如:%20s 就能限制最多只讀取 20 個字元
不要忘記字串的結尾字元 \0 null 字元
最大字元數設定成陣列大小減一,留一個空間給 null 字元
#include <stdio.h>
#include <stdlib.h> Prog3-20.c
int main(void)
{
char cAsk1[20] = "輸入你的姓名:";
char cAsk2[20] = "輸入你的學號:";
char cName[20] = ""; // 設定初始值為 \0 字元
char cId[20] = ""; // 設定初始值為 \0 字元
printf("%s",cAsk1); // 設定只能接受 19 個字元
scanf("%19[A-Za-z0-9 ]",cName); // 輸入姓名.設定只能接受 19 個字元
fflush(stdin);
puts(cAsk2);
gets(cId); // 輸入學號
printf("你的姓名: %s 學號: %s\n",cName,cId);
system("pause");
return(0); 60
}
尊重智慧財產權,請勿任意複製或是轉載!
字串的長度
strlen() ─ 被定義在 string.h 中
回傳所給予字串中字元的個數 (也稱為字串的長度)
語法如下:
strlen(字串常數); 或 strlen(字元陣列名稱);
比較 sizeof 與 strlen
sizoef 傳回字元陣列的大小(也就是整個陣列的大小)
strlen 傳回字串的長度(以 null 字元為計算的結束點,但不含 null 字元)
61
尊重智慧財產權,請勿任意複製或是轉載!
字串的長度
62
尊重智慧財產權,請勿任意複製或是轉載!
字串的長度
範例
#include <stdio.h>
#include <stdlib.h> Prog3-21.c
#include <string.h>
strlen(MOVIE_NAME) = 14
#define MOVIE_NAME "Transformers 2"
sizeof(MOVIE_NAME) = 15
int main(void) strlen(cStr) = 10
{ sizeof(cStr) = 15
char cStr[15] = "Bumble Bee";
printf("strlen(MOVIE_NAME) = %d\n",strlen(MOVIE_NAME));
printf("sizeof(MOVIE_NAME) = %d\n",sizeof(MOVIE_NAME));
printf("strlen(cStr) = %d\n",strlen(cStr));
printf("sizeof(cStr) = %d\n",sizeof(cStr));
system("pause"); return(0);
}
63
尊重智慧財產權,請勿任意複製或是轉載!
程式技術講座
64
尊重智慧財產權,請勿任意複製或是轉載!
本章結束
65
尊重智慧財產權,請勿任意複製或是轉載!