Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум на CrossPlatform.RU _ С\С++ _ Нужна срочно помощь, небольшая программка

Автор: eu8cc 31.5.2010, 11:59

Помогите с программкой, не могу понять как написать ее:

написать программу, находящую в заданном каталоге и всех его подкаталагах все файлы заданного размера. Имя
каталога задается пользователем в качестве третьего аргумента командной строки. Диапазон (мин мах)
размеров файлов задается пользователем в качестве первого и второго аргумента командной строки. Программа
выводит результат поиска в файл(четвертый аргумент командной строки) в виде полный путь, имя файла, его
размер. На консоль выводиться сообщения числа просмотренных файлов.

На линуксе

Автор: Iron Bug 31.5.2010, 12:05

а что непонятного в задании?
собственно, была какая-то попытка её решить вообще?
задания обычно даются с вполне конкретной целью - научить человека думать.

Автор: eu8cc 31.5.2010, 12:50

#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <ftw.h>
#include <sys/stat.h>
#include <time.h>
#include <stdint.h>

size_t s1,s2; //размер файлов в диапазоне s1 <= x <= s2
FILE *f = NULL;
time_t to_sec(char *date);



int main (int argc,char* argv[])
{
    
    if (argc != 5)
    {    
        fprintf(stderr,"Не все параметры заданы\n");
        errno = EINVAL; //invalid arguments
        perror(argv[0]);
        printf("формат: нач_размер кон_размер папка имя_файла\n");
        return -1;    
    }    
    f = fopen (argv[4],"w+");    
    if ( f == NULL)
    {
        printf("NULL\n");
        fprintf(stderr,"Ошибка создания файла \"%s\"",argv[4]);
        perror(", ");
        return -1;
    }    */
    DIR *dr = opendir(argv[3]);    
    if (dr == NULL)    
    {
        fprintf(stderr,"Невозможно открыть директорию \"%s\"",argv[1]);
        fclose(f);
        errno = ENOENT;// no such file or directory
        perror(", ");
        return -1;
    }
    s1 = atol(argv[1]);
    s2 = atol(argv[2]);
    ftw(argv[3],tree,0);    //обход дерева
    closedir(dr);
    fclose(f);
    return 0;
}


Как можно сделать поиск по размеру?

Автор: Iron Bug 31.5.2010, 12:57

а где у тебя сам обработчик обхода дерева, собственно? символ tree вообще непонятно где определён. у меня тут линя нет, но что-то я не припомню такой стандартной функции.

Автор: eu8cc 31.5.2010, 13:07

tree это есть моя функция обработки, тока как ее написать???

Автор: Iron Bug 31.5.2010, 13:16

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

Автор: eu8cc 31.5.2010, 13:47

по ходу так?

static int tree (const char *filename, const struct stat *status, int flag)
{    
    if (flag == FTW_F && status->st_size >= s1 && status->st_size <= s2)
    {

    }
    return 0; //возвращаем 0, чтобы продолжить обход дерева,иначе обход прерывается
}

Автор: Iron Bug 31.5.2010, 14:57

ну, что-то похожее.

Автор: eu8cc 31.5.2010, 15:41

Проверте, раюотает или нет

#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <ftw.h>
#include <sys/stat.h>
#include <time.h>
#include <stdint.h>

size_t s1,s2; //размер файлов в диапазоне s1 <= x <= s2
FILE *f = NULL;

static int tree (const char *filename, const struct stat *status, int flag)
    if (flag == FTW_F && status->st_size >= s1 && status->st_size <= s2)
    {
        fprintf(f,"%-40s %-10jd %s\n",filename, (intmax_t) status->st_size);//пишем в файл
    }
    return 0; //возвращаем 0, чтобы продолжить обход дерева,иначе обход прерывается
}

int main (int argc,char* argv[])
{
    
    if (argc != 5)
    {    
        fprintf(stderr,"Не все параметры заданы\n");
        errno = EINVAL; //invalid arguments
        perror(argv[0]);
        printf("формат: нач_размер кон_размер папка имя_файла\n");
        return -1;    
    }    
    f = fopen (argv[4],"w+");    
    if ( f == NULL)
    {
        printf("NULL\n");
        fprintf(stderr,"Ошибка создания файла \"%s\"",argv[4]);
        perror(", ");
        return -1;
    }    */
    DIR *dr = opendir(argv[3]);    
    if (dr == NULL)    
    {
        fprintf(stderr,"Невозможно открыть директорию \"%s\"",argv[1]);
        fclose(f);
        errno = ENOENT;// no such file or directory
        perror(", ");
        return -1;
    }
    s1 = atol(argv[1]);
    s2 = atol(argv[2]);
    ftw(argv[3],tree,0);    //обход дерева
    closedir(dr);
    fclose(f);
    return 0;
}


и как определить полный путь к файлу?

Автор: alex977 31.5.2010, 15:57

Цитата(eu8cc @ 31.5.2010, 13:50) *
...
ftw(argv[3],tree,0); //обход дерева
...


Из книжки А.Роббинс. Linux: программирование в примерах. Пер с англ. - М.: КУДИЦ-ОБРАЗ, 2005. - 656 с.

Глава 8
Цитата
Со временем стало ясно, что интерфейс ftw() не вполне выполнял свою работу; например, первоначально он не поддерживал символические ссылки. По этим причинам к Х/Ореn Portability Guide, который теперь является частью POSIX, была добавлена nftwO («new (новая) ftw()» [важно]).


eu8cc, похоже, что эта книжка будет тебе полезной, раз под Линукс прогр-ть собираешься.

Автор: Litkevich Yuriy 31.5.2010, 15:57

eu8cc, читай об оформлении сообщений: http://www.forum.crossplatform.ru/index.php?showtopic=1455

Автор: eu8cc 31.5.2010, 16:13

Цитата(alex977 @ 31.5.2010, 15:57) *
Из книжки А.Роббинс. Linux: программирование в примерах. Пер с англ. - М.: КУДИЦ-ОБРАЗ, 2005. - 656 с.
книга то полезная, но мне нужно срочно справиться с задачей, я так понимаю что мне нужно за мест ftw использовать nftw

#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <ftw.h>
#include <sys/stat.h>
#include <time.h>
#include <stdint.h>

size_t s1,s2; //размер файлов в диапазоне s1 <= x <= s2
FILE *f = NULL;

static int tree (const char *filename, const struct stat *status, int flag)
    if (flag == FTW_F && status->st_size >= s1 && status->st_size <= s2)
    {
        fprintf(f,"%-40s %-10jd %s\n",filename, (intmax_t) status->st_size);//пишем в файл
    }
    return 0; //возвращаем 0, чтобы продолжить обход дерева,иначе обход прерывается
}

int main (int argc,char* argv[])
{
    
    if (argc != 5)
    {    
        fprintf(stderr,"Не все параметры заданы\n");
        errno = EINVAL; //invalid arguments
        perror(argv[0]);
        printf("формат: нач_размер кон_размер папка имя_файла\n");
        return -1;    
    }    
    f = fopen (argv[4],"w+");    
    if ( f == NULL)
    {
        printf("NULL\n");
        fprintf(stderr,"Ошибка создания файла \"%s\"",argv[4]);
        perror(", ");
        return -1;
    }    */
    DIR *dr = opendir(argv[3]);    
    if (dr == NULL)    
    {
        fprintf(stderr,"Невозможно открыть директорию \"%s\"",argv[1]);
        fclose(f);
        errno = ENOENT;// no such file or directory
        perror(", ");
        return -1;
    }
    s1 = atol(argv[1]);
    s2 = atol(argv[2]);
    nftw(argv[1],tree,0, FTW_DEPTH || FTW_PHYS);    //обход дерева
    closedir(dr);
    fclose(f);
    return 0;
}


по ходу так?

Автор: BRE 31.5.2010, 16:35

Цитата(eu8cc @ 31.5.2010, 17:13) *
по ходу так?

    nftw(argv[1],tree,0, FTW_DEPTH || FTW_PHYS);    //обход дерева
    //     ~~~~~  Наверное здесь, все таки, argv[3]. Не?


Автор: alex977 31.5.2010, 16:36

Похоже. eu8cc, у меня линукса нет проверить.
Только вот

Цитата
} */


какой-то мусор (нет начала комментария).
Насколько я понял - главное ф-цию tree реализовать правильно.

Автор: Litkevich Yuriy 31.5.2010, 17:52

Цитата(eu8cc @ 31.5.2010, 20:13) *
по ходу так?
дык, а скомпилить и проверить?

Автор: eu8cc 31.5.2010, 18:17

Цитата(Litkevich Yuriy @ 31.5.2010, 17:52) *
дык, а скомпилить и проверить?


не могу у меня линукс стоит, но криво


подправил но согласно начальному условию нужно пройти все вложенные каталоги и подкаталоги, интересно это сможет сделать программка?
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <ftw.h>
#include <sys/stat.h>
#include <time.h>
#include <stdint.h>

size_t s1,s2; //размер файлов в диапазоне s1 <= x <= s2
FILE *f = NULL;

static int tree (const char *filename, const struct stat *status, int flag)
    if (flag == FTW_F && status->st_size >= s1 && status->st_size <= s2)
    {
        fprintf(f,"%-40s %-10jd %s\n",filename, (intmax_t) status->st_size);//пишем в файл
    }
    return 0; //возвращаем 0, чтобы продолжить обход дерева,иначе обход прерывается
}

int main (int argc,char* argv[])
{
    
    if (argc != 5)
    {    
        fprintf(stderr,"Не все параметры заданы\n");
        errno = EINVAL; //invalid arguments
        perror(argv[0]);
        printf("формат: нач_размер кон_размер папка имя_файла\n");
        return -1;    
    }    
    f = fopen (argv[4],"w+");    
    if ( f == NULL)
    {
        printf("NULL\n");
        fprintf(stderr,"Ошибка создания файла \"%s\"",argv[4]);
        perror(", ");
        return -1;
    }    */
    DIR *dr = opendir(argv[3]);    
    if (dr == NULL)    
    {
        fprintf(stderr,"Невозможно открыть директорию \"%s\"",argv[1]);
        fclose(f);
        errno = ENOENT;// no such file or directory
        perror(", ");
        return -1;
    }
    s1 = atol(argv[1]);
    s2 = atol(argv[2]);
    nftw(argv[3],tree,0, FTW_DEPTH || FTW_PHYS);    //обход дерева
    closedir(dr);
    fclose(f);
    return 0;
}

Автор: alex977 31.5.2010, 20:58

Из ранее упоминавшейся книги (буквально предыдущий абзац):

Цитата
Чтобы избавиться от проблем, System V предложила функцию ftw () («file tree walk» - обход дерева файлов). ftw() осуществляла всю работу по «прохождению» дерева (иерархии) файлов. Вы предоставляете ей указатель на функцию, и она вызывает эту функцию для каждого объекта файла, с которым сталкивается. Ваша функция должна затем обработать каждый объект файловой системы, как считает нужным.


Какие объекты будут обрабатываться - вложенные каталоги, файлы, символьные ссылки - определяют флаги.

Автор: Iron Bug 1.6.2010, 6:46

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

Автор: eu8cc 1.6.2010, 8:50

я тоже думаю что не нужны линки

Iron Buq, набросайте пожалуйста на ваше усмотрения кода, как Вы считаете она должна быть решаться?
Я уже дальше не знаю что делать. А сдать ее уже нужно.

Автор: alex977 1.6.2010, 9:26

Iron Bug, я к тому, что это универсальная ф-ция. Что перебирать - определяет пользователь, устанавливая нужные флаги.

eu8cc, у тебя в принципе все уже есть. Нужно только проверить работу программы на реальном каталоге.
По результатам - вносить изменения.

Автор: eu8cc 7.6.2010, 8:23

а если так организовать?

void find(char const *dirname,int minsize,int maxsize,FILE *out);
{
  DIR *dr=opendir (const char *dirname);  
  if (dr==NULL)
         {
     fprintf(stderr,"Невозможно открыть директорию \"%s\"",dirname);
     fclose(out);
     errno = ENOENT;
     perror(", ");
     return -1; exit(1);
   }
  
   struct dirent *dt;
   while((dt=readdir(dr)))
   {
        if(dt->d_type=DT_DIR) find;
        if(dt->d_type=DT_REG)
        {
            if(((dt->st_size)>minsize) $$ ((dt->st_size)<maxsize)))
            {
              fprintf(out,"%-40s %-10jd %s\n",filename, (intmax_t) dt->st_size);
              i=i+1;
            }
        }
   }
return 0;  
}
int main (int argc,char* argv[])
{
  
    if (argc != 5)
    {    
        fprintf(stderr,"Не все параметры заданы\n");
        errno = EINVAL; //invalid arguments
        perror(argv[0]);
        printf("формат: нач_размер кон_размер папка имя_файла\n");
        return -1;    
    }    
    out = fopen (argv[4],"w+");    
    if ( out == NULL)
    {
        printf("NULL\n");
        fprintf(stderr,"Ошибка создания файла \"%s\"",argv[4]);
        perror(", ");
        return -1;
    }    
    DIR *dr = opendir(argv[3]);    
    if (dr == NULL)    
    {
        fprintf(stderr,"Невозможно открыть директорию \"%s\"",argv[3]);
        fclose(out);
        errno = ENOENT;// no such file or directory
        perror(", ");
        return -1;
    }
    minsize = atol(argv[1]);
    maxsize = atol(argv[2]);
    dirname = argv[3]
    find(*dirname,minsize, maxsize, FILE *out);
    printf ("Число просмотренных файлов равно %d\n", i);
    closedir(dr);
    fclose(out);
    return 0;
}

Автор: Tonal 2.7.2010, 8:40

А чё тут думать?

# find ~ -size 100M

Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)