Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/28.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C程序从文件系统中获取随机文件_C_Linux_File_Random - Fatal编程技术网

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

C程序从文件系统中获取随机文件,c,linux,file,random,C,Linux,File,Random,我正在做一个游戏,我需要一个程序,可以从系统中找到随机文件名。我不确定该怎么做 到目前为止,我所拥有的是:请注意,我需要get_random_files函数的帮助。我不知道如何快速地抓取随机文件 char islld(char *path) { DIR *d = opendir(path); struct dirent *ds; struct stat st; char *buf = malloc(strlen(path) + 1024), r

我正在做一个游戏,我需要一个程序,可以从系统中找到随机文件名。我不确定该怎么做

到目前为止,我所拥有的是:请注意,我需要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;
 }
再次感谢您的帮助。我想避开像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);
 }
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括“无类型列表.h”
#定义debugv0
#定义最小\u级别4
整数(字符*路径)
{
int-ret=0;
DIR*d;
结构方向*ds;
结构统计;
char*buf;
if((d=opendir(path))==NULL)返回-1;
buf=malloc(strlen(路径)+1024);
而((ds=readdir(d))!=NULL)
{
如果(strcmp(ds->d_name,“.”)==0 | | strstr(ds->d_name,“./”)!=NULL)继续;
sprintf(buf,“%s/%s”,路径,ds->d_名称);
统计数据(buf和st);
if(S|u ISREG(圣圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣
++ret;
}
免费(buf);
closedir(d);
返回ret;
}
char*fullnamefromkey(char*path,int键)
{
DIR*d;
结构方向*ds;
结构统计;
char*buf;
int i=0;
if((d=opendir(path))==NULL)返回NULL;
buf=malloc(strlen(路径)+1024);
而((ds=readdir(d))!=NULL)
{
sprintf(buf,“%s/%s”,路径,ds->d_名称);
统计数据(buf和st);
if(S|u ISREG(圣圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣·圣
{
如果(i++==键)
{
closedir(d);
返回buf;
}
}
}
return NULL;//这种情况永远不会发生
}
int countstr(char*str,char*c)
{
if(strstr(str,c)==NULL)
返回0;
返回1+countstr(strstrstr(str,c)+1,c);
}
无效最小化路径(字符*s)
{
int i,j;
做
{
对于(i=0;iMIN_LEVELS&&strstr(tmpbuf,“…”)==NULL)
tlist_insert(retfiles,tmpbuf,(unsigned int)strlen(tmpbuf)+1);
免费(tmpbuf);
}
else//是一个目录
{
if(DEBUGV)printf(“[get\u random\u files]与basepath=%s\n”递归,basepath);
ttmp=获取随机文件(tmpbuf,-1);
如果(DEBUGV)printf(“[get_random_files]退出递归\n”);
如果(ttmp!=NULL)
{
t列表插入列表(retfiles,ttmp);
ttmp=tlist_free(ttmp);
}
//免费(tmpbuf);
}
如果(num==-1)
打破
}
返回文件;
}
int main(int argc,字符**argv)
{
tlist*l=获取随机文件(“/”,5),*t=l;
char-buf[1024];
//srand(时间(0));
while(t!=NULL)
{
如果(t->data!=NULL)
{
strcpy(buf,t->data);
printf(“已获取文件%s\n”,buf);
t=t->next;
}
否则就断了;
}
tlist_free(l);
}

允许哪些文件有任何限制?(设备节点、远程文件系统、FIFO等)(配置文件、程序文件、密码文件等)我只想要任何通过S_IFREG的文件。除此之外没有其他限制。“应该足够了”。。。直到有人绕了一个圈或堆得很深。为什么不使用这样的节点:
typedef结构节点{struct node*next;size\u t size;char data[];}节点?避免一半的分配。任何不是符号链接并通过S_IFREG的文件,然后lol…并忽略作为链接的目录。装载循环/net装载循环如何?你到底想用它做什么?请阅读
#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);
 }