最近在幫媽媽寫一個(gè)類似工具箱的小程序時(shí)脖含,要用到讀取配置文件的功能窖杀。一開始用的是:fgets,一行一行地讀取再用strtok對(duì)內(nèi)容進(jìn)行分割调衰。
后來無意中看到一篇文章(文章標(biāo)題好像是《fscanf讀取一行...》在此感謝這位同學(xué))膊爪,發(fā)現(xiàn)fscanf可以直接以格式化讀取文件。
我們先看看 fscanf 函數(shù):
int fscanf(FILE*stream, constchar*format, [argument...]);
其中最重要也最難理解的是第二個(gè)參數(shù):format嚎莉。這個(gè)參數(shù)的一般用法和scanf一樣米酬,網(wǎng)上到處都是,這里不再贅述趋箩。
我們要研究的是我們的配置文件如何按格式讀取赃额,來看一個(gè)配置文件的例子:
vc6 = C:\Program Files\VC6EN\COMMON\MSDEV98\BIN\MSDEV.EXE
python = C:\python36\python.exe
這是配置文件的一般形式(注意“=”左右側(cè)有空格),根據(jù)fscanf讀取的特性:在遇到空格或換行的時(shí)候停止讀取叫确。
那我們就可以這樣讀取全部信息:
int main(int argc, char* argv[])
{
FILE *fpconf;
fpconf = fopen("D:\\configure", "r"); //上面的配置信息寫在這個(gè)文件里
if(!fpconf)
{
printf("讀取配置文件失斕肌!");
return 1;
}
struct json
{
char key[256];
char value[256];
};
struct json myconf;
int index = 1;
while(!feof(fpconf))
{
memset(&myconf, 0, sizeof(myconf));
fscanf(fpconf, "%s = %s", myconf.key, myconf.value); //這里注意 “=” 左右要有空格
printf("第%d個(gè)應(yīng)用程序:%s, 路徑:%s\n", index, myconf.key, myconf.value);
index++;
}
if(fpconf)
fclose(fpconf);
return 0;
}
運(yùn)行結(jié)果:
可以看到竹勉,這明顯不是我們想要的結(jié)果飞盆。這是為什么呢,還是那個(gè)原因:在遇到空格或換行的時(shí)候停止讀取次乓。
因?yàn)榈谝粋€(gè)應(yīng)用程序的路徑中:C:\Program (這里有空格)Files\VC6EN\COMMON\MSDEV98\BIN\MSDEV.EXE吓歇,fscanf函數(shù)在這里停止了,把后面的內(nèi)容作為下一行來讀取票腰,所以出現(xiàn)了這樣的結(jié)果城看。
那么我們應(yīng)該怎么辦呢?這里要用到一個(gè)類似正則式的寫法:
...
fscanf(fpconf, "%s = %[^\n]", myconf.key, myconf.value); //這里注意 “=” 左右要有空格
...
結(jié)果:
可以看到杏慰,這里就是我們想要的運(yùn)行結(jié)果了测柠。
%[^\n]這是個(gè)什么東西呢?其實(shí)他類似于正則中的匹配逃默,意思是:不遇到“\n”就一直讀取鹃愤,那"\n"我們都知道簇搅,就是“換行”完域,而空格不是換行,所以就會(huì)把空格也讀取進(jìn)來瘩将,而不是遇到空格停止讀取吟税。
根據(jù)上面的功能引申一下:我們寫好程序凹耙,而其它人不知道編寫配置文件的規(guī)則,不知道要在 = 號(hào)兩邊加空格肠仪,而寫成這樣了:
vc6=C:\Program Files\VC6EN\COMMON\MSDEV98\BIN\MSDEV.EXE
python=C:\python36\python.exe
那會(huì)發(fā)生什么呢肖抱?我們來看看運(yùn)行結(jié)果:
這明顯不是我們想要的。那我們又應(yīng)該怎么辦呢异旧?
首先我們分析一下配置文件的結(jié)構(gòu):
=號(hào)左側(cè)是一個(gè)字符串
=號(hào)右側(cè)也是一個(gè)字符串
所以它一定是用=號(hào)來分隔意述,根據(jù):不遇到XX就一直讀取這一原則,我們應(yīng)該把讀取格式寫成:
fscanf(fpconf, "%[^=] = %[^\n]\n", myconf.key, myconf.value); //這里注意 “=” 左右要有空格
結(jié)果:
這就是我們想要的了吮蛹。
這句話分成兩個(gè)部分來理解:
- %[^=] 理解為不遇到 = 號(hào)就一直讀然绯纭;
- %[^\n] 理解為不遇到換行就一直讀瘸闭搿(空格也讀仁趸纭)。
那為什么 %[^=] 之后還有一個(gè) = 號(hào)呢每篷?那是因?yàn)榘昶荩灰獩]有寫在“格式”中的字符或字符串,fscanf都會(huì)理解為是程序員想要的內(nèi)容焦读,并將其讀取到我們的變量中子库,所以如果我們不想要 = 這個(gè)字符,就要把它寫上吨灭,避免被讀取進(jìn)我們要的內(nèi)容中刚照。
到這里,這篇文章就寫完了喧兄,如果后續(xù)還有好玩的用法无畔,再更新。