使用 C - 如何单独打开目录中的每个文件,假设您的程序不在所述目录中

发布于 2024-12-10 05:46:16 字数 6102 浏览 0 评论 0原文

所以我已经环顾了一段时间,找不到我的问题的答案...

我正在尝试创建一个程序,当在命令行参数中输入目录时,该程序将访问其中的每个单独文件目录并将文件名保存在链接列表中。然后,程序将对文件的内容进行标记,并将每个标记保存到以适当的文件名开头的链表中。该列表的构造如下:

[ListHeader][file1.txt][file2.txt][file3.txt]...[filen.txt]
            [token 1  ][token 1  ][token 1  ]...[token 1  ]
            [token 2  ][token 2  ][token 2  ]...[token 2  ]
            [token n  ][token n  ][token n  ]...[token n  ]

现在,我已经完成了分词器/链表功能。我在当前工作目录中使用 filestream fopen() 命令打开文件没有遇到任何问题。然而,我遇到的问题是在新目录中打开文件。

例如,假设我输入:

user@usermachine:~/Cprograms$ gcc -o d directorytokenizer.c
user@usermachine:~/Cprograms$ ./d test.txt

其中 test.txt 与程序本身位于同一目录(在上述情况下为 Cprograms)。 这个例子效果很好。

但是,如果输入的

user@usermachine:~/Cprograms$ gcc -o d directorytokenizer.c
user@usermachine:~/Cprograms$ ./d testdirectory

位置“testdirectory”是 Cprograms 目录中包含的目录(testdirectory 是 Cprograms 中的文件夹)。

我的程序可以很好地打开目录,并且可以输出目录中的文件名(我这样做是为了调试,并且它有效)。但是,当我尝试将各个文件名传递到文件流式传输的函数 (fopen()) 中时,filestream 命令找不到该文件。

以下是我的代码的相关部分:

//Sortedlist.h-

#ifndef SORTED_LIST_H
#define SORTED_LIST_H

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <ctype.h>

struct SLNodes
{
    char *word;
    struct SLNodes * next;
    int occurencecounter;
};
typedef struct SLNodes* SLNode;

struct SortedList_
{
    char * filename;
    SLNode Listhead;
    struct SortedList_ * nextfile;
};
typedef struct SortedList_* SortedList;

SortedList SLCreate();

void tokenstore(char *inputstr, SortedList NewList);


#endif

//indexer.c (truncated)-
//this is the mainfile

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <dirent.h>
#include "listheader.h"
#include "tokenstore.c"
#include "diropen.c"

int main(int argc, char *argv[])
{   
DIR *dip;
if (argc < 2)
    usage(argc, argv[0]);

if ((dip = opendir(argv[1])) == NULL)
{   
    printf("Not a directory, now attempting to open file...\n");

    SortedList NewList = CreateNewList(argv[1]);

    NewList = tokenize(NewList, argv[1]);

    SLNode curr = NewList->Listhead;

    if (curr != NULL)
    {
        SLNode curr = NewList->Listhead;
        printf("The following alphabetized and tokenized list of words is in the file: %s\n", NewList->filename);
        while(curr != NULL)
        {
            printf("<listbegin>\n");
            printf("The word <%s> appears <%d> times\n", curr->word, curr->occurencecounter);
            printf("<endlist>\n\n");
            curr = curr->next;
        }
    }
    else
        printf("File did not contain any words. Please make sure to input a         file with words in it. Remember, words consist of upper case and lower case letters, and numbers... Nothing else.\n");
}
else
{
    SortedList NewList = CreateNewList(argv[1]);
    printf("You have input a directory. Now attempting to open and sort...\n");
    openadir(argv[1], NewList);
}
}

//diropen.c (truncated)-

#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>

SortedList openadir(char *dirname, SortedList NewList)
{
    DIR *inputdir;
    struct dirent *dirstruct;

    SortedList placeholder;

    int i = 0;

    /* DIR *opendir(const char *name);
     *
     * Open a directory stream to argv[1] and make sure
     * it's a readable and valid (directory) */
    if ((inputdir = opendir(dirname)) == NULL)
    {
            perror("opendir");
            return;
    }

    printf("Directory stream is now open\n");

    /*  struct dirent *readdir(DIR *dir);
     *
     * Read in the files from argv[1] and print */
    while ((dit = readdir(dip)) != NULL)
    {
            i++;
            printf("\n%s\n", dit->d_name);

            NewList->filename = dirstruct->d_name;
            NewList = tokenize(NewList, dirstruct->d_name);
            NewList->nextfile = malloc(sizeof(SortedList));
            placeholder = NewList->nextfile;
            placeholder->filename = NULL;
            placeholder->Listhead = NULL;
            placeholder->nextfile = NULL;  
            NewList = placeholder;                           
    }
}

//tokenstore.c (truncated) - 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <ctype.h>
#include "listheader.h"


SortedList tokenize(SortedList NewList, char *filename) //tokenize the input file
{
printf("filename is : %s\n", filename);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * 
 * The following function simply steps through the input file and records the total
 * character count, in order to allocate a buffer of the correct size
 * to contain the eventual tokenized string.
 * 
 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
FILE *fc = fopen(filename, "r");                            
if(fc == NULL)                                              
    fatal(": Input file does not exist");                   

int hold;                                                   
int count=0;                                                

do                                                          
{                                                           
    hold = fgetc(fc);                                       
    count++;                                                
}                                                           
while( hold != EOF );                                       
fclose(fc); 
}

现在,正如我之前所说,输入与程序位于同一目录中的文件名可以正常工作,但当我尝试从不同的目录将文件名传递给 fopen 时,程序会抛出致命:找不到文件。 (致命错误函数不包含在我发布的源代码中,但它工作正常)。

我的问题是,如何将文件名从另一个目录传递到 fopen() 中,以便程序打开文件?

感谢您花时间阅读所有这些。

So I've been looking around for a while, and can't find an answer to my question...

I am attempting to create a program that, when a directory is inputted in a command line argument, will access each individual file in the directory and save the file name in a linked list. Then, the program will tokenize the contents of the file, and save each token to a linked list headed by the appropriate file name. The list will be constructed like this:

[ListHeader][file1.txt][file2.txt][file3.txt]...[filen.txt]
            [token 1  ][token 1  ][token 1  ]...[token 1  ]
            [token 2  ][token 2  ][token 2  ]...[token 2  ]
            [token n  ][token n  ][token n  ]...[token n  ]

Now, I have finished the tokenizer/linked list function. I am having no trouble in the current working directory with opening files using the filestream fopen() command. What I am having trouble with, however, is opening a file in a new directory.

For example, let's say I input:

user@usermachine:~/Cprograms$ gcc -o d directorytokenizer.c
user@usermachine:~/Cprograms$ ./d test.txt

Where test.txt is in the same directory (in the above case Cprograms) as the program itself.
This example works fine.

However, if the input is

user@usermachine:~/Cprograms$ gcc -o d directorytokenizer.c
user@usermachine:~/Cprograms$ ./d testdirectory

where "testdirectory" is a directory contained in the directory Cprograms (testdirectory is a folder in Cprograms).

My program opens the directory fine, and it can output the filenames within the directory (I did this to debug, and it worked). However, when I try to pass the individual filenames into a function that filestreams them (fopen()), the filestream command can't find the file.

Here are the relevant portions of my code:

//Sortedlist.h-

#ifndef SORTED_LIST_H
#define SORTED_LIST_H

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <ctype.h>

struct SLNodes
{
    char *word;
    struct SLNodes * next;
    int occurencecounter;
};
typedef struct SLNodes* SLNode;

struct SortedList_
{
    char * filename;
    SLNode Listhead;
    struct SortedList_ * nextfile;
};
typedef struct SortedList_* SortedList;

SortedList SLCreate();

void tokenstore(char *inputstr, SortedList NewList);


#endif

//indexer.c (truncated)-
//this is the mainfile

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <dirent.h>
#include "listheader.h"
#include "tokenstore.c"
#include "diropen.c"

int main(int argc, char *argv[])
{   
DIR *dip;
if (argc < 2)
    usage(argc, argv[0]);

if ((dip = opendir(argv[1])) == NULL)
{   
    printf("Not a directory, now attempting to open file...\n");

    SortedList NewList = CreateNewList(argv[1]);

    NewList = tokenize(NewList, argv[1]);

    SLNode curr = NewList->Listhead;

    if (curr != NULL)
    {
        SLNode curr = NewList->Listhead;
        printf("The following alphabetized and tokenized list of words is in the file: %s\n", NewList->filename);
        while(curr != NULL)
        {
            printf("<listbegin>\n");
            printf("The word <%s> appears <%d> times\n", curr->word, curr->occurencecounter);
            printf("<endlist>\n\n");
            curr = curr->next;
        }
    }
    else
        printf("File did not contain any words. Please make sure to input a         file with words in it. Remember, words consist of upper case and lower case letters, and numbers... Nothing else.\n");
}
else
{
    SortedList NewList = CreateNewList(argv[1]);
    printf("You have input a directory. Now attempting to open and sort...\n");
    openadir(argv[1], NewList);
}
}

//diropen.c (truncated)-

#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>

SortedList openadir(char *dirname, SortedList NewList)
{
    DIR *inputdir;
    struct dirent *dirstruct;

    SortedList placeholder;

    int i = 0;

    /* DIR *opendir(const char *name);
     *
     * Open a directory stream to argv[1] and make sure
     * it's a readable and valid (directory) */
    if ((inputdir = opendir(dirname)) == NULL)
    {
            perror("opendir");
            return;
    }

    printf("Directory stream is now open\n");

    /*  struct dirent *readdir(DIR *dir);
     *
     * Read in the files from argv[1] and print */
    while ((dit = readdir(dip)) != NULL)
    {
            i++;
            printf("\n%s\n", dit->d_name);

            NewList->filename = dirstruct->d_name;
            NewList = tokenize(NewList, dirstruct->d_name);
            NewList->nextfile = malloc(sizeof(SortedList));
            placeholder = NewList->nextfile;
            placeholder->filename = NULL;
            placeholder->Listhead = NULL;
            placeholder->nextfile = NULL;  
            NewList = placeholder;                           
    }
}

//tokenstore.c (truncated) - 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <ctype.h>
#include "listheader.h"


SortedList tokenize(SortedList NewList, char *filename) //tokenize the input file
{
printf("filename is : %s\n", filename);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * 
 * The following function simply steps through the input file and records the total
 * character count, in order to allocate a buffer of the correct size
 * to contain the eventual tokenized string.
 * 
 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
FILE *fc = fopen(filename, "r");                            
if(fc == NULL)                                              
    fatal(": Input file does not exist");                   

int hold;                                                   
int count=0;                                                

do                                                          
{                                                           
    hold = fgetc(fc);                                       
    count++;                                                
}                                                           
while( hold != EOF );                                       
fclose(fc); 
}

Now, as I said earlier, inputting a filename that is in the same directory as the program works fine, it's when I try to pass in filenames to fopen from a different directory that the program throws a fatal: file not found. (fatal error function is not included in the source code I posted, but it works fine).

My question is, how do I pass filenames from another directory into fopen() in such a manner that the program will open the files?

Thank you for taking the time to read all this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梓梦 2024-12-17 05:46:16

正如您所注意到的,struct direntd_name 成员仅包含文件名。它不包含目录名称。

您所需要做的就是连接目录名称、目录分隔符和 d_name 字符串,以获得可与 fopen 一起使用的相对路径。

另请注意:

NewList->filename = dirstruct->d_name;

这不好。如果您想保留该字符串,则必须复制该字符串。

您的 tokenize 函数声明返回一个 SortedList,但它不返回任何内容。

请确保您已打开编译器的警告。

The d_name member of the struct dirent contains, as you have noticed, only the file name. It does not contain the directory name.

All you need to do is to concatenate the directory name, directory separator, and that d_name string to get a relative path that you can use with fopen.

Also note:

NewList->filename = dirstruct->d_name;

This is not good. You must copy that string if you want to retain it.

Your tokenize function is declared are returning a SortedList, but it doesn't return anything.

Please make sure you've turned on your compiler's warnings.

鸠魁 2024-12-17 05:46:16

您可以首先使用 open 打开目录,然后使用 openat 访问其中的文件。

You could first open the directory with open and then access the files inside it with openat.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文