Загрузка...

Сохранение и считывание с бинарного файла

Тема в разделе C/C++ создана пользователем rorochan1999 16 апр 2024. 180 просмотров

Загрузка...
  1. rorochan1999
    rorochan1999 Автор темы 16 апр 2024 7 16 май 2022
    :anime_hi: Мне нужно чтобы все записывалось в бинарный файл (предусмотреть, если его нет, и тогда сказать что база данных пуста). Тоесть, чтобы при первом запуске бд была пустая, человек заполнил структуру, она сохранилась в бинарный файл и при следуюзем запуске, когда человек захочет посмотреть список студентов он увидит данные о том студенте, данные о котором вводил в прошлый раз. Не пойму то-ли я как-то неправильно считываю, то-ли сохраняю в файл что-то не то. Помогите умоляю!:с

    C
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>

    int isValidPositiveNaturalNumber2(const char* str) { // Check
    int r = 0;
    while (str[r] != '\0') {
    if (!isdigit(str[r]) || isalpha(str[r])) {
    return 0;
    }
    r++;
    }
    return 1;
    }

    typedef enum { // Enum
    MALE,
    FEMALE
    } Gender;

    typedef struct { // Struct
    int year;
    int month;
    int day;
    } Date;

    typedef struct Student { // Struct
    char *lastName;
    char *firstName;
    char *middleName;
    Date birthDate;
    char *group;
    Gender gender;
    struct Student* next;
    } Student;

    void freeStudentList(Student *students) { // Free list of students
    Student *current = students;
    while (current != NULL) {
    Student *temp = current;
    current = current->next;
    free(temp->lastName);
    free(temp->firstName);
    free(temp->middleName);
    free(temp->group);
    free(temp);
    }
    }

    void appendStudent(Student **head, Student *newStudent) { // Append student to the end of the list
    if (*head == NULL) {
    *head = newStudent;
    } else {
    Student *current = *head;
    while (current->next != NULL) {
    current = current->next;
    }
    current->next = newStudent;
    }
    }

    Student* createStudentNode(const char *lastName, const char *firstName, const char *middleName, Date birthDate, const char *group, Gender gender) { // Create a new student node
    Student *newStudent = (Student*)malloc(sizeof(Student));
    if (newStudent == NULL) {
    printf("Error: Failed to allocate memory for a new student\n");
    return NULL;
    }

    newStudent->lastName = strdup(lastName);
    newStudent->firstName = strdup(firstName);
    newStudent->middleName = strdup(middleName);
    newStudent->birthDate = birthDate;
    newStudent->group = strdup(group);
    newStudent->gender = gender;
    newStudent->next = NULL;

    return newStudent;
    }

    void printStudentList(Student *students) { // Print the list of students
    FILE *file = fopen("data.bin", "rb"); // Open file for reading in binary mode
    if (file == NULL) {
    printf("The list of students is empty.\n");
    return;
    }

    // Read data from the file
    Student *current = (Student*)malloc(sizeof(Student));
    if (current == NULL) {
    printf("Error: Failed to allocate memory for a student.\n");
    fclose(file);
    return;
    }

    size_t read = fread(current, sizeof(Student), 1, file);
    if (read != 1) {
    printf("The list of students is empty.\n");
    fclose(file);
    free(current);
    return;
    }

    printf("List of students:\n");
    while (!feof(file)) {
    printf("%s %s %s\n", current->lastName, current->firstName, current->group);
    read = fread(current, sizeof(Student), 1, file);
    }

    fclose(file);
    free(current);
    }

    void appendNewStudent(Student **head) { // Append a new student
    char lastName[50];
    char firstName[50];
    char middleName[50];
    char yearStr[20], monthStr[20], dayStr[20], genderChoiceStr[20];
    int year, month, day, genderChoice;
    char group[10];

    printf("Enter the student's last name: ");
    scanf("%s", lastName);
    printf("Enter the student's first name: ");
    scanf("%s", firstName);
    printf("Enter the student's middle name: ");
    scanf("%s", middleName);

    while (1) {
    printf("Enter the student's birth year: ");
    year = scanf("%s", yearStr);

    if (year != 1 || !isValidPositiveNaturalNumber2(yearStr)) {
    printf("Invalid input. Please enter a positive integer.\n");
    while (getchar() != '\n');
    continue;
    }

    year = atoi(yearStr);

    if (year < 1900 || year > 2024) {
    printf("The birth year should be between 1900 and 2024. Please try again.\n");
    } else {
    break;
    }
    }

    // Similar loops for month and day inputs

    printf("Enter the student's group: ");
    scanf("%s", group);

    // Similar loop for gender input

    Gender gender = genderChoice == 0 ? MALE : FEMALE;

    Date birthDate = {year, month, day};

    Student *newStudent = createStudentNode(lastName, firstName, middleName, birthDate, group, gender);
    if (newStudent == NULL) {
    printf("Error: Failed to add a new student.\n");
    return;
    }

    appendStudent(head, newStudent);

    // Get data from the file
    FILE *file = fopen("data.bin", "ab"); // Open file for appending in binary mode
    if (file == NULL) {
    printf("Error: Failed to open the file for writing.\n");
    return;
    }

    // Write data of the new student to the file
    size_t written = fwrite(newStudent, sizeof(Student), 1, file);
    if (written != 1) {
    printf("Error writing to the file.\n");
    } else {
    printf("The student has been successfully added to the list and written to the file.\n");
    }

    fclose(file);
    }

    void menu(Student *students) { // Main menu
    char userChoiceStr[20];
    int result;

    while (1) {
    result = scanf("%s", userChoiceStr);

    if (result != 1 || !isValidPositiveNaturalNumber2(userChoiceStr)) {
    printf("Invalid input. Please enter a positive integer.\n");
    while (getchar() != '\n');
    continue;
    }

    result = atoi(userChoiceStr);

    if (result == 4) {
    break;
    }

    switch (result) {
    case 1:
    printStudentList(students);
    break;

    case 2:
    appendNewStudent(&students);
    break;

    case 3:
    printf("sdfsd");
    break;

    default:
    printf("Invalid choice, please select again.\n");
    break;
    }
    }
    }

    int main() {
    Student* students = NULL; // Initialization

    menu(students);

    freeStudentList(students); // Cleanup

    return 0;
    }
     
  2. wolzar
    wolzar 16 апр 2024 Эм типо ок - https://lolz.live/threads/8613994/ 1481 21 окт 2022
    Сам я хз, но вот что нейронка написала:

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


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

    typedef enum {
    MALE,
    FEMALE
    } Gender;

    typedef struct {
    int year;
    int month;
    int day;
    } Date;

    typedef struct {
    char lastName[50];
    char firstName[50];
    char middleName[50];
    Date birthDate;
    char group[10];
    Gender gender;
    } Student;

    void printStudentList() {
    FILE *file = fopen("data.bin", "rb");
    if (file == NULL) {
    printf("The list of students is empty.\n");
    return;
    }

    Student current;
    printf("List of students:\n");
    while (fread(&current, sizeof(Student), 1, file)) {
    printf("%s %s %s\n", current.lastName, current.firstName, current.group);
    }

    fclose(file);
    }

    void appendNewStudent() {
    Student newStudent;

    printf("Enter the student's last name: ");
    scanf("%s", newStudent.lastName);
    printf("Enter the student's first name: ");
    scanf("%s", newStudent.firstName);
    printf("Enter the student's middle name: ");
    scanf("%s", newStudent.middleName);

    printf("Enter the student's birth year: ");
    scanf("%d", &newStudent.birthDate.year);
    printf("Enter the student's birth month: ");
    scanf("%d", &newStudent.birthDate.month);
    printf("Enter the student's birth day: ");
    scanf("%d", &newStudent.birthDate.day);

    printf("Enter the student's group: ");
    scanf("%s", newStudent.group);

    char genderChoice;
    do {
    printf("Enter the student's gender (M/F): ");
    scanf(" %c", &genderChoice);
    genderChoice = toupper(genderChoice);
    } while (genderChoice != 'M' && genderChoice != 'F');

    newStudent.gender = (genderChoice == 'M') ? MALE : FEMALE;

    FILE *file = fopen("data.bin", "ab");
    if (file == NULL) {
    printf("Error: Failed to open the file for writing.\n");
    return;
    }

    fwrite(&newStudent, sizeof(Student), 1, file);

    fclose(file);

    printf("The student has been successfully added to the list and written to the file.\n");
    }

    int main() {
    while (1) {
    printf("1. Print student list\n");
    printf("2. Add new student\n");
    printf("3. Exit\n");

    int choice;
    scanf("%d", &choice);

    switch (choice) {
    case 1:
    printStudentList();
    break;
    case 2:
    appendNewStudent();
    break;
    case 3:
    return 0;
    default:
    printf("Invalid choice\n");
    }
    }
    }
     
  3. Sokk0l
    Вроде как это должно фиксануть если я правильно проблему понял

    C
    void writeStringToFile(FILE *file, const char *str) {
    size_t len = strlen(str) + 1;
    fwrite(&len, sizeof(len), 1, file);
    fwrite(str, sizeof(char), len, file);
    }

    char* readStringFromFile(FILE *file) {
    size_t len;
    if (fread(&len, sizeof(len), 1, file) != 1) {
    return NULL;
    }
    char *str = malloc(sizeof(char) * len);
    if (fread(str, sizeof(char), len, file) != len) {
    free(str);
    return NULL;
    }
    return str;
    }

    void appendNewStudent(Student **head) {
    // ... твой код ...

    FILE *file = fopen("data.bin", "ab");
    if (file == NULL) {
    printf("Error: Failed to open the file for writing.\n");
    return;
    }

    fwrite(newStudent, sizeof(Student), 1, file);
    writeStringToFile(file, newStudent->lastName);
    writeStringToFile(file, newStudent->firstName);
    writeStringToFile(file, newStudent->middleName);
    writeStringToFile(file, newStudent->group);

    // ... твой код ...
    }

    void printStudentList(Student *students) {
    FILE *file = fopen("data.bin", "rb");
    if (file == NULL) {
    printf("The list of students is empty.\n");
    return;
    }

    Student *current = (Student*)malloc(sizeof(Student));
    if (current == NULL) {
    printf("Error: Failed to allocate memory for a student.\n");
    fclose(file);
    return;
    }

    while (fread(current, sizeof(Student), 1, file) == 1) {
    current->lastName = readStringFromFile(file);
    current->firstName = readStringFromFile(file);
    current->middleName = readStringFromFile(file);
    current->group = readStringFromFile(file);

    printf("%s %s %s\n", current->lastName, current->firstName, current->group);

    free(current->lastName);
    free(current->firstName);
    free(current->middleName);
    free(current->group);
    }

    fclose(file);
    free(current);
    }
     
    1. rorochan1999 Автор темы
      18 апр 2024 Изменено
Top