首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C opendir()不打开目录?

C opendir()不打开目录?
EN

Stack Overflow用户
提问于 2018-04-27 21:00:58
回答 1查看 5.5K关注 0票数 4

我不具备C方面的所有经验,但在我的一个类中有一个作业,而且我在打开目录时遇到了一些问题。

该方案的目的是(转述):

  1. 如果没有提供标志或目录,请列出当前目录中的文件名。
  2. 如果提供了标志(-l),请列出有关每个文件的更多信息。
  3. 如果提供了标志和目录,请转到该目录并列出该目录中每个文件(或目录)的信息。没有必要通过子目录进行递归。

它不需要处理只获取一个目录,但是没有标记,或者一个无效的目录。更像是概念的证明。

我设法满足了第1部分和第2部分,但是第3部分一直中断,给出了一个分段错误。

我的代码如下:

代码语言:javascript
复制
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");
    }
}

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

fileinfo是一个函数,它输出给定DIRdirent作为参数的文件信息。但是,错误肯定不在我所能知道的代码中。

编辑:我犯了一个错误,没有分享所有的东西。我的主要方法很简单。

代码语言:javascript
复制
int main (int argc, char** argv)
{
    char* flag = argv[1];
    char* directory = argv[2];

    recursedirect(flag, directory);
}//main

它包括以下内容:

代码语言:javascript
复制
#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的论证了):

代码语言:javascript
复制
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中使用Ubuntu14.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。谢谢你们的一切!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-04-28 01:44:36

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

代码语言:javascript
复制
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 )。

代码语言:javascript
复制
int more_file_info = 0;
if (flag != NULL) {
    if(strcmp(flag, "-l") == 0) {
        more_file_info = 1;
    } else {
        printf("Invalid flag.\n");
        return;
    }
}

然后,您可以简化/重构上面的代码,如下所示:

代码语言:javascript
复制
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); 
    }
}

这消除了大量重复的代码,并有望使故障排除变得更容易。还请注意,这将处理指定目录但不指定标志的情况,您可以显式检查是否需要不同的行为。希望有更多的信息,我们可以提供一个更合适的答案。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50070252

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档