写一个程序,统计本身C语言共写了多少行代码。ver2.00

概要

完成一个程序,做用是统计一个文件夹下面全部文件的代码行数。输入是一个文件夹的绝对路径,输出是代码行数。因此此程序的新特色有两个:html

  1. 统计某一文件夹下的全部文件;
  2. 能够任意指定本机硬盘上任何位置的某一个文件夹。

前言

上一篇随笔中熟悉了文件的基本操做。但仍然有改进的余地:统计特定文件时,仍是须要手动输入文件名。若是文件数量不少怎么办?可不能够直接统计某个文件夹下面的全部文件的代码行数?今天解决的就是这个问题。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的工做已经完成。如今已经有了存储文件名字符串的文本文件,下面只须要从这些文件中读取文件名,再调用上一篇随笔中实现的功能,便可实现此次须要添加的新功能了。

实现的简单的从list.txt中读取文件名。打开文件进行行数统计:

#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文件进行测试,看看运行结果如何:

我以为代码意思都很明了了,然而执行结果仍是失败的。

仔细观察结果,发现几个奇怪的点。

  • .c文件是没问题的,统计代码行数的几行代码是由上一个版本引进的因此也应该是没问题的,可是结果倒是0;
  • 输出中有多余的空行

找到问题所在了!因为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

最后,固然就是有什么错误,或者是有疑惑的地方均可以跟我说哦!

相关文章
相关标签/搜索