簡體   English   中英

C opendir()沒有打開目錄?

[英]C opendir() not opening a directory?

我不是在C中經驗豐富,但在我的一個課程中有一個作業,而且我在打開一個目錄時遇到了一些問題。

該計划的目的是(轉述):

  1. 如果未提供標志或目錄,則列出當前目錄中的文件名。
  2. 如果提供了標志(-l),請列出有關每個文件的更多信息。
  3. 如果提供了標志和目錄,請轉到該目錄並列出有關該目錄中每個文件(或目錄)的信息。 沒有必要通過子目錄進行遞歸。

它不需要處理只獲取目錄但沒有標志或無效目錄。 這是更多的概念驗證。

我已經成功地滿足了第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。 謝謝大家!

除了chux留下的注釋之外,您還可以通過重構代碼來重用類似的塊。 你提到你已經解決了第1部分和第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 )。

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); 
    }
}

這消除了大量重復的代碼,並且應該有助於簡化故障排除。 另請注意,這會處理指定目錄但不指示標志的情況,您可以明確檢查是否需要不同的行為。 希望通過更多信息,我們可以提供更合適的答案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM