所以我一直在寻找一段时间,不能找到我的问题的答案…
我正在尝试创建一个程序,当在命令行参数中输入目录时,将访问目录中的每个单独文件并将文件名保存在链表中。然后,程序将标记文件的内容,并将每个标记保存到以适当文件名为首的链表中。该列表将像这样构造:
[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 ]
现在,我已经完成了标记器/链表函数。我在当前工作目录中使用fileststream 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中的一个文件夹)。
我的程序很好地打开了目录,它可以输出目录中的文件名(我这样做是为了调试,它工作了)。但是,当我尝试将单个文件名传递给一个对它们进行filestream (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: %sn", NewList->filename);
while(curr != NULL)
{
printf("<listbegin>n");
printf("The word <%s> appears <%d> timesn", curr->word, curr->occurencecounter);
printf("<endlist>nn");
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 openn");
/* struct dirent *readdir(DIR *dir);
*
* Read in the files from argv[1] and print */
while ((dit = readdir(dip)) != NULL)
{
i++;
printf("n%sn", 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 : %sn", 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传递文件名时,程序会抛出致命的:file not found。(致命错误函数不包括在我发布的源代码中,但它工作得很好)。
我的问题是,我如何将文件名从另一个目录传递到fopen()中,以便程序打开文件?
感谢您花时间阅读所有这些。
您已经注意到,struct dirent
的d_name
成员只包含文件名。不包含目录名。
您所需要做的就是将目录名,目录分隔符和d_name
字符串连接起来,以获得您可以与fopen
使用的相对路径。
注意:
NewList->filename = dirstruct->d_name;
这是不好的。如果您想保留该字符串,则必须复制该字符串。
你的tokenize
函数被声明为返回SortedList
,但它不返回任何东西。
请确保你已经打开了编译器的警告
您可以先使用open
打开目录,然后使用openat
访问其中的文件。