完成一個程序,做用是統計一個文件夾下面全部文件的代碼行數。輸入是一個文件夾的絕對路徑,輸出是代碼行數。因此此程序的新特色有兩個:html
在上一篇隨筆中熟悉了文件的基本操做。但仍然有改進的餘地:統計特定文件時,仍是須要手動輸入文件名。若是文件數量不少怎麼辦?可不能夠直接統計某個文件夾下面的全部文件的代碼行數?今天解決的就是這個問題。linux
咱們已經解決了一個問題:寫一個帶有文件操做的C語言程序,輸入文件名,輸出此文件下的換行數。git
考慮了一下現有的成果以及新增的目標,有須要更改的地方應該是輸入,由文件名換成一個文件夾,而後經過程序掃描一遍這個文件夾下面全部的文件。而後讀取全部的文件名,存放到數組裏。再把字符串由fopen一個個調用,統計行數。細節差很少是這樣,但總歸要先掃描文件夾吧!github
搜索引擎搜索:C語言怎麼掃描文件目錄?編程
有找到幾個連接,比較有用,能夠參考:windows
比較惋惜的是,上述網站提供的參考方法有使用函數opendir,查找了一下,發現這是一個在Linux系統下的函數。本人沒有用過Linux。想了想,並無直接開始搜索「安裝Linux教程」,我心想:總有不用這個函數的方法吧!因而依舊在搜索引擎上不斷地尋找。網站
找了接近一小時也無果,我打算換個問法。因而我在搜索引擎打入了:統計一個文件夾下文件
馬上映入我眼簾的就有一個黑科技,我驚呆了。
我馬上在桌面按照步驟進行實驗。不得不說,看到結果,我很是滿意。這不就我要的文件夾下面的全部文件名的字符串組合嘛!
馬上經過編程實現這一功能,效果拔羣。
#include<stdio.h> int main() { FILE *fp; fp = fopen("TEXT.bat","w"); fputs("DIR *.* /B> LIST.TXT",fp); fclose(fp); return 0; }
這裏面有一行神祕的操做碼,
DIR *.* /B> LIST.TXT
問題來了,這一行代碼究竟是什麼呢?仍是搜索引擎幫助你:)
大概知道了:
dir 顯示目錄中的文件和子目錄列表;
/B 使用空格式(沒有標題信息或摘要);
* . * (兩個星號中間一個句點)就是說顯示全部文件,文件名和擴展名沒有限制。舉例說明:若是是*.txt,則是顯示全部擴展名爲txt的文件;
最後面是字符串,很容易就知道是重定向輸出的文件名。
好了。那麼進行下一步的操做。咱們考慮到一個文件夾只統計C語言代碼的行數,因此這裏我考慮只對.c後綴的文件進行這種操做。
#include<stdio.h> int main() { FILE *fp; fp = fopen("Text.bat","w"); fputs("DIR *.c /B> list.txt",fp); fclose(fp); fp=fopen("Text.bat","r"); fclose(fp); return 0; }
這兒遇到了第一個問題,運行可執行文件main.exe以後,文件夾內的文件狀況以下圖:
沒有產生預期想要得到的文本文件list.txt。看來問題出在:
fp = fopen("Text1.bat","r");
這行語句上。由於,已經正常生成.bat文件,而且雙擊運行的話仍是能生成文本文件,說明.bat文件沒有問題,應該是打開文件的方式有問題。
馬上搜索:c語言打開bat文件。獲得解決方法:
在程序中使用system() 函數。
假設bat文件的名稱叫a.bat 即:
system("a.bat");
經過搜素來的方法,輕鬆解決這個問題。
#include<stdio.h> int main() { FILE *fp; fp = fopen("Text.bat","w"); fputs("DIR *.c /B> list.txt",fp); fclose(fp); system("Text.bat"); return 0; }
編譯後運行結果:
獲得了咱們想要的list.txt。也就是說.bat文件被正確地執行了。生成LIST的工做已經完成。如今已經有了存儲文件名字符串的文本文件,下面只須要從這些文件中讀取文件名,再調用上一篇隨筆中實現的功能,便可實現此次須要添加的新功能了。
#include<stdio.h> #include<Windows.h> #include<string.h> int main() { FILE *fp; fp = fopen("Text.bat","w"); fputs("DIR *.c /B>list.txt",fp); fclose(fp); system("Text.bat"); /*~~~the end of creating file name list~~~*/ /*~~~the beginning of get .c file name from list~~~*/ static int count = 0; FILE *fp1, *fp2; fp1 = fopen("list.txt","r"); char s[100], singleline[1000]; while(fgets(s, 100, fp1))//get the name(one line) of a file from the list { // int len=strlen(s); // if(s[len-1]=='\n') s[len-1]='\0'; what is this? printf("%s: ",s); fp2 = fopen(s,"r");//open the correct file, according to the file name while(fgets(singleline, 1000, fp2)) { count++; } printf("%d\n", count); fclose(fp2); } printf("\n"); fclose(fp1); system("pause"); return 0; }
咱們先不要管帶有註釋 what is this? 的那一行代碼。
編譯後執行,此次我在可執行文件.exe的目錄下放了一些.c文件進行測試,看看運行結果如何:
我以爲代碼意思都很明瞭了,然而執行結果仍是失敗的。
仔細觀察結果,發現幾個奇怪的點。
找到問題所在了!因爲fgets函數碰到'\n'是會中止輸入的,\n留在了緩衝區,下一次fgets時會致使文件讀取失敗(我的猜測,可能有誤)因此咱們要設法處理掉這個'\n'。
思考一下,數組s是存儲文件名的。舉"C++.txt"爲例,假設形成讀入失敗的緣由是字符串後面跟了一個\n
C | + | + | . | t | x | t | \n | \0 |
---|
'\n'的位置是s[strlen(s)-1]爲此咱們經過以下代碼進行debug
int len=strlen(s); if(s[len-1]=='\n') s[len-1]='\0';
再次編譯運行,完成功能。此時距離成功已經很近了!
絕對路徑是什麼?請看下面的代碼:
FILE * fp; fp = fopen("test.txt", "r");
咱們知道fopen函數的第一個參數是一個字符串,表明文件名,這裏的"test.txt"就不是絕對路徑,而是當前文件夾下(也能夠理解爲.exe可執行程序的文件夾)的文件。若是要使用絕對路徑名,就把絕對路徑輸入進第一個參數便可。怎麼看文件夾or文件的絕對路徑呢?
很簡單,鼠標右鍵,屬性,就能夠看了。例如上圖test的文件夾的絕對路徑是E:\test
這裏有一個注意點,在代碼中操做字符串時,要想表明輸入一個反斜槓,須要輸入兩個反斜槓。你們還記得轉義字符嗎?還有就是注意輸入時要把中文輸入法關掉了。
貼上比較粗略的代碼,附贈註釋,以及執行效果圖一張:
#include<stdio.h> #include<Windows.h> #include<string.h> int main() { char filepath[1000], batpath[1010]; //the absolute path of a file folder and a .bat file. gets(filepath);//input absolute path of a file folder strcpy(batpath, filepath); strcat(batpath, "\\Text1.bat"); FILE *fp; fp = fopen(batpath, "w"); fputs("DIR *.c /B>list.txt", fp); fclose(fp); system(batpath); /*~~~the end of creating file name list~~~*/ /*~~~the beginning of get .c file name from list~~~*/ static int count = 0; FILE *fp1, *fp2; fp1 = fopen("list.txt", "r"); char s[100]; char singleline[1000]; while(fgets(s, 100, fp1))//get one line from list, each line refers to a .c file name { int len = strlen(s); if(s[len-1] == '\n') s[len-1] = '\0'; printf("%s: ", s); fp2 = fopen(s, "r"); /*~~~the beginning of counting lines of code~~~*/ while(fgets(singleline, 1000, fp2))//open the correct file, according to the file name { count++; } printf("%d\n", count); fclose(fp2); } printf("\n"); fclose(fp1); system("pause"); return 0; }
由圖片能夠看出,咱們想要的功能:輸入一個文件夾的路徑,統計文件夾下面的.c文件的代碼行數,已經實現了。
主要的工做實現原理都在上面這段代碼裏,最後要作的工做就是
稍後我會把完成版代碼推上個人github。
想了想仍是要感謝下棟哥的啓發式教學,讓我完成了一個小小的東西,雖然沒啥技術含量吧,可是也是本身獨立完成的,成就感仍是有的。
這個問題我想了一早上,到了中午卡在絕對路徑那兒,結果頭暈暈的就去睡午覺了,醒來以後才解決的。233
最後,固然就是有什麼錯誤,或者是有疑惑的地方均可以跟我說哦!