#c #linux
#c #linux
Вопрос:
предыдущая проблема была плохо описана. Мне нужно получить имя файла и присвоить это имя переменной. Единственное, что файл может иметь любое имя. То, что я знаю, это расширение файла, и может быть только один файл с этим расширением. Есть ли какой-либо способ реализовать это на C?
Обновление # 1 Расширением файла является *.knb
, а целью является система Linux.
#include <stdio.h>
#include <dirent.h>
#define LOG_() do{fprintf(stdout, " UNIT TESTING...n");}while(0)
char* knbname;
void fName(void);
int main()
{
LOG_();
fName(void);
//do some more code
return 0;
}
void fName(void){
DIR *d;
struct dirent *dir;
d = opendir(".");
if (d)
{
//find file with *.knb extension and place name into knbname
}
closedir(d);
}
Я не знаю, как найти *.knb
файл в функции fName() и как присвоить имя knbname
. Любая помощь будет оценена
Комментарии:
1. Добавьте
while( (dir = readdir(d)) != NULL )
цикл и сравните значениеdir->d_name
. (Обратите внимание, что «dir», вероятно, не лучшее имя дляstruct dirent
, поскольку запись каталога не обязательно является каталогом, и на самом деле вам, вероятно, наплевать на каталоги, если вы не хотите выполнять рекурсивный спуск.)2. В цикле, предложенном @WilliamPursell, вы можете затем проанализировать каждое имя записи каталога с
strtok()
помощью (используя ‘.’ в качестве разделителя), пока не найдете нужное расширение.3. OT: не выстраивайте свои переменные таким образом. Что произойдет, если вам нужно изменить тип переменной? Как насчет того, когда это несколько переменных? Вы потратите много времени, просто заставляя их выстраиваться снова. Это время, потраченное на ничего полезного.
4. Вы можете использовать POSIX
nftw()
для обхода дерева каталогов. Вы могли бы использоватьfnmatch()
для сопоставления с именем файла glob.5. Нет необходимости, даже
strtok()
если вы ищете только суффикс, можно просто использоватьstrcmp()
нацеленный на хвостовую часть строки в правильном положении в зависимости от длины.
Ответ №1:
Вы заново изобретаете glob()
функцию POSIX. Вот пример того, как его использовать (дополнительные параметры см. в разделе Флаги в manpage):
#include <glob.h>
int main(void)
{
glob_t glob_res = { 0 };
glob("*.knb", 0, NULL, amp;glob_res);
if (glob_res.gl_pathc == 0) puts("No match.");
else printf("First match is %sn", glob_res.gl_pathv[0]);
globfree(amp;glob_res);
return 0;
}
Ответ №2:
После того, как Эндрю указал на некоторые серьезные недостатки в предыдущем дизайне, я сделаю еще одну попытку решения…
int hasExtension(char *filename, char *extension);
int main(void)
{
DIR *directory;
struct dirent *entry;
if(NULL == (directory = opendir(".")))
{
perror("Failed to open directoryn");
exit(1);
}
while( NULL != (entry = readdir(directory)) )
{
if(DT_REG == entry->d_type) { // Regualar files only
if(hasExtension(entry->d_name, ".knb"))
{
printf("Match - %sn", entry->d_name);
} else {
printf("No match - %sn", entry->d_name);
}
}
}
closedir(directory);
return 0;
}
int hasExtension(char *filename, char *extension)
{
size_t filename_len, extension_len;
if((NULL == filename) || (NULL ==extension))
return 0;
filename_len = strlen(filename);
extension_len = strlen(extension);
if(filename_len < extension_len)
return 0;
return !strcmp(filename filename_len - extension_len, extension);
}
Комментарии:
1. И если
filename
это..
илиxxx
?2. Эндрю, да, теперь я понимаю… вы бы вышли за пределы границ… 🙁 Плохая идея…
3. На самом деле функция hasExtension должна быть переработана / переименована в strEndsWith (строка заканчивается на), что в основном и делает, и там, делая код более универсальным / многоразовым.