Как реализовать функцию find () в Unix с использованием рекурсивной функции (с C) - PullRequest
0 голосов
/ 27 сентября 2019

найти [путь]

То, как я хочу, показано на прикрепленном рисунке.Я использую Mac Terminal.Все, что я хочу сделать, это показать путь с функцией поиска.

Я хочу реализовать команду UNIX-find () на языке Си.Я написал код, но я ничего не понимаю, и мне кажется, что он слишком запутанный, поэтому я попрошу вас, ребята, о помощи.Разве нет более простого кода, который легче понять?

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

#define MAX_SIZE 1024

void do_ls(char[], char[]);
void print_error(int, char[]);

int main( int ac, char *av[] )
{
    if( ac == 1 ) {
        print_error(1, NULL);
    }
    else {
        printf("%s\n", av[1]);
        do_ls(av[1], av[1]);
    }
}

void do_ls( char path[], char dirname[] ) { // recursive func

    DIR *dir_ptr;
    struct dirent *direntp;
    char buffer[MAX_SIZE] = "";

    strcat(buffer, path);

    if((dir_ptr = opendir(dirname)) == NULL) {
        print_error(2, dirname);
    }
    else {
        chdir(dirname);
        while((direntp = readdir(dir_ptr)) != NULL) {
            if(opendir(direntp->d_name) != NULL) {
                if(strcmp(direntp->d_name, ".") != 0 && strcmp(direntp->d_name, "..") != 0) {
                    strcat(buffer, "/");
                    strcat(buffer, direntp->d_name);
                    printf("%s\n", buffer);
                    do_ls(buffer, direntp->d_name);
                    strcpy(buffer, dirname);
                    if(strcmp(buffer, ".") != 0) {
                        strcpy(buffer, "./");
                        strcat(buffer, dirname);
                    }
                }
            }
            else {
                printf("%s/%s\n", buffer, direntp->d_name);
                if(strcmp(buffer, ".") != 0) {
                    chdir("..");
                    strcpy(buffer, ".");
                }
            }
        }
    }


}

void print_error(int error_num, char dirname[]) {
    switch(error_num) {
        case 1:
            printf("usage : find [-H | -L | -P] [-EXdsx] [-f path] path ... [expression]\n");
            printf("        find [-H | -L | -P] [-EXdsx] -f path [path ...] [expression]\n");
            break;
        case 2:
            fprintf(stderr, "error: cannot open %s\n", dirname);
            break;
    }
}

Это мой код.Сначала я написал код без буфера, но он не работал.Я думал, что смогу понять это и решить это самостоятельно, но я не мог написать идеальный код, потому что у меня не было достаточного понимания о C.

1 Ответ

2 голосов
/ 27 сентября 2019

У вас есть функция, которая имеет 5 уровней вложенных условных блоков, что слишком много, потому что ее сложнее читать.Вы должны попытаться создать меньшие функции с одним или двумя уровнями.Более того, для рекурсивных функций, чем меньше она использует переменную, тем меньше она будет съедать ваш стек.Небольшие функции часто приводят к функциям, которые по отдельности занимают меньше места в памяти.

C, в отличие от python, не рассматривается как попытка чего-либо и посмотреть, работает ли .Ваш второй opendir может вызвать проблемы.допустим, он открывает каталог /home/users/toto/work.Вы открыли свой каталог, и сразу после того, как вы вызовете do_ls, который .... откроет /home/users/toto/work в другой раз.Если дважды открыть один и тот же каталог ... ну, я понятия не имею, работает ли он, но это не хорошо.Не используйте opendir, чтобы увидеть, является ли файл каталогом, используйте stat ( man 2 )

. Вы никогда не закрываете свои каталоги.Вы не сможете использовать свою находку на большом дереве.В C вы должны вручную освобождать все ресурсы, которые не являются частью стека памяти.

Использование рекурсивной функции в этом случае не является проблемой, на мой взгляд, проще рекурсивно реализовать такую ​​программу.Но было бы лучше открыть каталог, сохранить весь его контент, закрыть каталог, а затем прочитать сохраненный контент.Таким образом, вы всегда сохраняете как можно меньше каталогов.

Создайте функцию, которая предназначена для компонентов пути concatenante (и которые будут), когда начинаются малые функциональные возможности, подобные этой, часто бывает скучно отлаживать, и вы можете захотетьиметь выделенную и простую для тестирования функцию для выполнения этой работы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...