c++ - 递归目录和文件流以及搜索字符串

标签 c++ c recursion directory

我对 walkThroughFunction 中的递归调用有疑问。 该代码应该遍历目录并计算子目录,如果找到文件,则应打开该文件并搜索特定字符串。 该代码仅遍历一个目录。有人可以帮我弄这个吗。你会发现牙套有点错位。请忽略这些。

int directories=0;
void walkThroughDirectory(char *directory_name,char  *searchString){

DIR * directory;
struct dirent * walker;
char d_name[PATH_MAX];
int path_length;
char path[PATH_MAX];
directory=opendir(directory_name);
if(directory==NULL){
    cout<<"Error"<<endl;
    cout<<directory_name<<"  Cannot be Opened"<<endl;
    exit(10000);
}
while((walker=readdir(directory)) !=NULL){




    strcpy(d_name,walker->d_name);
    cout<<directory_name<<"/"<<endl;
    if (strcmp (d_name, "..") == 0 &&
            strcmp (d_name, ".") == 0){
        continue;
    }
    else{


        path_length =      snprintf(path,PATH_MAX,"%s/%s\n",directory_name,d_name);
        cout<<"HELLO"<<endl;
        cout<<path<<endl;
        if (path_length >= PATH_MAX){
            cout<<"Path is too long"<<endl;
            exit (1000);
        }
        if(walker->d_type==DT_DIR){
            cout<<"Hello"<<endl;
            directories++;
            walkThroughDirectory (path,searchString);
        }
        else if(walker->d_type==DT_REG){   
            ifstream openFile;
            openFile.open(path);
            char line[1500];
            int currentLine = 0;
            if (openFile.is_open()){
                while (openFile.good()){
                    currentLine++;
                    openFile.getline(line, 1500);
                    if (strstr(line, searchString) != NULL)
                        cout<<path<<": "<<currentLine<<": "<<line<<endl;
                }
            }
            openFile.close();    
        }
        /*
        struct stat directory_stat;
        if (stat(path, &directory_stat) == -1){

            return;
        }
        if (S_ISDIR(directory_stat.st_mode)){
            cout<<"HELLO"<<endl;

            directories++;
            walkThroughDirectory(path, searchString);
        } 
        else if (S_ISREG(directory_stat.st_mode)){

            ifstream openFile;
            openFile.open(path);
            char line[1500];
            int currentLine = 0;
            if (openFile.is_open()){
                while (openFile.good()){
                    currentLine++;
                    openFile.getline(line, 1500);
                    if (strstr(line, searchString) != NULL)
                        cout<<path<<": "<<currentLine<<": "<<line<<endl;

                }

            }
            // it's a file so search for text in file

        }
        */

    }

}

if (closedir (directory)) 
{
    cout<<"Unable to close  "<<directory_name<<endl;
    exit (1000);
}
}

int main(){

    char * name;
    name=new char;

    cout<<"Total Directories  "<< directories<<endl;



    name=get_current_dir_name();
    cout<<"Current Directory is:  "<<name<<endl;
    /*
    cout<<"Now Enter The Desired Directory from the root or the current path"<<endl;
    char *desiredDirectory;
    desiredDirectory=new char;
    cin>>desiredDirectory;
    cout<<"Enter The String You want to search"<<endl;
    char *searchString;
    searchString=new char;
    cin>>searchString;
    */
    char ourpath[400];
    strcpy(ourpath,name);

    walkThroughDirectory(ourpath,"diminutive");
    cout<<"Total Directories  "<< directories<<endl;


    return 0;
}

最佳答案

这段代码有几个问题。首先,当您执行 strcmp 时检查 d_name 是否为“.”或“..”,您需要使用 OR,而不是 AND。其次,当您调用 sprintf 创建 C 字符串路径时,字符串末尾不应有换行符。这就是导致您的代码只深入一层的原因。第三,当您调用get_current_dir_name时,它会为您完成所有malloc工作。您所做的是为单个字符分配空间,这本身不起作用,并且不是 API 的正确使用。请参阅man page for get_current_dir_name .

下面的代码解决了这些问题(并且也有适当的缩进)。

#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <limits.h>
#include <string.h>

int directories=0;
void walkThroughDirectory(char *directory_name,char *searchString)
{
    DIR *directory;
    struct dirent *walker;
    char d_name[PATH_MAX];
    int path_length;
    char path[PATH_MAX];
    directory = opendir(directory_name);

    if(directory == NULL)
    {
        std::cout << directory_name << "  Cannot be Opened" << std::endl;
        exit(1);
    }

    while((walker=readdir(directory)) != NULL)
    {
        strcpy(d_name, walker->d_name);

        // Needs to be || not &&
        if (strcmp(d_name, "..") == 0 || strcmp(d_name, ".") == 0) 
        {
            continue;
        }
        else
        {
            // No newline on the path name.
            path_length = snprintf(path, PATH_MAX, "%s/%s", directory_name, d_name);

            if (path_length >= PATH_MAX) 
            {
                std::cout << "Path is too long" << std::endl;
                exit(2);
            }

            if(walker->d_type == DT_DIR)
            {
                directories++;
                walkThroughDirectory(path, searchString);
            }
            else if(walker->d_type==DT_REG)
            {
                std::ifstream openFile;
                openFile.open(path);
                char line[1500];
                int currentLine = 0;

                if (openFile.is_open())
                {
                    while (openFile.good())
                    {
                        currentLine++;
                        openFile.getline(line, 1500);
                        if (strstr(line, searchString) != NULL)
                        std::cout << path << ": " << currentLine << ": " << line << std::endl;
                    }
                }
                openFile.close();    
            }
        }
    }

    if (closedir(directory)) 
    {
        std::cout << "Unable to close " << directory_name << std::endl;
        exit(3);
    }
}

int main()
{
    // get_current_dir_name() mallocs a string for you.
    char *name;

    name = get_current_dir_name();
    walkThroughDirectory(name, "matthew");
    free(name);
    std::cout << "Total Directories: " <<  directories << std::endl;

    return 0;
}

关于c++ - 递归目录和文件流以及搜索字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10110055/

相关文章:

c - 如何链接到 Tcl C API 中的 tclOO 函数

c - 在 C 中声明全局多维数组

java - 排序列表递归插入方法

objective-c - 如何开始在 iOS 上使用 ARM?

c++ - 在 C++ 中递归排序(学习目的)

使用模板函数的 C++ 模板元编程

c++ - 不允许创建临时对象

c++ - 元素乘法——每三个元素

c++ - 这两种添加字符串的情况有什么区别?

c++ - 如何在CTreeCtrl/CWnd中接收ON_UPDATE_COMMAND_UI?