@Mishele123

Почему возникает такая проблема с динамическим массивом (Язык Си)?

Мне нужно, чтобы в функции add_datas я мог добавить запись в массив после текущей. Текущая запись это переменная current. (После вызова функции программа обрывается и выводит: (процесс 13692) завершил работу с кодом -1073740940.) Грубо говоря я хочу сдвинуть все элементы относительно этой ячейки вправо и записать в нее значения. Но ошибка возникает на моменте сдвига элементов. Как ее исправить?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale>
#include <conio.h>
#include <Windows.h>


struct Student
{
    char name[256];
    char last_name[256];
    int age;
};

// Удалить дубликанты
void delete_dublicates(Student** arr, int* size)
{
    int count = *size;
    Student* data = *arr;
    for (int i = 0; i < count; i++)
    {
        for (int j = i + 1; j < count; j++)
        {
            if ((strcmp(data[i].name, data[j].name) == 0) && (strcmp(data[i].last_name, data[j].last_name) == 0) && (data[i].age == data[j].age))
            {
                for (int k = j; k < count - 1; k++)
                {
                    data[k] = data[k + 1];
                }
                count--;
            }
        }
    }
    data = (Student*)realloc(data, count * sizeof(Student));
    *size = count;
    *arr = data;
}

// Загрузить данные из файла
bool Read_datas(Student **arr, int *size)
{
    printf("\n");
    Student* data = *arr;
    Student tmp;
    int count = *size;
    FILE* file = fopen("datas.txt", "r");

    if (file != NULL)
    {
        while (!feof(file))
        {
            int read = fscanf(file, "%255[^,],%255[^,],%d\n",
                tmp.name,
                tmp.last_name,
                &tmp.age
            );

            if (read == 3)
            {
                count++;
                data = (Student*)realloc(data, count * sizeof(Student));
                data[count - 1] = tmp;
            }
            else
            {
                printf("Проблема при работе с файлом\n");
                fclose(file);
                return false;
            }
        }
    }
    else
    {
        printf("Ошибка при работе с файлом\n");
        return false;
    }

    delete_dublicates(&data, &count);

    *arr = data;
    *size = count;
    fclose(file);
    printf("Данные загружены\n");
    return true;
}
// Очистить массив
bool clean_arr(Student** arr, int* size)
{
    printf("\n");
    if (*arr == NULL)
    {
        printf("Массив и так пуст\n");
        return false;
    }
    else
    {
        *size = 0;
        *arr = NULL;
        printf("Массив очищен\n");
        return true;
    }
}  // 
// Загрузить данные в файл
bool update_datas(Student *arr, int size)
{
    printf("\n");
    FILE* file = fopen("datas.txt", "w");
    if (file != NULL)
    {
        for (int i = 0; i < size; i++)
        {
            fprintf(file, "%s,%s,%d", arr[i].name, arr[i].last_name, arr[i].age);
            fprintf(file, "\n");
        }
    }
    else
    {
        return false;
    }
    printf("Данные обновлены\n");
    fclose(file);
    return true;
}
// Сохранить файл результат
bool save_file_result(Student* arr, int size)
{
    printf("\n");
    char filename[FILENAME_MAX] = { 0 };
    printf("Введите название файла результата (не используйте пробел):");
    scanf("%s", filename);
    strcat(filename,".txt");
    FILE* file = fopen(filename, "a+");
    if (file != NULL)
    {
        for (int i = 0; i < size; i++)
        {
            fprintf(file, "%s,%s,%d", arr[i].name, arr[i].last_name, arr[i].age);
            fprintf(file, "\n");
        }
    }
    else
    {
        printf("Ошибка открытия файла");
    }
    printf("Данные сохранены в новый файл\n");
    fclose(file);
    return true;
}
// Вывести текущий элемент массива
void print_current(Student *arr, int i)
{
    system("cls");
    if (arr == NULL)
    {
        printf("\n");
        printf("Массив данных пуст");
    }
    else
    {
        printf("\n");
        printf("%s %s %d", arr[i].name, arr[i].last_name, arr[i].age);
        printf("\n");
    }
}

// Добавить элемент в массив после текущего
void add_datas(Student** arr, int* size, int offset)
{
    printf("\n");
    Student* data = *arr;
    int count = *size;
    count++;

    data = (Student*)realloc(data, count * sizeof(Student));

    for (int i = count; i > offset; i--)
    {
        data[i] = data[i - 1];
    }

    for (int i = 0; i < count; i++)
    {
        printf("%s %s %d\n", data[i].name, data[i].last_name, data[i].age);
    }
    *arr = data;
    *size = count;
}

int get_key()
{
    int key = _getch();
    if ((key == 0) || (key == 224)) key = _getch();
    return key;
}

int menu1()
{
    printf("\n");
    printf("Esc - конец программы\n1 - Загрузить данные из файла\n2 - Очистить массив данных\n3 - Сохранить данные в файл\n4 - сохранить файл результат\n5 - Работа с данными");
    while (true)
    {
        int key = get_key();
        if ((key == 27) || (key == 49) || (key == 50) || (key == 51) || (key == 52) || (key == 53)) return key;
    }
}

int menu2()
{
    printf("\n");
    printf("Следующая ->\nПредыдущая <-\nНазад: Esc\n1 - Добавить элемент после текущего");
    while (true)
    {
        int key = get_key();
        if ((key == 27) || (key == 75) || (key == 77) || (key == 49)) return key;
    }
}

int main()
{
    setlocale(LC_ALL, "ru");
    int size = 0;
    Student* arr = NULL;
    
    int current;
    while (true)
    {
        system("cls");
        printf("Начало программы\n");
        int m1 = menu1();
        if (m1 == 27) break;
        switch (m1)
        {
        case 49:
            Read_datas(&arr, &size);
            system("pause");
            break;
        case 50:
            clean_arr(&arr, &size);
            system("pause");
            break;
        case 51:
            update_datas(arr, size);
            system("pause");
            break;
        case 52:
            save_file_result(arr, size);
            system("pause");
            break;
        case 53:
            current = 0;
            while (true)
            {
                print_current(arr, current);
                int m2 = menu2();
                if (m2 == 27) break;
                switch (m2)
                {
                case 49:
                    add_datas(&arr, &size, current);
                    system("pause");
                    break;
                case 75:
                    if (current > 0) current--;
                    break;
                case 77:
                    if (current < size - 1) current++;
                    break;
                }
            }
        }
    }
    free(arr);
    return 0;
}
  • Вопрос задан
  • 89 просмотров
Решения вопроса 1
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
ошибка возникает на моменте сдвига элементов. Как ее исправить?
data = (Student*)realloc(data, count * sizeof(Student));

    for (int i = count; i > offset; i--)
    {
        data[i] = data[i - 1];
    }

Этот код пишет за конец массива, потому что если в массиве count элементов, то последний имеет индекс count - 1. Этот цикл должен быть таким: for (int i = count - 1; i > offset; i--)
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы