首页 > 解决方案 > 遍历文件目录试图计算 C 中具有特定扩展名的文件中的行数

问题描述

我正在尝试遍历文件系统树。当我遇到具有特定扩展名的文件时,我想打开该文件,然后计算文件中的行数。似乎我遇到了分段错误,我相信它是在我打开文件并尝试计算行数之后/时。任何有关为什么这是段错误的帮助将不胜感激。

编辑:我已经删除了旧代码,因为我修复了段错误。现在我更改了要在命令行中输入的数据。但似乎文件没有打开,或者没有正确计算行数,因为当我运行它时,程序总是返回 0 行。

这是更新的代码:

#include <unistd.h>
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>

const char *get_filename_ext(const char *filename) {
    const char *dot = strrchr(filename, '.');
    if(!dot || dot == filename) return "";
    return dot + 1;
}

int printdir(char *dir, char *targetFileExt, int depth)
{
    DIR *dp;
    struct dirent *entry;
    struct stat statbuf;
      int spaces = depth*4;
    int totalLines=0;

    if((dp = opendir(dir)) == NULL) {
        fprintf(stderr,"cannot open directory: %s\n", dir);
        return -1;
    }
    chdir(dir);
    while((entry = readdir(dp)) != NULL) {
        lstat(entry->d_name,&statbuf);
        if(S_ISDIR(statbuf.st_mode)) {
            /* Found a directory, but ignore . and .. */
            if(strcmp(".",entry->d_name) == 0 || strcmp("..",entry->d_name) == 0){
                continue;
            }
            printf("%*s%s/\n",spaces,"",entry->d_name);
            /* Recurse at a new indent level */
            totalLines = printdir(entry->d_name, targetFileExt, depth+1);
        }
        else {
          printf("%*s%s\n",spaces,"",entry->d_name);

          char *currentFileExt = get_filename_ext(entry->d_name);

          if(*currentFileExt == *targetFileExt){
            //open the file for reading
            FILE *fPtr = fopen(entry->d_name, "r");

            //traverse the file
            while(!feof(fPtr)){
              //if there is a new line character
              int temp = fgetc(fPtr);
              if(temp=='\n'){
                //add a line to the total amount of lines
                totalLines++;
              }
            }

            //close the file
            fclose(fPtr);
            fPtr=NULL;
          }
        }
    }
    chdir("..");
    closedir(dp);

    return totalLines;
}

int main(int argc, char* argv[])
{
    char *topdir, pwd[2]=".";
    char *ext;
    if (argc < 2 || argc > 3)
        topdir=pwd;
    else if(argc == 2){
      topdir=argv[1];
    }
    else if(argc == 3){
      topdir=argv[1];
      ext=argv[2];
    }

    printf("Directory scan of %s\n",topdir);
    int lines = printdir(topdir, ext, 0);
    printf("You have written %d lines of %s code!\n", lines, ext);

    return 0;
}

标签: cfilesystems

解决方案


首先,文件扩展名检查:if(*currentFileExt == *targetFileExt)仅适用于具有单个字符的文件扩展名。考虑搜索“.com”,您会遇到一个“.c”文件。get_filename_ext()将返回指向点后第一个字符的指针。然后你会比较'c' == 'c'。考虑strcmp()改用,并确保targetFileExt不包含前导点,因为这是您的代码按原样设置的方式。

其次,printdir()在其当前形式中,不会从子目录中累积行数。考虑以下场景:

  • 我们正在搜索 .c 文件。
  • 您正在搜索的目录包含两个子目录 A 和 B,仅此而已。
  • A 包含一个 10 LOC 的 .c 文件,B 包含一个 20 LOC 的 .c 文件。

运行代码时:

  1. 您调用printdir()from main(),假设您的代码首先遇到 A
  2. 该函数递归调用自身并返回 10,因此totalLines被赋值为 10。
  3. 在下一次循环迭代中,函数遇到 B。
  4. 该函数递归调用自身,返回 20,因此totalLines被赋值为 20。
  5. 您从第一次循环迭代中丢失了 10 行。

为了解决这个问题,您有三个选择:

  • 将函数签名更改为:int printdir(char *dir, char *targetFileExt, int depth, int totalLines);并删除int totalLines=0;. 在函数中调用它就像:通过为 totalLines 传递 0 来totalLines = printdir(entry->d_name, targetFileExt, depth+1, totalLines);调用它。main()

  • 更改为函数签名以接受指向行数变量的指针,并在遇到行时将其递增。(impl。留作作业)

  • 使用全局行数变量。(impl。留作作业)


推荐阅读