gpt4 book ai didi

从文件系统获取随机文件的C程序

转载 作者:行者123 更新时间:2023-11-30 17:34:24 25 4
gpt4 key购买 nike

我正在开发一款游戏,我需要一个可以从系统中查找随机文件名的程序。我不确定我应该如何去做。

这是我到目前为止所得到的:注意,我需要有关 get_random_files 函数的帮助。我完全不知道如何以快速且占用大量内存的方式抓取随机文件。

 char islld(char *path)
{
DIR *d = opendir(path);
struct dirent *ds;
struct stat st;
char *buf = malloc(strlen(path) + 1024), ret = -1;
while ((ds = readdir(d)) != NULL)
{
sprintf(buf, "%s/%s", path, ds->d_name);
stat(buf, &st);
if (S_ISDIR(st.st_mode))
goto err;
}
ret = 1;
err:
ret = ret < 0 ? 0 : ret;
closedir(d);
free(buf);
return ret;
}

char hasfiles(char *path)
{
DIR *d = opendir(path);
struct dirent *ds;
struct stat st;
char *buf = malloc(strlen(path) + 1024);
while ((ds = readdir(d)) != NULL)
{
sprintf(buf, "%s/%s", path, ds->d_name);
stat(buf, &st);
if (S_ISREG(st.st_mode))
{
free(buf);
closedir(d);
return 1;
}
}
free(buf);
closedir(d);
return 0;
}

tlist *getdirs(char *path)
{
tlist *ret = tlist_init();
DIR *d = opendir(path);
struct dirent *ds;
struct stat st;
char *buf = malloc(strlen(path) + 1024);
while ((ds = readdir(d)) != NULL)
{
sprintf(buf, "%s/%s", path, ds->d_name);
stat(buf, &st);
if (S_ISDIR(st.st_mode))
tlist_insert(ret, buf, (unsigned int)strlen(buf) + 1);
}
free(buf);
closedir(d);
return ret;
}

tlist *getfiles(char *path)
{
tlist *ret = tlist_init();
DIR *d = opendir(path);
struct dirent *ds;
struct stat st;
char *buf = malloc(strlen(path) + 1024);
while ((ds = readdir(d)) != NULL)
{
sprintf(buf, "%s/%s", path, ds->d_name);
stat(buf, &st);
if (S_ISREG(st.st_mode))
tlist_insert(ret, buf, (unsigned int)strlen(buf) + 1);
}
free(buf);
closedir(d);
return ret;
}

tlist *get_random_files(char *basepath, int num)
{
tlist *dirs = NULL, *files = NULL, *retfiles = tlist_init();
char buf[4096]; //should be plenty
int i, j, nf;
strcpy(buf, basepath);
for (nf = 0; nf < num;)
{
if (files == NULL) files = tlist_init();
if (dirs == NULL)
{
if (!islld(buf))
if (hasfiles(buf))
files = getfiles(buf);
}
}
return NULL;
}

我不知道我是否需要完全废弃整个事情,但我需要帮助来完成 get_random_files 函数。作为引用,这是我的 tlist 定义:

struct typelesslist_node
{
void *data;
struct typelesslist_node *next;
unsigned int size;
};

typedef struct typelesslist_node tlist;

tlist * tlist_init(void);
void tlist_insert(tlist *list, void *data, unsigned int size);
tlist * tlist_remove(tlist *list, unsigned int key);
void tlist_get(tlist *list, void *dest, unsigned int key);
tlist * tlist_free(tlist *list);
void tlist_insert_list(tlist *dest, tlist *src);

再次,非常感谢任何帮助。我想避开 C++、boost 等。我希望这个程序不依赖于任何外部库。

谢谢。

最佳答案

我想出了一个解决办法。获取每个目录的条目数,将该数字作为 arc4random 的 mod,然后如果这是一个常规文件,则将其添加到列表中,否则递归到该目录并重复。

#include <stdio.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <curses.h>
#include <sys/dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "typelesslist.h"

#define DEBUGV 0
#define MIN_LEVELS 4

int numentries(char *path)
{
int ret = 0;
DIR *d;
struct dirent *ds;
struct stat st;
char *buf;
if ((d = opendir(path)) == NULL) return -1;
buf = malloc(strlen(path) + 1024);
while ((ds = readdir(d)) != NULL)
{
if (strcmp(ds->d_name, ".") == 0 || strstr(ds->d_name, "./") != NULL) continue;
sprintf(buf, "%s/%s", path, ds->d_name);
stat(buf, &st);
if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))
++ret;
}
free(buf);
closedir(d);
return ret;
}

char *fullnamefromkey(char *path, int key)
{
DIR *d;
struct dirent *ds;
struct stat st;
char *buf;
int i = 0;
if ((d = opendir(path)) == NULL) return NULL;
buf = malloc(strlen(path) + 1024);
while ((ds = readdir(d)) != NULL)
{
sprintf(buf, "%s/%s", path, ds->d_name);
stat(buf, &st);
if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))
{
if (i++ == key)
{
closedir(d);
return buf;
}
}
}
return NULL; //this should never happen
}

int countstr(char *str, char * c)
{
if (strstr(str, c) == NULL)
return 0;
return 1 + countstr(strstr(str, c) + 1, c);
}

void minimize_path(char *s)
{
int i, j;
do
{
for (i = 0; i < strlen(s); i++)
{
if (s[i] == '/' && s[i + 1] == '/') //double /
for (j = i; j < strlen(s) + 1; j++)
s[j] = s[j + 1];
if (s[i] == '.' && s[i + 1] == '/')
for (j = i; j < strlen(s) + 1; j++)
s[j] = s[j + 2];
}
} while (strstr(s, "//") != NULL);
}

tlist *get_random_files(char *basepath, int num)
{
tlist *retfiles = tlist_init(), *ttmp;
char *tmpbuf; //should be plenty
struct stat st;
int i, ne = numentries(basepath), found = 0;
if (DEBUGV) printf("[get_random_files] enter with basepath=%s and num=%d\n", basepath, num);
while (found < num || num == -1)
{
if (ne < 5) return NULL;
found = tlist_num_entries(retfiles);
do
{
i = arc4random() % ne;
tmpbuf = fullnamefromkey(basepath, i);
} while (tmpbuf == NULL);
stat(tmpbuf, &st);
if (S_ISREG(st.st_mode))
{
minimize_path(tmpbuf);
if (strstr(tmpbuf, "/./") != NULL || strstr(tmpbuf, " ") != NULL) continue;
if (countstr(tmpbuf, "/") > MIN_LEVELS && strstr(tmpbuf, "..") == NULL)
tlist_insert(retfiles, tmpbuf, (unsigned int)strlen(tmpbuf) + 1);
free(tmpbuf);
}
else //is a directory
{
if (DEBUGV) printf("[get_random_files] recursing with basepath=%s\n", basepath);
ttmp = get_random_files(tmpbuf, -1);
if (DEBUGV) printf("[get_random_files] exited recursion\n");
if (ttmp != NULL)
{
tlist_insert_list(retfiles, ttmp);
ttmp = tlist_free(ttmp);
}
//free(tmpbuf);
}
if (num == -1)
break;
}
return retfiles;
}

int main(int argc, char * * argv)
{
tlist *l = get_random_files("/", 5), *t = l;
char buf[1024];
//srand(time(0));
while (t != NULL)
{
if (t->data != NULL)
{
strcpy(buf, t->data);
printf("Got file %s\n", buf);
t = t->next;
}
else break;
}
tlist_free(l);
}

关于从文件系统获取随机文件的C程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23352375/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com