递归目录和文件流和搜索字符串

时间:2012-04-11 16:29:03

标签: 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;
}

1 个答案:

答案 0 :(得分:0)

此代码有几个问题。首先,当您执行strcmp以检查d_name是否为“时”。或“..”,你需要使用OR,而不是AND。其次,当您调用sprintf来创建c-string path时,您不应该在字符串的末尾添加换行符。这就是导致您的代码只能达到一个深度的原因。第三,当您致电get_current_dir_name时,它会为您完成所有malloc工作。你正在做的是为一个char分配空间,这本身不会起作用,也不能正确使用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;
}