我的 C 程序遇到问题,该程序旨在打印从根目录到给定文件的路径。示例:
./pathto
/users/cs/a1066199/
./pathto .
/users/cs/a1066199/
./pathto file.txt
/users/cs/a1066199/file.txt
./pathto ..
/users/cs/
./pathto ../teaching/somefile.c
/users/cs/teaching/somefile.c
正在使用的算法如下,我必须用递归来实现它:
let d be a directory.
open the parent of d (ie d/..)
loop
Get next entry, e, in the parent diretory
get the status of e, using stat, into es
until es.device==d.device and es.inum==d.inum
endloop
我已经编写了程序并运行了该程序,但是虽然第一次有效,但任何后续的递归函数 seg 调用都会出现错误。
我不确定问题出在哪里。
感谢任何帮助。
代码:
#define _BSD_SOURCE
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<dirent.h>
#include<string.h>
char* compare(char currDir[1024], char newDir[1024], struct stat D){
int found = 0;
struct stat Dnew;
struct stat ES;
struct dirent* direntp;
DIR* dirp;
char* p;
char dirName[1024];
char filePath[1024];
char newDir2[1024];
char rootPath[1024];
dirp = opendir(newDir);//open parent directory
while ((direntp = readdir(dirp)) != NULL){//read parent
//printf("%s\n", direntp->d_name);
strcpy(filePath, newDir);//create path to the file in the parent
strcat(filePath, "/");
strcat(filePath, direntp->d_name);
if(stat(filePath, &ES) == -1){//read into stat
perror("stat");
}
if(ES.st_dev == D.st_dev){//check es.device == d.device
//printf("st_dev are the same\n");
if(ES.st_ino == D.st_ino){//check es.inum == d.inum
//printf("st_ino are the same\n");
printf("The child Dir is %s\n", direntp->d_name);//print this if they are the same
found = 1;
if(ES.st_mode & S_IFDIR){//if its a directory, put / on the end
strcpy(dirName, direntp->d_name);
strcat(dirName, "/");
} else {
strcpy(dirName, direntp->d_name);
}
} else {
found = 0;
}
} else {
found = 0;
}
}
closedir(dirp);
if(D.st_ino == 2){
//strcpy(dirName, "/");//if root, return /
return "/";
} else {
dirp = opendir(newDir);
while ((direntp = readdir(dirp)) != NULL){
if (strcmp(direntp->d_name, "..") == 0){//find ..
strcpy(filePath, newDir);
strcat(filePath, "/");
strcat(filePath, direntp->d_name);
if(stat(filePath, &Dnew) == -1){//read .. into Dnew
//perror("stat");
}
}
}
closedir(dirp);
strcpy(newDir2, newDir);//make new dir
strcat(newDir2, "/..");
printf("%s\n", newDir);
printf("%s\n", newDir2);
strcpy(rootPath, "");
/*strncpy(rootPath, */p = compare(newDir, newDir2, Dnew)/*, 1024)*/;//call recursivly
while(*p != '\0'){
strcat(rootPath, *p);
p++;
}
strcat(rootPath,dirName);
return rootPath;
}
}
int main(int argc, char* argv[]){
struct stat D;
//struct stat E;
//struct stat ES;
//struct dirent* direntp;
//DIR* dirp;
//char filePath[1024];
char* p;
char rootPath[1024];
char currDir[1024];
char newDir[1024];
strcpy(currDir, argv[1]);
if(stat(argv[1], &D) == -1){
//perror("stat");
}
strcpy(newDir, currDir);
strcat(newDir, "/..");
printf("%s\n", currDir);
printf("%s\n", newDir);
/*strncpy(rootPath, */p = compare(currDir, newDir, D)/*, 1024)*/;
while(*p != '\0'){
strcat(rootPath, *p);
p++;
}
printf("%s", rootPath);
/*if(D.st_mode & S_IFDIR){
printf("/\n");
}*/
return 0;
}
终端输出:
/usr
/usr/..
The child Dir is usr
/usr/..
/usr/../..
The child Dir is ..
The child Dir is .
./pathto: line 6: 27236 Segmentation fault (core dumped) ./pathto.o $*
最佳答案
问题代码中有一些内容需要修复。
1) 考虑以下问题代码片段(在问题代码中出现两次):
while(*p != '\0'){
strcat(rootPath, *p);
p++;
}
strcat() 函数需要两个字符串的地址。变量'p'被定义为一个char ptr,它可以存储这样的地址。但是,“*p”引用字符串的第一个字符值,因此通常会导致编译器警告警告:传递“strcat”的参数2使指针来自整数而不进行强制转换。仅此一点就可能并且很可能确实导致了段错误。也许下面的代码会更好?
size_t len = strlen(rootPath);
while(*p != '\0')
{
rootpath[len++] = *p++;
}
rootpath[len] = '\0';
2)现在考虑以下事项:
char* compare(char currDir[1024], char newDir[1024], struct stat D){
...
char rootPath[1024];
...
...
return rootPath;
}
显然,compare() 函数已经努力计算值 rootPath,将有值(value)的值返回给调用者很重要。但这里有一个缺陷。变量“rootPath”仅存在于compare()函数的大括号内。在“返回”之后,变量和分配给变量的存储空间都不能存在。因此,编译器通常会发出警告:警告:函数返回局部变量的地址 这也会(最终)导致段错误。
为了返回有值(value)的值,必须将其放置在比compare()函数更持久的存储中。也许是这样的:
char* compare(char currDir[1024], char newDir[1024], struct stat D){
...
char rootPath[1024];
...
...
return strdup(rootPath);
}
strdup() 函数将为该值分配“堆”内存(可以比函数更持久),并将该内存的地址返回给调用者。请记住,调用者的工作是在不再需要该内存时调用 free() 将其返回到堆。
关于c - 用于打印给定文件路径的 C 程序错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24216174/