嵌入式物聯(lián)網(wǎng)全unix環(huán)境高級(jí)編程io庫_第1頁
嵌入式物聯(lián)網(wǎng)全unix環(huán)境高級(jí)編程io庫_第2頁
嵌入式物聯(lián)網(wǎng)全unix環(huán)境高級(jí)編程io庫_第3頁
嵌入式物聯(lián)網(wǎng)全unix環(huán)境高級(jí)編程io庫_第4頁
嵌入式物聯(lián)網(wǎng)全unix環(huán)境高級(jí)編程io庫_第5頁
已閱讀5頁,還剩13頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、92理,避免了應(yīng)用程序需要考慮這一點(diǎn)所帶來的麻煩。不幸的是,標(biāo)準(zhǔn) I/O庫令人最感迷惑的也是它的緩存。標(biāo)準(zhǔn)I/O提供了三種類型的緩存:全緩存。在這種情況下,當(dāng)填滿標(biāo)準(zhǔn)I/O緩存后才進(jìn)行實(shí)際I/O操作。對(duì)于駐在磁盤上的文件通常是由標(biāo)準(zhǔn)I/O庫實(shí)施全緩存的。在一個(gè)流上執(zhí)行第一次I/O操作時(shí),相關(guān)標(biāo)準(zhǔn)I/O函數(shù)通常調(diào)用malloc(見7.8節(jié))獲得需使用的緩存。術(shù)語刷新( flush)說明標(biāo)準(zhǔn)I/O緩存的寫操作。緩存可由標(biāo)準(zhǔn)I/O例程自動(dòng)地刷新(例如當(dāng)填滿一個(gè)緩存時(shí)),或者可以調(diào)用函數(shù) fflush刷新一個(gè)流。值得引起注意的是在 UNIX環(huán)境中,刷新有兩種意思。在標(biāo)準(zhǔn)I/O庫方面,刷新意味著將緩存中

2、的內(nèi)容寫到磁盤上(該緩存可以只是局部填寫的)。在終端驅(qū)動(dòng)程序方面(例如在第 11章中所述的tcflush函數(shù)),刷新表示丟棄已存在緩存中的數(shù)據(jù)。行緩存。在這種情況下,當(dāng)在輸入和輸出中遇到新行符時(shí),標(biāo)準(zhǔn)I/O庫執(zhí)行I/O操作。這允許一次輸出一個(gè)字符(用標(biāo)準(zhǔn)I/O fp函數(shù)),但只有在寫了一行之后才進(jìn)行實(shí)際 I/O操作。當(dāng)流涉及一個(gè)終端時(shí)(例如標(biāo)準(zhǔn)輸入和標(biāo)準(zhǔn)輸出),典型地使用行緩存。對(duì)于行緩存有兩個(gè)限制。第一個(gè)是:因?yàn)闃?biāo)準(zhǔn) I/O庫用來收集每一行的緩存的長度是固定的,所以只要填滿了緩存,那么即使還沒有寫一個(gè)新行符,也進(jìn)行 I/O操作。第二個(gè)是:任何時(shí)候只要通過標(biāo)準(zhǔn)輸入輸出庫要求從 (a)一個(gè)不帶緩

3、存的流,或者(b)一個(gè)行緩存的流(它預(yù)先要求從內(nèi)核得到數(shù)據(jù))得到輸入數(shù)據(jù),那么就會(huì)造成刷新所有行緩存輸出流。在 (b)中帶了一個(gè)在括號(hào)中的說明的理由是,所需的數(shù)據(jù)可能已在該緩存中,它并不要求內(nèi)核在需要該數(shù)據(jù)時(shí)才進(jìn)行該操作。很明顯,從不帶緩存的一個(gè)流中進(jìn)行輸入( (a)項(xiàng))要求當(dāng)時(shí)從內(nèi)核得到數(shù)據(jù)。(3) 不帶緩存。標(biāo)準(zhǔn)I/O庫不對(duì)字符進(jìn)行緩存。如果用標(biāo)準(zhǔn) I/O函數(shù)寫若干字符到不帶緩存的流中,則相當(dāng)于用 write系統(tǒng)調(diào)用函數(shù)將這些字符寫至相關(guān)聯(lián)的打開文件上。標(biāo)準(zhǔn)出錯(cuò)流 stderr通常是不帶緩存的,這就使得出錯(cuò)信息可以盡快顯示出來而不管它們是否含有一個(gè)新行字符。ANSI C要求下列緩存特征:當(dāng)

4、且僅當(dāng)標(biāo)準(zhǔn)輸入和標(biāo)準(zhǔn)輸出并不涉及交互作用設(shè)備時(shí),它們才是全緩存的。標(biāo)準(zhǔn)出錯(cuò)決不會(huì)是全緩存的。但是,這并沒有告訴如果標(biāo)準(zhǔn)輸入和輸出涉及交互作用設(shè)備時(shí),它們是不帶緩存的還是行緩存的,以及標(biāo)準(zhǔn)輸出是不帶緩存的,還行緩存的。 SVR4和4.3+BSD的系統(tǒng)默認(rèn)使用下列類型的緩存標(biāo)準(zhǔn)出錯(cuò)是不帶緩存的如若是涉及終端設(shè)備的其他流,則它們是行緩存的;否則是全緩存的。對(duì)任何一個(gè)給定的流,如果更改緩存類型:并不喜歡這些系統(tǒng)默認(rèn),則可調(diào)用下列兩個(gè)函數(shù)中的一個(gè)# i n c l ud e vo i d s e t bu f( F I LE fp *, c h a r*buf ) ;s e t vbu f ( F I

5、LEfp ,* c h a r*buf ,mode ,s i ze _ t size ) ;返回:若成功則為0,若出錯(cuò)則為非0這些函數(shù)一定要在流已被打開后調(diào)用(這是十分明顯的,因?yàn)槊總€(gè)函數(shù)都要求一個(gè)有效的文件93指針作為它們的第一個(gè)參數(shù)),而且也應(yīng)在對(duì)該流執(zhí)行任何一個(gè)其他操作之前調(diào)用??梢允褂胹etbuf函數(shù)打開或關(guān)閉緩存機(jī)制。為了帶緩存進(jìn)行 I/O,參數(shù)buf 必須指向一個(gè)長度為BUFSIZ的緩存(該常數(shù)定義在中)。通常在此之后該流就是全緩存的,但是如果該流與一個(gè)終端設(shè)備相關(guān),那么某些系統(tǒng)也可將其設(shè)置為行緩存的。為了關(guān)閉緩存,將 buf設(shè)置為NULL。使用setvbuf,可以精確地說明所需的

6、緩存類型。這是依靠mode參數(shù)實(shí)現(xiàn)的:_ IOFBF_ IOLBF_ I ONBF如果指定一個(gè)不帶緩存的流,則忽略 buf 和size全緩存 行緩存 不帶緩存參數(shù)。如果指定全緩存或行緩存,則 buf 和size可以可選擇地指定一個(gè)緩存及其長度。如果該流是帶緩存的,而 buf 是NULL,則標(biāo)準(zhǔn)I/O庫將自動(dòng)地為該流分配適當(dāng)長度的緩存。適當(dāng)長度指的是由 struct結(jié)構(gòu)中的成員st_blksize所指定的值(見4.2節(jié))。如果系統(tǒng)不能為該流決定此值(例如若此流涉及一個(gè)設(shè)備或一個(gè)管道),則分配長度為BUFSIZ的緩存。表5-1列出了這兩個(gè)函數(shù)的動(dòng)作,以及它們的各個(gè)選擇項(xiàng)表5-1 setbuf 和s

7、etvbuf 函數(shù)要了解,如果在一個(gè)函數(shù)中分配一個(gè)自動(dòng)變量類的標(biāo)準(zhǔn) I/O緩存,則從該函數(shù)返回之前,必須關(guān)閉該流。(7.8節(jié)將對(duì)此作。)另外, SVR4將緩存的一部分用于它自己的管理操作,所以可以存放在緩存中的實(shí)際數(shù)據(jù)字節(jié)數(shù)少于 size。一般而言,應(yīng)由系統(tǒng)選擇緩存的長度,并自動(dòng)分配緩存。在這樣處理時(shí),標(biāo)準(zhǔn)I/O庫在關(guān)閉此流時(shí)將自動(dòng)此緩存。任何時(shí)候,都可強(qiáng)制刷新一個(gè)流。# i n c l u d e f f l u s h ( F ILE f*p ) ;返回:若成功則為0,若出錯(cuò)則為E O F函數(shù)modebuf緩存及長度緩存的類型s e t b u fn o n n u l l長度為B U F

8、 S I 的Z 用戶緩存全緩存或行緩存NU L L(無緩存不帶緩存s e t v b u f_ I O F B Fn o n n u l l長度為size的用戶緩存全緩存NU L L合適長度的系統(tǒng)緩存_ I O L B Fn o n n u l l長度為size的用戶緩存行緩存NU L L合適長度的系統(tǒng)緩存_ I ON B F忽略無緩存不帶緩存系統(tǒng)首先使用st_blksize表示緩存長度。較早的系統(tǒng)V版本使用標(biāo)準(zhǔn)I/O常數(shù)BUFSIZ(其典型值是1024)。即使4.3+BSD使用st_blksize決定最佳的I/O緩 長度,它仍將BUFSIZ設(shè)置為1024。94此函數(shù)使該流所有未寫的數(shù)據(jù)都被傳

9、遞至內(nèi)核。作為一種特殊情形,如若 fp是NULL,則此函數(shù)刷新所有輸出流。5.5打開流下列三個(gè)函數(shù)可用于打開一個(gè)標(biāo)準(zhǔn)I/O流。# i n c l ud e F ILE* f o p e n ( c o n s t c h a r p*athname ,c on s t c h a r typ*e ) ;F I LE * fr e op e n ( c on s t c h aprath*name ,c on s tc h a r typ*e , F I LE fp*) ;F I LE * f dop e n (ledes ,c on s t c h a r typ*e ) ;三個(gè)函數(shù)的返回:若

10、成功則為文件指針,若出錯(cuò)則為 NU L L這三個(gè)函數(shù)的區(qū)別是:fopen 打開路徑名由pathname 指示的一個(gè)文件。freopen在一個(gè)特定的流上(由fp指示)打開一個(gè)指定的文件(其路徑名由pathname 指示),如若該流已經(jīng)打開,則先關(guān)閉該流。此函數(shù)一般用于將一個(gè)指定的文件打開為一個(gè)預(yù)定義的流:標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出或標(biāo)準(zhǔn)出錯(cuò)。(3) fdopen取一個(gè)現(xiàn)存的文件描述符(可能從 open,dup,dup2,fcntl或pipe函數(shù)得到此文件描述符),并使一個(gè)標(biāo)準(zhǔn)的I/O流與該描述符相結(jié)合。此函數(shù)常用于由創(chuàng)建管道和網(wǎng)絡(luò)通信通道函數(shù)獲得的插述符。因?yàn)檫@些特殊類型的文件不能用標(biāo)準(zhǔn) I/O fop

11、en函數(shù)打開,首先必須先調(diào)用設(shè)備函數(shù)以獲得一個(gè)文件描述符,然后用 fdopen使一個(gè)標(biāo)準(zhǔn)I/O流與該描述符相結(jié)合。type參數(shù)指定對(duì)該I/O流的讀、寫方式, ANSI C規(guī)定type參數(shù)可以有15種不同的值,它們示于表5-2中。表5-2打開標(biāo)準(zhǔn)I/O流的type參數(shù)type說明r 或 r bw 或 w b a 或 a b為讀而打開使文件成為0長,或?yàn)閷懚鴦?chuàng)建添加;為在文件尾寫而打開,或?yàn)閷懚鴦?chuàng)建為讀和寫而打開使文件為0長,或?yàn)樽x和寫而打開為在文件尾讀和寫而打開或創(chuàng)建r + w+a+或 r +b或 w+b或 a+b或 r b +或 w b +或 a b +fopen和freopen是ANSI C

12、的所屬部分。而ANSI C并不涉及文件描述符,所以僅有IX.1具有fdopen。傳送一個(gè)空指針以強(qiáng)迫刷新所有輸出流,這是由ANSI C新引入的。非ANSI C庫(例如較早的系統(tǒng)V版本和4.3BSD)并不支持此種特征。95使用字符b作為type的一部分,使得標(biāo)準(zhǔn) I/O系統(tǒng)可以區(qū)分文本文件和二進(jìn)制文件。因?yàn)?UNIX內(nèi)核并不對(duì)這兩種文件進(jìn)行區(qū)分,所以在 UNIX系統(tǒng)環(huán)境下指定字符b作為type的一部分實(shí)際上并無作用。對(duì)于fdopen,type參數(shù)的意義則稍有區(qū)別。因?yàn)樵撁枋龇驯淮蜷_,所以 fdopen為寫而打開并不截短該文件。(例如,若該描述符原來是由 open函數(shù)打開的,該文件那時(shí)已經(jīng)存在,

13、則其O_TRUNC標(biāo)志將決定是否截短該文件。fdopen函數(shù)不能截短它為寫而打開的任一文件。)另外,標(biāo)準(zhǔn)I/O添加方式也不能用于創(chuàng)建該文件(因?yàn)槿缛粢粋€(gè)描述符一定已經(jīng)存在)。一個(gè)文件,則該文件當(dāng)用添加類型打開一文件后,則每次寫都將數(shù)據(jù)寫到文件的當(dāng)前尾端處。如若有多個(gè)進(jìn)程用標(biāo)準(zhǔn)I/O添加方式打開了同一文件,那么來自每個(gè)進(jìn)程的數(shù)據(jù)都將正確地寫到文件中。當(dāng)以讀和寫類型打開一文件時(shí)( type中+號(hào)),具有下列限制:如果中間沒有fflush、fseek、fset或rewind,則在輸出的后面不能直接跟隨輸入。如果中間沒有fseek、fset作之后不能直接跟隨輸出?;騬ewind,或者一個(gè)輸出操作沒有到

14、達(dá)文件尾端,則在輸入操按照表5-2,在表5-3中列出了打開一個(gè)流的六種不同的方式。表5-3打開一個(gè)標(biāo)準(zhǔn)I/O流的六種不同的方式限制rwar +w +a +文件必須已存在擦除文件以前的內(nèi)容流可以讀流可以寫流只可在尾端處寫注意,在指定w或a類型創(chuàng)建一個(gè)新件時(shí),無法說明該文件的存取權(quán)位(第 3章中所述的open函數(shù)和creat函數(shù)則能做到這一點(diǎn))。IX.1要求以這種方式創(chuàng)建的文件具有下列存取權(quán):S _ I R U SRS _ I WU SRS _ I R G RPS _ I WG RPS _ I R O THS _ I WO T H除非流終端設(shè)備,否則按系統(tǒng)默認(rèn),它被打開時(shí)是全緩存的。終端設(shè)備,則該

15、流是行緩存的。一旦打開了流,那么在對(duì)該流執(zhí)行任何操作之前,如果希望,則可使用前節(jié)所述的setbuf和setvbuf改變緩存的類型。調(diào)用fclose關(guān)閉一個(gè)打開的流。# i n c l ud e f c l o s e ( F I LEfp )* ;4.3+BSD以前的版本以及Kernighan和Ritchie1988177頁上所示的簡單版本并不能正確地處理添加方式。這些版本在打開流時(shí),調(diào)用 lseek到達(dá)文件尾端。在涉及多個(gè)進(jìn)程時(shí),為了正確地支持添加方式,該文件必須用 O_APPEND標(biāo)志打開, 已在3.3節(jié)中對(duì)此進(jìn)行了 。在每次寫前,做一次 lseek操作同樣也不能正確工作(如同在3.11節(jié)

16、中 的一樣)。96返回:若成功則為0,若出錯(cuò)則為E O F在該文件被關(guān)閉之前,刷新緩存中的輸出數(shù)據(jù)。緩存中的輸入數(shù)據(jù)被丟棄。如果標(biāo)準(zhǔn) I/O庫已經(jīng)為該流自動(dòng)分配了一個(gè)緩存,則此緩存。當(dāng)一個(gè)進(jìn)程正常終止時(shí)(直接調(diào)用exit函數(shù),或從main函數(shù)返回),則所有帶未寫緩存數(shù)據(jù)的標(biāo)準(zhǔn)I/O流都被刷新,所有打開的標(biāo)準(zhǔn)I/O流都被關(guān)閉。讀和寫流一旦打開了流,則可在三種不同類型的非格式化 I/O中進(jìn)行選擇,對(duì)其進(jìn)行讀、寫操作。(5.11節(jié)說明了格式化I/O函數(shù),例如prf和scanf。)每次一個(gè)字符的I/O。一次讀或?qū)懸粋€(gè)字符,如果流是帶緩存的,則標(biāo)準(zhǔn)I/O函數(shù)處理所有緩存。每次一行的I/O。使用fgets

17、和fputs一次讀或?qū)懸恍?。每行都以一個(gè)新行符終止。當(dāng)調(diào)用 fgets時(shí),應(yīng)說明能處理的最大行長。5.7節(jié)將說明這兩個(gè)函數(shù)。直接I/O。fread和fwrite函數(shù)支持這種類型的I/O。每次I/O操作讀或?qū)懩撤N數(shù)量的對(duì)象,而每個(gè)對(duì)象具有指定的長度。這兩個(gè)函數(shù)常用于從二進(jìn)制文件中讀或?qū)懸粋€(gè)結(jié)構(gòu)。 5.9節(jié)將說明這兩個(gè)函數(shù)。5.6.1 輸入函數(shù)以下三個(gè)函數(shù)可用于一次讀一個(gè)字符。# i n c l u d e g e t c ( F I LE fp*) ;f g e t c ( F I LEfp *) ;g e t c h a r( vo i d ) ;三個(gè)函數(shù)的返回:若成功則為下一個(gè)字符,若已處文

18、件尾端或出錯(cuò)則為 E O F函數(shù)getchar等同于getc(stdin)。前兩個(gè)函數(shù)的區(qū)別是getc可被實(shí)現(xiàn)為宏,而fgetc則不能實(shí)現(xiàn)為宏。這意味著:getc的參數(shù)不應(yīng)當(dāng)是有副作用的表達(dá)式。因?yàn)閒getc一定是個(gè)函數(shù),所以可以得到其地址。這就允許將 fgetc的地址作為一個(gè)參數(shù)傳送給另一個(gè)函數(shù)。調(diào)用fgetc所需時(shí)間很可能長于調(diào)用getc,因?yàn)檎{(diào)用函數(shù)通常所需的時(shí)間長于調(diào)用宏。檢驗(yàn)一下頭文件的大多數(shù)實(shí)現(xiàn),從中可見getc是一個(gè)宏,其編碼具有較高的工作效率。這三個(gè)函數(shù)以u(píng)nsigned char 類型轉(zhuǎn)換為的方式返回下一個(gè)字符。說明為不帶符號(hào)的理由是,如果最為1也不會(huì)使返回值為負(fù)。要求整型返

19、回值的理由是,這樣就可以返回所有可能的字符值再加上一個(gè)已發(fā)生錯(cuò)誤或已到達(dá)文件尾端的指示值。在 中的常數(shù)EOF被要直接I/O(direct I/O) 這個(gè)術(shù)語來自ANSI C標(biāo)準(zhǔn),有時(shí)也被稱為:二進(jìn)制 I/O、一次一個(gè)對(duì)象I/O、面向的I/O或面向結(jié)構(gòu)的I/O。97求是一個(gè)負(fù)值,其值經(jīng)常是 1。這就意味著不能將這三個(gè)函數(shù)的返回值存放在一個(gè)字符變量中,以后還要將這些函數(shù)的返回值與常數(shù)EOF相比較。注意,不管是出錯(cuò)還是到達(dá)文件尾端,這三個(gè)函數(shù)都返回同樣的值。為了區(qū)分這兩種不同的情況,必須調(diào)用ferror或feof。# i n c l u d e f e rr o r( F I LE fp*) ;f

20、e o f( F I LE fp*) ;兩個(gè)函數(shù)返回:若條件為真則為非 0 (真),否則為0(假v o i d c l e a r e r r ( F ILE *fp ) ;在大多數(shù)實(shí)現(xiàn)的FILE對(duì)象中,為每個(gè)流保持了兩個(gè)標(biāo)志出錯(cuò)標(biāo)志。文件結(jié)束標(biāo)志。調(diào)用clearerr則清除這兩個(gè)標(biāo)志。從一個(gè)流讀之后,可以調(diào)用ungetc將字符再送回流中# i n c l u d e u ng e t c (, F ILE *fp ) ;返回:若成功則為C,若出錯(cuò)則為E O F送回到流中的字符以后又可從流中讀出,但讀出字符的順序與送回的順序相反。應(yīng)當(dāng)了解,雖然ANSI C允許支持任何數(shù)量的字符回送的實(shí)現(xiàn),但是

21、它要求任何一種實(shí)現(xiàn)都要支持一個(gè)字符的回送功能。回送的字符,不一定必須是上一次讀到的字符。 EOF不能回送。但是當(dāng)已經(jīng)到達(dá)文件尾端時(shí),仍可以回送一字符。下次讀將返回該字符,再次讀則返回 EOF。之所以能這樣做的原因是一次成功的ungetc調(diào)用會(huì)清除該流的文件結(jié)束指示。當(dāng)正在讀一個(gè)輸入流,并進(jìn)行某種形式的 字或分記號(hào)操作時(shí),會(huì)經(jīng)常用到回送字符操作。有時(shí)需要先看一看下一個(gè)字符,以決定如何處理當(dāng)前字符。然后就需要方便地將剛查看的字符送回,以便下一次調(diào)用getc時(shí)返回該字符。如果標(biāo)準(zhǔn)I/O庫不提供回送能力,就需將該字放到一個(gè)自己的變量中,并設(shè)置一個(gè)標(biāo)志以便判別在下一次需要一個(gè)字符時(shí)是調(diào)用 getc,還是

22、從自己的變量中取用5.6.2 輸出函數(shù)對(duì)應(yīng)于上面所述的每個(gè)輸入函數(shù)都有一個(gè)輸出函數(shù)。# i n c l u d ep(, F ILE *fp ) ;f p(, F I LE fp*) ;98ph a r () ;三個(gè)函數(shù)返回:若成功則為C,若出錯(cuò)則為E O F與輸入函數(shù)一樣, phar(c) 等同于p為宏。(c, stdout),p可被實(shí)現(xiàn)為宏,而fp則不能實(shí)現(xiàn)5.7每次一行I/O下面兩個(gè)函數(shù)提供每次輸入一行的功能。# i n c l ud e c h a r * f g e t s ( c h a rbuf*,c h a r *g e t s ( c h a r bu*f ) ;n,F(xiàn) I

23、LE *fp ) ;兩個(gè)函數(shù)返回:若成功則為b u f,若已處文件尾端或出錯(cuò)則為N U L L這兩個(gè)函數(shù)都指定了緩存地址,讀入的行將送入其中。 gets從標(biāo)準(zhǔn)輸入讀,而fgets則從指定的流讀。對(duì)于fgets,必須指定緩存的長度 n。此函數(shù)一直讀到下一個(gè)新行符為止,但是不超過 n1個(gè)字符,讀入的字符被送入緩存。該緩存以 null字符結(jié)尾。如若該行,包括最后一個(gè)新行符的字符數(shù)超過n1,則只返回一個(gè)不完整的行,而且緩存總是以 null字符結(jié)尾。對(duì)fgets的下一次調(diào)用會(huì)繼續(xù)讀該行。gets是一個(gè)不使用的函數(shù)。問題是調(diào)用者在使用 gets時(shí)不能指定緩存的長度。這樣就可能造成緩存越界(如若該行長于緩存

24、長度),寫到緩存之后的空中,從而產(chǎn)生不可預(yù)料的。這種缺陷曾被利用,造成1 9 8 8 年的因特網(wǎng)蠕蟲事件有關(guān)說明請(qǐng)見1 9 8 9 . 6 .Communications of the ACM(vol.32, no.6) gets與fgets的另一個(gè)區(qū)別是, gets并不將新行入緩存中。雖然ANSI C要求提供gets,但請(qǐng)不要使用它。 fputs和puts提供每次輸出一行的功能。# i n c l ud e f pu t s ( c on s tc h a srtr , *F I LE fp*) ;pu t s ( c on s t c h a sr tr )*;兩個(gè)函數(shù)返回:若成功則為非負(fù)

25、值,若出錯(cuò)則為 E O F函數(shù)fputs將一個(gè)以null符終止的字符串寫到指定的流,終止符 null不寫出。注意,這并不一定是每次輸出一行,因?yàn)樗⒉灰笤?null符之前一定是新行符。通常,在 null符之前是一個(gè)新行符,但并不要求總是如此。puts將一個(gè)以null符終止的字符串寫到標(biāo)準(zhǔn)輸出,終止符不寫出。但是, puts然后又將一個(gè)新行符寫到標(biāo)準(zhǔn)輸出。這兩個(gè)函數(shù)對(duì)新行符進(jìn)行處理方面的差別與 UNIX的進(jìn)展有關(guān)。早在V7冊中就說明 “為了向后兼容,gets刪除新行符 而fgets則保持新行符。”99puts并不像它所對(duì)應(yīng)的gets那樣不安全。但是還是應(yīng)避免使用它,以免需要記住它在最后又加上了

26、一個(gè)新行符。如果總是使用 fgets和fputs, 那么就會(huì)熟知在每行終止處己加一個(gè)新行符。須自5.8標(biāo)準(zhǔn)I/O的效率使用前面所述的函數(shù),應(yīng)該對(duì)標(biāo)準(zhǔn) I/O系統(tǒng)的效率有所了解。程序 5-1類似于程序3-3,到標(biāo)準(zhǔn)輸出。這兩個(gè)函數(shù)可以實(shí)現(xiàn)為宏。它使用getc和p將標(biāo)準(zhǔn)輸入程序5-1 用getc和p將標(biāo)準(zhǔn)輸入到標(biāo)準(zhǔn)輸出可以用fgetc和fp細(xì)節(jié))。改寫該程序,這兩個(gè)一定是函數(shù),而不是宏(沒有給出對(duì)源代碼更改的最后,還編寫了一個(gè)讀、寫行的版本,見程序5-2。程序5-2 用fgets和fputs將標(biāo)準(zhǔn)輸入到標(biāo)準(zhǔn)輸出注意,在程序5-1和程序5-2中,沒有顯式地關(guān)閉標(biāo)準(zhǔn)I/O流。知道exit函數(shù)將會(huì)刷新任

27、寫的數(shù)據(jù),然后關(guān)閉所有打開的流(在 8.5節(jié)這一點(diǎn))。將這三個(gè)程序的時(shí)間與表3-1中的時(shí)間進(jìn)行比較是很有趣的。表 5-4中顯示了對(duì)同一文件( 1.5M字節(jié), 30,000行)進(jìn)行操作所得的數(shù)據(jù)。100表5-4 使用標(biāo)準(zhǔn)I/O例程得到的時(shí)間結(jié)果函數(shù)用戶CPU(秒)系統(tǒng)CPU(秒)時(shí)鐘時(shí)間(秒)程序正文字節(jié)數(shù)表3-1中的最佳時(shí)間f g e t s , f p u t s g e t c , pf g e t c , f p表3-1中的單字節(jié)時(shí)間0.00.30.334.85.0423.4184384152對(duì)于這三個(gè)標(biāo)準(zhǔn)I/O版本的每一個(gè),其用

28、戶CPU時(shí)間都大于表3-1中的最佳read版本,因?yàn)槊看巫x一個(gè)字符版本中有一個(gè)要執(zhí)行 150萬次的循環(huán),而在每次讀一行的版本中有一個(gè)要執(zhí) 30 000次的循環(huán)。在read版本中,其循環(huán)只需執(zhí)行180次(對(duì)于緩存長度為8192字節(jié))。因?yàn)橄到y(tǒng)CPU時(shí)間都相同,所以用戶CPU時(shí)間的差別造成了時(shí)鐘時(shí)間的差別。系統(tǒng)CPU時(shí)間相同的原因是因?yàn)樗羞@些程序?qū)?nèi)核讀、寫請(qǐng)求數(shù)相同。注意,使用標(biāo)準(zhǔn)I/O例程的一個(gè)優(yōu)點(diǎn)是無需考慮緩存及最佳I/O長度的選擇。在使用fgets時(shí)需要考慮最大行長,但是最佳I/O長度的選擇要方便得多。表5-4中的最后一列是每個(gè)main函數(shù)的文本空間字節(jié)數(shù)(由C編譯產(chǎn)生的機(jī)器指令)。從中

29、可見,使用getc的版本在文本空間中作了 getc和p的宏代換,所以它所需使用的指令數(shù)超過了調(diào)用fgetc和fp函數(shù)所需指令數(shù)。觀察getc版本和fgetc版本在用戶CPU時(shí)間方的差別,可以看到在程序中作宏代換和調(diào)用兩個(gè)函數(shù)在進(jìn)行本測試的系統(tǒng)上并沒有造成多大差別。使用每次一行I/O版本其速度大約是每次一個(gè)字符版本的兩倍(包括用戶 CPU時(shí)間和時(shí)鐘時(shí)間)。如果fgets和fputs函數(shù)用getc和p實(shí)現(xiàn)(例如,見Kernighan和Ritchie1988的7.7節(jié)),那么,可以預(yù)期fgets版本的時(shí)間會(huì)與getc版本相接近。實(shí)際上,可以預(yù)料每次一行的版本會(huì)更慢一些,因?yàn)槌爽F(xiàn)已存在的 60 00

30、0次函數(shù)調(diào)用外還需增加 3百萬次宏調(diào)用。而在本測試中所用的每次一行函數(shù)是用mem非C語言編寫y(3)實(shí)現(xiàn)的。通常,為了提高效率, memy函數(shù)用匯編語言而這些時(shí)間數(shù)字的最后一個(gè)有趣之處在于: fgetc版本較表3-1中BUFFSIZE1的版本要快得多。兩者都使用了約3百萬次的函數(shù)調(diào)用,而fgetc版本的速度在用戶CPU時(shí)間方面,大約是后者的5倍,而在時(shí)鐘時(shí)間方面則幾乎是100倍。造成這種差別的原因是:使用read的版本執(zhí)行了 3百萬次函數(shù)調(diào)用,這也就引起 3百萬次系統(tǒng)調(diào)用。而對(duì)于fgetc版本,它也執(zhí)行3百萬次函數(shù)調(diào)用,但是這只引起360次系統(tǒng)調(diào)用。系統(tǒng)調(diào)用與普通的函數(shù)調(diào)用相比是很花費(fèi)時(shí)間的。

31、需要的是這些時(shí)間結(jié)果只在某些系統(tǒng)上才有效。這種時(shí)間結(jié)果依賴于很多實(shí)現(xiàn)的特征,而這種特征對(duì)于不同的UNIX系統(tǒng)卻可能是不同的。盡管如此,使這樣一組數(shù)據(jù),并對(duì)各種版本的差別作出解釋,這有助于更好地了解系統(tǒng)。在本節(jié)及3.9節(jié)中學(xué)到的基本事實(shí)是:標(biāo)準(zhǔn)I/O庫與直接調(diào)用read和write函數(shù)相比并不慢很多。觀察到使用getc和p1M字節(jié)數(shù)據(jù)大約需3.0秒CPU時(shí)間。對(duì)于大多數(shù)比較復(fù)雜的應(yīng)用程序,最主要的用戶CPU時(shí)間是由應(yīng)用本身的各種處理花費(fèi)的,而不是由標(biāo)準(zhǔn)I/O例程消耗的。5.9二進(jìn)制I/O5.6節(jié)中的函數(shù)以一次一個(gè)字符或一次一行的方式進(jìn)行操作。如果為二進(jìn)制 I/O,那么更愿意一次讀或?qū)懻麄€(gè)結(jié)構(gòu)。為

32、了使用 getc或p做到這一點(diǎn),必須循環(huán)通過整個(gè)結(jié)構(gòu),一次101讀或?qū)懸粋€(gè)字節(jié)。因?yàn)閒puts在遇到null字節(jié)時(shí)就停止,而在結(jié)構(gòu)中可能含有 null字節(jié),所以不能使用每次一行函數(shù)實(shí)現(xiàn)這種要求。相類似,如果輸入數(shù)據(jù)中包含有 null字節(jié)或新行符,則 fgets也不能正確工作。因此,提供了下列兩個(gè)函數(shù)以執(zhí)行二進(jìn)制I/O操作。# i n c l ud e s i z e _ t f r e a d ( v o i d *ptr ,s i ze _ t size ,s i ze _ t nobj , F ILE *fp ) ;s i ze _ tf w r i t e ( c on s t vo i

33、 pdtr ,* s i ze _ t size ,s i ze _ t nobj , F ILE *fp ) ;兩個(gè)函數(shù)的返回:讀或?qū)懙?象數(shù)這些函數(shù)有兩個(gè)常見的用法:(1) 讀或?qū)懸粋€(gè)二進(jìn)制數(shù)組。例如,將一個(gè)浮點(diǎn)數(shù)組的第 2至第5個(gè)元素寫至一個(gè)文件上,可以寫作:f l o a td a t a1 0;i f(f w r i t e ( &d a ta 2, s i z e o f ( f l o a t ) , 4 , f p ) ! = 4 ) e r r _ s y s ( fw r i t e e r r o r ) ;其中,指定size為每個(gè)數(shù)組元素的長度,nobj為欲寫的元素?cái)?shù)。

34、(2) 讀或?qū)懸粋€(gè)結(jié)構(gòu)。例如,可以寫作s t r u c t s ho r t l o n gc h a r i t em ;c oun t ; t o t a l ;n am e NAME S I ZEi f ( fw r i t e (& i t em , s i z e o f ( i t em ) , 1 , f p ) ! = 1 ) e r r _ s y s ( fw r i t e e r r o r ) ;其中,指定size為結(jié)構(gòu)的長度, nobj為1(要寫的對(duì)象數(shù))。將這兩個(gè)例子結(jié)合起來就可讀或?qū)懸粋€(gè)結(jié)構(gòu)數(shù)組。為了做到這一點(diǎn), size應(yīng)當(dāng)是該結(jié)構(gòu)的sizeof,nobj應(yīng)

35、是該數(shù)組中的元素?cái)?shù)。fread和fwrite返回讀或?qū)懙膶?duì)象數(shù)。對(duì)于讀,如果出錯(cuò)或到達(dá)文件尾端,則此數(shù)字可以少于nobj。在這種情況,應(yīng)調(diào)用ferror或feof以判斷究竟是那一種情況。對(duì)于寫,如果返回值少于所要求的nobj,則出錯(cuò)。使用二進(jìn)制I/O的基本問題是,它只能用于讀已寫在同一系統(tǒng)上的數(shù)據(jù)。多年之前,這并無問題(那時(shí),所有UNIX系統(tǒng)都運(yùn)行于PDP-11上),而現(xiàn)在,很多異構(gòu)系統(tǒng)通過網(wǎng)絡(luò)相互連接起來,而且,這種情況已經(jīng)非常普遍。常常有這種情形,在一個(gè)系統(tǒng)上寫的數(shù)據(jù),在另一個(gè)系統(tǒng)上處理。在這種環(huán)境下,這兩個(gè)函數(shù)可能就不能正常工作,其原因是:(1) 在一個(gè)結(jié)構(gòu)中,同一成員的位移量可能隨編譯

36、程序和系統(tǒng)的不同而異(由于不同的對(duì)準(zhǔn)要求)。確實(shí),某些編譯程序有一選擇項(xiàng),它允許緊密包裝結(jié)構(gòu)(節(jié)省空間,而運(yùn)行性能則可能有所下降)或準(zhǔn)確對(duì)齊,以便在運(yùn)行時(shí)易于存取結(jié)構(gòu)中的各成員。這意味著即使在單一系統(tǒng)上,一個(gè)結(jié)構(gòu)的二進(jìn)制存放方式也可能因編譯程序的選擇項(xiàng)而不同。(2) 用來多字節(jié)整數(shù)和浮點(diǎn)值的二進(jìn)制格式在不同的系統(tǒng)結(jié)構(gòu)間也可能不同。在不同系統(tǒng)之間交換二進(jìn)制數(shù)據(jù)的實(shí)際解決方法是使用較次的協(xié)議。關(guān)于網(wǎng)絡(luò)協(xié)議使用的交換二進(jìn)制數(shù)據(jù)的某些技術(shù),請(qǐng)參閱Stevens1990的18.2節(jié)。102在8.13節(jié)中,賬。再回到fread函數(shù),那時(shí)將用它讀一個(gè)二進(jìn)制結(jié)構(gòu)UNIX的進(jìn)程記5.10定位流有兩種方法定位標(biāo)準(zhǔn)

37、I/O流。(1) fl和fseek。這兩個(gè)函數(shù)自V7以來就存在了,但是它們都假定文件的位置可以存放在一個(gè)長整型中。(2) fget和fset。這兩個(gè)函數(shù)是新由ANSI C引入的。它們引進(jìn)了一個(gè)新的抽象數(shù)據(jù)類型f_t,它文件的位置。在非UNIX系統(tǒng)中,這種數(shù)據(jù)類型可以定義為一個(gè)文件的位置所需的長度。需要移植到非UNIX系統(tǒng)上運(yùn)行的應(yīng)用程序應(yīng)當(dāng)使用fget和fset。# i n c l ud e l o n g fl ( F ILE f*p ) ;返回:若成功則為當(dāng)前文件位置指示,若出錯(cuò)則為 1Lf s ee k ( F I LE fp *, l ong offset ,whence ) ;返回:

38、若成功則為0,若出錯(cuò)則為非0vo i d r e w i nd ( F I L Efp )*;對(duì)于一個(gè)二進(jìn)制文件,其位置指示器是從文件起始位置開始度量,并字節(jié)為計(jì)量的。fl用于二進(jìn)制文件時(shí),其返回值就是這種字節(jié)位置。為了用 fseek定位一個(gè)二進(jìn)制文件,必須指定一個(gè)字節(jié) offset,以及解釋這種位移量的方式。 whence的值與3.6節(jié)中l(wèi)seek函數(shù)的相同: SEEK_SET表示從文件的起始位置開始SEEK_CUR表示從當(dāng)前文件位置, SEEK_END表示從文件的尾端。ANSI C并不要求一個(gè)實(shí)現(xiàn)對(duì)二進(jìn)制文件支持 SEEK_END規(guī)格說明,其原因是某些系統(tǒng)要求二進(jìn)制文件的長度是某個(gè)幻數(shù)的整

39、數(shù)倍,非際內(nèi)容部分則充填為 0。但是在UNIX中,對(duì)于二進(jìn)制文件SEEK_END是得到支持的。對(duì)于文本文件,它們的文件當(dāng)前位置可能不簡單的字節(jié)位移量來度量。再一次,這主要也是在非 U N I X系統(tǒng)中,它們可能以不同的格式存放文本文件。為了定位一個(gè)文本文件, whence一定要是SEEK_SET,而且offset只 有兩種值: 0(表示反繞文件至其起始位置),或是對(duì)該文件的fl所返回的值。使用rewind函數(shù)也可將一個(gè)流設(shè)置到文件的起始位置。正如已提及的,下列兩個(gè)數(shù)是C標(biāo)準(zhǔn)新引進(jìn)的。# i n c l ud ef g e t( F I LEfp ,* f_ t) ;f s e t( F I L

40、Efp ,* c on s tf_ t) ;兩個(gè)函數(shù)返回:若成功則為0,若出錯(cuò)則為非0fget將文件位置指示器的當(dāng)前值存入由指向的對(duì)象中。在以后調(diào)用fset時(shí),可以使用此值將流重新定位至該位置。1035.11格式化I/O5.11.1 格式化輸出執(zhí)行格式化輸出處理的是三個(gè)prf函數(shù)。# i n c l u d ep rf( c on s t c h a rform*at ,. . . ) ;f p rf ( F ILE fp* , c on s t c h a r for*mat , . . . ) ;兩個(gè)函數(shù)返回:若成功則為輸出字符數(shù),若輸出出錯(cuò)則為負(fù)值s p rf ( c h a r b*u

41、f , c on s t c h a r for*mat , . . . ) ;返回:存入數(shù)組的字符數(shù)prf將格式化數(shù)據(jù)寫到標(biāo)準(zhǔn)輸出,fprf寫至指定的流 sprf將格式化的字符送入數(shù)組buf中sprf在該數(shù)組的尾端自動(dòng)加一個(gè)null字節(jié),但該字節(jié)不包括在返回值中。對(duì)這三個(gè)函數(shù)可能使用的各種格式變換,請(qǐng)參閱UNIX手冊,或Kernighan和Ritchie1988的附錄B。下列三種prf族的變體類似于上面的三種,但是可變參數(shù)表(.)代換成了arg。# i n c l u d e # i n c l u d e vp rf( c on s t c h a rform* at , v a _ l

42、i s t arg ) ;v f p rf ( F I LEfp ,* c on s t c h a r for*mat ,v a _ l i s t arg ) ;兩個(gè)函數(shù)返回:若成功則為輸出字符數(shù),若輸出出錯(cuò)則為負(fù)值v s p rf ( c h a rb*uf ,c o n s t c h a r for*mat , v a _ l i s t arg ) ;返回:存入數(shù)組的字符數(shù)在附錄B的出錯(cuò)例程中,將使用vsprf函數(shù)。關(guān)于ANSI C標(biāo)準(zhǔn)中有關(guān)可變長度參數(shù)表的詳細(xì)說明請(qǐng)參閱 Kernighan和Ritchie1988的 7.3節(jié)。應(yīng)當(dāng)了解的是,由ANSI C提供的可變長度參數(shù)表例程(

43、 頭文件和相關(guān)的例程)與由SVR3(以及更早版本)和4.3BSD提供的例程是不同的。5.11.2 格式化輸入執(zhí)行格式化輸入處理的是三個(gè)scanf函數(shù)。4.3BSD定義sprf返回其第一個(gè)參數(shù)(緩存指針,類型為 char* ),而不是一個(gè)整型。ANSI C要求sprf返回一個(gè)整型。注意, sprf可能會(huì)造成由buf指向的緩存的溢出。保證該緩存有足夠長度是調(diào)用者的責(zé)任。104# i n c l u d e s ca n f( c on s t c h a rform*at , . . . ) ;f s ca n f( F I LE fp*,c on s t c h a r for*mat , .

44、. . ) ;s s c a n f ( c o n s t c h a r b*uf , c on s t c h a r for*mat , . . . ) ;三個(gè)函數(shù)返回:指定的輸入項(xiàng)數(shù),若輸入出錯(cuò),或在任意變換前已至文件 端則為 E O F如同prf族一樣,關(guān)于這三個(gè)函數(shù)的各個(gè)格式選擇項(xiàng)的詳細(xì)情況,請(qǐng)參閱UNIX手冊。5.12實(shí)現(xiàn)細(xì)節(jié)正如前述,在UNIX中,標(biāo)準(zhǔn)I/O庫最終都要調(diào)用第3章中說明的I/O例程。每個(gè)I/O流都有一個(gè)與其相關(guān)聯(lián)的文件描述符,可以對(duì)一個(gè)流調(diào)用fileno以獲得其描述符# i n c l ud e f i l e no ( F I LE fp*) ;返回:與該流相

45、關(guān)聯(lián)的文件描述符如果要調(diào)用dup或fcntl等函數(shù),則需要此函數(shù)為了了解你所使用的系統(tǒng)中標(biāo)準(zhǔn) I/O庫的實(shí)現(xiàn),最好從頭文件開始。從中可以看到:FILE對(duì)象是如何定義的,每個(gè)流標(biāo)志的定義,定義為宏的各個(gè)標(biāo)準(zhǔn) I/O例程(例如getc)。 Kernighan和Ritchie1988中的8.5節(jié)含有一個(gè)簡單的實(shí)現(xiàn),從中可以看到很多UNIX實(shí)現(xiàn)的基本樣式。Plauger1992的第12章提供了標(biāo)準(zhǔn)I/O庫一種實(shí)現(xiàn)的全部源代碼。4.3BSD中標(biāo)準(zhǔn) I/O庫的實(shí)現(xiàn)(由Chris Torek編寫)也是可以公開使用的。實(shí)例程序5-3為三個(gè)標(biāo)準(zhǔn)流以及一個(gè)與一個(gè)普通文件相關(guān)聯(lián)的流打印有關(guān)緩存狀態(tài)信息。注意,在打印

46、緩存狀態(tài)信息之前,先對(duì)每個(gè)流執(zhí)行 I/O操作,為第一個(gè)I/O操作通常就造成為該流分配緩存。結(jié)員_flag、_bufsiz以及常數(shù)_IONBF和_IOLBF是由作者所使用的系統(tǒng)定義的。如果運(yùn)行程序5-3兩次,一次使三個(gè)標(biāo)準(zhǔn)流與終端相連接,另一次使它們重定向到普通文件,則所得結(jié)果是$ a . o u te n t e r a ny c h a r ac t e rstdin, stdout 和stderr 都連至終端鍵入新行符on e l i n et o s t a nd a r de rr o rs t r e am s t r e am s t r e ams t r e am=s t d

47、i n , l i n e b u f f e r e d , b u f f e r s i z e = 1 2 8 s t d o u t , l i n e b u f f e r e d , b u f f e r s i z e = 1 2 8 s t d e r r , u n b u f f e r e d , b u f f e r s i z e = 8/ e t c /m o t d , f u l l y b u f f e r e d , b u f f e r s i z e = 8 1 9 2/ e t c / t e rm c a p s t d . o u t

48、2 s t d . e r r三個(gè)流都重定向,再次運(yùn)行該程序$ a . o u t $ c a t s t d . e r ron e l i n e t o s t a nd a r d e rr o r$ c a t s t d . o u te n t e r a ny c h a r ac t e rs t r eam = s t d i n ,f u l l y bu f f e r e d , bu f f e r s i ze = 8192 105s t r e am s t r e ams t r e am=s t d o u t , f u l l y b u f f e r

49、 e d , b u f f e r s i z e = 8 1 9 2s t d e r r , u n b u f f e r e d , b u f f e r s i z e = 8/ e t c /m o t d , f u l l yb u f f e r e d , b u f f e r s i z e = 8 1 9 2程序5-3對(duì)各個(gè)標(biāo)準(zhǔn)I/O流打印緩存狀態(tài)信息從中可見,該系統(tǒng)的默認(rèn)是:當(dāng)標(biāo)準(zhǔn)輸入、輸出連至終端時(shí),它們是行緩存的。行緩存的長度是128字節(jié)。注意,這并沒有將輸入、輸出的行長限制為 128字節(jié),這只是緩存的長度。如果要將512字節(jié)的行寫到標(biāo)準(zhǔn)輸出則要進(jìn)行四次wr

50、ite系統(tǒng)調(diào)用。當(dāng)將這兩個(gè)流重新定向到普通文件時(shí),它們就變成是全緩存的,其緩存長度是該文件系統(tǒng)優(yōu)先選用的 I/O長度(從s 結(jié)構(gòu)中得到的st_blksize)。從中也可看到,標(biāo)準(zhǔn)出錯(cuò)如它所應(yīng)該的那樣是非緩存的,而普通文件按系統(tǒng)默認(rèn)是全緩存的。5.13臨時(shí)文件標(biāo)準(zhǔn)I/O庫提供了兩個(gè)函數(shù)以幫助創(chuàng)建臨時(shí)文件。# i n c l u d e c h a r * t mpn am ( c h a rptr*) ;返回:指向一唯一路徑名的指針106F ILE * tm p f i l e ( v o i d ) ;返回:若成功則為文件指針,若出錯(cuò)則為NU L Ltmpnam產(chǎn)生一個(gè)與現(xiàn)在文件名不同的一個(gè)有

51、效路徑名字符串。每次調(diào)用它時(shí),它都產(chǎn)生一個(gè)不同的路徑名,最多調(diào)用次數(shù)是TMP_MAX。TMP_MAX定義在中。若ptr是NULL,則所產(chǎn)生的路徑名存放在一個(gè)靜態(tài)區(qū)中,指向該靜態(tài)區(qū)的指針作為函數(shù)值返回。下一次再調(diào)用tmpnam時(shí),會(huì)重寫該靜態(tài)區(qū)。(這意味著,如果調(diào)用此函數(shù)多次,而且想保存路徑名,則應(yīng)當(dāng)保存該路徑名的副本,而不是指針的副本。)如若ptr不是NULL,則認(rèn)為它指向長度至少是L_tmpnam個(gè)字符的數(shù)組。(常數(shù)L_tmpnam定義在頭文件中。)所產(chǎn)生的路徑名存放在該數(shù)組中, ptr也作為函數(shù)值返回。tmpfile創(chuàng)建一個(gè)臨時(shí)二進(jìn)制文件(類型 wb+),在關(guān)閉該文件或程序結(jié)束時(shí)將自動(dòng)刪除

52、這種文件。注意, UNIX對(duì)二進(jìn)制文件不作特殊區(qū)分。實(shí)例程序5-4說明了這兩個(gè)函數(shù)的應(yīng)用。若執(zhí)行程序5-4,則得:$ a . o u t/ u s r / t m p / a a a a 0 0 4 7 0/ u s r / t m p / b a a a 0 0 4 7 0 on el i n e o f ou t pu t加到臨時(shí)文件名中的5位數(shù)字后綴是進(jìn)程ID,這就保證了對(duì)各個(gè)程產(chǎn)生的路徑名各不同。tmpfile函數(shù)經(jīng)常使用的標(biāo)準(zhǔn)UNIX技術(shù)是先調(diào)用tmpnam產(chǎn)生一個(gè)唯一的路徑名,然后立即 unlink它。程序5-4 tmpnam和tmpfile函數(shù)實(shí)例雖然TMP_MAX是由ANSI

53、C定義的。但該C標(biāo)準(zhǔn)只要求其值至少應(yīng)為25。但是,XPG3卻要求其值至少為10 000。在此最小值允許一個(gè)實(shí)現(xiàn)使用 4位數(shù)字作為臨時(shí)文件名的同時(shí)(00009999),大多數(shù)UNIX實(shí)現(xiàn)使用的卻是大、小寫字符。107請(qǐng)回憶4.15節(jié),對(duì)一個(gè)文件解除連接并不刪除其內(nèi)容,關(guān)閉該文件時(shí)才刪除其內(nèi)容。tempnam是tmpnam的一個(gè)變體,它允許調(diào)用者為所產(chǎn)生的路徑名指定目錄和前綴。# i n c l ud e c h a r* t empn am ( c on s t c hdairrecto*ry , c on s t c h a r pr*efix ;返回:指向一唯一路徑名 指針對(duì)于目錄有四種不同

54、的選擇,并且使用第一個(gè)為真的作為目錄:如果定義了環(huán)境變量TMPDIR,則用其作為目錄。(在7.9節(jié)中將說明環(huán)境變量 )如果參數(shù)directory非NULL,則用其作為目錄。將中的字符串P_tmpdir用作為目錄。將本地目錄,通常是/tmp,用作為目錄。如果prefix非NULL,則它應(yīng)該是最多包含5個(gè)字符的字符串,用其作為文件名的頭幾個(gè)字符。該函數(shù)調(diào)用malloc函數(shù)分配動(dòng)態(tài)區(qū),用其存放所構(gòu)造的路徑名。當(dāng)不再使用此路徑名時(shí)就可此區(qū)(7.8節(jié)將說明malloc和fiee函數(shù))。實(shí)例程序5-5顯示了tempnam的應(yīng)用。程序5-5 tempnam函數(shù)的應(yīng)用注意,如果命令行參數(shù)(目錄或前綴)中的任一一個(gè)以空白開始,則將其作為送給該函數(shù)。下面顯示使用該程序的各種方式。null指針傳$ a

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(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)論