我有这个目录树:
xy@xy:/test# find .
.
./2
./2/Asd
./2/Asd/qwe
./2/Asd/qwe/txt.txt
./1
在“test”文件夹中可以有更多目录,如4,5,6,但asd,Asd,ASD,qwe,Qwe,QWE是不变的。 目的是计算所有可能的路径:
/test/1/ASD/QWE/txt.txt
/test/2/asd/qwe/txt.txt
/test/2/Asd/Qwe/txt.txt
然后读取文件(txt.txt)
我创建(复制并粘贴在一起......)以下内容并且它已经工作了一段时间。 我标记了我遇到的问题。
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <stdlib.h>
char *filetosearch="txt.txt";
char *test="/test/";
char *slash="/";
char *directory[3][3] = {{"asd", "Asd", "ASD"}, {"qwe","Qwe","QWE"}};
int dircounter1=0;
int dircounter2=0;
FILE *filetosf;
char **dirpatharr=NULL;
int dirpathcount=0;
char **hdarr=NULL;
int hdarrcount=0;
char **fullpath=NULL;
int count,size;
char *dirname;
DIR *d;
struct dirent *dir;
int main(void)
{
d = opendir(test);
if (d)
{
while ((dir = readdir(d)) != NULL)
{
if( dir->d_type==DT_DIR )
{
dirname=dir->d_name;
if((strcmp( dirname, ".." ) == 0) || (strcmp( dirname, "." ) == 0) )
{
}
else
{
hdarr=(char **)realloc(hdarr,(hdarrcount+1)*sizeof(dirname));
hdarr[hdarrcount]=dirname;
hdarrcount++;
}
}
else
{
}
}
}
closedir(d);
for (count=0; count<hdarrcount; count++ )
{
for (dircounter1 = 0; dircounter1 < 3; dircounter1++ )
{
for (dircounter2 = 0; dircounter2 < 3; dircounter2++ )
{
fullpath = malloc ( strlen(test) + strlen(hdarr[count]) + strlen(slash) + strlen(directory[0][dircounter2]) + strlen(slash) + strlen(directory[1][dircounter1]) + strlen(slash) + strlen(filetosearch)+1);
strcpy (fullpath,test);
strcat (fullpath,hdarr[count]);
strcat (fullpath,slash);
strcat (fullpath,directory[0][dircounter2]);
strcat (fullpath,slash);
strcat (fullpath,directory[1][dircounter1]);
strcat (fullpath,slash);
strcat (fullpath,filetosearch);
printf("fullpath:%s\n",fullpath);
// filetosf = fopen(fullpath,"r"); //THIS WILL BE THE PROBLEM!!!!
if (filetosf){
fseek (filetosf, 0L, SEEK_END);
size=ftell(filetosf);
fclose(fullpath);
printf("file exist:%s\n",fullpath);
}
free (fullpath);
}
}
}
}
------- CUT HERE --------------------
它有这个输出(就像我想要的那样):
fullpath:/test/2/asd/qwe/txt.txt
fullpath:/test/2/Asd/qwe/txt.txt
fullpath:/test/2/ASD/qwe/txt.txt
fullpath:/test/2/asd/Qwe/txt.txt
fullpath:/test/2/Asd/Qwe/txt.txt
fullpath:/test/2/ASD/Qwe/txt.txt
fullpath:/test/2/asd/QWE/txt.txt
fullpath:/test/2/Asd/QWE/txt.txt
fullpath:/test/2/ASD/QWE/txt.txt
fullpath:/test/1/asd/qwe/txt.txt
fullpath:/test/1/Asd/qwe/txt.txt
fullpath:/test/1/ASD/qwe/txt.txt
fullpath:/test/1/asd/Qwe/txt.txt
fullpath:/test/1/Asd/Qwe/txt.txt
fullpath:/test/1/ASD/Qwe/txt.txt
fullpath:/test/1/asd/QWE/txt.txt
fullpath:/test/1/Asd/QWE/txt.txt
fullpath:/test/1/ASD/QWE/txt.txt
但是当我删除备注标记并激活文件打开部分filetosf = fopen(fullpath,"r");
时
我无法读取该文件。当我检查输出时,我得到了这个:
fullpath:/test/2/asd/qwe/txt.txt
fullpath:/test//Asd/qwe/txt.txt
fullpath:/test//ASD/qwe/txt.txt
fullpath:/test//asd/Qwe/txt.txt
fullpath:/test//Asd/Qwe/txt.txt
fullpath:/test//ASD/Qwe/txt.txt
fullpath:/test//asd/QWE/txt.txt
fullpath:/test//Asd/QWE/txt.txt
fullpath:/test//ASD/QWE/txt.txt
fullpath:/test//asd/qwe/txt.txt
fullpath:/test//Asd/qwe/txt.txt
fullpath:/test//ASD/qwe/txt.txt
fullpath:/test//asd/Qwe/txt.txt
fullpath:/test//ASD/Qwe/txt.txt
fullpath:/test//asd/QWE/txt.txt
fullpath:/test//Asd/QWE/txt.txt
fullpath:/test//ASD/QWE/txt.txt
如果我在fopen
推荐之前打印出这些行,就会发生这种情况。为什么会这样?
我不是一位经验丰富的程序员,所以请尽量解释一下。
答案 0 :(得分:2)
在此代码中奇怪的许多事物中,显而易见的直接错误是:
fullpath = malloc ( strlen(test) + strlen(hdarr[count]) + strlen(slash) + strlen(directory[0][dircounter2]) + strlen(slash) + strlen(directory[1][dircounter1]) + strlen(slash) + strlen(filetosearch)+1);
接下来是一大堆字符串副本,如:
strcpy (fullpath,test);
注意:fullpath
声明为:
char **fullpath = NULL;
其中声明了一个指向char指针的指针; 不指向char的指针。尝试打开警告,然后在正确声明后重新检查您使用此变量的每个位置:
char *fullpath = NULL;
接下来,你保存(并且我松散地使用这个术语)你正在构建的目录名称:
dirname=dir->d_name;
...
hdarr[hdarrcount]=dirname;
但这样做是将d_name地址保存到hdarr动态数组的新插槽中。只要再次调用readdir()(或closedir()),该地址就无效。来自readdir()
文档:
“ readdir()返回的数据可能会被后续对同一目录流的readdir()调用覆盖。”
因此,您存储的所有指针都在实现拥有的内存中,只要它认为合适,它就可以完全自由地进行爆破。如果你想保留它们,你需要复制这些副本(当然,你完成时,这些副本是免费的)。
如何解决这个问题:
我通常不推荐这个,但在你的情况下我会:在dirname上使用strdup()。这是一个穷人“为我分配一个字符串缓冲区大小的字符串缓冲区,包括空格的空间,复制字符串,并将指针返回给我。所以你的代码将如下所示:
else
{
char **pp = realloc(hdarr,(hdarrcount+1)*sizeof(*pp));
if (pp)
{
hdaerr = pp;
hdarr[hdarrcount++] = strdup(dir->d_name);
}
else
{ // panic ensues
exit(EXIT_FAILURE);
}
}
不要忘记正确释放它。 hdarr中的每个字符串指针都是动态分配的。确保你释放它们,然后释放阵列本身。代码的尾部(在退出之前)看起来应该是这样的:
for (i=0;i<hdarrcount;i++)
free(hdarr[i]);
free(hdarr);
轻微,但很重要:
从不这样做:
hdarr=(char **)realloc(hdarr,(hdarrcount+1)*sizeof(dirname));
如果realloc()
失败,则返回NULL并且您刚丢失(从而泄露)您是原始数据指针。这样做:
char **pp = realloc(hdarr,(hdarrcount+1)*sizeof(*pp));
if (pp)
{
hdaerr = pp;
// .. continue with the rest of your assignment code
}
else
{ // allocation error, but at least you still have the
// old hdaerr so you can free it.
}
接下来,正如其他人所指出的那样:
fclose(fullpath);
这是完全错误的。 fclose()
期望FILE *
,而不是char **。传递你之前打开的filetosf(并且打开后,我的意思是在取消你当前取出的问题行之后。一旦你这样做了:
fclose(filetosf);
注意:直到你通过fclose()代码行注释掉fopen的全部。当他们点击一个NULL文件指针再一次说它跟我们一样...... 未定义。
答案 1 :(得分:0)
这是错误的:
fclose(fullpath);