c - 遍历文件目录试图计算 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;
}
解决方案
首先,文件扩展名检查:if(*currentFileExt == *targetFileExt)
仅适用于具有单个字符的文件扩展名。考虑搜索“.com”,您会遇到一个“.c”文件。get_filename_ext()
将返回指向点后第一个字符的指针。然后你会比较'c' == 'c'。考虑strcmp()
改用,并确保targetFileExt
不包含前导点,因为这是您的代码按原样设置的方式。
其次,printdir()
在其当前形式中,不会从子目录中累积行数。考虑以下场景:
- 我们正在搜索 .c 文件。
- 您正在搜索的目录包含两个子目录 A 和 B,仅此而已。
- A 包含一个 10 LOC 的 .c 文件,B 包含一个 20 LOC 的 .c 文件。
运行代码时:
- 您调用
printdir()
frommain()
,假设您的代码首先遇到 A - 该函数递归调用自身并返回 10,因此
totalLines
被赋值为 10。 - 在下一次循环迭代中,函数遇到 B。
- 该函数递归调用自身,返回 20,因此
totalLines
被赋值为 20。 - 您从第一次循环迭代中丢失了 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。留作作业)
推荐阅读
- android - 如何从 onAnimationUpdate 设置可见性
- c# - 我应该如何写一个算法,它应该在彼此面前?
- linux - 想将以相同时间戳结尾的文件 tar 到单个 tar
- sharepoint - 基于多列强制执行唯一值
- vue.js - 如果 pass 或 email 错误,如何防止 nuxt auth 进入错误页面
- mariadb - 在生产站点而不是暂存站点上使用 mysql restore 出错。可以用mysql通用日志恢复吗?
- selenium - Windows 或 ubuntu 中的 Selenium Webdriver 测试(Safari)
- javascript - 如何通过不同文件中的函数重新渲染 index.js。反应
- sapui5 - 如何在 UI5 1.38 中重用来自另一个应用程序的组件?
- javascript - 如何使用 TypeScript 和 React 关闭单击按钮时的对话框?