Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Центр помощи > [C] Обработка файла


Автор: Hersio 5.12.2006, 14:58
Дана информация о владельцах автомобилей одного города в файле А1. Элемент файла включает фамилию, имя, отчество владельца, марку автомобиля, год его выпуска и номер автомобиля(номер задаётся 4 цифрами) 
Найти:
Число автомобилей каждой марки с учётом года выпуска. Эти сведения должны включать марку автомобиля, год выпуска, число автомобилей.

С файлами пока не работал и даже вообще незнаю что делать, помогите?

Автор: Mercator 5.12.2006, 16:38
Взять книжку по си и почитать, что делать с файлами.

Автор: Hersio 5.12.2006, 17:44
Книга есть по С++ но там слишком замудрено и непонятно.
Вообще алгоритм какой?
Открыть файл записать в массив а - фамилию, в б - Имя, в с- отчество, потом две переменые для года и номера. 
Вот как дальше то ?
Потом сравнивать строки и искать на повторение марки и года выпуска, далее создать новый файл и туа записать результаты?                                                        

Автор: Mercator 6.12.2006, 10:53
Hersio, пожалуйста, уточните, надо ли вам на си или си++, потому что у них файловый ввод-вывод  разный. И если надо все-таки на си, то читайте книжку по си. И надо скорее всего пользоваться структурами, то есть информацию по каждому владельцу хранить в каждом отдельном экземпляре объявленной вами соответствующей структуры, то есть объявить стуктуру, создать массив структур и в него и читать (про структуры тоже в книжке). К сожалению, сейчас не имею доступа к конкретным материалам, поэтому только даю совет.

Автор: Hersio 8.12.2006, 12:34
мне  нужно на си, вот я понять не могу, мне весь файл в массив а потом посимвольно проверять, или каждую строку? помогите объясните как хоть делать?smile

Автор: Mercator 8.12.2006, 16:57
Hersio, так, давайте следующим образом. Тут два главных аспекта я вижу для вас в задаче: первое - как организовать структуры для хранения данных, второе - непосредственно алгоритм подсчета чего вам  надо (кстати, объясните, пожалуйста, более подробно, что именно надо посчитать). Вижу вам никто не пишет, так хоть я чего скажу. К сожалению, на си писала давно и сейчас ничего нет под рукой, поэтому могу только дать направление, куда идти.
Начнем с первого. Не знаю, какие у вас есть книжки по Си, я зашла сюда: http://forum.vingrad.ru/topic-33456.html и скачала книжку номер 8 (на русском, естественно). Керниган и Ритчи знают, о чем говорят, когда пишут про Си. Там читаем раздел "структуры" и создаем свою структуру (н-р, autoOwner) с 6 полями, вам нужными. Скорее всего, строковые поля будут указателями на массив символов. Обращайтесь к книжке, там много полезной информации. Ну а год выпуска и номер автомобиля обычные инты. 
Я не знаю, как у вас организован файл. Допустим, каждое новое значение в новой строке. У нас должен быть массив структур того типа, какой вы определили. Тогда открываем файл и построчно функцией fgets из нее читаем. Значения первых 6 строчек присваиваем соответствующим полям в первой структурке в массиве, следующих 6 строчек - второй и т.д., пока не кончатся строчки, то бишь, файл. Это вам придется самому подумать, как организовать. Наверное, будет проблема, как прочитанную строчку привести к типу инт для года и номера авто. К сожалению, не помню, как это делается. Поищите сами.
Про файлы написано у Кернигана доступно в отдельной главе (открыли файл на чтение, прочитали, закрыли файл. Не забывайте закрывать)). 

Если я правильно поняла, то надо посчитать для каждого года число автомобилей каждой марки. Я бы наверно сделала так (что-то более простое в голову не пришло).  Как бы это объяснить попонятнее... Мне понадобится еще один массив строк (назовем его "Марка" и массив целых чисел ("Год"). А в описание структуры я ввожу еще два целочисленных поля, типа марка_id и год_выпуска_id. Фактически каждой отдельной марке (это же строка, да?) я хочу поставить в соответствие целое число, назовем его идентификатором марки, а каждому встречающемуся году - свой идентификатор года. Таким образом в дополнительном массиве строк "Марка" у меня на i-том месте будет записана какая-то марка машины (все марки, естественно, по одному разу), то же самое для года выпуска. Будем считать, что у нас есть уже готовый массив структур с данными, прочитанными из файла. Теперь мне надо в цикле просмотреть все структуры и заполнить эти поля идентификаторы, то есть привести к виду, что например если 3-им элементом у меня в массиве "Марка" идет марка "Хонда", то все структуры с "Хондой" должны в поле марка_id иметь 3, то же самое с годом выпуска. Это можно сделать за один проход массива структур, одновременно заполняя поля-идентификаторы и формируя нужные массивы. Фактически я "проиндексировала" марки и года выпуска.
Далее я делаю квадратную матрицу m*n, где m - число разных марок (фактически количество строк в массиве "Марка"), n - число разных годов выпуска. Пусть это будет матрица А и она вся нулевая. Потом еще раз просматриваю массив структур и для каждой увеличиваю А[марка_id][год_выпуска_id] на единицу. В результате получаю матрицу с нужным количеством машин i-той марки j-того года выпуска. Далее тупо просматриваю матрицу и если элемент больше 0 (А[i][j]>0)пишу в файл, что мол в год[j] было А[i][j] машинок марки Марка[i] (то есть как бы обратная замена: вместо индексов - реальные значения). Вот мне как-то так видится....
А для сравнения строк скорее всего придется написать отдельную функцию посимвольного сравнения, на вход подаете две строки (по-видимому, два указателя на char) и на выходе "истина" или "ложь"
Прошу прощения, если что не так)))

Автор: Hersio 10.12.2006, 12:01
Mercator Большое вам спасибо, сам принцип я понел, а вот как это организовать?smile Хотелось бы чтобы помог Олегыч)
Олегыч помоги сделаю всё что хочешьsmile

Автор: Oleg_Ci 10.12.2006, 16:14
Тут наверно на курсовик потянет smile 
Код

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define len 100 // максимальная длинна слов

#define inStr( report, str )  printf( report ); \
    scanf("%s", str ); \
    if( !strcmp( str, "end" )){ \
        delete c; \
        return NULL; }

#define inInt( report, a ) printf( report ); \
    if( !scanf( "%d", &a )){ \
    delete c; \
    return NULL; }

typedef struct CAR{
    char
        famile[len], // фамилия
        name[len], // имя
        patronymic[len], // фамилия
        brand[len]; // марка автомобиля
    int
        year, // год выпуска
        number; // номер автомобиля
    struct CAR * next;
}Car;

typedef struct NODE{
    Car * car; // указатель на авто
    struct NODE * next;
    int count; // количесто "подобных" авто
}Node;

Car * NewCar ( FILE * file ); // функция создаёт и заполняет структуру Car
void WriteList( FILE * file, Car * c ); // функция записи структуры
Car * ReadList( FILE * file, Car ** c ); // функция создаёт связанный список, возвращает первый элемент
void FreeCar( Car * c ); // удаление связанного списка
void IsOpen( FILE * file ); // если неможем открыть файл то выходим мз программы

/////////////// main ///////////////////
int main(int argc, char *argv[])

    // создание файла "A1.txt"
    FILE * file = fopen( "A1.txt", "w+" ); // файл для записи и чтения
    IsOpen( file );

    Car *begin = NULL, *node;
    ReadList( stdin, &begin );// читаем с консоли
    WriteList( file, begin ); // запись в файл
    FreeCar( begin ); // Удаление списка

    fflush( file );
    rewind( file );

    ReadList( file, &begin ); // счивываем данные из файла
    puts("\n\n\n_____Data is read file:_____ \n\n"); // Данные являются прочитанными из файла
    WriteList( stdout, begin ); // вывод прочитанных данных на консоль
    fclose( file );
    clearerr( file );
/*
Найти:
Число автомобилей каждой марки с учётом года выпуска. 
Эти сведения должны включать марку автомобиля, год выпуска, число автомобилей.
*/
    Node *beg = NULL, *en, *data;// список "похожих" авто
    // поиск "похожих" авто
    int flag=1;
    for( node = begin; node; node=node->next ){ //  перебираем все авто
        flag = 1;
        for( data = beg; data; data=data->next ){
            if( !strcmp( data->car->brand, node->brand ) && // если марки авто совпадают
                data->car->year == node->year && beg ){// если один и тотже год выпуска
                data->count++; // значит это ещё один "похожий" авто
                flag = 0;
                break;
            }// end fi
        }// end for Node
        if( flag ){ // если авто не похожи
            if( !beg ) beg = en = (Node*)malloc( sizeof(Node));
            else    en = en->next = (Node*)malloc( sizeof(Node));

            en->car = node;
            en->count = 1;
            en->next = NULL;
        }// end if
    }// end for Car

    file = fopen("A2.txt", "w"); // файл для записи
    // вывод строки :"Число автомобилей каждой марки с учётом года выпуска:"
    puts("\n\nNumber of cars of every brand taking into account the year of release:\n");

    for( data = beg; data;  ){
        printf("%s  %d,  count = %d\n", data->car->brand, data->car->year, data->count );
        fprintf( file, "%s  %d,  count = %d\n", data->car->brand, data->car->year, data->count );
        data = data->next;
        free(beg); // удаление элемента из списка
        beg = data;
    }
    FreeCar( begin ); // Удаление списка
    fclose( file );
    puts("\n\nPress the key ENTER for the program exit");
    fflush(stdin);
    getchar(); // пауза
    return 0;
}
///////////////// End main //////////////////////

Car * NewCar ( FILE * file ){
    Car * c = (Car*) malloc( sizeof(Car));
    if( file != stdin ){ // если читаем из файла
        if( fscanf( file, "%s%s%s%s%d%d", c->famile, c->name , c->patronymic, c->brand,
            &c->year, &c->number ) <=0 ){
            free( c );
            return NULL;
        }
    }
    else{ // если читаем с консоли
        puts("\nNew Car, \"end\" - to exit :");
        inStr( "famile > ", c->famile );
        inStr( "name > ", c->name );
        inStr( "patronymic > ", c->patronymic );
        inStr( "brand car > ", c->brand );
        inInt( "year > ", c->year );
        inInt( "nubber car > ", c->number );
    }
    c->next = NULL;
    return c;
}
void WriteList( FILE * file, Car * c ){
    for(; c; c=c->next )
        fprintf( file, "%s %s %s %s %d %d\n", c->famile, c->name , c->patronymic, c->brand,
            c->year, c->number );
}
Car * ReadList( FILE * file, Car ** c ){
    Car *end = NULL, *node; // указатели на конец, и добавляемый элемент (автомобиль)
    // цикл чтения, пока читается...
    while(( node = NewCar( file )) != NULL ){
        if( !end ) *c = end = node; // если "вставляем" первый раз
        else{
            end->next = node; // указатель последнего на новый элемент
            end = node; // указатель конца на новый эл.
        }
    }
    return *c;
}
void FreeCar( Car * c ){
    Car * a;
    while( c ){
        a = c;
        c = c->next;
        delete a;
    }
}
void IsOpen( FILE * file ){
    if( !file ){
        puts("\n\nError open file !!!");
        puts("\n\nPress the key ENTER for the program exit");
        fflush( stdin );
        getchar();
        exit(1);
    }
}

Автор: Oleg_Ci 10.12.2006, 17:44
Ну если создавать файл не надо, то так мажно попробовать
Код

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define len 100 // максимальная длинна слов

typedef struct NODE{
    char brand[len]; // марка автомобиля
    int year, // год выпуска
        count; // количесто "подобных" авто
    struct NODE * next;
}Node;

void IsOpen( FILE * file );

/////////////// main ///////////////////
int main(int argc, char *argv[])

    // создание файла "A1.txt"
    FILE * file = fopen( "A1.txt", "r" ); // файл для чтения
    IsOpen( file );
    char ch[len];
    int num;
/*
Найти:
Число автомобилей каждой марки с учётом года выпуска. 
Эти сведения должны включать марку автомобиля, год выпуска, число автомобилей.
*/
    Node *beg, *en, *data, node;// список "похожих" авто
    beg = (Node*)malloc( sizeof(Node));
    en = beg->next = NULL;
    // поиск "похожих" авто
    int flag=1;
    while( fscanf( file, "%s%s%s%s%d%d", ch, ch, ch, node.brand, &node.year, &num ) >0 ){
        flag = 1;
        for( data = beg; data; data=data->next ){
            if( !strcmp( data->brand, node.brand ) && // если марки авто совпадают
                data->year == node.year && en ){// если один и тотже год выпуска
                data->count++; // значит это ещё один "похожий" авто
                flag = 0;
                break;
            }// end fi
        }// end for Node
        if( flag ){ // если авто не похожи
            if( !en ) en = beg;
            else en = en->next = (Node*)malloc( sizeof(Node));
            strcpy( en->brand, node.brand );
            en->year = node.year;
            en->count = 1;
            en->next = NULL;
        }// end if
    }// end for Car

    fclose( file );
    clearerr( file );
    file = fopen("A2.txt", "w"); // файл для записи
    IsOpen( file );
    // вывод строки :"Число автомобилей каждой марки с учётом года выпуска:"
    puts("\n\nNumber of cars of every brand taking into account the year of release:\n");

    for( data = beg; data;  ){
        printf("%15s %5d, \tcount = %d\n", data->brand, data->year, data->count );
        fprintf( file, "%15s %5d, \tcount = %d\n", data->brand, data->year, data->count );
        data = data->next;
        free(beg); // удаление элемента из списка
        beg = data;
    }
    fclose( file );
    puts("\n\nPress the key ENTER for the program exit");
    fflush(stdin);
    getchar(); // пауза
    return 0;
}
///////////////// End main //////////////////////
void IsOpen( FILE * file ){
    if( !file ){
        puts("\n\nError open file !!!");
        puts("\n\nPress the key ENTER for the program exit");
        fflush( stdin );
        getchar();
        exit(1);
    }
}

Автор: Hersio 10.12.2006, 18:33
Вот большое тебе спасибо и респект, ты мозгsmile Шас буду разбиратьсяsmile Если, что-нибудь понадобится пиши, сделаю всё возможноеsmile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)