Почему строки и столбцы становятся случайными числами, когда я изменяю их входные данные?

Вопрос или проблема

Почему строки и столбцы становятся случайными числами, когда я изменяю их входные данные?

Привет, я создавал симуляцию распространения огня в лесу, и в принципе, почти закончил. Единственная проблема заключается в том, что, когда я изменяю числа строк и столбцов, они становятся огромными числами ниоткуда. Я уверен, что упускаю что-то простое, но не могу понять, в чем дело.

#include <stdio.h>

void InfoInput(int *rows, int *colm, int *seed, int *fireProb){
    FILE *file;
    char line[256];
    file = fopen("Test.txt", "r");
    if (file ==NULL){
        printf("фатальная ошибка\n");
    }

    fscanf(file, "%d",rows);
    fscanf(file, "%d",colm);
    fscanf(file, "%d",seed);
    fscanf(file, "%d",fireProb);
}

void treeInput(char forest[][102], int rows, int colm, int *totTrees){
    FILE *file;
    char line[256];
    file = fopen("Test.txt", "r");
    if (file ==NULL){
        printf("фатальная ошибка\n");
    }

    char temp;
    int x=0, tempRow, tempColm;
    while(x<100){
        fscanf(file, " %c", &temp);
        if(temp == 'Q'){
            x=1;
            break;
        } else if(temp == 'A'){
            for(int i = 0; i<rows; i++){
                for(int j = 0; j<colm; j++){
                    forest[i][j] = 'T';
                }
            }
        } else if (temp == 'T'||temp == 'E'||temp == 'F'){
            fscanf(file, "%d", &tempRow);
            fscanf(file, "%d", &tempColm);
            if(temp == 'T'){
                forest[tempRow-1][tempColm-1] = 'T';
            } if(temp == 'F'){
                forest[tempRow-1][tempColm-1] = 'F';
            }
            else {
                forest[tempRow-1][tempColm-1] = '.';
            }
        }
    }
    for(int i = 0; i<rows; i++){
        for(int j = 0; j<colm; j++){
            if (forest[i][j] == 'T'){
                *totTrees += 1;
            }
        }
    }

}

void printInfo(char forest[][102], int rows, int colm, int seed, int fireProb, int totTrees){
    printf("S. Madden 9/20\n\n");
    printf("строки: %d\n", rows);
    printf("столбцы: %d\n", colm);
    printf("деревья: %d\n",totTrees);
    printf("семя: %d\n", seed);
    printf("вероятность: %d%%\n\n",fireProb);

}

int main()
{
    FILE *file;
    char line[256];
    file = fopen("Test.txt", "r");
    if (file ==NULL){
        printf("фатальная ошибка\n");
    }

    int rows, colm, seed, fireProb, Time=0;
    int totTrees = 0;

    InfoInput(&rows, &colm, &seed, &fireProb);
    //manualInput(&rows, &colm, &seed, &fireProb);

    char forest[rows][colm];

    treeInput(forest, rows, colm, &totTrees);

    printInfo(forest, rows, colm, seed, fireProb, totTrees);

    return 0;
}

это файл, который я вызываю

8
20
28
75
A
F 3 4
E 1 12
E 2 12
E 3 12
E 4 12
E 4 13
E 4 14
E 5 12
E 5 15
E 6 12
E 1 16
E 2 16
E 3 16
E 4 16
E 7 1
E 7 2
E 7 3
E 7 4
E 8 3
Q

вывод следующий

S. Madden 9/20

строки: 777278548
столбцы: 1414812756
деревья: 141
семя: 28
вероятность: 75%

эта программа работает идеально, когда есть 9 строк и 20 столбцов (с чем я проводил тесты), но когда я переключаюсь на 8, начинается безумие. (Кстати, это фрагмент кода, где я нашел проблему, есть и другое, но это не имеет значения для этой проблемы)

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

Проблема в том, что вы объявляете forest в функции main с динамическими числом строк и столбцов…

char forest[rows][colm];

Затем вы используете его в сигнатурах ваших функций с фиксированным числом столбцов.

char forest[][102]

Это приводит к тому, что C читает и записывает за пределами выделенных границ для forest, перезаписывая данные, хранящиеся в других переменных.


Например, пусть будет…

int rows = 3;
int colm = 4;
char forest[rows][colm];

forest выделен блок данных размером 3 x 4 = 12 байт. Некоторые другие переменные могут находиться в памяти сразу после этого.

___forest___
            __other__
123456789012345678901
^   ^   ^
^   ^   forest[2][0]
^   ^ 
^   forest[1][0]
^
forest[0][0]

Для краткости, я буду использовать forest[][10]. Если вы попытаетесь получить доступ к этому как forest[][10], это будет означать, что каждая строка занимает 10 байт. forest[0][0] аналогично, но forest[1][0] теперь указывает на 11 байт, а forest[2][0] на 21 байт.

___forest___
            __other__
123456789012345678901
^         ^         ^
^         ^         forest[2][0]
^         ^ 
^         forest[1][0]
^
forest[0][0]

Как видно, доступ к данным, выделенным для forest, как char forest[][10] пересекается с данными других переменных. В вашем случае это влияет на row и colm.

Ответ или решение

Проблема, с которой вы столкнулись, связана с тем, как вы объявляете и используете массив forest в вашем коде. Рассмотрим подробнее причины возникновения "случайных" значений для переменных rows и colm, когда вы изменяете их ввод.

Анализ проблемы

  1. Объявление многомерного массива: В вашем коде массив forest объявлен с динамическими размерами в функции main следующим образом:

    char forest[rows][colm];

    Это означает, что размер массива зависит от значений rows и colm, которые вы считываете из файла.

  2. Использование массива с фиксированным размером: Однако в различных функциях, таких как treeInput и других, вы передаете массив forest с фиксированным значением для второго измерения:
    void treeInput(char forest[][102], int rows, int colm, int *totTrees);

    Здесь forest объявлен с фиксированной шириной, равной 102. Эта разница в способах объявления массива приводит к неправильному обращению к памяти.

Последствия

Когда вы пытаетесь обратиться к элементам массива forest, который на самом деле имеет размеры [rows][colm], но используете его как если бы он был [x][102], вы выходите за пределы выделенной памяти, что может затереть значения других переменных (rows, colm и других) в стеке. Это и приводит к тому, что вы видите "гигантские" числа при выводе rows и colm.

Решение

  1. Используйте правильный синтаксис: Для передачи многомерного массива в функции с динамическими размерами, вам нужно передать размер второго измерения как параметр функции. Например, вы можете изменить функцию treeInput следующим образом:

    void treeInput(char forest[][MAX_COL], int rows, int colm, int *totTrees);

    Где MAX_COL — это максимальное значение числа колонн, которое ваше приложение может поддерживать (например, 102).

  2. Использовать указатели: Либо вы можете рассмотреть возможность использования указателей для передачи массива:

    void treeInput(char **forest, int rows, int colm, int *totTrees);

    При этом вам нужно будет динамически выделить память с использованием malloc, что усложняет код, но полностью исключает проблему с фиксированными размерами.

  3. Пример использования malloc:
    Если вы выберете динамическую аллокацию, то ваш код будет выглядеть примерно так:
    char **forest = malloc(rows * sizeof(char *));
    for (int i = 0; i < rows; i++)
       forest[i] = malloc(colm * sizeof(char));

Заключение

Таким образом, основная причина вашей проблемы в том, что вы неправильно обращаетесь к многомерному массиву с различными размерами, что приводит к перезаписи данных. Исправление объявления массивов и/или обращение к ним будет решать вашу проблему. Убедитесь, что размеры массива совпадают везде, где он используется!

Оцените материал
Добавить комментарий

Капча загружается...