第三章 初窺天機之順序程序設計

在程序設計中有三種基本的結構,而正是這三種基本的結構組成了程序設計的主體。它們分別是:順序結構,選擇結構,循環結構。本章我們將會講解有關順序結構設計,並且以幾個實際的函數作爲實例,進行相關編程,讓大家對順序結構設計能夠深刻的理解和掌握。

前面我們已經大概講了一點printf函數的輸出結果。其實printf函數還有很多的使用技巧,我們將會在本章進行更加詳細的介紹。實際上在我們寫代碼時總是少不了程序的輸入和輸出。輸入輸出就像是一個數學函數,輸入是變量,輸出則是結果。但是在實際的程序設計中輸入輸出是有格式要求,我們可以按照我們想要的方式輸出結果,比如在輸入時只接受數字或字母,輸出要求是金字塔或倒金字塔等。說了這麼多,接下來讓我們見證輸入和輸出函數的神奇吧!

本章我們主要會講解三對輸入輸出函數和一對特殊的輸入函數,三對輸入輸出函數分別是:printf和scanf函數、puts和gets函數、putchar和getchar函數。一對特殊的輸入函數是:getche函數和getch函數。想知道它們有什麼具體的效果和作用嗎?請接着看。

3.1 順序結構

順序結構在程序設計中是最簡單的,只需要按照問題解決的順序寫出相應的語句就行,它的執行順序是自上而下,依次執行的。

爲了更加直觀的理解設計我們通常會使用流程圖或者N-S圖來顯示程序運行的過程。不過我個人還是贊同使用流程圖的,雖然N-S在很多方面比流程圖效果要好。但是無論是在使用頻率上,還是可理解上,我個人感覺還是流程圖距離我們更近。好像最早應該高中時我們就已經開始接觸流程圖了,所以會有一種親切感。

圖3.1 順序結構流程圖

 

如圖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表示爲空。

表3.1 printf函數語法要點

所需頭文件

#include <stdio.h>

函數原型

void printf(const char *format, ...);

函數輸出格式

format:爲函數輸出的格式字符串

函數傳入值

傳入值根據具體的format中要求的格式信息輸入

函數返回值

void

“格式信息”參數包含三種對象類型的字符串:

  1. 無格式字符串複製到輸出流。
  2. 轉換規範,每個規範導致在參數列表中檢索一個或多個項。
  3. 轉義序列。

上面這三種說法是不是太文藝了呢?不用管它,我們稍後會以一個實際代碼實例來進行詳細的說明。此處留作將來查詢用。

例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格式化字符串中允許使用的修飾符。

表3.2 格式化字符串中允許使用的修飾符

字符

字符名稱

說明

範例

-

(標誌)

負號

設置左對齊。但總寬度必須比實際寬度大才有效

%-4d

%-6.4f

+

(標誌)

正號

默認爲正號,可以不寫。若設定的寬度比實際寬度大,數據向右看齊

%+4d(或%4d)

%+6.4f(或%6.4f)

width

(最小寬度)

寬度

設置數據顯示的寬度。如果寬度比數值本身寬度小,則以實際寬度顯示。若輸出含有小數部分,則寬度包括整數位數、小數點、小數位數以及正負號

%4d

%6.4f

.

小數點

設置小數

%6.4f

prec

(精度)

小數點後面的位數

設置小數點後面的位數:

  1. type=d,i,o,u,x時,沒有影響;
  2. type=e,E,f時,不顯示小數點。同時還表示最大寬度。

 

 

(空格)

空格

若正數前面加空格,則顯示空格。若負數前面加空格,則顯示負號

printf("% 4d", 43);

結果: 43

printf("% 4d", -43);

結果:-43

0

數字零

將輸出的前面補上0,直到佔滿指定列寬爲止(不可以搭配使用“-”)

printf("%04d", 43);

結果:0043

#

井號

  1. type是o,x,X時,增加前綴0,0x,0X。
  2. type是e,E,f,g,G時,一定使用小數點。
  3. type是g,G時,尾部的0保留。
  1. printf("%#o", 43);

結果:053

2. printf("%#e", 43.3);

結果:4.330000e+001

3. printf("%#g", 43.3);

結果:43.3000

注:表格正文第六行是空格,所以好像感覺不到任何效果。該按鍵就是鍵盤正下面那個長鍵。

  • 規定數據的格式

此處我們講解數據的格式,也就是上面“格式信息”中對應的“類型”信息。如果我們想要使用printf輸出一個十進制整數,該怎麼辦呢?一個字符或字符串呢?這些都是由數據格式來控制的,因此可見我們“類型”的重要性。

另外從“格式信息”中我們也可以看出“類型”的重要性,在“%”之後除了“類型”外,其他的都是可有可無的可選項。而“類型”卻是必須有的。

在我們的“類型”中又以“%d”、“%f”、“%lf”、“%c”、“%s”更爲常用,所以這幾種類型大家要重點記憶。詳細的數據格式大家參考表3.3即可。

表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轉義字符所示。表中所示轉義序列中的字符,看上去像是兩個或多個字符的組合,其實就是一個字符。

表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’、‘\’’,‘\”’、‘\\’等幾種形式。請大家重點記憶。

使用轉義字符是有以下幾點需要注意的要點:

  1. 轉義字符只能使用小寫字母。
  2. 轉義字符‘\0’表示空字符NULL,它的值是0,對應的ASCII值是48。所以空字符‘\0’不是字符‘0’。且空字符(ASCII碼值48)也不等於空格字符(ASCII碼值32)。
  3. ‘\v’垂直製表符和‘\f’換頁符對屏幕沒有任何影響,影響打印機的響應操作。
  4. 如果反斜槓‘\’和其之後的字符不構成轉義字符,則因‘\’不起轉義作用而被忽略。
  5. 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函數的語法要點。

表3.5 scanf函數語法要點

所需頭文件

#include <stdio.h>

函數原型

int scanf(const char *format, ...);

函數傳入值

函數傳入值由format中要接受的類型傳入

函數返回值

 

成功

正確輸入參數的個數

失敗

0

或EOF

scanf函數執行成功返回賦值的數據項數,失敗出錯時返回EOF。

【例3.7scanf函數介紹。

解題思路:經過表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.8scanf函數整型輸入

解題思路:由於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需要注意一下兩點:

  1. scanf讀入一組整數時,會自動跳過空格、tab和回車符,尋找下一個輸入域。每個輸入域都是由一串連續的非空白字符的整型數據。
  2. 格式信息中除了要有以%開始的字符轉換說明,還可以有普通的字符或字符組合。這些字符或字符組合是限制使用者輸入數據格式使用的,並不在屏幕上顯示。

 

二:scanf函數浮點數輸入

函數的浮點數輸入,就是接受各種類型的浮點數。最常用的浮點數就是單精度浮點數和雙精度浮點數兩種類型。下面看一下浮點數輸入的格式。

通常意義上的“格式信息”的格式如下:

語法:%[+][-][width][.prec][f|e|g]

在標準C語言中有兩種浮點數:單精度浮點數(float)和雙精度浮點數(double)。

例如兩種浮點數變量的定義:

float f;

double d;

單精度浮點數和雙精度浮點數在計算機中的表示形式是非常類似的,只是所佔用的二進制位數不同而已。因此,這兩者對應的有效精度和取值範圍是不同的。

單精度浮點數通過輸入轉移字符%f或%e來接受,前提定義float類型的變量。雙精度浮點數通過輸入轉移字符%lf或%le來接受。

表3.6 float與double的精度表

類型

佔字節數

數值範圍

十進制精度位數

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.10scanf函數字符輸入

解題思路:參考例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寫到終端屏幕上。

表3.7 fflush函數的語法要點

所需頭文件

#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 putsgets函數

前面講解了一對輸入輸出函數: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函數語法要點。

表3.8 puts函數語法要點

所需頭文件

#include<stdio.h>

函數原型

int puts(char *string);

功能

輸出字符串到流stdout中

函數返回值

成功:非負數

失敗:EOF

注意:

  1. puts函數只能輸出字符串,不能輸入數值或者進行格式轉換。
  2. 可以把要輸出的字符串直接寫入puts()函數中,形如:puts(“IloveC.”)。
  3. 在輸出字符串時會自動換行。

 

表3.9 爲gets函數語法要點。

表3.9 爲gets函數語法要點。

所需頭文件

#include <stdio.h>

函數原型

char * gets ( char * str );

功能

從stdin流中讀取字符串,直至接受到換行符或EOF時停止

函數返回值

成功:返回與參數str相同的指針

遇到EOF或發生錯誤:返回NULL

注意:

  1. gets函數讀到\n(回車)時,停止讀取,但是它並不把\n保存到字符串裏去,而是在末尾添加‘\0’字符。
  2. 在遇到返回值爲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 putchargetchar函數

上一節我們講解了字符串的輸入輸出函數,那麼這一節我們將會講解字符的輸入輸出函數。這對函數就是putchar和getchar函數。這對函數與puts和gets函數有什麼具體的區別呢?請聽接着分解!!!哈哈。

 

3.5.1 putchargetchar函數說明

C語言提供了兩個單字符操作的函數,用於單字符的輸入輸出。

(1) putchar函數用於向標準輸入輸出設備輸出一個字符。

一般的標準輸出設備是指顯示器。格式爲putchar(c),其中c可以被單引號引起來,或者c是介於0~127之間的一個十進制整型數,c也可以是之前定義好的char類型字符變量。

  1. getchar函數用於從標準輸入裏讀取下一個字符。

getchar函數是由宏實現的:#define getchar() getc(stdin)。當程序調用getchar()函數時,程序會等待用戶輸入字符,而用戶輸入的字符被存放在鍵盤的緩衝區中,直到用戶輸入回車爲止,回車字符也會被放到緩衝區中。

3.5.2 putchargetchar函數格式

表3.10與表3.11分別是putchar和getchar函數的語法要點。

表3.10 putchar函數語法要點

所需頭文件

#include<stdio.h>

函數原型

void putchar(c);

功能

輸出單個字符

函數返回值

void

 

表3.11 getchar函數語法要點

所需頭文件

#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 getchegetch函數

上面幾節講解的都是成對的輸入輸出函數,那麼本節我們將會講解一對輸入函數,因爲這對輸入函數在程序設計中使用的頻率還是挺高的。比如如果我們要輸入一個字符,要求程序立刻做出反應,而不是等到我們輸入回車或者其他字符等才做出反應。那麼getche和getch函數將會大放異彩。

可是這兩個函數又有什麼具體的區別呢?getche函數在我們輸入字符後會在屏幕立刻顯示我們輸入的字符。而getch函數則不會顯示字符。那麼這兩個函數是如何使用呢?我們接着往下學。

 

3.6.1 getchegetch函數說明

getche函數功能:輸入後立即從控制檯獲取輸入字符,不以回車結束,有回顯,非緩衝。

getch函數功能:輸入後立即從控制檯獲取一個字符,不以回車結束,無回顯,非緩衝。是非標準C函數。

注:getche函數和getch函數都是接受字符的。

 

3.6.2 getchegetch函數格式

表3.12和表3.13分別是getche和getch函數的語法要點。

表3.12 getche函數語法要點

所需頭文件

#include<conio.h>

函數原型

int getche(void);

功能

接受單個字符

函數返回值

成功:返回用戶輸入的ASCII碼

失敗:-1(即EOF)

 

表3.13 getch函數語法要點

所需頭文件

#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'”,這就是無回顯。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章