遍历文件目录尝试计算 C 中具有特定扩展名的文件中的行数
Traversing File Directory Trying to Count Lines in Files With a Specific Extension in C
我正在尝试遍历文件系统树。当我遇到具有特定扩展名的文件时,我想打开该文件,然后计算文件中的行数。看来我遇到了分段错误,我相信是 after/when 我打开文件并尝试计算行数。任何关于为什么这是段错误的帮助将不胜感激。
编辑:
我删除了旧代码,因为我修复了段错误。现在我更改了要在命令行输入的数据。但似乎文件没有打开或者它没有正确计算行数,因为当我 运行 它时程序总是 return 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()
将 return 指向点后第一个字符的指针。那么你将比较 'c' == 'c'。考虑改用 strcmp()
,并确保 targetFileExt
不包含前导点,因为这是您的代码按原样设置的方式。
其次,printdir()
目前的形式不会从子目录中累积行数。
考虑场景:
- 我们正在搜索 .c 文件。
- 您正在搜索的目录包含两个子目录,A 和 B,没有其他内容。
- A 包含一个 10 LOC .c 文件,B 包含一个 20 LOC .c 文件。
当您 运行 代码:
- 您从
main()
调用 printdir()
,假设您的代码第一次遇到 A
- 该函数递归调用自身,returns 10,因此
totalLines
被赋值为 10。
- 在下一次循环迭代中,函数遇到 B。
- 函数递归调用自身,returns 20,所以
totalLines
被赋值为20。
- 您丢失了第一个循环迭代中的 10 行。
要解决此问题,您有以下三种选择:
将函数签名更改为:int printdir(char *dir, char *targetFileExt, int depth, int totalLines);
并删除 int totalLines=0;
。在函数中这样调用它:totalLines = printdir(entry->d_name, targetFileExt, depth+1, totalLines);
从 main()
调用它,为 totalLines 传递 0。
更改函数签名以接受指向行计数变量的指针,并在遇到行时递增它。 (暗示留作作业)
使用全局行计数变量。 (暗示留作作业)
我正在尝试遍历文件系统树。当我遇到具有特定扩展名的文件时,我想打开该文件,然后计算文件中的行数。看来我遇到了分段错误,我相信是 after/when 我打开文件并尝试计算行数。任何关于为什么这是段错误的帮助将不胜感激。
编辑: 我删除了旧代码,因为我修复了段错误。现在我更改了要在命令行输入的数据。但似乎文件没有打开或者它没有正确计算行数,因为当我 运行 它时程序总是 return 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()
将 return 指向点后第一个字符的指针。那么你将比较 'c' == 'c'。考虑改用 strcmp()
,并确保 targetFileExt
不包含前导点,因为这是您的代码按原样设置的方式。
其次,printdir()
目前的形式不会从子目录中累积行数。
考虑场景:
- 我们正在搜索 .c 文件。
- 您正在搜索的目录包含两个子目录,A 和 B,没有其他内容。
- A 包含一个 10 LOC .c 文件,B 包含一个 20 LOC .c 文件。
当您 运行 代码:
- 您从
main()
调用printdir()
,假设您的代码第一次遇到 A - 该函数递归调用自身,returns 10,因此
totalLines
被赋值为 10。 - 在下一次循环迭代中,函数遇到 B。
- 函数递归调用自身,returns 20,所以
totalLines
被赋值为20。 - 您丢失了第一个循环迭代中的 10 行。
要解决此问题,您有以下三种选择:
将函数签名更改为:
int printdir(char *dir, char *targetFileExt, int depth, int totalLines);
并删除int totalLines=0;
。在函数中这样调用它:totalLines = printdir(entry->d_name, targetFileExt, depth+1, totalLines);
从main()
调用它,为 totalLines 传递 0。更改函数签名以接受指向行计数变量的指针,并在遇到行时递增它。 (暗示留作作业)
使用全局行计数变量。 (暗示留作作业)