在程序設計中有三種基本的結構,而正是這三種基本的結構組成了程序設計的主體。它們分別是:順序結構,選擇結構,循環結構。本章我們將會講解有關順序結構設計,並且以幾個實際的函數作爲實例,進行相關編程,讓大家對順序結構設計能夠深刻的理解和掌握。
前面我們已經大概講了一點printf函數的輸出結果。其實printf函數還有很多的使用技巧,我們將會在本章進行更加詳細的介紹。實際上在我們寫代碼時總是少不了程序的輸入和輸出。輸入輸出就像是一個數學函數,輸入是變量,輸出則是結果。但是在實際的程序設計中輸入輸出是有格式要求,我們可以按照我們想要的方式輸出結果,比如在輸入時只接受數字或字母,輸出要求是金字塔或倒金字塔等。說了這麼多,接下來讓我們見證輸入和輸出函數的神奇吧!
本章我們主要會講解三對輸入輸出函數和一對特殊的輸入函數,三對輸入輸出函數分別是:printf和scanf函數、puts和gets函數、putchar和getchar函數。一對特殊的輸入函數是:getche函數和getch函數。想知道它們有什麼具體的效果和作用嗎?請接着看。
3.1 順序結構
順序結構在程序設計中是最簡單的,只需要按照問題解決的順序寫出相應的語句就行,它的執行順序是自上而下,依次執行的。
爲了更加直觀的理解設計我們通常會使用流程圖或者N-S圖來顯示程序運行的過程。不過我個人還是贊同使用流程圖的,雖然N-S在很多方面比流程圖效果要好。但是無論是在使用頻率上,還是可理解上,我個人感覺還是流程圖距離我們更近。好像最早應該高中時我們就已經開始接觸流程圖了,所以會有一種親切感。
如圖3.1所示,爲順序結構流程圖。對應(a),首先執行“語句1”,然後執行“語句2”,最後執行“語句3”。對於現代的任何人來說,上學都有着美好的記憶,在學校我們學到了很多的知識,爲我們將來的發展奠定了良好的基礎。那麼如圖(b)就是上學的一個流程圖。首先我們需要等待“錄取通知”,一般情況下就是一個錄取通知書了。然後我們知道錄取之後,我們就需要“交學費”,交完學費,我們就可以等到開學“上學”了。對於圖3.5中的(c)便是一個啓動轎車的流程圖了。首先我們需要給轎車點火啓動,也就是“轎車點火”,啓動轎車之後我們就需要“掛檔”了,因爲“掛檔”之後轎車纔會前行。
比如:
int a=1;
a++;
a += 6;
這就是一個順序結構,首先定義一個變量a,然後執行a自加1,最後執行a加上6再賦值給變量a。
我們將用三個順序結構實現的數據交換來進一步理解順序結構。
【例3.1】順序結構設計之三種數據交換方法。
解題思路:我們使用順序結構實現三種數據的交換算法,一種是使用的加法運算,一種使用的是乘法運算,一種使用的是除法運算。注意:除法運算最好在整數類型下,否則容易出現錯誤。
編寫程序:
#include <stdio.h>
int main()
{
int a,b,temp;
//////////////////////////////
//方法1
a = 13;
b = 16;
printf("a=%d, b=%d\n", a, b);
temp = a;
a = b;
b = temp;
printf("a=%d, b=%d\n", a, b);
//////////////////////////////
//////////////////////////////
//方法2
a = 13;
b = 16;
printf("a=%d, b=%d\n", a, b);
a = a+b;
b = a-b;
a = a-b;
printf("a=%d, b=%d\n", a, b);
//////////////////////////////
//////////////////////////////
//方法3
a = 13;
b = 16;
printf("a=%d, b=%d\n", a, b);
a = a*b;
b = a/b;
a = a/b;
printf("a=%d, b=%d\n", a, b);
return 0;
}
運行結果:
a=13, b=16
a=16, b=13
a=13, b=16
a=16, b=13
a=13, b=16
a=16, b=13
Press any key to continue
程序分析:程序第1行爲下面printf函數的頭文件,第2行爲程序的入口main函數,任何C語言程序都會需要這個函數。int表示程序返回值爲整數,我們在第34行發現程序返回0,就是說程序正常結束。要編寫的程序都需要卸寫在花括號之間,即第3~35行之間。第4行定義了三個變量。第5~6行是用‘\\’註釋。第7~8行爲變量賦值,分別把13賦值給a,把16賦值給b。第9行輸出變量a,b的值。第10行把a中的值13賦值給temp,此時a和temp的值一樣。第11行把b的值賦值給a,a原來的值13就會被b中的值16所覆蓋,即a成爲16。第12行把temp的值賦值給b,b原來是16就會被temp中的13所覆蓋,b就變成了13。現在a由原來的13變成了16,b也由原來的16變成了13。因此實現了數據交換。第13行輸出交換後的a,b值。剩餘的程序用這樣的方式即可分析,此處就不再贅述。
如上爲三種基本且經典的數據交換方法,另外還有其他的方法實現數據的交換,比如位運算等。大家可以從網絡上查到大量相應的信息。
3. printf函數
3.2.1 printf函數的說明
printf函數是格式輸出函數,一般用於向標準輸出設備按規定格式輸出信息。printf函數是被定義在頭文件stdio.h裏的,因此在使用時需要加上#include <stdio.h>。
3.2.2 printf函數格式
表3.1列舉了printf函數的語法要點。通過該表我們就可以查的printf函數的使用規則。比如所需頭文件是#include <stdio.h>,返回值是void。void表示爲空。
所需頭文件 |
#include <stdio.h> |
函數原型 |
void printf(const char *format, ...); |
函數輸出格式 |
format:爲函數輸出的格式字符串 |
函數傳入值 |
傳入值根據具體的format中要求的格式信息輸入 |
函數返回值 |
void |
“格式信息”參數包含三種對象類型的字符串:
- 無格式字符串複製到輸出流。
- 轉換規範,每個規範導致在參數列表中檢索一個或多個項。
- 轉義序列。
上面這三種說法是不是太文藝了呢?不用管它,我們稍後會以一個實際代碼實例來進行詳細的說明。此處留作將來查詢用。
【例3.2】printf函數的基本使用。
解題思路:編寫該程序的主要目的就是爲了幫助大家瞭解類似表3.1中的信息並如何使用表中所給的信息進行編程。
編程程序:
#include <stdio.h>//頭文件
int main()//函數入口,main函數
{
printf("Hello friends,");//printf函數基本格式,不帶參數
printf("hello %d", 1);//printf函數基本格式,帶一個常量參數
return 0;//說明程序正常結束返回0
}
運行結果:
Hello friends,hello 1Press any key to continue
程序分析:首先我們觀察表3.1,第一行是printf所需頭文件爲#include <stdio.h>,就是在要求在使用printf函數時需要寫上這個頭文件。正如我們程序中第一行所寫,就是頭文件。然後任何程序都需要一個入口函數就是main函數,main函數下用一對大括號括起來所有程序就是我們書寫程序的主體框架,是我們寫程序的基本框架。在大括號裏面纔是我們要寫的程序。表3.1中第二行說函數原型,就對應程序第4~5行。在printf函數原型中有省略號表明參數可有可無。這就是程序中第4~5行的區別,第4行沒有參數,第5行有參數1。“%d”就是把1保存到雙引號的字符串中。後面會介紹“%d”及相關信息的介紹。函數的傳入值就是1。傳入值不僅可以是常數也可是是變量或者字符串。相應的接受的類型“%d”,也需要做對應的改變。返回值是void,表示返回值爲空,在編寫程序中寫成我們程序第4~5行的無返回值的格式就行。
3.2.3 輸出數據格式的規定
什麼是輸出格式?輸出格式就是按照一種什麼類型的樣式輸出,比如輸出整數,輸出字符,輸出十六進制數或八進制數等。
通常意義上的“格式信息”的格式如下:
%[flags][width][.prec][F|N|h|l]type
看上去都是英文,不好理解。看看漢語是如何表示的:
%[標誌][輸出最小寬度][.精度][長度]類型
格式字符串都是以%開頭,後面接着是“標誌”,即“+”或“-”。如果程序中有“精度”,則“精度”前面的小數點必須有。“類型”就是輸出的格式信息,比如十進制輸出,類型就是d。字符輸出,類型就是c。而“[]”是作爲可選項來使用的,就是說凡是用“[]”表示的格式都是可選的,可有可無。其他變成語言中也有類似的情況。具體表示方式和詳細信息請參考下面四部分和代碼講解。
- 格式化字符串中允許使用的修飾符
接下來這幾部分我們將會對應上面“格式信息”中的格式進行詳細的說明。那麼此部分我們將會說明“格式信息”中的“標誌”、“輸出的最小寬度”、“精度”、“長度”以及擴展且常用的信息“ ”(空格)、“0”、“#”。詳細信息參考表3.2格式化字符串中允許使用的修飾符。
字符 |
字符名稱 |
說明 |
範例 |
- (標誌) |
負號 |
設置左對齊。但總寬度必須比實際寬度大才有效 |
%-4d %-6.4f |
+ (標誌) |
正號 |
默認爲正號,可以不寫。若設定的寬度比實際寬度大,數據向右看齊 |
%+4d(或%4d) %+6.4f(或%6.4f) |
width (最小寬度) |
寬度 |
設置數據顯示的寬度。如果寬度比數值本身寬度小,則以實際寬度顯示。若輸出含有小數部分,則寬度包括整數位數、小數點、小數位數以及正負號 |
%4d %6.4f |
. |
小數點 |
設置小數 |
%6.4f |
prec (精度) |
小數點後面的位數 |
設置小數點後面的位數:
|
|
(空格) |
空格 |
若正數前面加空格,則顯示空格。若負數前面加空格,則顯示負號 |
printf("% 4d", 43); 結果: 43 printf("% 4d", -43); 結果:-43 |
0 |
數字零 |
將輸出的前面補上0,直到佔滿指定列寬爲止(不可以搭配使用“-”) |
printf("%04d", 43); 結果:0043 |
# |
井號 |
|
結果:053 2. printf("%#e", 43.3); 結果:4.330000e+001 3. printf("%#g", 43.3); 結果:43.3000 |
注:表格正文第六行是空格,所以好像感覺不到任何效果。該按鍵就是鍵盤正下面那個長鍵。
- 規定數據的格式
此處我們講解數據的格式,也就是上面“格式信息”中對應的“類型”信息。如果我們想要使用printf輸出一個十進制整數,該怎麼辦呢?一個字符或字符串呢?這些都是由數據格式來控制的,因此可見我們“類型”的重要性。
另外從“格式信息”中我們也可以看出“類型”的重要性,在“%”之後除了“類型”外,其他的都是可有可無的可選項。而“類型”卻是必須有的。
在我們的“類型”中又以“%d”、“%f”、“%lf”、“%c”、“%s”更爲常用,所以這幾種類型大家要重點記憶。詳細的數據格式大家參考表3.3即可。
數據類型 |
字符 |
對應數據類型 |
含義 |
整數 |
d/i |
int |
接受整數值並表示有符號的十進制整數,i是老式的寫法 |
o |
unsigned int |
無符號的八進制整數(不輸出前綴0) |
|
u |
unsigned int |
無符號10進制整數 |
|
x/X |
unsigned int |
無符號16進制整數,x對應小寫,如abcdef;X對應大寫,如ABCDEF(不輸出前綴0x) |
|
浮點數 |
f/lf |
float(double) |
單精度浮點數用f(默認六位小數位),雙精度浮點數用lf |
e/E |
double |
科學計數法表示的數,此處"e"的大小寫表示輸出時是否用的“e”的大寫或小寫 |
|
g/G |
double |
使用以上兩種中最短的形式,使用同%e和%E |
|
字符或字符串 |
c |
char |
字符型。把輸入的數字按照ASCII碼轉換爲對應的字符 |
s/S |
char */wchar_t * |
字符串。輸出字符串中的字符直至字符串中的空字符(字符串以'\0‘結尾,這個'\0'即空字符) |
|
其他類型 |
p |
void * |
以十六進制形式輸出指針 |
n |
int * |
到此字符之前爲止,一共輸出的字符個數,不輸出文本 |
|
% |
無輸入 |
不進行轉換,輸出字符‘%’(百分號)本身 |
|
m |
無 |
打印errno值對應的出錯內容,(例: printf("%m\n");) |
注:%g,%G在小數點位數四位或指數大於等於精度時用%e、%E,否則用%f。
【例3.3】經過以上的格式輸出的瞭解,對應的編寫相應的程序代碼。
程序分析:爲了便於理解上表中各個格式的使用,我們採用一個實際的實例來進行說明,幫助大家理解。抽象具體化。
編寫程序:
#include <stdio.h>//頭文件
int main()//main函數
{
char c,s[20]="Hello world";//字符與字符串變量定義及初始化
int a=1234;//整數變量定義及初始化
double f=3.141592653589;//雙精度浮點數變量定義及初始化
double x=0.12345678987654321;//雙精度浮點數變量定義及初始化
c='\x41';//字符初始化
printf("a=%d\n",a); /*結果輸出十進制整數a=1234*/
printf("a=%u\n",-a); /*結果輸出無符號的十進制整數a=4294966062*/
printf("a=%6d\n",a); /*結果輸出6位十進制數a=1234*/
printf("a=%06d\n",a); /*結果輸出6位十進制數a=001234*/
printf("a=%-4d\n",a); /*輸出左對齊4位十進制整數a=1234*/
printf("a=%o\n",a); /*結果輸出八進制整數a=2322*/
printf("a=%x\n",a); /*結果輸出十六進制整數a=000004D2*/
printf("a=%p\n",a); /*輸出地址a=06E4*/
printf("f=%f\n",f); /*輸出浮點數f=3.141593*/
printf("f=%6.4f\n",f); /*輸出6位其中小數點後4位的浮點數f=3.1416*/
printf("f=%*.*f\n", 6, 4, f);/*與printf("f=%6.4f\n",f);類似*/
printf("x=%lf\n",x); /*輸出長浮點數x=0.123457,因爲原本x=0.1234567,而最後一位7需要四捨五入,所以把小數點後第六位的6變成7*/
printf("x=%18.16lf\n",x);/*輸出18位其中小數點後16位的長浮點數x=0.1234567898765432*/
printf("x=%e\n", x); /*以科學計數法表示,輸出爲x=1.234568e-001*/
printf("x=%E\n", x); /*以科學計數法表示,輸出爲x=1.234568E-001*/
printf("c=%c\n",c); /*輸出字符c=A*/
printf("c=%x\n",c); /*輸出字符的ASCII碼值c=41*/
printf("s[]=%s\n",s); /*輸出數組字符串s[]=Hello world*/
printf("s[]=%6.9s\n",s);/*輸出最多9個字符的字符串s[]=Hello wor*/
printf("s=%p\n",s); /*輸出數組字符串首字符地址s=0012FF30*/
return 0;//程序正常結束返回0
}
運行結果:
a=1234
a=4294966062
a= 1234
a=001234
a=1234
a=2322
a=4d2
a=000004D2
f=3.141593
f=3.1416
f=3.1416
x=0.123457
x=0.1234567898765432
x=1.234568e-001
x=1.234568E-001
c=A
c=41
s[]=Hello world
s[]=Hello wor
s=0012FF30
Press any key to continue
程序分析:程序第1行爲頭文件,應爲我們使用了pintf函數,所以需要此頭文件。第2~3行以及第30~31行爲程序基本的框架。第4~7行爲各種類型變量的定義以及初始化。第8行給字符變量賦值爲十六進制的數據‘\x41’。第9~28行就對應表3.3的數據格式。在此處需要注意的是第10行,由於輸出格式是無符號的整數,但是卻接受了一個負數,所以就會造成程序中所示的輸出結果。其中‘\n’表示換行,我們將會在下面的部分講解。
三.F|N|h|l
我們已經在前兩部分說明了“格式信息”中除“長度”以外的所有信息格式。對於“長度”信息我們也會做一個簡短的介紹。
表示指針是否是遠指針、是否是近指針、是否是整數、是否是長整數。
F:遠指針
N:近指針
h:短整數(short int)
l:長整數(long int)
注:對於長整數l,此處如果與d搭配爲%lld,則爲long long int(C99),與f搭配爲%llf則爲long double(C99)。
四.轉義字符
既然上面三部分都已經講完了“格式信息”,那爲什麼還有這一部分呢?那是因爲當我們解決了溫飽問題,該想想小康社會了。哈哈。上面三部分的確已經對“格式信息”做了簡要講解,那只是滿足了基本的需求,只解決了溫飽問題而已。如果要求你一行一行的輸出信息,你會怎麼辦?你可能回想我把一行一行的填滿數據,不就是一行一行的輸出了嗎!那要是不讓你填滿一行就輸出下一行呢?這個怎麼辦?這就需要我們用“轉義字符”來步入“小康社會”。
什麼是轉義字符?就是通過添加一個‘\’與ASCII表中的一個字符組合而成。比如‘\n’,表示換行。同時“\”後面組合的字符並不是它在ASCII表中的的含義。此點需要大家注意。
轉義字符會在字符串中自動轉換爲相應操作命令。具體如表3.4轉義字符所示。表中所示轉義序列中的字符,看上去像是兩個或多個字符的組合,其實就是一個字符。
轉義序列 |
說明 |
轉義序列 |
說明 |
\n |
換行 |
\f |
換頁 |
\a |
響鈴 |
\b |
Backspace |
\r |
回車 |
\0 |
空字符(數值爲0) |
\t |
水平製表符 |
\v |
垂直製表符 |
\’ |
單引號 |
\” |
雙引號 |
\\ |
反斜槓 |
\? |
文本問號 |
\ooo(例如\043) |
ASCII字符(OCX) |
\xhh(例如\x43) |
ASCII字符(HEX) |
\xhhhh |
寬字符(兩字節HEX) |
\ddd |
ASCII字符(OCT) |
在實際的使用中我們使用頻率較多的幾個轉義字符是:‘\n’、‘\r’、‘\t’、‘\’’,‘\”’、‘\\’等幾種形式。請大家重點記憶。
使用轉義字符是有以下幾點需要注意的要點:
- 轉義字符只能使用小寫字母。
- 轉義字符‘\0’表示空字符NULL,它的值是0,對應的ASCII值是48。所以空字符‘\0’不是字符‘0’。且空字符(ASCII碼值48)也不等於空格字符(ASCII碼值32)。
- ‘\v’垂直製表符和‘\f’換頁符對屏幕沒有任何影響,影響打印機的響應操作。
- 如果反斜槓‘\’和其之後的字符不構成轉義字符,則因‘\’不起轉義作用而被忽略。
- C語言中不可打印的字符通常使用轉義字符。
【例3.4】轉義字符的使用。
解題思路:通過一個簡單的實例加深對轉義字符的理解。參考轉義字符的注意要點,我們就知道有些轉義字符對屏幕沒有任何影響等原因,我們就不再在程序中寫出事例。另外在每一行程序結束時,添加換行符‘\n’,爲了便於觀察。大家需要注意。
編寫程序:
#include <stdio.h>//頭文件
int main()//main函數
{
printf("Hello C Program\n");//轉義字符\n,表示換行
printf("Hello C\a Program\n");//轉義字符\a,表示響鈴
printf("Hello C\b Program\n");//轉義字符\b,表示退格鍵,刪除光標前一個字符
printf("Hello C\r Program\n");//轉義字符\r,表示回車
printf("\tHello C Program\n");//轉義字符\t,表示水平製表符
printf("Hello C\0 Program\n");//轉義字符\0,表示空字符
printf("Hello \'C\' Program\n");//轉義字符\',表示單引號
printf("Hello C \"Program\"\n");//轉義字符\",表示雙引號
printf("\\Hello C Program\\\n");//轉義字符\\,表示反斜槓
printf("\?Hello C Program\?\n");//轉義字符\?,表示文本問號
return 0;//正常返回0
}
運行結果:
Hello C Program
Hello C Program
Hello Program
Program
Hello C Program
Hello CHello 'C' Program
Hello C "Program"
\Hello C Program\
?Hello C Program?
Press any key to continue
程序分析:第1~3行以及程序最後2行不再解釋,如果忘記什麼意思,看之前的代碼示例。第4行我們使用的轉義字符是‘\n’,就是換行轉義。程序運行結果中第一行,我們看到在輸出“Hello C Program”字符串之後,並沒有填充整個一行數據,就直接換行了。這就是轉義字符中換行的作用。第5行轉義字符是‘\a’,表示響鈴。第6行轉義字符是‘\b’,表示退格,功能是刪除該轉義字符相鄰的前一個字符。在運行結果中就會出現只輸出“Hello Program”,少了字符‘C’,這就是轉義字符‘\b’的作用。第7行轉義字符‘\r’,表示回車。運行結果第三行只出現了該轉義字符後面的字符串。第8行轉義字符爲‘\t’,該轉義字符作用是跳到下一個製表符的位置,一般佔用8位。該轉移字符還有對齊的作用。第9行是轉義字符‘\0’,表示空字符。printf函數遇到到‘\0’就會結束輸出,導致‘\n’並沒有實現換行的作用。同時下一次輸出的結果,會在上一次輸出結果的末尾輸出。所以出現了第六行的運行結果。第10~13行分別是轉義字符‘\’’、‘\”’、‘\\’、‘\?’對應的輸出結果分別是’’、‘”’、‘\’、‘?’。簡單說,就是‘\’後面的那一個字符。程序中使用兩個相同的轉義字符,爲了在運行結果中便於觀察。
經過上面對printf函數的講解我們應該已經掌握了printf函數的使用,如果對此還是有什麼不解,再回去看看。下面就讓我們使用printf函數來兩個開胃菜吧!
【例3.5】輸出一個正方體,並且在正面顯示hello world。
解題思路:我們使用printf函數一行一行輸出對應的圖形邊界信息。
編寫程序:
#include <stdio.h>
int main()
{
printf(" ________________\n");
printf(" / /|\n");
printf(" / / |\n");
printf("|---------------| |\n");
printf("| | |\n");
printf("| hello world | |\n");
printf("| | /\n");
printf("|_______________|/\n");
return 0;
}
運行結果:
【例3.6】輸出駝羊的圖像。
解題思路:在網站上我們會經常看到各式各樣的圖像,駝羊就是其中一種,下面我們輸出的就是用printf函數輸出駝羊外形。
編寫程序:
#include <stdio.h>
int main()
{
printf("┏┛┻━━━┛┻┓\n");
printf("┃|||||||┃\n");
printf("┃ ━ ┃\n");
printf("┃ ┳┛ ┗┳ ┃圍觀是一種態度\n");
printf("┃ ┃\n");
printf("┃ ┻ ┃\n");
printf("┃ ┃圍觀是爲了提高知名度\n");
printf("┗━┓ ┏━┛\n");
printf(" ┃ ┃ \n");
printf(" ┃ ┃ \n");
printf(" ┃ ┃ \n");
printf(" ┃ ┃ \n");
printf(" ┃ ┗━━━┓\n");
printf(" ┃ ┣┓\n");
printf(" ┃圍觀專用寵物 ┃\n");
printf(" ┗┓┓┏━┳┓┏┛\n");
printf(" ┃┫┫ ┃┫┫\n");
printf(" ┗┻┛ ┗┻┛\n");
return 0;
}
運行結果:
看到上面兩個程序輸出的圖形是不是很激動呢?沒想到我們用printf函數就能玩出花樣來。程序的世界魅力無窮,要想探索更多的未知,那就接着學習,提高實力,等我們一劍封江湖。努力!!!
3.3 scanf函數
3.3.1 scanf函數的說明
scanf函數是格式輸入函數,即按用戶指定的格式從標準輸入流stdio(標準輸入設備,一般是鍵盤)中把數據輸入到指定的變量中去,按照要求的格式讀入一個或多個數據,並保存到對應地址的變量中。
3.3.2 scanf函數格式
上一節我們講解了輸出函數printf,這一節我們講解輸入函數scanf。因爲成雙成對比較對稱嘛!printf函數負責輸出數據,scanf函數就是負責輸入數據了。如表3.5所示列舉了scanf函數的語法要點。
所需頭文件 |
#include <stdio.h> |
|
函數原型 |
int scanf(const char *format, ...); |
|
函數傳入值 |
函數傳入值由format中要接受的類型傳入 |
|
函數返回值
|
成功 |
正確輸入參數的個數 |
失敗 |
0 或EOF |
scanf函數執行成功返回賦值的數據項數,失敗出錯時返回EOF。
【例3.7】scanf函數介紹。
解題思路:經過表3.5scanf函數語法要點的講解,我們對scanf函數有一個大概的認知,現在通過代碼的編寫可以使大家能夠輕鬆學會scanf函數的使用。
編寫程序:
#include <stdio.h>
int main()
{
int cnt = 0;
int a,b;
cnt = scanf("%d", &a);
printf("成功輸入一個變量時,scanf返回值個數:%d\n", cnt);
cnt = scanf("%d %d", &a, &b);
printf("成功輸入兩個變量時,scanf返回值個數:%d\n", cnt);
cnt = scanf("%d", &a);//此處輸入字符串
printf("錯誤輸入變量時,scanf返回值個數:%d\n", cnt);
fflush(stdin);//後面將會介紹
cnt = scanf("%d", &a);//輸入Ctrl+z,然後按回車
printf("出現EOF的情況,scanf返回值個數:%d\n", cnt);
return 0;
}
運行結果:
32
成功輸入一個變量時,scanf返回值個數:1
32 34
成功輸入兩個變量時,scanf返回值個數:2
right
錯誤輸入變量時,scanf返回值個數:0
^Z
出現EOF的情況,scanf返回值個數:-1
Press any key to continue
程序分析:首先我們觀察表3.5,scanf的頭文件是#include <stdio.h>,所以我們程序第1行爲#include <stdio.h>。第2~3行以及第15~16行爲程序的基本框架,不在過多介紹。程序第4~5行是變量的定義及初始化。觀察表中scanf函數的返回值爲int型,所以第6行用scanf函數給整型變量a賦值後,返回一個整數,即輸入參數的個數。顯然我們輸入的變量是一個,所以返回整數應該爲1,如運行結果第1~2行所示。我們用符號‘&’表示取地址,就是從鍵盤中讀取一個整數,放到名字爲a的內存地址。同樣在程序第8行,兩個變量a和b被成功讀入,則返回值爲2。程序第10行,由於要求輸入整型變量,而輸入的卻是字符串“right”,不能成功被讀取,所以變量就是0。第12行fflush函數的功能爲清空讀寫緩衝區,我們會在後面介紹。第13行我們輸入ctrl+z後回車,就會出現運行結果中所示的結果。
注意:
在函數返回值失敗時,返回的0或者EOF分別表示:
0:用戶輸入的不匹配,無法正確輸入任何值。
EOF:定義在#include <stdio.h>,通常值爲-1。表示輸入流已經結束。在Windows平臺下,按Ctrl+z,會出現一個^Z,表示輸入結束。就會輸出-1,即EOF,詳情請看代碼。
3.3.3 scanf函數各種類型輸入
有輸出格式就有輸入格式,這一節中我們將會詳細介紹各種類型的輸入格式。由於輸入格式的語法方式與printf函數類似,因此我們後面講到相應的語法時,大家可以結合前面的printf函數語法的思想來學習scanf函數的語法。
實際上,scanf函數的格式信息和printf函數的格式信息相同,誰讓他們是一對呢!所以此處我們貼出的scanf函數格式信息,也是printf函數的格式信息。其“格式信息”的格式如下:
%[flags][width][.prec][F|N|h|l]type
同樣漢語的表示比如下:
%[標誌][輸出最小寬度][.精度][長度]類型
如果大家忘記了“格式信息”中各項表示的具體含義,還請大家返回到前面的scanf函數的定義來再次加深理解。而我們將會具體講解scanf函數各種類型的輸入。使大家能夠輕鬆理解。
一:scanf函數整型輸入
函數的整型輸入,就是接受各種類型的整數。比如長整型,短整型,整型,無符號的整型等整型類型。另外大家需要注意的是此處的語法表示就是3.3.3中的具體化。後面的部分也是這樣,需大家謹記。
語法:%[*][width][l|h][d|u|o|x]
其中,[]表示:可選項,width表示:指定輸入數據所佔寬度。l表示:輸入長數據,是長度修飾符。h表示:輸入短數據,也是長度修飾符。d,u,o,x分別表示:十進制整數輸入,無符號十進制整數輸入,八進制整數輸入,十六進制整數輸入。
“*”表示該輸入項讀入後不賦予任何變量,即跳過該輸入值。
【例3.8】scanf函數整型輸入
解題思路:由於scanf函數和printf函數是兩個對應的函數,所以數據的修飾符、數據格式以及轉義字符等都是類似的,大家可以參考表3.2,表3.3和表3.4。
編寫程序:
#include <stdio.h>
int main()
{
long a;//定義一個長整型變量
short b;//定義一個短整型變量
int c,d,e;//定義三個普通整型變量
//分別按照長整型,短整型,無符號整型,八進制,十六進制格式輸入
scanf("%ld%hd%2u%o%x", &a, &b, &c, &d, &e);
//輸出結果
printf("a = %d, b = %d, c = %d, d = %d, e = %d\n", a, b, c, d, e);
return 0;
}
運行結果:
111 112 113
114 115
a = 111, b = 112, c = 11, d = 3, e = 276
Press any key to continue
程序分析:有很多不理解的人就會對這樣的一個結果感到疑惑,接下來咱們就好好分析一下這樣的結果吧。首先輸入111後,111會自動保存到長整型變量a中;然後輸入空格後,再輸入112,則112會保存到短整型變量b中;之後輸入了兩個空格加一個tab製表符,再輸入113,此時需要注意,整型變量c接收的是2個長度的無符號的整型,所以就會有c = 11這樣一個結果;那爲什麼d = 3呢?這是因爲c取113的兩位數,造成3被整型變量d接受,以八進制的形式保存,所以輸出的結果d = 3實質上是八進制的3,因爲我們是以“%o”的格式接受數據。最後回車,再輸入114,一個tab製表符和115,回車程序輸入結束。可是爲什麼e = 276呢?其實與d = 3類似,因爲114被整型變量e所接收,並以十六進制的形式保存到內存中,所以十六進制的114,就是十進制的276。由於115沒有變量接收,編譯器自動捨棄。
使用scanf需要注意一下兩點:
- scanf讀入一組整數時,會自動跳過空格、tab和回車符,尋找下一個輸入域。每個輸入域都是由一串連續的非空白字符的整型數據。
- 格式信息中除了要有以%開始的字符轉換說明,還可以有普通的字符或字符組合。這些字符或字符組合是限制使用者輸入數據格式使用的,並不在屏幕上顯示。
二:scanf函數浮點數輸入
函數的浮點數輸入,就是接受各種類型的浮點數。最常用的浮點數就是單精度浮點數和雙精度浮點數兩種類型。下面看一下浮點數輸入的格式。
通常意義上的“格式信息”的格式如下:
語法:%[+][-][width][.prec][f|e|g]
在標準C語言中有兩種浮點數:單精度浮點數(float)和雙精度浮點數(double)。
例如兩種浮點數變量的定義:
float f;
double d;
單精度浮點數和雙精度浮點數在計算機中的表示形式是非常類似的,只是所佔用的二進制位數不同而已。因此,這兩者對應的有效精度和取值範圍是不同的。
單精度浮點數通過輸入轉移字符%f或%e來接受,前提定義float類型的變量。雙精度浮點數通過輸入轉移字符%lf或%le來接受。
類型 |
佔字節數 |
數值範圍 |
十進制精度位數 |
float |
4 |
-3.4e-38~3.4e38 |
6~7 |
double |
8 |
-1.7e-308~1.7e308 |
14~15 |
【例3.9】scanf函數浮點輸入。
解題思路:上面理論講了很多,此程序就是講解float和double的具體使用,和對應區別。
編寫程序:
#include <stdio.h>
int main()
{
float f;
double d;
printf("float佔%d字節, double佔%d字節\n", sizeof(float), sizeof(double));
scanf("%f", &f);
printf("%f\n", f);
scanf("%lf", &d);
printf("%lf\n", d);
return 0;
}
運行結果:
float佔4字節, double佔8字節
123.456789876
123.456787
123.456789876
123.456790
Press any key to continue
程序分析:同樣程序第1~3行,11~12行不在講解。第4~5行分別是float和double的變量定義。第6行輸出float和double各佔字節數,運行結果發現float佔4個字節,double佔8個字節,這與表3.6中“佔字節數”對應相同。注意此處我們用sizeof來測量變量所佔字節數,該函數在程序編寫中會被經常用到,請牢記。具體sizeof的語法要點,請參考表3.7。第7~8行和第9~10行分別是float和double的輸入輸出。
注意:sizeof是一個宏。是判斷數據類型長度符的關鍵字。頭文件是stddef.h,返回值類型爲size_t。size_t類型就是無符號的整型。
三: scanf函數字符與字符數組輸入
單字符語法:%[*]c
字符串語法:%[*][width]s
C語言中的char類型表示一個字符。那麼如何表示一串字符呢?這就會引用字符串數組。一維字符串數組裏面存放的是單個字符的序列。形如:char arr[12] = {'h','e','l','l','o',' ','w','o','r','l','d'}。此處會注意到字符串序列只有11個,而申請的字符串長度卻是12個?細心的同學會發現,此處在輸入時不會出現問題,但是在輸出時就會發現輸出hello world之後出現了亂碼。因爲無論是字符串常量還是字符串變量,在結束時都需要隱藏字符來結束,而多出來的第12位,也就是下表爲11的那一位,程序會自動添加一個隱藏字符,也就是空字符。
【例3.10】scanf函數字符輸入
解題思路:參考例3.7的解題思路即可。
編寫程序:
#include <stdio.h>
int main()
{
char c,arr[16];
scanf("%c", &c);//字符輸入
printf("%c\n", c);
fflush(stdin);/*清空緩衝區*/
scanf("%s", arr);//字符串輸入
printf("%s\n", arr);
fflush(stdin);
return 0;
}
運行結果:
w
w
ds3ds
ds3ds
Press any key to continue
程序分析:程序第4行是字符變量c和字符數組arr的定義。第5行讀入一個字符保存到內存地址爲‘c’的變量中。第7行清空輸入緩衝區下面會詳解。第8行從鍵盤中讀取一個字符串,保存到arr字符數組中,但是讀取字符的長度不能超過arr定義的長度16。如果超過,超過部分會自動捨去。另外我們發現此處並沒有使用取地址符‘&’,這是因爲數組名又可以表示這個數組的開始地址。
fflush(stdin)功能:清空輸入緩衝區。一般使用的目的是確保不應現後面數據的讀取,如程序中就是避免上次輸入字符對本次再輸入字符的影響。如果沒有fflush(stdin)函數就有可能造成上一次輸入緩衝區的數據沒有被上一次讀取完,而被下一次的讀取獲得,影響最終結果。同學們可以嘗試去掉fflush(stdin)函數,並且在第一次輸入一個字符串,就會理解的更透徹。詳細的fflush函數信息請查看錶3.7。
stdin:標準輸入,std即standard(標準),in即input(輸入)。一般指鍵盤輸入到緩衝區的數據。
注意:
除了stdin之外還有stdout,stderr。內核進程會打開三個流:0,1,2。分別代表stdin,stdout,stderr。
stdout:標準輸出。是程序寫入其輸出的位置。缺省情況下,進程將stdout寫到終端屏幕上。
stderr:標準出錯。是程序寫入起錯誤消息的位置。缺省情況下,進程將stderr寫到終端屏幕上。
所需頭文件 |
#include <stdio.h> |
|
函數原型 |
int fflush(FILE *stream); |
|
函數傳入值 |
stream是要衝洗的流 |
|
函數返回值 |
成功 |
0 |
失敗 |
EOF |
如果大家想要更深入的瞭解fflush函數的使用,請自行學習。知識是靠自己的積累,成功是靠自己的努力。加油!!!
3.3.4 scanf函數特殊使用
在學習C語言時,通過scanf的特殊使用,會爲程序增色不少,提高程序設計的效率,進而寫出優美的程序算法。
如果我們輸入一個規定長度的整數,應該怎麼辦?
如果我們輸入一個規定長度的浮點型,應該怎麼辦?
如果我們輸入一個規定長度的字符串時,應該怎麼辦?
如果我們只接受字母或者數字呢?
如果我們只接受規定長度的字母或者數字呢?
如果我們只有當讀入某一個字符時才結束輸入呢?
...
或許你認爲這會非常的容易,如果要求只能使用scanf實現以上功能呢?
由此引入scanf的特殊用法:
scanf("%nd", &a);表示至多接受n位整數數據
scanf("%nf", &d);表示至多接受n位浮點型數據
scanf("%ns", arr);表示至多接受n位字符串類型數據
scanf("%[a-z]s", arr);表示只接受a-z的小寫字母,遇到非a-z的字符結束
scanf("%[A-Z]s", arr);表示只接受A-Z的大寫字母,遇到非A-Z的字符結束
scanf("%[a-zA-Z]s", arr);表示只接受a-z的小寫字母和A-Z的大寫字母,遇到非a-z和 A-Z的字符結束
scanf("%[0-9]s", arr);表示只接受0-9的字符,遇到非0-9的字符結束
scanf("%n[0-9]s", arr);表示至多接受n位的0-9的字符,或者遇到非0-9的字符結束
scanf("%[^=]s", arr);表示讀任意多個字符,直到遇到"="停止
scanf("%n[^=]s", arr);表示在遇到"="停止前至多讀入n個字符
scanf("%[^\n]%*c", arr);表示當讀入回車後結束字符串輸入
...
當然還可以經過以上輸入格式的各種組合,來獲取更多種輸入方式,此處不再贅述,請同學們自行學習。
【例3.11】多種格式輸入。
解題思路:在此程序中我們會重點講解一些scanf函數的使用技巧。這樣在我們以後的編程中就會大大的提高編程的效率和正確性。廢話不多說,直接上程序。
編寫程序:
#include <stdio.h>
int main()
{
char arr[1024];
int a;
double d;
scanf("%4d", &a);/*至多接受4位整數數據*/
printf("%d\n", a);
fflush(stdin);/*清空緩衝區*/
scanf("%6lf", &d);/*至多接受6位浮點型數據*/
printf("%lf\n", d);
fflush(stdin);
scanf("%4s", arr);/*至多接受4位字符串類型數據*/
printf("%s\n", arr);
fflush(stdin);
scanf("%[a-z]s", arr);/*只接受a-z的小寫字母,遇到非a-z的字符結束*/
printf("%s\n", arr);
fflush(stdin);
scanf("%[A-Z]s", arr);/*只接受A-Z的大寫字母,遇到非A-Z的字符結束*/
printf("%s\n", arr);
fflush(stdin);
scanf("%[a-zA-Z]s", arr);/*只接受a-z的小寫字母和A-Z的大寫字母,遇到非a-z 和A-Z的字符結束*/
printf("%s\n", arr);
fflush(stdin);
scanf("%[0-9]s", arr);/*只接受0-9的字符,遇到非0-9的字符結束*/
printf("%s\n", arr);
fflush(stdin);
scanf("%6[0-9]s", arr);/*至多接受6位的0-9的字符,或者遇到非0-9的字符結束*/
printf("%s\n", arr);
fflush(stdin);
scanf("%[^=]s", arr);/*讀任意多個字符,直到遇到"="停止*/
printf("%s\n", arr);
fflush(stdin);
scanf("%4[^=]s", arr);/*在遇到"="停止前至多讀入4個字符*/
printf("%s\n", arr);
fflush(stdin);
scanf("%[^\n]%*c", arr);/*當讀入回車後結束字符串輸入*/
printf("%s\n", arr);
fflush(stdin);
return 0;
}
運行結果:
12313
1231
321.123445
321.120000
EW23ds32
EW23
awefdwe23
awefdwe
ASD12ds
ASD
AdseDsdswSSS123
AdseDsdswSSS
123243sdAdDSw
123243
2312dsd322
2312
dsfew23\<.?'"we23*&dfdewewfew=
dsfew23\<.?'"we23*&dfdewewfew
f*</12
f*</
few2323d.,23/][]2\23@#$%^&*()[]\
few2323d.,23/][]2\23@#$%^&*()[]\
Press any key to continue
程序分析:此處看上去挺複雜,其實很簡短,說白了就是紙老虎。大家根據程序中的註釋,以及運行結果進行操作,理解即可。程序是一種語言,既然是語言,只有經常的使用和練習才能更快的提高,所以大家要努力練習喲。
【例3.12】從鍵盤輸入字符串,只獲取字符串中的整數。比如輸入“12ab34cd56”按行分別輸出12,34,56,如運行結果所示。
解題思路:我們用scanf函數實現這樣的功能,要求變量只接受數字,不接受其他字符即可。
程序編寫:
#include <stdio.h>
int main()
{
int n;
while (scanf("%*[^0-9]") != EOF && scanf("%d", &n) != EOF)
{
printf("%d\n", n);
}
return 0;
}
運行結果:
12ab34cd56
12
34
56
程序分析:程序第5行是一個while循環表示。while循環執行的順序是:先執行while後面中括號中的數據,然後再執行大括號中的數據,執行完後再返回執行中括號中的數據,直到中括號中的數據爲0或者NULL時,結束循環,順序執行右花括號後面的語句。scanf("%*[^0-9]") 表示輸入的數據不保存到任何變量中且遇到0-9中的任何一個或多個整數結束。另scanf("%d", &n)表示接受一個整數值。當輸入12ab34cd56時,發現檢測到又整數的數據,結束scanf("%*[^0-9]")的執行。然後執行scanf("%d", &n),即把12賦值給變量n,接着輸出n等於12。可是爲什麼還會有34,56的輸出呢?那是因爲當你輸入12ab34cd56後,這所有的數據都在緩存區中,你通過while循環依次的把所有的整數讀入並且輸出。如果你把while循環換成if判斷,就會發現就只有12輸出了,並不會再去讀緩衝區中的其他數據。或者你在while循環中加入fflush(stdin);就會只輸出第一次遇到的整數,而不再會輸出該緩衝區之後遇到的整數。
同以上輸入類似,那麼如何只接受字符的輸入呢?
【例3.13】輸入一個字符串,只接受字母。
解題思路:與例3.11解題思路類似,不同的是此處要求只接受字母。同樣,我們用scanf函數實現這樣的功能,要求變量只接受字母,不接受其他字符即可。
程序編寫:
#include <stdio.h>
int main()
{
char ch;
while (scanf("%*[^a-zA-Z]c") != EOF && scanf("%c", &ch) != EOF)
{
printf("%c\n", ch);
}
return 0;
}
運行結果:
1H2ell23o,.W9orl65d';][
H
e
l
l
o
W
o
r
l
d
程序分析:程序第5行是一個while循環,while循環的使用大家參考例3.11即可。while循環後面的兩個scanf函數表示只接受字符。如果不是字符就捨棄。比如在程序中輸入“1H2ell23o,.W9orl65d';][”,結果輸出爲‘H’,‘e’,‘l’,‘l’,‘o’,‘w’,‘o’,‘r’,‘l’,‘d’。
3.4 puts和gets函數
前面講解了一對輸入輸出函數:printf和scanf函數,這節我們將會講解另一對輸入輸出函數——puts和gets函數。與printf和scanf函數不同,puts和gets函數只是從鍵盤接受字符串。而printf和scanf函數可以接受任何想要的數據類型。詳細的puts和gets函數請大家接着往下學習。
3.4.1 puts和gets函數說明
puts函數用來向標準輸出設備(一般是指輸出到顯示器)寫字符串或字符數組或字符串指針。puts(s)函數的作用等效於printf(“%s\n”, s),需要注意:s是C語言風格的字符串,最後以’\0’結尾。
gets函數從標準輸入設備(一般是指輸出到顯示器)讀字符串函數。在緩衝區足夠大且不會溢出的情況下,可以無限讀取,不會判斷上限,以回車結束讀取。
但是gets函數函數在使用中如果不注意就會出現很多的問題。如果緩衝區較小,導致數據溢出,那麼多出來的數據將被寫入到堆棧中,這就覆蓋了堆棧裏原先的內容,破壞一個或多個與之不相關的變量的值。所以在真正的使用中我們多會使用fgets(stdin)或者使用scanf函數來代替gets函數的使用。
3.4.2 puts和gets函數格式
表3.8爲 puts函數語法要點。
所需頭文件 |
#include<stdio.h> |
函數原型 |
int puts(char *string); |
功能 |
輸出字符串到流stdout中 |
函數返回值 |
成功:非負數 失敗:EOF |
注意:
- puts函數只能輸出字符串,不能輸入數值或者進行格式轉換。
- 可以把要輸出的字符串直接寫入puts()函數中,形如:puts(“IloveC.”)。
- 在輸出字符串時會自動換行。
表3.9 爲gets函數語法要點。
所需頭文件 |
#include <stdio.h> |
函數原型 |
char * gets ( char * str ); |
功能 |
從stdin流中讀取字符串,直至接受到換行符或EOF時停止 |
函數返回值 |
成功:返回與參數str相同的指針 遇到EOF或發生錯誤:返回NULL |
注意:
- gets函數讀到\n(回車)時,停止讀取,但是它並不把\n保存到字符串裏去,而是在末尾添加‘\0’字符。
- 在遇到返回值爲NULL的情況時,需要用ferror或feof函數檢查是發生錯誤還是遇到EOF。
【例3.14】puts函數的基本使用。
解題思路:通過表3.8中有關puts函數的信息,進行編程。使用puts函數的頭文件是stdio.h。puts函數功能輸出一個字符串至輸出流(一般是到屏幕上)。返回值暫時不用,且不管它。
編寫程序:
1. #include <stdio.h>
2. int main()
3. {
4. char str[100] = "Hello My Lovely world!";
5. puts("Hello My Lovely world!");
6. puts(str);
7. return 0;
8. }
運行結果:
Hello My Lovely world!
Hello My Lovely world!
Press any key to continue
程序分析:程序第5行和第6行可以看出,puts函數既可以直接輸出字符串,又可以直接輸出字符數組。
【例3.15】gets函數的基本使用。
解題思路:gets函數與puts函數使用類似,我們參考表3.9和例3.14的解題思路,來使用我們的gets函數。
編寫程序:
1. #include <stdio.h>
2. int main()
3. {
4. char str[100];
5. gets(str);
6. printf("%s\n", str);
7. puts(str);
8. return 0;
9. }
運行結果:
Hello C Program!
Hello C Program!
Hello C Program!
Press any key to continue
程序分析:第4行我們定義一個字符數組,用第5行的gets函數接受一個字符串。gets函數是以換行結束輸入。輸入的結果既可以printf函數輸出,又可以用puts函數輸出,請看程序第6~7行。
【例3.16】puts和gets函數的使用之用戶登錄。
解題思路:程序例3.15中就有puts函數和gets函數結合的簡單使用。本程序以一個用戶登錄程序進行詳細的使用說明。
編寫程序:
1. #include <stdio.h>
2. #include <string.h>
3. int main()
4. {
5. char inputusername[24],inputpwd[24];//定義用戶名和密碼數組
6. //使用puts函數輸出提示信息
7. puts("歡迎使用用戶管理系統:");
8. puts("請輸入用戶名:");
9. //gets函數輸入用戶名,保存到inputusername中
10. gets(inputusername);
11. //使用strcmp函數進行比較,判斷輸入的用戶名和正確的用戶名是否一致
12. if (strcmp("username" , inputusername)!=0)
13. {
14. puts("用戶名輸入錯誤!");
15. return -1;
16. }
17. puts("請輸入密碼:");
18. gets(inputpwd);//gets函數輸入密碼,保存到inputpwd中
19. //使用strcmp函數進行比較,判斷輸入的密碼和正確的密碼是否一致
20. if (strcmp("password" , inputpwd)!=0)
21. {
22. puts("密碼輸入錯誤!");
23. return -1;
24. }
25. //如果用戶名和密碼一致,那就輸出“登錄成功”的提示信息
26. puts("登陸成功...");
27. return 0;
28. }
第一次運行結果:
歡迎使用用戶管理系統:
請輸入用戶名:
username
請輸入密碼:
password
登陸成功...
Press any key to continue
第二次運行結果:
歡迎使用用戶管理系統:
請輸入用戶名:
username
請輸入密碼:
pwd
密碼輸入錯誤!
Press any key to continue
第三次運行結果:
歡迎使用用戶管理系統:
請輸入用戶名:
usrname
用戶名輸入錯誤!
Press any key to continue
程序分析:在程序講解前我們首先了解strcmp函數的使用。strcmp函數傳入兩個參數。頭文件爲string.h。功能是比較兩個傳入的字符串的大小。字符串大小的比較是以ASCII碼錶上的順序決定的。我們會在後面的章節對strcmp函數以及相應的字符串操作函數進行詳細的介紹,大家此處只需要大概瞭解即可。接着我們做程序分析,在程序第1行爲stdio.h,是puts和gets函數的頭文件。第2行爲string.h,是strcmp函數的頭文件,第3行爲main函數,爲程序的入口。程序寫在第4行和28行之間的花括號之間。程序第5行定義兩個長度爲24的字符串數組。第7~8行使用puts函數輸出提示信息。第10行使用gets函數輸入用戶名。第12行if語句中是進行strcmp函數的判斷,如果兩個相等輸出0,。如果第一個字符串大於(小於)第二個字符串輸出大於(小於)0。如果輸出結果不等於0,就表示兩個字符串不相等。不行等就說明輸入的結果不對,所以我們提示輸入錯誤,然後結束程序的運行,返回-1表示程序出錯。如果相等程序從第17行順序執行。接下來程序的分析與上面相同。
3.5 putchar和getchar函數
上一節我們講解了字符串的輸入輸出函數,那麼這一節我們將會講解字符的輸入輸出函數。這對函數就是putchar和getchar函數。這對函數與puts和gets函數有什麼具體的區別呢?請聽接着分解!!!哈哈。
3.5.1 putchar和getchar函數說明
C語言提供了兩個單字符操作的函數,用於單字符的輸入輸出。
(1) putchar函數用於向標準輸入輸出設備輸出一個字符。
一般的標準輸出設備是指顯示器。格式爲putchar(c),其中c可以被單引號引起來,或者c是介於0~127之間的一個十進制整型數,c也可以是之前定義好的char類型字符變量。
- getchar函數用於從標準輸入裏讀取下一個字符。
getchar函數是由宏實現的:#define getchar() getc(stdin)。當程序調用getchar()函數時,程序會等待用戶輸入字符,而用戶輸入的字符被存放在鍵盤的緩衝區中,直到用戶輸入回車爲止,回車字符也會被放到緩衝區中。
3.5.2 putchar和getchar函數格式
表3.10與表3.11分別是putchar和getchar函數的語法要點。
所需頭文件 |
#include<stdio.h> |
函數原型 |
void putchar(c); |
功能 |
輸出單個字符 |
函數返回值 |
void |
所需頭文件 |
#include<stdio.h> |
函數原型 |
int getchar(void); |
功能 |
接受單個字符 |
函數返回值 |
成功:返回用戶輸入的ASCII碼 失敗:-1(即EOF) |
【例3.17】 putchar和getchar函數的使用。
解題思路:此處我們就直接使用兩個函數,不在單獨介紹。具體使用當然還是請大家觀察表3.10和表3.11的對應語法要點。
編寫程序:
1. #include <stdio.h>
2. int main()
3. {
4. int c;
5. while ((c=getchar())!='\n')//當輸入回車時程序結束
6. {
7. if (EOF == c)//判斷輸入的結果是否正確
8. {
9. break;
10. }
11. putchar(c);//使用putchar函數輸出輸入的結果
12. }
13. getchar();//是程序暫停,按任意字符結束
14. return 0;
15. }
運行結果:
I love C program.
I love C program.
Press any key to continue
程序分析:程序第5行,會等到輸入一個回車後,結束循環接受數據,然後把接受到的數據用putchar函數依次輸出,因此程序會讓你輸入一個字符串“I love C program.”,按輸入一個回車後,程序第11行纔會通過putchar函數把所有的數據輸出。第13行的getchar函數功能是讓程序在該位置暫停,等待用戶輸入任意一個字符後,程序執行下一條語句。所以在程序輸出“I love C program.”後,程序會處於等待接受狀態,只有當你輸入任意字符時程序纔會結束。有人會對程序中的if語句產生疑問,爲什麼還需要判斷c時候等於EOF呢?其實這個問題我們前面已經講過,這是因爲如果在程序中你輸入Ctrl+z那麼程序就會返回一個EOF值,就代表了程序結束。就是預防輸入錯誤。
注意:
getchar()函數可以實現實現暫停,但是還有一種方法也是可以實現暫停的。該語句就是system(“pause”),不過需要頭文件#include <stdlib.h>或#include <windows.h>。
3.6 getche與getch函數
上面幾節講解的都是成對的輸入輸出函數,那麼本節我們將會講解一對輸入函數,因爲這對輸入函數在程序設計中使用的頻率還是挺高的。比如如果我們要輸入一個字符,要求程序立刻做出反應,而不是等到我們輸入回車或者其他字符等才做出反應。那麼getche和getch函數將會大放異彩。
可是這兩個函數又有什麼具體的區別呢?getche函數在我們輸入字符後會在屏幕立刻顯示我們輸入的字符。而getch函數則不會顯示字符。那麼這兩個函數是如何使用呢?我們接着往下學。
3.6.1 getche與getch函數說明
getche函數功能:輸入後立即從控制檯獲取輸入字符,不以回車結束,有回顯,非緩衝。
getch函數功能:輸入後立即從控制檯獲取一個字符,不以回車結束,無回顯,非緩衝。是非標準C函數。
注:getche函數和getch函數都是接受字符的。
3.6.2 getche與getch函數格式
表3.12和表3.13分別是getche和getch函數的語法要點。
所需頭文件 |
#include<conio.h> |
函數原型 |
int getche(void); |
功能 |
接受單個字符 |
函數返回值 |
成功:返回用戶輸入的ASCII碼 失敗:-1(即EOF) |
所需頭文件 |
#include<conio.h> |
函數原型 |
int getch(void); |
功能 |
接受單個字符 |
函數返回值 |
成功:返回用戶輸入的ASCII碼 失敗:-1(即EOF) |
【例3.18】getche與getch函數的使用
解題思路:此處我們以一個簡單的實例進行說明。廢話不多說,程序見“真情”。
程序編寫:
1. #include <stdio.h>
2. #include <conio.h>
3. int main()
4. {
5. char ch;
6. printf("使用getche()函數輸入一個字符:");
7. ch = getche();
8. printf("\n輸入的是'%c'\n", ch);
9. printf("使用getch()函數輸入一個字符:");
10. ch = getch();
11. printf("\n輸入的是'%c'\n", ch);
12. return 0;
13. }
運行結果:
使用getche()函數輸入一個字符:f
輸入的是'f'
使用getch()函數輸入一個字符:
輸入的是'd'
Press any key to continue
程序分析:運行程序時,第6行輸出提示語句“使用getche()函數輸入一個字符:”,然後等待輸入數據。在程序第7行輸入“f”後,不等按下回車,就會在控制檯第2行輸出字符‘f’,並且程序會順序執行第8行,輸出“輸入的是'f'”。字符‘f’在控制檯上顯示出來的情況,這就表示有回顯。順序執行第9行輸出“使用getch()函數輸入一個字符:”,等待用戶輸入字符,而當輸入字符‘d’後,發現控制檯上並沒有輸出字符‘d’,直接輸出了一句“輸入的是'd'”,這就是無回顯。