#c #directory #filestream
#c #каталог #filestream
Вопрос:
Итак, я некоторое время осматривался и не могу найти ответ на свой вопрос…
Я пытаюсь создать программу, которая, когда каталог вводится в аргумент командной строки, будет обращаться к каждому отдельному файлу в каталоге и сохранять имя файла в связанном списке. Затем программа будет маркировать содержимое файла и сохранять каждый токен в связанном списке, возглавляемом соответствующим именем файла. Список будет построен следующим образом:
[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 ]
Теперь я завершил функцию tokenizer / linked list . В текущем рабочем каталоге у меня нет проблем с открытием файлов с помощью команды 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).
Моя программа отлично открывает каталог и может выводить имена файлов внутри каталога (я сделал это для отладки, и это сработало). Однако, когда я пытаюсь передать отдельные имена файлов в функцию, которая передает их в filestreams (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() таким образом, чтобы программа открывала файлы?
Спасибо, что нашли время, чтобы прочитать все это.
Ответ №1:
d_name
Член struct dirent
содержит, как вы заметили, только имя файла. Он не содержит имени каталога.
Все, что вам нужно сделать, это объединить имя каталога, разделитель каталогов и эту d_name
строку, чтобы получить относительный путь, с которым вы можете использовать fopen
.
Также обратите внимание:
NewList->filename = dirstruct->d_name;
Это нехорошо. Вы должны скопировать эту строку, если хотите ее сохранить.
Ваша tokenize
объявленная функция возвращает a SortedList
, но она ничего не возвращает.
Пожалуйста, убедитесь, что вы включили предупреждения вашего компилятора.
Комментарии:
1. Или вы можете
chdir()
сначала перейти в каталог.2. Да, chdir работает, но я стараюсь избегать этого, особенно в том, что может оказаться в «библиотечном» коде. Вы должны быть осторожны, чтобы вернуться в начальный каталог, и чтобы все, что вы вызываете из обхода каталога, знало, что вы
cd
редактируете. Упрощает код (меньше манипуляций со строками / вероятность утечки), поэтому в этом случае это может быть хорошо.
Ответ №2:
Вы можете сначала открыть каталог с open
помощью, а затем получить доступ к файлам внутри него с openat
помощью .