Как я могу записать структуру из двоичного файла во вложенную структуру в другом двоичном файле? - PullRequest
0 голосов
/ 14 мая 2019

У меня есть этот код. Допустим, я хочу связать полет 1 (сгенерированный с помощью функции InputFlight) с пользователем 1 (сгенерированный с помощью функции InputUser). Примечание: struct user имеет еще одну вложенную структуру с именем booking , которая имеет вложенную структуру с именем flight .

Перемещаясь с указателями через двоичные файлы, все, что я делаю, это:

Спросите пользователя номер рейса (предположим, первый рейс) -> Итак, я перехожу на первый рейс.

Спросите пользователя, какой он пользователь (предположим, первый пользователь) -> Итак, я перехожу к первому пользователю.

Затем через fread () и fwrite () , я пытаюсь скопировать то, что находится внутри структуры flight в travel.b.list , но как-то не получится.

Я уже все перепробовал. Я попытался изменить параметры в fwrite () и fseek () , но безуспешно. Я предполагаю, что основная проблема заключается в функции checkin () внутри booking.h, но я не могу ее решить.

main.c

#include <stdio.h>
#include <stdlib.h>

#include "flight.h"
#include "user.h"

void login_admin();

int main() {
    setbuf(stdout, NULL);

    login_admin();

return 0;
}

void login_admin() {

    FILE *file;
    FILE *file1;

    unsigned short int userchoice1 = 0;
    unsigned short int s = 0;

    while (s != 1) {    
        printf("\n-------------- M E N U --------------");
        printf("\n----- A D M I N I S T R A T O R -----");
        printf("\n1) Insert user");
        printf("\n2) Insert flight");
        printf("\n3) Check-in");
        printf("\n9) Exit program");
        printf("\n-------------------------------------");
        printf("\nYOUR CHOICE: ");
        scanf("%hu", &userchoice1);

        if (s != getchar()) {
        }
        switch (userchoice1) {
        case 1:
            inputUser(file);
            break;
        case 2:
            inputFlight(file);
            break;
        case 3:
            checkin(file, file1);
            break;
        case 9:
            s = 1;
            exit(0);
            break;
        default:
            printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
            printf("\nValue not valid.");
            break;
        }
    }
}

booking.h

#include <stdio.h>

 typedef struct {
    flight list;
    char booking_code[MAX_BOOKING_CODE];
} booking; //struct booking

 typedef struct {
    char name[MAX_NAME];
    char surname[MAX_SURNAME];
    date date_of_birth;
    char place_of_birth[MAX_PLACE_OF_BIRTH];
    char passport_number[MAX_PASSPORT];
    booking b;
 } user; //struct user

void checkin(FILE *flights, FILE *users) {

    flight list;
    user travelers;

    int user_number = 0;
    int choice = 0;
    int choice1= 0;

    if( (users = fopen("users.dat", "rb") ) == NULL) {
        printf("Error.(1)");
    }
    else
    {
        printf("\nWhat's your user number?");
        printf("\nUSER NUMBER: ");
        scanf("%d", &user_number);
        fseek(users, (user_number-1)*sizeof(user), SEEK_SET);
        fread(&travelers, 1, sizeof(user), users);

        if( (flights = fopen("flights.dat", "rb") ) == NULL) {
            printf("Error.");
        }
        else {
            printf("Available flights:\n\n");

                flights = fopen("flights.dat", "rb");

                while( !(feof(flights)))
                {

                int read = fread(&list, 1, sizeof(flight), flights);
                if ( read > 0) {
                    printf("Flight code: %s\nCompany name: %s\nDEPARTURE FROM: %s\nARRIVAL AT: %s\nPlane code: %s\nDay of flight: %hu\nMonth of flight: %hu\n"
                            "Year of flight: %hu\nHour of departure: %hu:%hu\nHour of arrival: %hu:%hu\nFlight time: %hu min.\n\n",
                            list.flight_code, list.companyname, list.departure,
                            list.arrival, list.plane_code, list.date_of_flight.day,
                            list.date_of_flight.month, list.date_of_flight.year, list.hour_departure,
                            list.minute_departure,list.hour_arrival,list.hour_departure, list.flight_time);
                }

            }

            printf("Which flight you want to choose?\n");
            printf("YOUR CHOICE: ");
            scanf("%d", &choice1);

            fseek(flights, (choice1-1)*sizeof(flight), SEEK_SET);
            fread(&list, 1, sizeof(flight), flights);

            printf("\n--------YOU CHOSE FLIGHT %d-------- \n\n", choice1);
                    printf("Flight code: %s\nCompany name: %s\nDEPARTURE FROM: %s\nARRIVAL AT: %s\nPlane code: %s\nDay of flight: %hu\nMonth of flight: %hu\n"
                            "Year of flight: %hu\nHour of departure: %hu:%hu\nHour of arrival: %hu:%hu\nFlight time: %hu min.\n\n",
                            list.flight_code, list.companyname, list.departure,
                            list.arrival, list.plane_code, list.date_of_flight.day,
                            list.date_of_flight.month, list.date_of_flight.year, list.hour_departure,
                            list.minute_departure,list.hour_arrival,list.hour_departure, list.flight_time);


            users = fopen("users.dat", "rb+");
            fseek(users, (user_number-1)*sizeof(user), SEEK_SET);

            fwrite(&travelers.b.list, 1, sizeof(user), users);

            fclose(users);
            fclose(flights);

flight.h

#include <stdio.h>
#include "define.h"

typedef struct {
    unsigned short int day;
    unsigned short int month;
    unsigned short int year;
 } date; //struct date

 typedef struct {
    char flight_code[MAX_FLIGHT_CODE];
    char companyname[MAX_COMPANY_NAME];
    char departure[MAX_DEPARTURE];
    char arrival[MAX_ARRIVAL];
    char plane_code[MAX_PLANE_CODE];
    unsigned short int seats[MAX_SEATS];
    date date_of_flight;
    unsigned short int hour_departure;
    unsigned short int minute_departure;
    unsigned short int hour_arrival;
    unsigned short int minute_arrival;
    unsigned short int flight_time;
} flight; //struct flight

void inputFlight(FILE *flight_file);

void inputFlight(FILE *flight_file) {

    flight list;

    static int i = 0;

    //for (int i = 0; i < 20; i++) {

        flight_file = fopen("flights.dat","wb");
        printf("Flight code %d: ", i+1);
        scanf("%6s", list.flight_code);
        fflush(stdin);
        printf("Company name of flight %d: ", i+1);
        scanf("%19s", list.companyname);
        fflush(stdin);
        printf("DEPARTURE: ");
        scanf("%19s", list.departure);
        fflush(stdin);
        printf("ARRIVAL: ");
        scanf("%19s", list.arrival);
        fflush(stdin);
        printf("Plane code of flight %d: ", i+1);
        scanf("%4s", list.plane_code);
        fflush(stdin);
        printf("Day of flight %d: ", i+1);
        scanf("%hu", &list.date_of_flight.day);
        fflush(stdin);
        printf("Month of flight %d: ", i+1);
        scanf("%hu", &list.date_of_flight.month);
        fflush(stdin);
        printf("Year of flight %d: ", i+1);
        scanf("%hu", &list.date_of_flight.year);
        fflush(stdin);
        printf("Hour and minutes of departure flight %d (separated by spacebar): ", i+1);
        scanf("%hu%hu", &list.hour_departure, &list.minute_departure);
        fflush(stdin);
        printf("Hour and minutes of arrival flight %d (separated by spacebar): ", i+1);
        scanf("%hu%hu", &list.hour_arrival, &list.minute_arrival);
        fflush(stdin);
        printf("Flight time: ");
        scanf("%hu", &list.flight_time);
        fflush(stdin);

        fwrite(&list, 1, sizeof(flight), flight_file);

        fclose(flight_file);

    //}
}

user.h

#include <stdio.h>
#include <stdlib.h>
#include "booking.h"

void inputUser(FILE *input);

void inputUser(FILE *input) {


    if( (input = fopen("users.dat", "wb") ) == NULL) {
        printf("Error.");
    }
    else {

        user travelers;

        static int i = 0;

        //for (int p = 0; p < 3; p++) {

            printf("Name user %d: ", i+1);
            scanf("%19s", travelers.name);
            fflush(stdin);
            printf("Surname user %d: ", i+1);
            scanf("%19s", travelers.surname);
            fflush(stdin);
            printf("Day of birth user %d: ", i+1);
            scanf("%hu", &travelers.date_of_birth.day);
            fflush(stdin);
            printf("Month of birth user %d: ", i+1);
            scanf("%hu", &travelers.date_of_birth.month);
            fflush(stdin);
            printf("Year of birth user %d: ", i+1);
            scanf("%hu", &travelers.date_of_birth.year);
            fflush(stdin);
            printf("Place of birth user %d: ", i+1);
            scanf("%9s", travelers.place_of_birth);
            fflush(stdin);
            printf("Passport number user %d: ", i+1);
            scanf("%8s", travelers.passport_number);
            fflush(stdin);

            fwrite(&travelers, 1, sizeof(user), input);
            i++;

        //}

        fclose(input);
    }
}

define.h

#ifndef DEFINE_H_
#define DEFINE_H_

#define MAX_NAME 20
#define MAX_SURNAME 20
#define MAX_PASSPORT 9
#define MAX_PLACE_OF_BIRTH 15

#define MAX_FLIGHT_CODE 6
#define MAX_COMPANY_NAME 20
#define MAX_DEPARTURE 20
#define MAX_ARRIVAL 20
#define MAX_PLANE_CODE 5
#define MAX_SEATS 150

#define MAX_BOOKING_CODE 5

#endif /* DEFINE_H_ */

Ожидаемые результаты: struct list , ищется (в основном выбран) через fseek () в функции checkin () должно быть сохранено внутри структуры travel.b.list , в то время как все, что я получаю, это сочетание различных символов и т. д., когда я пытаюсь распечатать его.

Надеюсь, у вас все ясно и заранее извините за плохое форматирование и т. Д.

Это действительно большой университетский проект для меня, надеюсь, кто-нибудь может мне помочь.

Спасибо.

1 Ответ

1 голос
/ 15 мая 2019

В inputUser вы пишете, делая

fwrite(&travelers, 1, sizeof(user), input);

кажется более логичным сделать

fwrite(&travelers, sizeof(user), 1, input);

потому что fwrite равно

size_t fwrite (const void * ptr, size_t size, size_t nmemb, FILE * stream);

вместо

size_t fwrite (const void * ptr, size_t nmemb, size_t size, ФАЙЛ * поток);

Конечно, это то же самое, что и в checkIn , и для fread , где вы также обмениваете nmemb и size


Примечание в регистрация вы делаете два раза flights = fopen("flights.dat", "rb"):

    if( (flights = fopen("flights.dat", "rb") ) == NULL) {
        printf("Error.");
    }
    else {
        printf("Available flights:\n\n");

            flights = fopen("flights.dat", "rb");

потому что вы используете ту же самую переменную flight , только второй ФАЙЛ может быть закрыт. Через некоторое время вы не сможете снова открыть файл, так как количество одновременно открытых файлов ограничено.


Внимание

 while( !(feof(flights)))

обычно не работает , используйте результат fread , чтобы остановить чтение


Вы можете удалить все свои fflush(stdin);, они ничего не делают:

Для входных потоков, связанных с доступными для поиска файлами (например, дисковые файлы, но не каналы или терминалы ), fflush () отбрасывает любые буферизованные данные ...


Я рекомендую вам проверить результат вашего scanf , чтобы убедиться, что введен правильный ввод, поэтому для проверки он возвращает 1, когда вы читаете значение, и 2, в нескольких случаях вы читаете 2 значения

Также в

   scanf("%d", &user_number);
   fseek(users, (user_number-1)*sizeof(user), SEEK_SET);
   fread(&travelers, 1, sizeof(user), users);

и

       scanf("%d", &choice1);

       fseek(flights, (choice1-1)*sizeof(flight), SEEK_SET);
       fread(&list, 1, sizeof(flight), flights);

нет проверки вообще

То есть вы не знаете, что читаете, вы предполагаете, что для user_number и choice1 было введено действительное значение int , вы предполагаете, что их значение совместимо с размером файла, тогда вы предполагаете Вы можете прочитать пользователь / полет

Вам действительно нужно добавить чеки


Полагаю, главная проблема в функции checkin () внутри booking.h

Да, при регистрации ваш способ изменения полетной части пользователя не верен, вы делаете

 fseek(users, (user_number-1)*sizeof(user), SEEK_SET);

 fwrite(&travelers.b.list, 1, sizeof(user), users);

fseek устанавливает положение в начале пользователя в файле, а не fwrite всех пользователей, которых вы fwrite подраздел travelers.b.list, поэтому вы заменяете имя / фамилию /... на полет (и память после него, потому что вы пишете размер пользователя, а не размер полета) ) который, кроме того, не инициализируется, поскольку ранее вы fread в переменной list , а не в travelers.b.list.

Способ исправить можно обновить travelers.b.list, чтобы потом написать все пользователю, чтобы заменить

       fread(&list, 1, sizeof(flight), flights);

       printf("\n--------YOU CHOSE FLIGHT %d-------- \n\n", choice1);
               printf("Flight code: %s\nCompany name: %s\nDEPARTURE FROM: %s\nARRIVAL AT: %s\nPlane code: %s\nDay of flight: %hu\nMonth of flight: %hu\n"
                       "Year of flight: %hu\nHour of departure: %hu:%hu\nHour of arrival: %hu:%hu\nFlight time: %hu min.\n\n",
                       list.flight_code, list.companyname, list.departure,
                       list.arrival, list.plane_code, list.date_of_flight.day,
                       list.date_of_flight.month, list.date_of_flight.year, list.hour_departure,
                       list.minute_departure,list.hour_arrival,list.hour_departure, list.flight_time);


       users = fopen("users.dat", "rb+");
       fseek(users, (user_number-1)*sizeof(user), SEEK_SET);

       fwrite(&travelers.b.list, 1, sizeof(user), users);

от

        fread(&travelers.b.list, sizeof(flight), 1, flights);

        printf("\n--------YOU CHOSE FLIGHT %d-------- \n\n", choice1);
                printf("Flight code: %s\nCompany name: %s\nDEPARTURE FROM: %s\nARRIVAL AT: %s\nPlane code: %s\nDay of flight: %hu\nMonth of flight: %hu\n"
                        "Year of flight: %hu\nHour of departure: %hu:%hu\nHour of arrival: %hu:%hu\nFlight time: %hu min.\n\n",
                        travelers.b.list.flight_code, travelers.b.list.companyname, travelers.b.list.departure,
                        travelers.b.list.arrival, travelers.b.list.plane_code, travelers.b.list.date_of_flight.day,
                        travelers.b.list.date_of_flight.month, travelers.b.list.date_of_flight.year, travelers.b.list.hour_departure,
                        travelers.b.list.minute_departure,travelers.b.list.hour_arrival,travelers.b.list.hour_departure, travelers.b.list.flight_time);


        users = fopen("users.dat", "rb+");
        fseek(users, (user_number-1)*sizeof(user), SEEK_SET);

        fwrite(&travelers, sizeof(user), 1, users);

Другой способ приблизиться к вашему коду - fseek в правильном положении и написать правильный полет с нужным размером, чтобы заменить

 fseek(users, (user_number-1)*sizeof(user), SEEK_SET);

 fwrite(&travelers.b.list, 1, sizeof(user), users);

от

 fseek(users, (user_number-1)*sizeof(user) + (((char *) &travelers.b.list) - ((char *) &travelers)), SEEK_SET);

 fwrite(&list, sizeof(list), 1, users);
...