單片機(jī)編程-c程序設(shè)計(jì)語(yǔ)言_第1頁(yè)
單片機(jī)編程-c程序設(shè)計(jì)語(yǔ)言_第2頁(yè)
單片機(jī)編程-c程序設(shè)計(jì)語(yǔ)言_第3頁(yè)
單片機(jī)編程-c程序設(shè)計(jì)語(yǔ)言_第4頁(yè)
單片機(jī)編程-c程序設(shè)計(jì)語(yǔ)言_第5頁(yè)
已閱讀5頁(yè),還剩276頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

者的 專家指導(dǎo)PrefacetotheChinease 中文版 譯者 校譯者簡(jiǎn) 譯者簡(jiǎn) 審校人簡(jiǎn) 第1版 引 第1 導(dǎo) 入 for語(yǔ) 符號(hào)常 文件字符計(jì) 行計(jì) 單詞計(jì) 數(shù) 函 字符數(shù) 第2 變量 常 算術(shù)運(yùn)算 類(lèi)型轉(zhuǎn) 按位運(yùn)算 條件表達(dá) 第3 控制 else-if語(yǔ) switch語(yǔ) while循環(huán)與for循 break語(yǔ)句與continue語(yǔ) goto語(yǔ)句與標(biāo) 第4 外部變 作用域規(guī) 頭文 靜態(tài)變 寄存器變 程序塊結(jié) 初始 遞 C預(yù)處理 文件包 宏替 條件包 第5 指針與數(shù) 指針與地 指針與數(shù) 數(shù) 指針與數(shù) 命令行參 復(fù)雜第6 結(jié) 結(jié)構(gòu)與函 結(jié)構(gòu)數(shù) 自結(jié) 表查 類(lèi)型定義 聯(lián) 位字 第7 輸入與輸 變長(zhǎng)參數(shù) 文件錯(cuò)誤處理——stderr和 其它函 ungetc函 數(shù)學(xué)函 第8 UNIX系統(tǒng)接 文件描述 低級(jí)I/O——read和 實(shí)例——fopen和getc函數(shù)的實(shí) 附錄 參考手 引 詞 記 注 標(biāo)識(shí) 關(guān)鍵 常 語(yǔ)法符 基本類(lèi) 派生類(lèi) 類(lèi)型限定 對(duì)象和左 轉(zhuǎn) 整型提 整型轉(zhuǎn) 浮點(diǎn)類(lèi) 指針和整 表達(dá) 指針生 初等表達(dá) 后綴表達(dá) 一元運(yùn)算 移位運(yùn)算 關(guān)系運(yùn)算 條件運(yùn)算 賦值表達(dá) 逗號(hào)運(yùn)算 常量表達(dá) 類(lèi)型說(shuō)明 結(jié)構(gòu)和聯(lián)合枚 初始 類(lèi)型 類(lèi)型等 語(yǔ) 帶標(biāo)號(hào)語(yǔ) 表達(dá)式語(yǔ) 復(fù)合語(yǔ) 選擇語(yǔ) 循環(huán)語(yǔ) 跳轉(zhuǎn)語(yǔ) 外部函數(shù)定 外部 詞法作用 連 預(yù)處 三字符序 行連 文件包 條件編 行控 空指 預(yù)定義名 語(yǔ) 附錄 標(biāo)準(zhǔn) 文件操 格式化輸 格式化輸 數(shù)學(xué)函數(shù) 實(shí)用函數(shù) 診斷 信號(hào) 與具體實(shí)現(xiàn)相關(guān)的限制:<limits.h>和 附錄 變更小 索 第1章導(dǎo)言CC元素,至于其中的具體細(xì)節(jié)、規(guī)則以及一些例外情況,在此暫時(shí)不多做討論。因此,本章不C是希望讀者能盡快地編寫(xiě)出有用的程序,為此,本章將重點(diǎn)介紹一些基本概念,比如變量與常量、算術(shù)運(yùn)算、控制流、函數(shù)、基本輸入/輸出等。而對(duì)于編寫(xiě)較大型程序所涉及到的一CC語(yǔ)言的所有強(qiáng)大功能,因此,這些例子也許并不簡(jiǎn)潔、精煉。雖然我們已經(jīng)盡它的影響。o,盡管這個(gè)練習(xí)很簡(jiǎn)單,但對(duì)于初學(xué)語(yǔ)言的人來(lái)說(shuō),它仍然可能成為一大,因?yàn)橐獙?shí)#include<stdio.h>{ o,} 執(zhí)行文件a.out。然后,我們輸入:o,world{ o,}

main的函數(shù),它不接受參數(shù)值main函數(shù)的語(yǔ)句都被括在花括號(hào)中main函數(shù)調(diào)用庫(kù)函數(shù)printf\n第一個(gè)CC語(yǔ)言程序,無(wú)論其大小如何,都是由函數(shù)和變量組成的。函數(shù)中包含一些語(yǔ)句,以指定所要執(zhí)行的計(jì)算操作;變量則用于計(jì)算過(guò)程中使用的值。CFortranPascal語(yǔ)言中的過(guò)程和函數(shù)也main函數(shù)。main函數(shù)通常會(huì)調(diào)用其它函數(shù)來(lái)幫助完成某些工作,被調(diào)用的函數(shù)可以是程序設(shè)計(jì)人員#include含這一行語(yǔ)句。在第7章和附錄B中對(duì)標(biāo)準(zhǔn)庫(kù)進(jìn)行詳細(xì)介紹。函數(shù)之間進(jìn)行數(shù)據(jù)交換的法是調(diào)用函數(shù)向被調(diào)用函數(shù)提供一個(gè)值(稱為參數(shù))列 o,調(diào)用函數(shù)時(shí),只需要使用函數(shù)名加上用圓括號(hào)括起來(lái)的參數(shù)表即可。上面這條語(yǔ)句將"o,world\n"。作為參數(shù)調(diào)用printf函數(shù)。printf是一個(gè)用于打印輸出的庫(kù)函數(shù),在此處, o,world\n"就是一個(gè)字符串。目前我們僅使用字符串作為printf及其它函數(shù)的參數(shù)。 o,world#include{ o,}請(qǐng)注意,\n只代表一個(gè)字符。類(lèi)似于\n的轉(zhuǎn)義字符序列為表示無(wú)法輸入的字符或不可見(jiàn)字符提供了一種通用的可擴(kuò)充的機(jī)制。除此之外,C語(yǔ)言提供的轉(zhuǎn)義字符序列還包括:\t表示制表符;\b表示回退符;\"表示雙引號(hào);\\表示反斜杠符本身。2.3節(jié)將給出轉(zhuǎn)義字符序列1-1在你自己的系統(tǒng)中運(yùn)行“o,world”程序。再有意去掉程序中的部分1-2printf函數(shù)的參數(shù)字符串中包含\c(c是上面的轉(zhuǎn)義14此程序中仍然只包括一個(gè)名為main的函數(shù)定義。它比前面打印“ o,world”的程序 #include {intfahr,intlower,upper,lower /*upper /*step /*fahr=while(fahr<=upper)celsius=5*(fahr-32)/9;printf("%d\t%d\n",fahr,celsius);fahr=fahr+step;}}打印華氏溫度與攝氏溫度對(duì)照表*/在C語(yǔ)言中,所有變量都必須先后使用。通常放在函數(shù)起始處,在任何可執(zhí)行語(yǔ)句之前。用于說(shuō)明變量的屬性,它由一個(gè)類(lèi)型名和一個(gè)變量表組成,例如:intfahr,intlower,upper,可以帶有小數(shù)部分的數(shù)。intfloat類(lèi)型的取值范圍取決于具體的機(jī)器。對(duì)于int類(lèi)型,16位,其取值范圍在-32768~3276732int類(lèi)型。float類(lèi)型通常是32位,它至少有6位有效數(shù)字,取值范圍一般在10-38~1038之間。char 構(gòu)、聯(lián)合,指向這些類(lèi)型的指針以及返回這些類(lèi)型值的函教。在后續(xù)相應(yīng)的章節(jié)中分lower=upper=step=20;fahr=lower;while(fahr<=upper)}while循環(huán)語(yǔ)句的執(zhí)行方式是這樣的:首先測(cè)試圓括號(hào)中的條件;如果條件為真條件,如果為真,則再次執(zhí)行循環(huán)體;當(dāng)圓括號(hào)中的條件為假(fahr>upper)時(shí),while語(yǔ)句的循環(huán)體可以是用花括號(hào)括起來(lái)的一條或多條語(yǔ)句(如上面的溫度轉(zhuǎn)換程while(i<j)i=2*celsius=5*(fahr-32)/是整數(shù),5/9相除后經(jīng)截取所得的結(jié)果為0,因此這樣求得的所有攝氏溫度都將為0。從該例子中也可以看出printf函數(shù)的一些功能。printf是一個(gè)通用輸出格式化函數(shù),printf("%d\t%d\n",fahr,功能。printfC語(yǔ)言程序中C7章之前的各章中將不再對(duì)輸入/輸出做的介紹,并且,特別將格式化輸入推后到第7章講解。如果讀者想了解數(shù)據(jù)輸入,可以先閱7.4節(jié)中對(duì)scanf函數(shù)的討論部分,scanf函數(shù)類(lèi)似于printf函數(shù),但它用于讀輸printf("%3d%6d\n",fahr,fahrcelsius的值,這樣,fahr的值占3個(gè)數(shù)字寬,celsius的值6個(gè)數(shù)字寬,04#include/*printFahrenheit-Celsiusforfahr=0,20,...,300;floating-pointversion*/{floatfahr,celsius;floatlower,upper,step;lower=0; /*lowerlimitoftemperatuirescale*/upper=300; /*upperlimit*/step= /*stepsizefahr=while(fahr<=upper)celsius=(5.0/9.0)*(fahr-32.0);printf("%3.0f%6.1f\n",fahr,celsius);fahr=fahr+step;}}這個(gè)程序與前一個(gè)程序基本相同,不同的是,它把fahr與celsius為float類(lèi)型,轉(zhuǎn)換公式的表述方式也更自然一些。一個(gè)程序中,之所以不能使用5/9的形式,fahr=while(fahr<=printf中的轉(zhuǎn)換說(shuō)明%3.0f表明待打印的浮點(diǎn)數(shù)(即fahr)至少占3個(gè)字符寬,且不帶小數(shù)點(diǎn)和小數(shù)部分;%6.1f表明另一個(gè)待打印的數(shù)(celsius)至少占6個(gè)字符寬,且小數(shù)點(diǎn)后面有1位數(shù)字。其輸出如下所示:0格式說(shuō)明可以省略寬度與精度,例如,%6f表示待打印的浮點(diǎn)數(shù)6個(gè)字符寬;%.2f 表示字符;%s表示字符串;%%表示百分號(hào)(%)本身。練習(xí)1- 練習(xí)1- for#include{intfor(fahr=0;fahr<=300;fahr=fahr+20)printf("%3d%6.1f\n",fahr,(5.0/9.0)*(fahr-32));}這個(gè)程序與上節(jié)中介紹的程序執(zhí)行結(jié)果相同,但程序本身卻有所不同。最主要的改進(jìn)在于它去掉了大部分變量,而只使用了一個(gè)nt類(lèi)型的變量fahr。在新引入的or語(yǔ)句中,溫度f(wàn)函數(shù)的第三個(gè)C語(yǔ)言中一個(gè)通用規(guī)則的實(shí)例:在允許使用某種類(lèi)型變量printf函數(shù)的第三個(gè)參數(shù)必須是與%6.1f匹配的浮點(diǎn)值,所以可以在此處使用任何浮點(diǎn)表達(dá)式。while語(yǔ)句比較,就會(huì)發(fā)現(xiàn)for語(yǔ)句的操作更直觀一些。圓括號(hào)中共包含3個(gè)部分,各部分fahr=fahr<=(true循環(huán)體(本例中的循環(huán)體僅包含一個(gè)printf函數(shù)調(diào)用語(yǔ)句。此后將執(zhí)行第三部分fahr=fahr+環(huán)將終止執(zhí)行。與while語(yǔ)句一樣,for循環(huán)語(yǔ)句的循環(huán)體可以只有一條語(yǔ)句,也可以是用在實(shí)際編程過(guò)程中,可以選擇whi1e與for中的任意一種循環(huán)語(yǔ)句,主要要看使用哪一種更清晰。for語(yǔ)句比較適合初始化和增加步長(zhǎng)都是單條語(yǔ)句并且邏輯相關(guān)的情形,因?yàn)樗鼘⒀h(huán)控制語(yǔ)句集中放在一起,且比while語(yǔ)句更緊湊。練習(xí)1-5修改溫度轉(zhuǎn)換程序,要求以逆序(3000度的順序)打印溫在結(jié)束討論溫度轉(zhuǎn)換程序前,我們?cè)賮?lái)看一下符號(hào)常量。在程序中使用300、20等類(lèi)似的序的修改變得更加。處理這種幻數(shù)的法是賦予它們有意義的名字。#define指令#include#defineLOWER0 /*lowerlimitoftable*/#defineUPPER300/*upperlimit*/#defineSTEP /*stepsize/*printFahrenheit-Celsiustable*/{intfor(fahr=LOWER;fahr<=UPPER;fahr=fahr+STEP)printf("%3d%6.1f\n",fahr,(5.0/9.0)*(fahr-}其中,LOWER、UPPER與STEP都是符號(hào)常量,而非變量,因此不需要出現(xiàn)在中。符號(hào)#define指令行的末尾沒(méi)有分號(hào)。標(biāo)準(zhǔn)庫(kù)提供的輸入/輸出模型非常簡(jiǎn)單。無(wú)本從何處輸入,輸出到何處,其輸入/輸出都是按照字符流的方式處理。文本流是由多行字符構(gòu)成的字符序列,而每行字符則由0型。使用標(biāo)準(zhǔn)庫(kù)的C語(yǔ)言程序員不必關(guān)心在程序之外這些行是如何表示的。函數(shù)。每次調(diào)用時(shí),getchar函數(shù)從文本流中讀入下一個(gè)輸入字符,并將其作為結(jié)果值返回。c=c中將包含輸入流中的下一個(gè)字符。這種字符通常是通過(guò)鍵盤(pán)輸入的。關(guān)于從文件輸入字符的方法,在第7章中討論。文件借助于getchar與putchar函數(shù),可以在不了解其它輸入/輸出知識(shí)的情況下編寫(xiě)出數(shù)量驚人的有用的代碼。最簡(jiǎn)單的例子就是把輸入一次一個(gè)字符地到輸出,其基本思想#include/*copyinputtooutput;1stversion*/{intc=getchar();while(c!=EOF){c=}}這里需要解決如何區(qū)分文件中有效數(shù)據(jù)與輸入結(jié)束符的問(wèn)題。C語(yǔ)言采取的解決方法是:在沒(méi)有輸入時(shí),getchar函數(shù)將返回一個(gè)特殊值,這個(gè)特殊值與任何實(shí)際字符都不同。這個(gè)值稱為EOF(endoffile,文件結(jié)束。我們?cè)谧兞縞的時(shí)候,必須讓它大到足以存任何char類(lèi)型的值都不相同即可。這里使用符號(hào)常量,可以確保程序不需要依賴于其對(duì)應(yīng)的任c=賦值可以作為更大的表達(dá)式的一部分出現(xiàn)。如果將為c賦值的操作放在while循環(huán)語(yǔ)句的測(cè)試部分中,上述字符程序便可以改寫(xiě)成下列形式:#include/*copyinputtooutput;2ndversion*/{intwhile((c=getchar())!=EOF)}在該程序中,whilec,然后測(cè)試該字符是否為文件執(zhí)行while語(yǔ)句。當(dāng)?shù)竭_(dá)輸入的結(jié)尾位置時(shí),while循環(huán)語(yǔ)句終止執(zhí)行,從而整個(gè)main函對(duì)while語(yǔ)句的條件部分來(lái)說(shuō),賦值表達(dá)式兩邊的圓括號(hào)不能省略。不等于運(yùn)算符!=的c=getchar()!=c=(getchar()!=該語(yǔ)句執(zhí)行后,c的值將被置01(取決于調(diào)用getchar函數(shù)時(shí)是否碰到文件結(jié)束標(biāo)志,這并不是我們所希望的結(jié)果(更詳細(xì)的內(nèi)容,請(qǐng)參見(jiàn)第2章的相關(guān)部分。練習(xí)1- 驗(yàn)證表達(dá)式getchar()!=EOF的值是0還是1練習(xí)1- #include/*countcharactersininput;1stversion*/{longnc=while(getchar()!=printf("%ld\n",nc);}引入了一個(gè)新的運(yùn)算符++1ncnc1代替它,但語(yǔ)句++nc更精煉一些,且通常效率也更高。與該運(yùn)算符相應(yīng)的是自減運(yùn)算符--。++與--這++ncnc++該字符計(jì)數(shù)程序使用long類(lèi)型的變量存放計(jì)數(shù)值,而沒(méi)有使用int類(lèi)型的變量。long整型數(shù)(長(zhǎng)整型)至少要占用32位單元。在某些機(jī)器上int與long類(lèi)型的長(zhǎng)度相同,32767當(dāng)小的輸入都可能使int類(lèi)型的計(jì)數(shù)變量溢出。轉(zhuǎn)換說(shuō)明%ld告訴printf函數(shù)其對(duì)應(yīng)的參數(shù)是long整型。使用double(雙精度浮點(diǎn)數(shù))類(lèi)型可以處理更大的數(shù)字。我們?cè)谶@里不使用while循環(huán)語(yǔ)句,而用for循環(huán)語(yǔ)句來(lái)展示編寫(xiě)此循環(huán)的另法:#include/*countcharactersininput;2ndversion*/{doublefor(nc=0;gechar()!=EOF;;}小數(shù)部分,因此小數(shù)部分的位數(shù)為0。在該程序段中,for循環(huán)語(yǔ)句的循環(huán)體是空的,這是因?yàn)樗泄ぷ鞫荚跍y(cè)試(條件)部分與增加步長(zhǎng)部分完成了。但C語(yǔ)言的語(yǔ)則要求for循環(huán)語(yǔ)句必須有一個(gè)循環(huán)體,因此第一次調(diào)用getchar函數(shù)的叫候,while語(yǔ)句或for語(yǔ)句中的條件測(cè)試從一開(kāi)始就為假,程序的執(zhí)行結(jié)果將為0,這也是正確的結(jié)果。這一點(diǎn)很重要。whi1e語(yǔ)句與for語(yǔ)句的優(yōu)點(diǎn)之一就是在執(zhí)行循環(huán)體之前就對(duì)條件進(jìn)試,如果條件不滿足,則不執(zhí)行循環(huán)體,這就可0長(zhǎng)度的輸入時(shí),程序的處理應(yīng)該靈活一些,在出現(xiàn)邊界條件時(shí),while語(yǔ)句與for語(yǔ)句有助于確保程序執(zhí)行合理的操作。#include/*countlinesininput*/{intc,nl=while((c=getchar())!=EOF)if(c=='\n')printf("%d\n",nl);}在該程序中,while循環(huán)語(yǔ)句的循環(huán)體是一個(gè)if語(yǔ)句,它控制自增語(yǔ)句++nl。if語(yǔ)句的.EQ.。由于C語(yǔ)言將單等于號(hào)=作為賦值運(yùn)算符,因此使等于號(hào)==表示相等的邏輯關(guān)==,C有時(shí)會(huì)錯(cuò)誤地寫(xiě)成單等于號(hào)=。在第2章看到,即使這樣誤用了,其結(jié)果通常仍然是合65整型數(shù)而已;而"\n"2練習(xí)1- 練習(xí)1- 練習(xí)1- 4個(gè)實(shí)用程序用于統(tǒng)計(jì)行數(shù)、單詞數(shù)與字符數(shù)。這里對(duì)單詞的定義比較UNIX系統(tǒng)中wc程序的骨分:#include#defineIN1/*insideaword*/#defineOUT0/*outsideaword*//*countlines,words,andcharactersininput*/{intc,nl,nw,nc,state=nl=nw=nc=while((c=getchar())!=EOF)if(c==if(c==''||c=='\n'||c='\t')state=OUT;elseif(state=={state=}}printf("%d%d%d\n",nl,nw,}程序執(zhí)行時(shí),每當(dāng)遇到單詞的第一個(gè)字符,它就作為一個(gè)新單詞加以統(tǒng)計(jì)。state變量們?cè)谶@里使用了符號(hào)常量IN與OUT,而沒(méi)有使用其對(duì)應(yīng)的數(shù)值1與0,這樣程序更易讀。在nl=nw=nc=n1=(nw=(nc=運(yùn)算符||代表OR(邏輯或所以下列語(yǔ)if(c==''||c=='\n'||c==c是空格,則沒(méi)有必要再測(cè)試它是否為換行符或制表符,這樣就不必執(zhí)這段程序中還包括一個(gè)else部分,它指定當(dāng)if語(yǔ)句中的條件部分為假時(shí)所要執(zhí)行的動(dòng)if表述式列。在單詞計(jì)數(shù)程序中,else之后的語(yǔ)句仍是一個(gè)if語(yǔ)句,該if語(yǔ)句控制了包含在花括練習(xí)1-11你準(zhǔn)備如何測(cè)試單詞計(jì)數(shù)程序?如果程序中存在某種錯(cuò)誤,那么什么樣的輸1-12該程序討論C語(yǔ)言多方面的問(wèn)題。10#include/*countdigits,whitespace,others*/{intc,i,nwhite,nother;intndigit[10];nwhite=nother=0;for(i=0;i<10;++i)ndigit[i]=while((c=getchar())!=EOF)if(c>='0'&&c<='9')elseif(c==''||c=='\n'||c==for(i=0;i<10;++i)printf("%d",ndigit[i]);printf(",whitespace=%d,other=%d\n",nwhite,nother);}digits=9300000001,whitespace=123,other=int化和打印數(shù)組的兩個(gè)for循環(huán)語(yǔ)句反映出來(lái)。if(c>='0'&&c<=c-由定義可知,char類(lèi)型的字符是小整型,因此char類(lèi)型的變量和常量在算術(shù)表達(dá)式中int類(lèi)型的變量和常量。這樣做既自然又方便,例如,c0'是一個(gè)整型表達(dá)式,如果在c中的字符是'0'~'9',其值將為0~9,因此可以充當(dāng)數(shù)組ndigit的合法下if(c>='0'&&c<=elseif(c==''||c=='\n'||c==ifelseif在這種方式中,各條件從前往后依次求值,直到滿足某個(gè)條件,然后執(zhí)行對(duì)應(yīng)的語(yǔ)句部分。這部分語(yǔ)句執(zhí)行完成后,整個(gè)語(yǔ)句體執(zhí)行結(jié)束(其中的任何語(yǔ)句都可以是括在花括號(hào)中的若干條語(yǔ)句e之后的語(yǔ)句。efe0elseif條件否則,如果每個(gè)if都比前一個(gè)else向里縮進(jìn)一些距離,那么較長(zhǎng)的判定序列就可能超出頁(yè)1-13編寫(xiě)一個(gè)程序,打印輸入中單詞長(zhǎng)度的直方圖。水平方向的直方圖比較容易繪制,垂直方向的直方圖則要些。1-14CFortranPascal語(yǔ)言中的過(guò)程或C語(yǔ)言中可以簡(jiǎn)單、方便、高效地使用函數(shù)。我們經(jīng)常會(huì)看到在定義后僅調(diào)用了中提供的函數(shù)?,F(xiàn)在,讓我們自己動(dòng)手來(lái)編寫(xiě)一些函數(shù)。CFortran語(yǔ)言一樣提供類(lèi)似于**的求冪運(yùn)算符,我們現(xiàn)在通過(guò)編寫(xiě)一個(gè)求冪的函數(shù)power(m,n)來(lái)說(shuō)明函數(shù)定義的方法power(m,n)函數(shù)用于計(jì)算整數(shù)m的n次冪,其中n是正整數(shù)。對(duì)函數(shù)調(diào)用power(2,次冪,但這對(duì)于說(shuō)明問(wèn)題已足夠了。(xypow(xy))下面是函數(shù)power(m,n)的定義及調(diào)用它的主程序,這樣我們可以看到一個(gè)完整的程#includeintpower(intm,int/*testpowerfunction*/{intfor(i=0;i<10;printf("%d%d%d\n",i,power(2,i),power(-3,i));return0;}/*power:raisebaseton-thpower;n>=0*/intpower(intbase,intn){inti,p=for(i=1;i<=n;++i)p=p*base;return}返回值類(lèi)型函數(shù)名(0個(gè)或多個(gè)參數(shù){}在多個(gè)文件中。如果源程序分散在多個(gè)文件中,那么,在編譯和加載時(shí),就需要做的工作,但這是操作系統(tǒng)的原因,并不是語(yǔ)言的屬性決定的。我們暫且假定將main和power這兩個(gè)函數(shù)放在同一文件中,這樣前面所學(xué)的有關(guān)運(yùn)行C語(yǔ)言程序的知識(shí)仍然有效。printf("%d%d%d\n",i,power(2,i),power(-i,每次調(diào)用main函數(shù)向power函數(shù)傳遞兩個(gè)參在調(diào)用執(zhí)行完power函數(shù)向main函數(shù)返回一個(gè)格式化的整數(shù)并打印。在表達(dá)式中,power(2,i)同2和i一樣都是整數(shù)(并不是所有函數(shù)的結(jié)果都是整型值,在第4章中討論。intpower(intbase,int數(shù)內(nèi)部有效,對(duì)其它任何函數(shù)都是不可見(jiàn)的:其它函數(shù)可以使用與之相同的參數(shù)名字而不會(huì)引起。變量i與p也是這樣:power函數(shù)中的i與main函數(shù)中的i無(wú)關(guān)。power函數(shù)計(jì)算所得的結(jié)果通過(guò)return語(yǔ)句返回給main函數(shù)。關(guān)鍵字return的后return語(yǔ)句將把控制權(quán)返回給調(diào)用者,但不返回有00表示出現(xiàn)異常情況或出錯(cuò)結(jié)束條件。為簡(jiǎn)潔起見(jiàn),前面的intpower(intm,intintpower(int,C語(yǔ)言的最初定義,power函數(shù)應(yīng)該寫(xiě)成下列形式:/*power:raisebaseton-thpower;n>=0 (old-styleversion)*/power(base,n)intbase,{inti,p=for(i=1;i<=n;++i)p=p*base;return}其中,參數(shù)名在圓括號(hào)內(nèi)指定,參數(shù)類(lèi)型在左花括號(hào)之前。如果沒(méi)有某個(gè)參數(shù)的類(lèi)型,則默認(rèn)為int類(lèi)型。函數(shù)體與ANSIC中形式相同。int型方面的錯(cuò)誤。ANSIC仍然支持舊式的函數(shù)與定義,這樣至少可以有一個(gè)過(guò)渡階段。但我們還是強(qiáng)烈建議讀者:在使用新式的編譯器時(shí),最好使用新式的函數(shù)原型方式。練習(xí)1- 參數(shù)——傳值調(diào)習(xí)慣其它語(yǔ)言(Fortran語(yǔ)言)的程序員可能會(huì)C語(yǔ)言的函數(shù)參數(shù)傳遞方式感到陌生。在C語(yǔ)言中,所有函數(shù)參數(shù)都是“通過(guò)值”傳遞的。也就是說(shuō),傳遞給被調(diào)用函數(shù)的/*power:raisebaseton-thpower;n>=0;version2*/intpower(intbase,intn){intfor(p=1;n>0;--n)p=p*base;return}其中,參數(shù)n用作臨時(shí)變量,并通過(guò)隨后執(zhí)行的for循環(huán)語(yǔ)句遞減,直到其值為0,這樣就不需要額外引入變量i;power函數(shù)內(nèi)部對(duì)n的任何操作不會(huì)影響到調(diào)用函數(shù)中n的原始參要將對(duì)應(yīng)的參數(shù)為指針類(lèi)型,并通過(guò)它間接變量。在第5章中討論指針。起始元素的位置或地址——它并不數(shù)組元素本身。在被調(diào)用函數(shù)中,可以通過(guò)數(shù)組下標(biāo)C語(yǔ)言中最常用的數(shù)組類(lèi)型。下面我們通過(guò)編寫(xiě)一個(gè)程序,來(lái)說(shuō)明字符數(shù)組while還有未處理的行if該行比已處理的最長(zhǎng)行還要長(zhǎng)立的函數(shù)getline,它輸入的下一行。我們盡量保持該函數(shù)在其它場(chǎng)臺(tái)也有用。至少標(biāo)志文件結(jié)束的返回值。每一行至少包括一個(gè)字符,只包含換行符的行,其長(zhǎng)度為1。說(shuō),我們需要用另一個(gè)函數(shù)copy把新行到一個(gè)安全的位置。最后,我們需要在主函數(shù)main中控制getline和copy這兩個(gè)函數(shù)。以下便是我們編#include#defineMAXLINE1000 uminputlinelengthintgetline(charline[],intmaxline);voidcopy(charto[],charfrom[]);/*printthelongestinputline*/{int /*currentlinelengthintmax; /*umlengthseensofar*/charline[MAXLINE]; /*currentinputline*/charlongest[MAXLINE];/*longestlinesavedheremax=while((len=getline(line,MAXLINE))>0)if(len>max){max=len;copy(longest,line);}if(max>0)/*therewasaline*/printf("%s",longest);return}/*getline:readalineintos,returnlength*/intgetline(chars[],intlim){intc,for(i=0;i<lim-1&&(c=getchar())!=EOF&&c!='\n';++i)s[i]=c;if(c=={s[i]=}s[i]='\0';returni;}/*copy:copy'from'into'to';assumetoisbigenough*/voidcopy(charto[],charfrom[]){inti=while((to[i]=from[i])!=}intgetline(chars[],int的大小是在main函數(shù)中設(shè)置的。如同power函數(shù)一樣,getline函數(shù)使用了一個(gè)return語(yǔ)句將值返回給其調(diào)用者。上述程序行也了getline數(shù)的返回值類(lèi)型為int。由于函數(shù)的默認(rèn)返回值類(lèi)型為int,因此這里的int可以省略。如CC語(yǔ)言程序中出現(xiàn)類(lèi)似于printf函數(shù)中的格式規(guī)范%s規(guī)定,對(duì)應(yīng)的參數(shù)必須是以這種形式表示的字符串。copy函數(shù)題。例如,當(dāng)讀入的行長(zhǎng)度大于允許的最大值時(shí),main函數(shù)應(yīng)該如何處理,getline函數(shù)調(diào)用getline函數(shù)的程序無(wú)法預(yù)先知道輸入行的長(zhǎng)度,因此getline函數(shù)需要檢查是否溢出。另一方面,調(diào)用copy函數(shù)的程序知道(也可以找出)字符串的長(zhǎng)度,因此該函數(shù)不需1-16main,使之可以打印任意長(zhǎng)度的輸入1-1780練習(xí)1- main函數(shù)中的變量(如line、longest等)是main函數(shù)的私自變量或局部變量。由于它們是在main函數(shù)中的,因此其它函數(shù)不能直接它們。其它函數(shù)中的變量也同樣如此。例如,getline函數(shù)中的變量i與copy函數(shù)中的變量i沒(méi)有關(guān)系。函數(shù)第最外層程序塊的變量非常類(lèi)似。由于外部變量可以在全局范圍內(nèi),因此,函數(shù)間可以通過(guò)外部變量交換數(shù)據(jù),而不必使用參數(shù)表。再者,外部變量在程序執(zhí)行期間一直存在,而不是在函數(shù)調(diào)用時(shí)產(chǎn)生、在函數(shù)執(zhí)行完畢時(shí)。即使在對(duì)外部變量賦值的函數(shù)返回后,外部變量必須定義在所有函數(shù)之外,且只能定義一次,定義后編譯程序?qū)樗峙鋯卧?。在每個(gè)需要外部變量的函數(shù)中,必須相應(yīng)的外部變量,此時(shí)說(shuō)明其類(lèi)型。聲明時(shí)可以用extern語(yǔ)句顯式,也可以通過(guò)上下文隱式。為了更詳細(xì)地討論外部變量,我們改寫(xiě)上述打印最長(zhǎng)文本行的程序,把line、longest與max成外部變量。這需要修改這3個(gè)函數(shù)的調(diào)用、與函數(shù)體。intgetline(void);voidcopy(void);/*printlongestinputline;specializedversion*/{intlen;externintmax;externcharmax=while((len=getline())>0)if(len>max){max=len;}if(max>0)/*therewasaline*/printf("%s",longest);return}/*getline:specializedversion*/intgetline(void){intc,externcharfor(i=0;i<MAXLINE-&&(c=getchar))!=EOF&&c!='\n';++i)line[i]=c;if(c=={line[i]=}line[i]='\0';returni;}/*copy:specializedversion*/voidcopy(void){intexterncharline[],i=while((longest[i]=line[i])!=}ey了各外部變量的類(lèi)型,這樣編譯程序?qū)樗鼈兎峙鋯卧?。從語(yǔ)法角度看,外部變量的定義與局部變量的定義是相同的,但由于它們位于各函數(shù)的外部,因此這些變量是外部變量。函數(shù)在使用外部變量之前,必須要知道外部變量的名字。要達(dá)到該目的,式是在函數(shù)中使用xtrn類(lèi)型的。這種類(lèi)型的除了面加了一個(gè)關(guān)鍵字xern外,其它的。某些情況下可以省略extern。在源文件中,如果外部變量的定義出現(xiàn)在使用它的函數(shù)之前那么在那個(gè)函數(shù)中就沒(méi)有必要使用extern。因此,maingetline及copy中的幾個(gè)extern都是多余的。在通常的做法中,所有外部變量的定義都放在源文件的開(kāi)始處,這樣就可以省略extern。如果程序包含在多個(gè)源文件中,而某個(gè)變量在file1文件中定義、在file2和file3文件中使用,那么在文件file2與file3中就需要使用extern來(lái)建立該變量與其定義之間的聯(lián)系。人們通常把變量和函數(shù)的extern放在一個(gè)單獨(dú)的文件中(習(xí)慣上稱之為頭文件,并在每個(gè)源文件的開(kāi)頭使用#include語(yǔ)句把所要用的頭文件包含進(jìn)來(lái)。后綴的。更詳細(xì)的信息將在第4章中討論,第7章及附錄B將討論函數(shù)庫(kù)。在上述特別版本中,由于getline與copy函數(shù)都不帶參數(shù),因此從邏輯上講,在源文getline()copy()C語(yǔ)言程序兼容,ANSIC語(yǔ)言把空參數(shù)表看成老版本C語(yǔ)言的方式,并且對(duì)參數(shù)表不再進(jìn)行任何檢查。在可以簡(jiǎn)化數(shù)據(jù)的通信——參數(shù)表變短了,且在需要時(shí)總可以這些變量。但是,即使在不改又變得十分。我們前面編寫(xiě)的打印最長(zhǎng)文本行的程序的第2個(gè)版本就不如第1個(gè)版本2個(gè)版本中的函數(shù)將它們所操到目前為止,我們已經(jīng)對(duì)C語(yǔ)言的傳統(tǒng)部分進(jìn)行了介紹。借助于這些少量的語(yǔ)言元練習(xí)1-20detab,將輸入中的制表符替換成適當(dāng)數(shù)目的空格,使空格充滿到n列就會(huì)出現(xiàn)一個(gè)制表符終止位。n應(yīng)該作為變量還是符號(hào)常量呢?練習(xí)1-21entab,將空格串替換為最少數(shù)量的制表符和空格,但要保持單詞之間的間隔不變。假設(shè)制表符終止位的位置與練習(xí)1-20的detab程序的情況相同。當(dāng)使用一練習(xí)1-22編寫(xiě)一個(gè)程序,把較長(zhǎng)的輸入行“折”成短一些的兩行或多行,折行的位置n列之前的最后一個(gè)非空格之后。要保證程序能夠智能地處理輸入行很長(zhǎng)以及1-23C語(yǔ)言程序中所有的注釋語(yǔ)句。要正確處理帶引號(hào)的字符串與字符常量。在C語(yǔ)言中,注釋不允許嵌套。練習(xí)1-24C語(yǔ)言程序中的基本語(yǔ)法錯(cuò)誤,如圓括號(hào)、方括號(hào)、花第2變量和常量是程序處理的兩種基本數(shù)據(jù)對(duì)象。語(yǔ)句說(shuō)明變量的名字及類(lèi)型,也可以指ANSI標(biāo)準(zhǔn)對(duì)語(yǔ)言的基本類(lèi)型與表達(dá)式做了許多小的修改與增補(bǔ)。所有整型都包括signed(帶符號(hào))和unsigned(無(wú)符號(hào))兩種形式,且可以表示無(wú)符號(hào)常量與十六進(jìn)制字符常量。浮點(diǎn)運(yùn)算可以以單精度進(jìn)行,還可以使用更高精度的longdouble類(lèi)型運(yùn)算。字對(duì)象可以為const(常量)類(lèi)型,表明其值不能修改。該標(biāo)準(zhǔn)還對(duì)算術(shù)類(lèi)型之間的自動(dòng)強(qiáng)制轉(zhuǎn)換規(guī)則進(jìn)行了擴(kuò)充,以適合于的數(shù)據(jù)類(lèi)型。對(duì)變量名與符號(hào)常量名存在一些限制條件,這一點(diǎn)我們?cè)诘?章沒(méi)有說(shuō)明。常用于命名較長(zhǎng)的變量名,以提高其可讀性。由于例程的名字通常以下劃線開(kāi)頭,因此變量名不要以下劃線開(kāi)頭。大寫(xiě)字母與小寫(xiě)字母是有區(qū)別的,所以,x與X是兩個(gè)不同的名字。在C31個(gè)字符是有效的。函數(shù)名與外部變量名包含的字符數(shù)目可能小于31,這是因?yàn)閰R編程序和加載程序可能會(huì)使用這些外部名,而語(yǔ)言本身是無(wú)法控制加載和匯編程序的。對(duì)于外部名,ANSI6個(gè)字符的惟一性,并且不區(qū)分大小寫(xiě)。類(lèi)所有字中的字符都必須小寫(xiě)。 shortintlongintint通常代表特定機(jī)器中整數(shù)的自然長(zhǎng)度。short16位,1ong32位,int1632位。各編譯器可以根據(jù)硬件特性自主選擇合適的類(lèi)型長(zhǎng)度,類(lèi)型不得長(zhǎng)于int類(lèi)型,而int類(lèi)型不得長(zhǎng)于long類(lèi)型。類(lèi)型限定符signed與unsigned可用于限定char類(lèi)型或任何整型。unsigned類(lèi)型的數(shù)總是正0,并遵守算術(shù)2n定律,其n是該類(lèi)型占用的位數(shù)。例如,如果char對(duì)象占用8位,那么unsignedchar類(lèi)型變量的取值范圍為0~255signedchar類(lèi)型變量的取值范圍則為-128~127(在采用對(duì)二的補(bǔ)碼的機(jī)器上。不帶限定符的char類(lèi)型對(duì)象是longdouble類(lèi)型表示高精度的浮點(diǎn)數(shù)。同整型一樣,浮點(diǎn)型的長(zhǎng)度也取決于具體的實(shí)現(xiàn)。float、double與longdouble類(lèi)型可以表示相同的長(zhǎng)度,也可以表示兩種或三種不同的件<limits.h>與<float.h>中找到,這些內(nèi)容將在附錄B中討論。練習(xí)2-1signedunsignedchar、short、int與long類(lèi)型變量的取采用打印標(biāo)準(zhǔn)頭文件中的相應(yīng)值以及直接計(jì)算兩種方式實(shí)現(xiàn)。后法的實(shí)現(xiàn)較一些,因?yàn)橐_定各種浮點(diǎn)類(lèi)型的取值范圍。1234int類(lèi)型。longlLL。如果一個(gè)整數(shù)太大以至于無(wú)法用int類(lèi)型表示時(shí),也將被當(dāng)作long類(lèi)型處uUulULunsignedlong類(lèi)型。浮點(diǎn)數(shù)常量中包含一個(gè)小數(shù)點(diǎn)(如123.4)或一個(gè)指數(shù)(如1e-2),也可以兩者都有。沒(méi)有后綴的浮點(diǎn)數(shù)常量為double類(lèi)型。后綴fFfloat類(lèi)型lL則表示longdouble類(lèi)型。0的整型常量表示它為八進(jìn)制形式;前綴為0x或0X,則表示它為十六進(jìn)制形式。例如,十進(jìn)制數(shù)31可以寫(xiě)成八進(jìn)制形式037,也可以寫(xiě)成十六進(jìn)制形式0x1f0X1F。八進(jìn)制與十六進(jìn)制的常量也可以使用后綴L表示long類(lèi)型,使用后綴U表示unsigned類(lèi)型。例如,0XFUL是一個(gè)unsignedlong類(lèi)型(無(wú)符號(hào)長(zhǎng)整型)的常量,其值等于十進(jìn)制數(shù)15。集中的數(shù)值就是字符常量的值。例如,在SCI字符集中,字符0'的值為48,它與數(shù)值048心該字符對(duì)應(yīng)的具體值,增加了程序的易讀性。字符常量一般用來(lái)與其它字符進(jìn)行比較,但(0…7(0…9,a…,…F#defineVTAB'\013'/*ASCIIverticaltab*/#defineBELL'\007'/*ASCIIbellcharacter*/#defineVTAB'\xb'/*ASCIIverticaltab*/#defineBELL'\x7'/*ASCIIbellcharacter*/(null以強(qiáng)調(diào)某些表達(dá)式的字符屬性,但其數(shù)字值為0。#defineMAXLINE1000charline[MAXLINE+1];或#defineLEAP1/*inleapyearsint"Iama或 /* o,"" o,的結(jié)尾,因此。字符串的物理單元數(shù)比括在雙引號(hào)中的字符數(shù)多一個(gè)。這種表示方法strlen函數(shù)的一個(gè)版本:/*strlen:returnlengthofs*/intstrlen(chars[]){intwhile(s[i]!=return}一個(gè)字符(即字母x)以及一個(gè)結(jié)束符'\0'的字符數(shù)組。enumboolean{NO,YESenumescapes{BELL='\a',BACKSPACE='\b',TAB='\t',NEWLINE='\n',VTAB='\v',RETURN='\r'};enummonths{JAN=1,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC};它的優(yōu)勢(shì)在于常量值可以自動(dòng)生成。盡管可以enum類(lèi)型的變量,但編譯器查這種類(lèi)#define更具優(yōu)勢(shì)。此外,調(diào)試程序可以以符號(hào)形式打印出枚舉變量的值。 所有變量都必須先后使用,盡管某些變量可以通過(guò)上下文隱式地。一個(gè)指intlower,upper,step;charc,1ine[1000];一個(gè)語(yǔ)句中的多個(gè)變量可以拆開(kāi)在多個(gè)語(yǔ)句中。上面的兩個(gè)語(yǔ)句也可以等intlower;intupper;intstep;charc;cbar還可以在的同時(shí)對(duì)變量進(jìn)行初始化。在中,如果變量名的后面緊跟一個(gè)等號(hào)以charesc='\\';inti=0;intlimit=MAXLINE+1;floateps=1.0e-5;量與靜態(tài)變量將被初始化為0。顯式初始化的自動(dòng)變量的值為未定義值(即無(wú)效值。數(shù)組而言,const限定符指定數(shù)組所有元素的值都不能被修改:constdoublee=2.71828182845905;constcharmsg[]="warning:";intstrlen(constx%if((year%4==0&&year%100!=0)||year%400==0)printf("%disaleapyear\n",year);printf("%disnotaleapyear\n",取模運(yùn)算符%不能應(yīng)用于float或double類(lèi)型。在有負(fù)操作數(shù)的情況下,整數(shù)除法截二元運(yùn)算符+和-具有相同的優(yōu)先級(jí),它們的優(yōu)先級(jí)比運(yùn)算符*、/和%的優(yōu)先級(jí)低,而運(yùn)算符*、/和%的優(yōu)先級(jí)又比一元運(yùn)算符+和-的優(yōu)先級(jí)低。算術(shù)運(yùn)算符采用從左到右的結(jié)合規(guī)>>=<==C語(yǔ)言程序運(yùn)用了這些屬性。例如,下列在功能上與第1章的輸入函數(shù)getline中的循環(huán)語(yǔ)句等價(jià)的循環(huán)語(yǔ)句:for(i=0;i<lim-1&&(c=getchar())!='\n'&&c!=EOF;++i)s[i]=c;條件i<lim-1。如果這一測(cè)試失敗,就沒(méi)有必要繼續(xù)讀入下一字符。類(lèi)似地如果在調(diào)用getchar函數(shù)之前就測(cè)試c是否為EOF,結(jié)果也是不正確的,因此,函數(shù)的調(diào)用與賦值都必須在對(duì)c中的字符進(jìn)試之前進(jìn)行。i<lim-1&&(c=getchar())!='\n'&&c!=(c=getchar())!=中,就需要使用圓括號(hào),這樣才能達(dá)到預(yù)期的目的:先把函數(shù)返回值賦值給c,然后再將如果為假,則結(jié)果值為數(shù)值0。ifif(valid==是有效的”練習(xí)2-2在不使用運(yùn)算符&&或||for循環(huán)語(yǔ)句等價(jià)的循當(dāng)一個(gè)運(yùn)算符的幾個(gè)操作數(shù)類(lèi)型不同時(shí),就需要通過(guò)一些規(guī)則把它們轉(zhuǎn)換為某種共同的類(lèi)型。一般來(lái)說(shuō),自動(dòng)轉(zhuǎn)換是指把“比較窄的”操作數(shù)轉(zhuǎn)換為“比較寬的”操作數(shù),并且不丟失信息的轉(zhuǎn)換,例如,在計(jì)算表達(dá)式+i時(shí),將整型變量i的值自動(dòng)轉(zhuǎn)換為浮點(diǎn)型(這里ft為下標(biāo)。針對(duì)可能導(dǎo)致信息丟失的表達(dá)式,編譯器可能會(huì)給出警告信息,比如把較長(zhǎng)的整型不。由于char類(lèi)型就是較小的整型,因此在算術(shù)表達(dá)式中可以自由使用char類(lèi)型的變量,/*atoi:convertstointeger*/intatoi(chars[]){inti,n=for(i=0;s[i]>='0'&&s[i]<='9';++i)n=10*n+(s[i]-'0');return}s[i]-值是續(xù)的遞增序列。映射到對(duì)應(yīng)的小寫(xiě)字母。如果待轉(zhuǎn)換的字符不是大寫(xiě)字母,lower函數(shù)將返回字符本身。/*lower:convertctolowercase;ASCIIonly*/intlower(intc){if(c>='A'&&c<=returnc+'a'-'A';return}ASCII字符集設(shè)計(jì)的。ASCII字符集中,大寫(xiě)字母與對(duì)應(yīng)的小寫(xiě)字母作EBCDICEBCDIC字符集tolower(c)函數(shù)將c轉(zhuǎn)換為小寫(xiě)形式(如果c為大寫(xiě)形式的話可以使用tolower替代上述lower函數(shù)。類(lèi)似地,測(cè)試語(yǔ)句c>='0'&&c<=Cr號(hào)變量(iged)還是帶符號(hào)變量(unsigned。當(dāng)把一個(gè)har類(lèi)型的值轉(zhuǎn)換為int類(lèi)型的值時(shí),其結(jié)果有沒(méi)有可能為負(fù)整數(shù)?對(duì)于不同的機(jī)器,其結(jié)果也不同,這反映了不同機(jī)器結(jié)構(gòu)之間的區(qū)別。在某些機(jī)器中,如果hr類(lèi)型值的最左一位為1,則轉(zhuǎn)換為負(fù)整數(shù)(進(jìn)行“符號(hào)擴(kuò)展。而在另一些機(jī)器中,把hr類(lèi)型值轉(zhuǎn)換為int類(lèi)型時(shí),在har類(lèi)型值0,這樣導(dǎo)致的轉(zhuǎn)換結(jié)果值總是正值。上可能是正的。為了保證程序的可移植性,如果要在char類(lèi)型的變量中非字符數(shù)據(jù),最signedunsigned限定符。1;當(dāng)判定結(jié)果為假時(shí),表達(dá)式的值為0。因此,對(duì)于賦值語(yǔ)句d=c>='0'&&c<=來(lái)說(shuō)c為數(shù)字時(shí),d的值l,否d的值0。但是,某些函數(shù)(比isdigit)在結(jié)著“非0”,這二者之間沒(méi)有區(qū)別。longdouble1ongdouble類(lèi)型;d符號(hào)值與無(wú)符號(hào)值之間的比較運(yùn)算是與機(jī)器相關(guān)的,因?yàn)樗鼈內(nèi)Q于機(jī)器中不同整數(shù)類(lèi)型的t6g2L<dnt類(lèi)型的U將被提升為sgndong類(lèi)型;但1L>1UL,這是因?yàn)?L將被提升為dg類(lèi)型,因而成為一個(gè)比較大的正數(shù)。inti;chari=c;c=xfloat類(lèi)型,iint類(lèi)型,那么xiix在執(zhí)行時(shí)都要進(jìn)行類(lèi)型轉(zhuǎn)換。當(dāng)把float類(lèi)型轉(zhuǎn)換為int類(lèi)型時(shí),小數(shù)部分將被截取掉;當(dāng)把double類(lèi)型轉(zhuǎn)換為float類(lèi)型時(shí),是進(jìn)行四舍五入還是截取取決于具體的實(shí)現(xiàn)。有函數(shù)原型的情況下,char與short類(lèi)型都將被轉(zhuǎn)換為int類(lèi)型,float類(lèi)型將被轉(zhuǎn)換為double類(lèi)型。因此,即使調(diào)用函數(shù)的參數(shù)為char或float類(lèi)型,我們也把函數(shù)參數(shù)為int或double類(lèi)型。我們可以這樣來(lái)理解強(qiáng)制類(lèi)型轉(zhuǎn)換的準(zhǔn)確含義:在上述語(yǔ)句中,表達(dá)式首先被賦值給類(lèi)型名指定的類(lèi)型的某個(gè)變量,然后再用該變量替換上述整條語(yǔ)句。例如,庫(kù)函數(shù)t的參數(shù)為oube類(lèi)型,如果處理不當(dāng),結(jié)果可能會(huì)無(wú)意義(srt在mah.h>中。因此,如果n是整數(shù),可以使用sqrt((double)在把n傳遞給函數(shù)sqrt之前先將其轉(zhuǎn)換為double類(lèi)型。注意,強(qiáng)制類(lèi)型轉(zhuǎn)換只是生成一個(gè)指定類(lèi)型的n的值,n本身的值并沒(méi)有改變。強(qiáng)制類(lèi)型轉(zhuǎn)換運(yùn)算符與其它一元運(yùn)算符具有相同的優(yōu)先級(jí),表2-1對(duì)運(yùn)算符優(yōu)先級(jí)進(jìn)行了總結(jié)。在通常情況下,參數(shù)是通過(guò)函數(shù)原型的。這樣,當(dāng)函數(shù)被調(diào)用時(shí),將對(duì)參數(shù)進(jìn)行自動(dòng)強(qiáng)制轉(zhuǎn)換。例如,對(duì)于sqrt的函數(shù)原型doubleroot2=標(biāo)準(zhǔn)庫(kù)中包含一個(gè)可移植的實(shí)現(xiàn)偽隨機(jī)數(shù)發(fā)生器的函數(shù)rand以及一個(gè)初始化數(shù)的函數(shù)srand。前一個(gè)函數(shù)rand使用了強(qiáng)制類(lèi)型轉(zhuǎn)換。unsignedlongintnext=/*rand:returnpseudo-randomintegeron0..32767*/intrand(void){next=next +return(unsignedint)(next/65536)%}/*srand:setseedforrand()*/voidsrand(unsignedintseed){next=}練習(xí)2- 自減運(yùn)算符使其操作數(shù)遞減1。我們經(jīng)常使用++運(yùn)算符遞增變量的值,如下所示:if(c=面,如++n。也可以用作后綴運(yùn)算符(用在變量后面,如n+。在這兩種情況下,其效果都是將變n的值1。但是,它們之間有一點(diǎn)不同。表達(dá)式++nn的值1,然后再使用變量n的值,而表達(dá)式n++則是先使用變量n的值,然后再將n的值遞增1。也就是說(shuō),對(duì)于使用變量n的值的上下文來(lái)說(shuō),++nn++的效果是不同的。如果n5,那么x=x=變量,類(lèi)似于表達(dá)式(i+j)++是的。if(c=='\n')squeeze(sc)/*squeeze:deleteallcfroms*/voidsqueeze(chars[],intc){inti,for(i=j=0;s[i]!='\0';i++)if(s[i]!=c)s[j++]=s[j]=}增加1,以準(zhǔn)備處理下一個(gè)字符。其中的if語(yǔ)句完全等價(jià)于下列語(yǔ)句:if(s[i]!=c)s[j]=s[i];}的if語(yǔ)句:if(c=={s[i]=}if(c==s[i++]=我們?cè)賮?lái)看第三個(gè)例子??紤]標(biāo)準(zhǔn)函數(shù)strcat(s,t),它將字符串t連接到字符串s的尾部。函數(shù)strcat假定字符串s中有足夠的空間保存這兩個(gè)字符串連接的結(jié)果。下面編/*strcat:concatenatettoendofs;smustbebigenough*/voidstrcat(chars[],chart[]){inti,i=j=while(s[i]!='\0')/*findendofs*/while((s[i++]=t[j++])!='\0')/*copyt;}2-4squeeze(s1s2)s1s2中字符匹配的字符練習(xí)2-5any(s1s2)s2s1中第一次出現(xiàn)的位置作為結(jié)果返回。如果s1中不包含s2中的字符,則返回-1(標(biāo)準(zhǔn)庫(kù)函數(shù)strpbrk號(hào)或無(wú)符號(hào)char、short、int、long類(lèi)型: 按位與 按位或 按位異或 n=n&該語(yǔ)n中除7個(gè)低二進(jìn)制位外的其它各位均置為0。x=x|SET_ON;0定(右操作數(shù)的值必須是非負(fù)值。因此,表x<<2x2位,右邊2位用0填補(bǔ),該表達(dá)式等價(jià)于對(duì)左操作數(shù)乘以4。在對(duì)unsigned類(lèi)型的無(wú)符號(hào)值進(jìn)行右移0signed類(lèi)型的帶符號(hào)值進(jìn)行右移時(shí),某些機(jī)器將即“算術(shù)移位”1。例如:x=x&p位開(kāi)始向n位的字段。這里假定最右邊的一0位,np都是合理的正值。例如,getbits(x,4,3)x4、3、2三位的值。/*getbits:getnbitsfrompositionp*/unsignedgetbits(unsignedx,intp,intn){return(x>>(p+1-n))&~(~0<<}其中,表達(dá)式m<<(p+1-n)將期望獲得的字段移位到字的最右端。~0的所有位都為1,這里使用語(yǔ)句~0n將~0n位,并將最右n0填補(bǔ)。再使用~運(yùn)算對(duì)它按位取反,這樣就建立了最右邊n位全為1的碼。練習(xí)2-6setbits(x,p,ny)x執(zhí)行下列操作后的結(jié)果值:將x中從第p位開(kāi)始的n個(gè)(二進(jìn)制)位設(shè)置為y中最右邊n位的值,x的其余練習(xí)2-7invert(x,pn)x執(zhí)行下列操作后的結(jié)2-8rightrot(xn)x循環(huán)右移(即從最右端i=i+=op=,其中,op可以是下面這些運(yùn)算符之一:+-*/%<<>>&^|expr1expr2是表達(dá)式,那么expr1op=expr2expr1=(expr1)op它們的區(qū)別在于,前一種形式expr1只計(jì)算一次。注意,在第二種形式中,expr2兩邊的圓x*=y+x=x*(y+x=x*y+/*bitcount:count1bitsinx*/intbitcount(unsignedx){intfor(b=0;x!=0;x>>=1)if(x&01)return}出的位都用0(而不是符號(hào)位)填補(bǔ)。常會(huì)2i上”或i2”,而不會(huì)說(shuō)i的值,加2,再把結(jié)果放回到ii+=2i=i+2更自然,另外,對(duì)于復(fù)雜的表達(dá)式,例如:yyval[yypv[p3+p4]+yypv[p1+p2]]+=while((c=getchar())練習(xí)2-9 在求對(duì)二的補(bǔ)碼時(shí),表達(dá)式x&=(x–1)可以刪除x中最右邊值為1的if(a>z=a;z=供了另外法編寫(xiě)這段程序及類(lèi)似的代碼段,在表達(dá)式expr1?expr2:表達(dá)式的值,否則計(jì)算expr3的值,并以該值作為條件表達(dá)式的值。expr2與expr3中只z=(a>b)?a: /*z=max(a,b)例如,如果ffloat類(lèi)型,nint類(lèi)型,那么表達(dá)式(n>0)?f:個(gè)元素,每行打印10個(gè)元素,每列之間用一個(gè)空格隔開(kāi),每行用一個(gè)換行符結(jié)束(包括最后一for(i=0;i<n;printf("%6d%c",a[i],(i%10==9!!i==n-1)?'\n':'在每10個(gè)元后以及在第n個(gè)元后都要打印一個(gè)換行符,所有其它元素后都要打印一個(gè)空格。編寫(xiě)這樣的代碼可能需要一些技巧,但比用等價(jià)的if-else結(jié)構(gòu)編寫(xiě)的代碼要緊湊一printf("Youhave%ditem%s.\n",n,n==1?"":練習(xí)2-10 中的if-else結(jié)構(gòu)。用于結(jié)構(gòu)成員,第6章將討論這兩個(gè)運(yùn)算符以及sizeof(對(duì)象長(zhǎng)度)運(yùn)算符。第5章將討論運(yùn)算符*(通過(guò)指針間接)與&(對(duì)象地址第3章將討論逗號(hào)運(yùn)算符。表2-1 !~*type * <<>> *&^| if((x&MASK)==0)x=f()+的語(yǔ)句中,f()可以在g()之前計(jì)算,也可以在g()之后計(jì)算。因此,如果函數(shù)f或g改變x的結(jié)果可能會(huì)依賴于這兩個(gè)函數(shù)的計(jì)算順序。為了保證printf("%dd\n"npower(2n*在不同的編譯器中可能會(huì)產(chǎn)生不同的結(jié)果,這取決于n的自增運(yùn)算在power調(diào)用之前還是之printf("%d%d\n",n,power(2,a[i]=問(wèn)題是:數(shù)組下標(biāo)i是舊值還是新值?對(duì)這種情況編譯器的解釋可能不同,并因此第3章控制流x=0;用一對(duì)花括號(hào)“{”與“}”把一組和語(yǔ)句括在一起就構(gòu)成了一個(gè)復(fù)合語(yǔ)句(也叫else,whilefor之后被花括號(hào)括住的多條語(yǔ)句也是類(lèi)似的例子(在任何程序塊中都可以if表達(dá)式其中else部分是可選的。該語(yǔ)句執(zhí)行時(shí),先計(jì)算表達(dá)式的值,如果其值為真(即表達(dá)式的值為非0)1;如果其值為假(即表達(dá)式的值0),并且該語(yǔ)句else部分,則執(zhí)行語(yǔ)句2。if表達(dá)式ifif(n>if(a>z=a;z=if(n>{if(a>z=}z=if(n>for(i=0;i<n;i++)if(s[i]>0){returni;} /*WRONGprintf("error--nisifif語(yǔ)句嵌套的情況下使用花括號(hào)。if(a>z=a;z=if表達(dá)式elseif表達(dá)式elseif表達(dá)式elseif表達(dá)式因此我們?cè)谶@里單獨(dú)說(shuō)明一下。這種if語(yǔ)句序列是編寫(xiě)多路判定最常用的方法。其中的各表達(dá)式將被依次求值,一旦某個(gè)表達(dá)式結(jié)果為真,則執(zhí)行與之相關(guān)的語(yǔ)句,并終止整個(gè)語(yǔ)句序列最后一個(gè)le部分用于處理“上述條件均不成立”的情況或默認(rèn)情況,也就是當(dāng)上面各條件都不滿足時(shí)的情形。有時(shí)候并不需要針對(duì)默認(rèn)情況執(zhí)行顯式的操作,這種情況下,可以這里通過(guò)一個(gè)折半查找函數(shù)說(shuō)明三路判定程序的用法。該函數(shù)用于判定已排序的數(shù)組v中是否存在某個(gè)特定的值x。數(shù)組v的元素必須以升序排列。如果v中包含x,則該函數(shù)返回x在v中的位置(介于0~n-1之間的一個(gè)整數(shù);否則,該函數(shù)返回-1。在折半查找時(shí),首先將輸入值x與數(shù)組v的中間元素進(jìn)行比較。如果x小于中間元素的x與所選部分的中間元素進(jìn)行比較。這個(gè)過(guò)程一直進(jìn)行下去,直到找到指定的值或/*binsearch:findxinv[0]<=v[1]<=...<=v[n-1]*/intbinsearch(intx,intv[],intn){intlow,high,low=0;high=n-1;while(low<={mid=(low+high)/2;if(x<v[mid])high=mid+1;elseif(x>v[mid])low=mid+ /*foundmatch*/returnmid;}return-1;/*nomatch}該函數(shù)的基本判定是:在每一步判斷x小于、大于還是等于中間元素v[mid]。使用else-if結(jié)構(gòu)執(zhí)行這種判定很自然。練習(xí)3-1在上面有關(guān)折半查找的例子中,while循環(huán)語(yǔ)句內(nèi)共執(zhí)行了兩次測(cè)試,其實(shí)只要一次就足夠(代價(jià)是將的測(cè)試在循環(huán)外執(zhí)行。重寫(xiě)該函數(shù),使得在循環(huán)內(nèi)部只執(zhí)行switch表達(dá)式case常量表達(dá)式語(yǔ)句序列case常量表達(dá)式語(yǔ)句序列default:語(yǔ)句序列達(dá)式的值匹配,則該switchdefault分支的排列次序是任符及其它所有字符出現(xiàn)的次數(shù)。下面我們用switch語(yǔ)句改寫(xiě)該程序如下:#includemain()/*countdigits,whitespace,others{intc,i,nwhite,nother,nwhite=nother=0;for(i=0;i<10;i++)ndigit[i]=while((c=getchar())!={switch(c)case'0':case'1':case'2':case'3':casecase'5':case'6':case'7':case'8':case'9':case'casecase}}for(i=0;i<10;i++)printf("%d",ndigit[i]);printf(",whitespace=%d,other=%d\n",nwhite,nother);return}khhe的作用只是一個(gè)標(biāo)號(hào),因此,某個(gè)分支中的代碼執(zhí)行完后,程序?qū)⑦M(jìn)入下一分支繼續(xù)執(zhí)行,除非在程序中顯式地跳轉(zhuǎn)。跳出swtch語(yǔ)句最常用的方法是使用rek語(yǔ)句與rtun語(yǔ)句。brak語(yǔ)句還可強(qiáng)制控制從wile、or與o循環(huán)語(yǔ)句中立即退出,對(duì)于這一點(diǎn),我k全,這樣做在程序修改時(shí)很容易出錯(cuò)。除了一個(gè)計(jì)算需要多個(gè)標(biāo)號(hào)的情況外,應(yīng)盡量減少?gòu)囊粋€(gè)分支直接進(jìn)入下一個(gè)分支執(zhí)行這種用法,在不得不使用的情況下應(yīng)該加上適當(dāng)?shù)某绦蜃⑨尅W鳛橐环N良好的程序設(shè)計(jì)風(fēng)格,在switch語(yǔ)句最后一個(gè)分支(即default分支)的后面也加上一個(gè)break語(yǔ)句。這樣做在邏輯上沒(méi)有必要,但當(dāng)我們需要向該switch語(yǔ)句后添練習(xí)3-2編寫(xiě)一個(gè)函數(shù)escape(s,t),將字符串t到字符串s中,并在whileforwhile表達(dá)式一直進(jìn)行下去,直到該表達(dá)式的值為0為止,隨后繼續(xù)執(zhí)行語(yǔ)句后面的部分。for循環(huán)語(yǔ)句表達(dá)式1;while2}但當(dāng)while或for循環(huán)語(yǔ)句中包含continue語(yǔ)句時(shí),上述二者之間就不一定等價(jià)了。我們將在3.7節(jié)中介紹continue語(yǔ)句。與表達(dá)式3是賦值表達(dá)式或函數(shù)調(diào)用,表達(dá)式2是關(guān)系表達(dá)式。這3個(gè)組成部分中的任何部分都可以省略,但分號(hào)必須保留。如果在for語(yǔ)句中省略表達(dá)式1與表達(dá)式3,它就成了while循環(huán)語(yǔ)句。如果省略測(cè)試條件,即表達(dá)式2,則認(rèn)為其值是真值,因此,下列for循環(huán)語(yǔ)句:for(;;)}while((c=getchar())==''||c=='\n'||c=;/*skipwhitespacecharactersfor語(yǔ)句更合適一些,它將循環(huán)控for(i=0;i<n;CnFortranDO循環(huán)或Pascal語(yǔ)言中的for循環(huán)。但是,這種類(lèi)比并不完全準(zhǔn)確,因?yàn)樵贑語(yǔ)言中,for循環(huán)語(yǔ)句i的值仍然保留。因?yàn)閒or語(yǔ)句的各組成部分可以是任何表達(dá)式,所以for語(yǔ)句并不限于通過(guò)算術(shù)級(jí)數(shù)或減(-)(4atof,它用于對(duì)浮點(diǎn)數(shù)執(zhí)行同樣的轉(zhuǎn)換。)#include/*atoi:convertstointeger;version2*/intatoi(chars[]){inti,n,for(i=0;isspace(s[i]);i++)/*skipwhitespace;sign=(s[i]=='-')?-1:if(s[i]=='+'||s[i]=='-')/*skipsign*/for(n=0;isdigit(s[i]);n=10*n+(s[i]-returnsign*}數(shù)組進(jìn)行排序的S排序算法。S排序算法是D.L.S于1959年發(fā)明的,其基本思想少為1,這時(shí)排序變成了相鄰元素的互換。/*s sort:sortv[0]...v[n-1]intoincreasingorder*/voids sort(intv[],intn){intgap,i,j,for(gap=n/2;gap>0;gap/=2)for(i=gap;i<n;i++)for(j=i-gap;j>=0&&v[j]>v[j+gap];j-{temp=v[j]=v[j+gap];v[j+gap]=}}就說(shuō)明for語(yǔ)句具有很強(qiáng)的通用性。逗號(hào)運(yùn)算符“,Cfor語(yǔ)句中經(jīng)常會(huì)用到它。被逗reverse(s)來(lái)舉例。該函數(shù)用于倒置字符串s中各個(gè)字符的位置。#include/*reverse:re

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論