LinuxC函數(shù)Popen與fgets,feof配合使用碰到的問題
一、函數(shù)定義
二、需要包含下列頭文件
三、函數(shù)說明
popen()會調(diào)用fork()產(chǎn)生子進(jìn)程,然后從子進(jìn)程中調(diào)用/bin/sh -c來執(zhí)行參數(shù)command的指令。參數(shù)type可使用“r”代表讀取,“w”代表寫入。依照此type值,popen()會建立管道連到子進(jìn)程的標(biāo)準(zhǔn)輸出設(shè)備或標(biāo)準(zhǔn)輸入設(shè)備,然后返回一個文件指針。隨后進(jìn)程便可利用此文件指針來讀取子進(jìn)程的輸出設(shè)備或是寫入到子進(jìn)程的標(biāo)準(zhǔn)輸入設(shè)備中。此外,所有使用文件指針(FILE*)操作的函數(shù)也都可以使用,除了fclose()以外。
如果 type 為 r,那么調(diào)用進(jìn)程讀進(jìn)?command 的標(biāo)準(zhǔn)輸出。
如果 type 為 w,那么調(diào)用進(jìn)程寫到 command 的標(biāo)準(zhǔn)輸入。
四、具體使用
popen會將pwd的執(zhí)行結(jié)果讀取到文件指針fp中,fgets將指針中的結(jié)果傳到字符串?dāng)?shù)組buffer中;
五、使用中的問題
四中程序的執(zhí)行結(jié)果如下:

可以看出將pwd指令執(zhí)行的結(jié)果打印了兩次,下面分析原因:
1、當(dāng)文件指針為結(jié)束符時,feof執(zhí)行結(jié)果為非0,循環(huán)才會結(jié)束,而使用fgets去讀popen執(zhí)行結(jié)果fp中的內(nèi)容時,碰到第一個換行符\n,fgets會結(jié)束本次讀操作,此時fp還未到結(jié)束符EOF處,所以會繼續(xù)執(zhí)行循環(huán)中的內(nèi)容,在第二次讀取到EOF時就會結(jié)束循環(huán),而buffer中還是之前的內(nèi)容;
2、fgets在讀取文件指針時會將換行符\n也讀取進(jìn)去,修改代碼如下
修改后執(zhí)行結(jié)果:

六、其他注意事項(xiàng)
feof函數(shù):
feof判斷文件結(jié)束是通過讀取函數(shù)fread/fscanf等返回錯誤來識別的,故而判斷文件是否結(jié)束應(yīng)該是在讀取函數(shù)之后進(jìn)行判斷。比如,在while循環(huán)讀取一個文件時,如果是在讀取函數(shù)之前進(jìn)行判斷,則如果文件最后一行是空白行,可能會造成內(nèi)存錯誤。
fgets函數(shù):
1、從流中讀入 n-1 個字符放入 s 為起始地址的空間內(nèi)。如果在未讀滿 n-1 個字符之時,已讀到一個換行符(' ')或一個EOF(文件結(jié)束標(biāo)志),則結(jié)束本次讀操作,讀入的字符串中最后包含讀到的換行符(' ')。因此,確切地說,調(diào)用 fgets()?函數(shù)時,最多只能讀入 n-1 個字符。讀入結(jié)束后,系統(tǒng)將自動在最后加 '',并以 s 作為函數(shù)值返回。
2、每次調(diào)用,fgets都會把緩沖區(qū)的最后一個字符設(shè)為null,這意味著最后一個字符不能用來存放需要的數(shù)據(jù),所以如果有一行,含有LINE_SIZE個字符(包括換行符),要想把這行讀入緩沖區(qū),請把參數(shù)n設(shè)為LINE_SIZE+1
3、不能用fgets讀二進(jìn)制文件,因?yàn)閒gets會把二進(jìn)制文件當(dāng)成文本文件來處理,這勢必會產(chǎn)生亂碼。
4、給定參數(shù)n,fgets只能讀取n-1個字符(包括換行符),如果有一行超過n-1個字符,那么fgets返回一個不完整的行,也就是說,只讀取該行的前n-1個字符,但是,緩沖區(qū)總是以null字符結(jié)尾,對fgets的下一次調(diào)用會繼續(xù)讀該行。