錯誤報告
perror函數(shù)簡化向用戶報告特定錯誤的過程。它的原型定義于studio.h,如下:
void perror(char const *message);
如果message不是NULL并且指向一個非空的字符串舞吭,perror函數(shù)就打印出這個字符串镀梭,后面跟一個分號和一個空格餐曼,然后打印出一條用于解釋errno(標準庫函數(shù)用一個外部整型變量來保存錯誤碼)。
終止執(zhí)行
exit函數(shù)用來終止一個程序,它的原型定義于stdlib.h,如下:
void exit(int status);
status參數(shù)返回給操作系統(tǒng)颓鲜,用于提示程序是否正常完成孽水。這個值和main函數(shù)返回的整型狀態(tài)值一樣,預(yù)定義符號EXIT_SUCCESS和EXIT_FALIURE分別提示程序的終止成功還是失敗匣屡,雖然程序可以使用其他值封救,但它們的具體含義取決于編譯器。
注意這個函數(shù)沒有返回值耸采。當(dāng)exit函數(shù)結(jié)束時兴泥,程序已經(jīng)消失,所以它無處可返虾宇。
標準I/O函數(shù)庫
頭文件stdio.h包含了與ANSI函數(shù)庫的I/O部分有關(guān)的聲明搓彻。
流
就C程序而言,所有的I/O操作只是簡單地從程序移進或移出字節(jié)的事情,這些字節(jié)流便被稱為流旭贬。
流I/O總覽
I/O函數(shù)以三種基本的形式處理數(shù)據(jù):單個字符,文本行和二進制數(shù)據(jù)對于每一種都有特定的函數(shù)對他們進行處理稀轨。
??????????????????執(zhí)行字符奋刽,文本行和二進制I/O的函數(shù)
數(shù)據(jù)類型 | 輸 入 | 輸 出 | 描 述 |
---|---|---|---|
字符 | getchar | putchar | 讀扔缎场(寫入)單個字符 |
文本行 | gets | puts | 文本行未格式化的輸入(輸出) |
文本行 | scanf | printf | 格式化的輸入(輸出) |
二進制數(shù)據(jù) | fread | fwrite | 讀取(寫入)二進制數(shù)據(jù) |
打開流
fopen用于打開一個特定的文件罚攀,并把一個流和這個文件相關(guān)聯(lián)斋泄,它的原型如下:
File *fopen(char const *name,char const *mode);
參數(shù)name是打開的文件名炫掐,mode是打開文件的方式(見下表)任柜,F(xiàn)ile*類型的變量用來保存fopen的返回值宙地,并不影響哪個文件被打開。
數(shù)據(jù)格式 | 讀 取 | 寫 入 | 添 加 |
---|---|---|---|
文本 | "r" | "w" | "a" |
二進制 | "rb" | "wb" | "ab" |
如果一個文件打開是用于讀取的参袱,那么他應(yīng)該是原先已經(jīng)存在的抹蚀;
??如果一個文件打開是用于寫入的环壤,那么它原先的內(nèi)容就會被刪除郑现,如果它原先不存在,那么就創(chuàng)建一個新文件接箫;
??如果一個文件打開用于天機的文件原先并不存在那么它將被創(chuàng)建,如果它原先已經(jīng)存在辛友,那么它原先的內(nèi)容不會被刪除,無論那種情況都只能在文件的尾部寫入废累。
??freopen用于打開特定(重新打開)的文件流,它的原型如下:
File *freopen(char const *filename,char const *mode,File *stream);
最后一個參數(shù)就是要打開的流,它可能是一個先前用fopen函數(shù)打開的流震放,也可能是stdin,stdout或是stderr驼修。
關(guān)閉流
int fclose(File *f);
對于輸出流乙各,fclose函數(shù)在文件關(guān)閉前刷新緩沖區(qū)耳峦,如果它執(zhí)行成功焕毫,fclose返回零值邑飒,否則返回EOF疙咸。
字符I/O
字符輸入是由getchar函數(shù)家族執(zhí)行的撒轮,他們的原型如下:
int fgetc(File *stream);
int getc(File *stream);
int getchar(void);
這些函數(shù)都用于讀取字符题山,但它們都返回一個int型但是不是char型。
字符輸出是由putchar函數(shù)家族執(zhí)行的玖姑,它們的原型如下:
int fputc(int character,File *stream);
int putc(int character,File *stream);
int putchar(int character);
fgetc和fputc都是真正的函數(shù)客峭,但getc,putc,getchar,putchar,都是通過宏定義的舔琅。
撤銷字符I/O
函數(shù)原型如下:
int ungetc(int character,File*stream);
函數(shù)ungetc把一個先前讀入的字符返回流中备蚓,這樣它可在以后被重新讀入郊尝。
未格式化的行I/O
行I/O的執(zhí)行方式分為兩類——未格式化或格式化,這兩種形式都用于操作字符串扎即。
gets和puts家族函數(shù)的原型如下:
char *fgets(char *buffer,int buffer_size,File *stream);
char gets(char *buffer);
int fputs(char *buffer,File *stream);
int puts(char const *buffer);
fgets函數(shù)從制定的stream中讀取字符并把它們復(fù)制到buffer中谚鄙,當(dāng)它讀取到一個換行符并存儲到緩沖區(qū)之后就不在讀取闷营。
fgets函數(shù)從制定的流中讀取buffer_size字符和一個NULL字符(尾零)傻盟。
fgets函數(shù)返回它的第一個參數(shù)(執(zhí)行緩沖區(qū)的指針)娘赴,如果在未讀取任何字符就達到文件尾筝闹,fgets返回NULL关顷。
fputs函數(shù)的緩沖區(qū)必須包含一個以NULL結(jié)尾的字符串议双,所以該函數(shù)沒有字符串的長度參數(shù)平痰,這個字符串是逐字寫入的宗雇,如果它不包含一個換行符赔蒲,就不會寫入換行符。如果包含好幾個換行符欢际,所有的換行符都會被寫入损趋。
函數(shù)gets和puts幾乎和函數(shù)fgets和fputs相同浑槽,區(qū)別在于:
1.gets在讀取一行輸入時括荡,它并不在緩沖區(qū)中存儲結(jié)尾的換行符。
2.puts在寫入一個字符串時观腊,它在字符串寫入之后向輸出在添加一個換行符梧油。
格式化的I/O
scanf和printf函數(shù)家族負責(zé)格式化行的輸入與輸出儡陨。
scanf家族
scanf函數(shù)家族的原型中的省略號表示一個可變長的指針列表量淌。從輸入轉(zhuǎn)換而來的值逐個存儲到這些指針參數(shù)所指向的內(nèi)存位置胚股。
int fscanf(File *stream,char const *fomat,...);
inr scanf(char const *fomat,...);
int sscanf(char const *string,char const *format,...);
這些函數(shù)都是從輸入源讀取字符并根據(jù)format字符串個出的格式碼對他們進行轉(zhuǎn)換琅拌,fscanf的輸入源就是stream(流)进宝,scanf的輸入源就是stdin党晋,而sscanf則從第一個參數(shù)給出的字符串中讀取字符漏益。
當(dāng)格式化字符串達到末尾或者讀取的輸入不在匹配格式字符串所指定的類型事绰疤,輸入就停止轻庆,在任何一種情況下,被轉(zhuǎn)換的輸入值的數(shù)目作為函數(shù)的返回值蛾方。如果在任何輸入值被轉(zhuǎn)換之前就達到尾部桩砰,函數(shù)就返回常量值EOF。
scanf格式代碼
scanf函數(shù)家族中的format字符串可以是下列內(nèi)容:
- 空白字符——他們與輸入中的零個或多個空白符匹配煮纵,在處理過程中被忽略偏螺。
- 格式代碼——它們指定函數(shù)如何解釋接下來的輸入字符隘擎。
- 其他字符——當(dāng)任何其他字符出現(xiàn)在格式字符串中采幌,下一個輸入字符必須與他匹配震桶。如果匹配蹲姐,該輸入字符隨后被丟棄忙厌,如果不匹配逢净,函數(shù)就不在讀取直接返回。
scanf函數(shù)家族的格式字符串通常以一個%號開始,有下列內(nèi)容組成:
- 可選的星號(*)——將轉(zhuǎn)換后的值丟棄而不是存儲琼娘;
- 一個可選的寬度——限制輸入字符的個數(shù)轨奄,如果寬度未給出挨务,函數(shù)就連續(xù)輸入知道遇見輸入中的下一個空白字符丁侄;
- 一個可選的限定符——修改有些格式代碼的含義鸿摇;
- 格式代碼。
printf函數(shù)家族
printf函數(shù)家族用于創(chuàng)建格式化輸出往史。
int fprintf(File *stream,char const *format,...);
int printf(char connst *format,...);
int sprintf(char *buffer,char const *format,...);
prinnt結(jié)果輸出送到標準輸出(stdout);
fprintf可以使用任何輸出流;
sprintf把它的的結(jié)果作為一個NULL結(jié)尾的字符串存儲到指定的buffer緩沖區(qū)刷晋,而不是流;
printf家族函數(shù)的格式碼通常以%開始由下列要素組成:
- 零個或多個標志字符——修改轉(zhuǎn)換的執(zhí)行方式掏秩;
- 一個可選的最小字段——如果值的字符小于字段寬度胆筒,就對它進行填充增加長度仆救,標志決定填充使用空白還是零以及它出現(xiàn)在值得左邊還是右邊;
- 一個可選的精度——指定將出現(xiàn)結(jié)果中的最小的數(shù)字個數(shù)并覆蓋零標志,精度缺省為零征懈;
- 一個可選的修改字符;
- 轉(zhuǎn)換類型揩悄;
二進制I/O
??把數(shù)據(jù)寫入到文件效率最高的是二進制形式寫入卖哎。二進制輸出避免了在數(shù)值轉(zhuǎn)換成字符串過程的所涉及的開銷和精度損失。
??fread函數(shù)用于讀取二進制數(shù)據(jù),fwrite函數(shù)用于寫入二進制亏娜,他們的原型如下:
size_t fread(void *bffer,size_t size,sizet_cout,File *stream);
size_t fwrite(void *bffer,size_t size,sizet_cout,File *stream);
??buffer是一個指向用于保存數(shù)據(jù)的內(nèi)存位置的數(shù)據(jù)焕窝,size是緩沖區(qū)每個元素的字節(jié)數(shù),count是讀取或?qū)懭氲脑財?shù)照藻,stream是數(shù)據(jù)讀取或?qū)懭氲牧鳌?br> ??函數(shù)的返回值是實際讀取或?qū)懭氲?em>元素數(shù)目袜啃。
刷新或定位函數(shù)
- 函數(shù)fflush——它迫使一個輸出流的緩沖區(qū)內(nèi)的數(shù)據(jù)進行物理寫入,不管它是否已經(jīng)寫滿幸缕,原型如下:
int fflush(File *stream);
??當(dāng)我們需要立即把數(shù)據(jù)緩沖區(qū)的內(nèi)容吳莉莉?qū)懭霑r群发,就可以使用這個函數(shù)。
C語言支持隨機I/O发乔,也就是以任意的順序訪問文件中的不同位置熟妓,隨機訪問時通過在讀取或?qū)懭肭岸ㄎ坏轿募兴枰奈恢脕韺崿F(xiàn)的,ftell和fseek函數(shù)來實現(xiàn)這項操作栏尚。
long ftell(File *stream);
int fseek(File *stream,long offset,int from);
ftell函數(shù)返回當(dāng)前流的位置起愈,也就是說,下一個讀取或?qū)懭雽⒁_始的位置距離文件起始位置的偏移量译仗。
ftell函數(shù)的返回值總是可以作為函數(shù)fseek的參數(shù)抬虽,作為一個距離文件起始位置的偏移量。
函數(shù)fseek允許你在一個流中定位纵菌,這項操作將改變下一個讀取或?qū)懭氲奈恢貌郏牡诙谌齻€參數(shù)如下表。
數(shù)據(jù)格式 | 你將定位到的是 |
---|---|
SEEK_SET | 從流的起始位置起offset個字節(jié)咱圆,offset必須是一個非負值 |
SEEK_CUR | 從流的當(dāng)前位置起offset個字節(jié)笛辟,offset可正可負 |
SEEK_END | 從流的尾部位置起offset個字節(jié),offset可正可負序苏,如果是正直將定位到文件尾的后面 |
改變緩沖方式
??在流上的緩沖凡是有時候并不適合手幢,下面兩個函數(shù)可以改變流的緩沖方式,這兩個函數(shù)只有當(dāng)指定的流被打開還沒有在它上面執(zhí)行任何操作時才能夠被調(diào)用忱详。
void setbuf(File *stream,char *buf);
int setvbuf(File *stream,char *buf,int mode,size_t size);
setbuf函數(shù)設(shè)置了一個數(shù)組围来,用于對流進行緩沖。這個數(shù)組的長度必須是BUFSIZE(它在stdio中定義)如果以一個NULL參數(shù)調(diào)用這個函數(shù)匈睁,setbuf會將這個流關(guān)閉管钳。
setvbuf函數(shù)中的mode參數(shù)用于指定緩沖類型,_IOFBF指定一個完全緩沖流软舌,_IONBF指定一個不緩沖的流,_IOLBF指定一個行緩沖流(當(dāng)一個換行符寫入到緩沖區(qū)時牛曹,緩沖區(qū)就進行刷新)
文件操縱函數(shù)
??有兩個函數(shù)用于操縱文件但不執(zhí)行任何輸入/輸出操作佛点,執(zhí)行成功函數(shù)返回值為零,如果失敗返回非零。
int remove(char const *filename);
int rename(char const *oldname,char const *newname);
函數(shù)remove用于刪除一個指定的文件呢超营,文件處于打開狀態(tài)鸳玩,其結(jié)果取決于編譯器。
函數(shù)rename用于重命名文件名演闭。