C opendir()没有打开目录?

时间:2018-04-27 21:00:59

标签: c file opendir

我不是所有在C中都有过的,但是在我的某个课程中有一个作业,而且我在打开一个目录时遇到了一些问题。

该计划的目的是(转述):

  1. 如果未提供标志或目录,请列出当前目录中文件的名称。
  2. 如果提供了标志(-l),请列出有关每个文件的更多信息。
  3. 如果提供了标志和目录,请转到该目录并列出该目录中每个文件(或目录)的信息。没有必要通过子目录进行递归。
  4. 它不需要处理只获取目录但没有标记或无效目录。这是更多的概念验证。

    我设法满足第1部分和第2部分,但第3部分不断破坏,给出了分段错误。

    我的代码如下:

    void recursedirect(char* flag, char* directory)
    {
        DIR* dir;
        struct dirent *entry;
    
        printf("Flag: %s\nDirectory: %s\n\n", flag, directory);
    
        if (flag == NULL)
        // No flag provided, therefore only do file names.
        {
            dir = opendir(".");
            entry = readdir(dir);
    
            while (entry != NULL) 
            {
                printf ("%s\n", entry->d_name);
                entry = readdir(dir);
            }
        }
        else if (strcmp(flag, "-l") == 0 && directory == NULL)
        // No directory provided, but flag provided
        {
            dir = opendir(".");
            entry = readdir(dir);
    
            while (entry != NULL) 
            {
                fileinfo(directory);
                entry = readdir(dir);
            }   
        }
        else if (strcmp(flag, "-l") != 0)
        {
            printf("Invalid flag.\n");
        }
        else
        // A directory is provided
        {
            dir = opendir(directory);
    
            if (dir != NULL)
            {
                entry = readdir(dir);
    
                while (entry != NULL) 
                {
                    fileinfo(directory);
                    entry = readdir(dir);
                }   
            }
            else
                printf("Something went wrong. It might be an invalid filename.\n");
        }
    }
    

    具体来说,最后的else语句给了我麻烦。我试过给它任何我能想到的文件路径,硬编码和其他方式,它仍然给我带来问题。我猜它很简单,但我没有足够的经验知道它是什么。

    fileinfo是一个打印出DIRdirent作为参数的文件信息的函数。但是,该错误肯定不是我能说的最好的代码。

    编辑:我犯了不分享一切的错误。我的主要方法很简单。

    int main (int argc, char** argv)
    {
        char* flag = argv[1];
        char* directory = argv[2];
    
        recursedirect(flag, directory);
    }//main
    

    它包括以下内容:

    #include <dirent.h>
    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <time.h>
    #include <fcntl.h>
    

    fileinfo函数如下(稍微编辑,因为我意识到我不再需要给它DIR *dir的参数):

    void fileinfo(struct dirent *entry)
    {
        struct stat fileStats;
        stat(entry->d_name, &fileStats);
    
        printf("File Name: %s\n", entry->d_name);
        printf("File Size: %d bytes\n", (int) fileStats.st_size);
        printf("Number of Blocks: %d\n", (int) fileStats.st_blocks);
        printf("Number of Links/References: %d\n", (int) fileStats.st_nlink);
        printf("I-Node: %d\n", (int) fileStats.st_ino);
        printf("Device ID: %d\n", (int) fileStats.st_dev);
        printf("User ID: %d\n", (int) fileStats.st_uid);
        printf("Group ID: %d\n", (int) fileStats.st_gid);
    
        stat("alphabet",&fileStats);
        printf("Time of Last Access: %s", ctime(&fileStats.st_atime));
        printf("Time of Last Modification: %s", ctime(&fileStats.st_mtime));
        printf("Time of Last Status Change: %s", ctime(&fileStats.st_ctime));
    
        stat(entry->d_name, &fileStats);
        printf("File Permissions: ");
        printf((int) (S_ISDIR(fileStats.st_mode)) ? "d" : "-");
        printf((int) (fileStats.st_mode & S_IRUSR) ? "r" : "-");
        printf((int) (fileStats.st_mode & S_IWUSR) ? "w" : "-");
        printf((int) (fileStats.st_mode & S_IXUSR) ? "x" : "-");
        printf((int) (fileStats.st_mode & S_IRGRP) ? "r" : "-");
        printf((int) (fileStats.st_mode & S_IWGRP) ? "w" : "-");
        printf((int) (fileStats.st_mode & S_IXGRP) ? "x" : "-");
        printf((int) (fileStats.st_mode & S_IROTH) ? "r" : "-");
        printf((int) (fileStats.st_mode & S_IWOTH) ? "w" : "-");
        printf((int) (fileStats.st_mode & S_IXOTH) ? "x\n\n" : "-\n\n");
    }
    

    至于对失败输入的更多说明,./files./files -l都有效。带有任何无效标志的./files按预期捕获。但是,./files -l *any valid filepath*始终失败。

    所有内容都是使用c9.io IDE中的Ubuntu 14.04.5中的gcc编译的。

    谢谢!

    编辑2:我尝试删除并放回文件,现在奇怪的是我没有收到错误。但是,现在它不会打印任何内容的完整文件信息。我会解决更多问题。

    编辑3:我已经修复了一个例外。问题是检查标志的if语句不正确。显然,IDE中出现了问题。我现在收到此错误:Couldn't open MANPATH=/home/ubuntu/.nvm/versions/node/v6.11.2/share/man:/usr/local/rvm/rubies/ruby-2.4.0/share/man:/usr/local/man:/usr/local/share/man:/usr/share/man:/usr/local/rvm/man

    看起来这不是代码,并且在某种程度上是c9服务器的问题。我尝试过为源代码和已编译的代码文件提供完全权限,重新启动工作区,然后重新启动Apache2。谢谢大家!

1 个答案:

答案 0 :(得分:3)

除了chux留下的评论之外,您还可以通过重构代码来重用类似的块。你提到你已经解决了部分1&amp; 2(由if语句中的前两个分支表示)。因此,理论上以下if块产生正确的输出。如果你简化它以便重写代码,你可能会受益。

if (flag == NULL)
// No flag provided, therefore only do file names.
{
    dir = opendir(".");
    entry = readdir(dir);

    while (entry != NULL) 
    {
        printf ("%s\n", entry->d_name);
        entry = readdir(dir);
    }
}
else if (strcmp(flag, "-l") == 0 && directory == NULL)
// No directory provided, but flag provided
{
    dir = opendir(".");
    entry = readdir(dir);

    while (entry != NULL) 
    {
        fileinfo(directory);
        entry = readdir(dir);
    }   
}

不是以这种方式编写,而是可以预先检查标记,并设置变量(在这种情况下more_file_info != 0告诉我们打印,如果标志无效,我们return。< / p>

int more_file_info = 0;
if (flag != NULL) {
    if(strcmp(flag, "-l") == 0) {
        more_file_info = 1;
    } else {
        printf("Invalid flag.\n");
        return;
    }
}

然后,您可以按如下方式简化/重构上述(可能正常工作的)代码:

void recursedirect(char* flag, char* directory)
{
    DIR* dir;
    struct dirent *entry;
    int more_file_info = 0;

    printf("Flag: %s\nDirectory: %s\n\n", flag, directory);
    // Validate argument up front
    if (flag != NULL) {
        if(strcmp(flag, "-l") == 0) {
            more_file_info = 1;
        } else {
            printf("Invalid flag.\n");
            return;
        }
    }

    // The 'directory' parameter only changes opendir, so we reflect that here
    if(directory != NULL) {
        dir = opendir(directory);
    } else {
        dir = opendir(".");
    }
    // Adding some error checking, per comment
    if(dir == NULL) {
        printf("Couldn't open %s\n", directory);
        return;
    }
    // The readdir() loop is basically the same
    entry = readdir(dir);
    while (entry != NULL)
    {
        // Although we check a flag every time this loop runs,
        // it makes the code easier to follow
        if(more_file_info != 0) {
            printf ("%s\n", entry->d_name);
        } else {
            fileinfo(directory);
            // Or should this be:
            // fileinfo(entry);
        }
        entry = readdir(dir); 
    }
}

这消除了大量重复的代码,并且应该有助于简化故障排除。另请注意,这会处理指定目录但不指示标志的情况,您可以明确检查是否需要不同的行为。希望通过更多信息,我们可以提供更合适的答案。