0

我一直在尝试在 minix 中实现一个搜索功能,它将在当前或子目录中查找文件并打印路径。到目前为止,我的代码编译成功,但由于某种原因它只返回几个奇怪的 ascii 字符,知道我做错了什么吗?

#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

_PROTOTYPE(int main, (int argc, char **argv));
_PROTOTYPE(char *find_file, (char *name, char *directory));

int main(argc, argv)
int argc;
char **argv;
{
    char *path = find_file(argv[0], "./");
    if (strcmp(path, "") == 0) {
        printf("file could not be found.");
    } else {
        printf("File found in: %s\n", path);
    }
    return(0);
}

char *find_file(name, directory)
char *name;
char *directory;
{
    DIR *d;
    struct dirent *e;
    struct stat s;

    char *dr;
    char *res;
    char *result;

    d = opendir(directory);
    if (d != NULL) {
        while (e = readdir(d)) {
            if (e->d_name == name)
                return name;
        }
    }
    closedir(d);

    d = opendir(directory);
    if (d != NULL) {
        while (e = readdir(d)) {
            stat(e->d_name, &s);
            if (s.st_mode & S_IFDIR) {
                dr = malloc(strlen(directory) + strlen(e->d_name) + 2);
                strcpy(dr, directory);
                strcat(dr, e->d_name);
                strcat(dr, "/");
                res = find_file(name, dr));
                if (strcmp(res, "") != 0) {
                    strcpy(result, e->d_name);
                    strcat(result, "/");
                    strcat(result, res);
                    return result;
                }
            }
        }
    }
    closedir(d);
    return "";
}

所以我首先检查文件是否在当前目录中,然后再进入子文件夹,这就是我打开和关闭目录两次的原因。我唯一怀疑可能是非正统的事情是直接使用 malloc 并声明一个固定的数量,这是不可以吗?感谢您的帮助<3

编辑:所以我尝试使用 malloc 与字符串的大小而不是设置的数量但没有改变,这是一个截图:

在此处输入图像描述

EDIT2:由于建议更新了我的代码,但仍然无法 100% 工作,因为它正在使用父文件夹或类似的奇怪东西,如果我设法让它完美工作,将发布解决方案(y)

EDIT3:我已经设法让它工作(在某种程度上)它可以完美地工作,但在某些情况下它找不到现有文件,不知道原因并且太累了,无法确定为什么^_^这里是对于将来会寻找类似解决方案的任何其他人的最终工作代码:

#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

_PROTOTYPE(int main, (int argc, char **argv));
_PROTOTYPE(char *find_file, (char *name, char *directory));

int main(argc, argv)
int argc;
char **argv;
{
    char *path = find_file(argv[1], "./");
    if (strcmp(path, "") == 0) {
        printf("file could not be found.\n");
    } else {
        printf("File found in: %s\n", path);
    }
    return(0);
}

char *find_file(name, directory)
char *name;
char *directory;
{
    DIR *d;
    struct dirent *e;
    struct stat s;

    char *dr;
    char *res;
    char *result;

    d = opendir(directory);
    if (d != NULL) {
        while (e = readdir(d)) {
            if (strcmp(e->d_name, name) == 0)
                return e->d_name;
        }
    }
    closedir(d);

    d = opendir(directory);
    if (d != NULL) {
        while (e = readdir(d)) {
            stat(e->d_name, &s);
            if (strcmp(e->d_name, ".") != 0 && strcmp(e->d_name, "..") != 0) {    
                if (s.st_mode & S_IFDIR) != 0) {
                    dr = malloc(strlen(directory) + strlen(e->d_name) + 2);
                    strcpy(dr, directory);
                    strcat(dr, e->d_name);
                    strcat(dr, "/");
                    res = find_file(name, dr));
                    if (strcmp(res, "") != 0) {
                        result = malloc(strlen(e->d_name) + strlen(res) + 2);
                        strcpy(result, e->d_name);
                        strcat(result, "/");
                        strcat(result, res);
                        return result;
                    }
                }
            }
        }
    }
    closedir(d);
    return "";
}

由于某种原因,文件名是在 argv 1而不是 argv[0] 中传递的,这很奇怪,因为我实现了另一个通过 argv[0] 传递文件名的函数... Minix¯| (ツ)

4

3 回答 3

0

您正在给stat一个未初始化的指针。

struct stat *s
....
stat(e->d_name, s);

你应该做的是:

struct stat s
....
stat(e->d_name, &s);

另一个问题(除其他外)是这部分:

strcpy(res, find_file(name, dr));
if (res != "") {

你不能在 C 中比较这样的字符串,你必须使用strcmp(res, "") == 0,因为你在这里比较指针。它甚至可以在这种情况下工作(如果你的编译器重用静态字符串),但在一般情况下它不会。

于 2015-11-09T10:58:37.410 回答
0
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h> // added
#include <dirent.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>


char *find_file(char *name, char *directory); // corrected

int main(int argc, char * argv[]) // corrected
{
    // added to correct compiler warning about unused parameter 'argc'
    if( 2 != argc ) {perror( "wrong number of parameters "); exit( EXIT_FAILURE); }

    // corrected to use parameter rather than current executable name
    char *path = find_file(argv[1], "./");

    // corrected to make useful comparison
    if ( '\0' == path[0] )
    {
        printf("file could not be found.");
    }

    else
    {
        printf("File found in: %s\n", path);
    }

    return(0);
} // end function: main

char *find_file(char *name, char *directory) // corrected
{
    DIR *d;
    struct dirent *e;
    struct stat s;

    char *dr;
    char *res;
    char *result = malloc( 1024 ); // corrected so 'result' pointer to allocated memory

    printf("initial DIR: %s\n", directory); // added for debug

    d = opendir(directory);
    if (d != NULL)
    {
        // corrected to fix compiler warning
        while ( NULL != (e = readdir(d)) )
        {
            if (e->d_name == name)
                return name;
        }
    }
    closedir(d);

    d = opendir(directory);
    if (d != NULL)
    {
        // corrected to fix compiler warning
        while ( NULL != (e = readdir(d)) )
        {
            stat(e->d_name, &s); // corrected
            // corrected so actually works
            if (S_ISDIR(s.st_mode) )
            {
                dr = malloc(strlen(directory) + strlen(e->d_name) + 2);
                strcpy(dr, directory);
                strcat(dr, e->d_name);
                strcat(dr, "/");

                // added for debug
                printf( "nested DIR: %s\n", dr);

                res = find_file(name, dr);

                // corrected to make useful comparison
                if ( '\0' != res[0] )
                {
                    strcpy(result, e->d_name);
                    strcat(result, "/");
                    strcat(result, res);
                    return result;
                } // end if
            } // end of
        } // end while
    } // end if
    closedir(d);
    return "";
} // end function: find_file

(注意:这会在每次迭代时泄漏内存,因为 malloc 的内存没有被传递给free()

给出以下输出:

(注意:这是代码运行几秒钟后重复输出的一次快照。)

(注意:helloworld 是一个可执行文件,位于大约 70 个条目的目录的中间(按字母顺序))

(注意:命令行是:./untitled untitled.c

初始目录:./helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../ helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../ helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../ helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../ helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../ helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../你好世界/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/.. /helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/.. /helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/.. /helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/.. /helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/.. /helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/.. /你好世界/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/.. /helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/.. /helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/.. /helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/.. /helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/.. /helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/.. /你好世界/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/.. /helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/.. /helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/.. /helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/.. /helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/.. /helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/.. /你好世界/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/.. /helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/.. /helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/.. /helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/.. /helloworld/../helloworld//helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/.. /helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/.. /helloworld/../helloworld//helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/.. /helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/.. /helloworld/../helloworld/

于 2015-11-11T04:31:14.270 回答
0

我不熟悉 Minix,但您可能想排除 '.' 和 '..' 目录,因为 Minix 也是一个类 UNIX 系统。

其次,您不必打开目录两次,因为 readdir() 将遍历目录下的所有项目,包括 '.' 和'..',无论是目录还是文件。

第三,对于这个代码块:

d = opendir(directory);
if (d != NULL) {
    while (e = readdir(d)) {
        if (e->d_name == name)
            return name;
    }
}
closedir(d);

在这里只返回name不是很好,因为它只是一个文件名,没有关于其绝对路径的信息。这也是您应该将此代码块合并到find_file()的第二部分的原因。

此外,您不应在此处返回结果,因为很可能在另一个目录下有另一个与您正在搜索的名称相同的项目。更好的解决方案是打印出名称(带有绝对路径信息)并继续该过程。或者简单地说,你不必让你的find_file()返回一些东西。您只需打印出您已经找到的名称。

于 2015-11-09T12:15:26.817 回答