Вопрос или проблема
Почему строки и столбцы становятся случайными числами, когда я изменяю их входные данные?
Привет, я создавал симуляцию распространения огня в лесу, и в принципе, почти закончил. Единственная проблема заключается в том, что, когда я изменяю числа строк и столбцов, они становятся огромными числами ниоткуда. Я уверен, что упускаю что-то простое, но не могу понять, в чем дело.
#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
, когда вы изменяете их ввод.
Анализ проблемы
-
Объявление многомерного массива: В вашем коде массив
forest
объявлен с динамическими размерами в функцииmain
следующим образом:char forest[rows][colm];
Это означает, что размер массива зависит от значений
rows
иcolm
, которые вы считываете из файла. - Использование массива с фиксированным размером: Однако в различных функциях, таких как
treeInput
и других, вы передаете массивforest
с фиксированным значением для второго измерения:void treeInput(char forest[][102], int rows, int colm, int *totTrees);
Здесь
forest
объявлен с фиксированной шириной, равной 102. Эта разница в способах объявления массива приводит к неправильному обращению к памяти.
Последствия
Когда вы пытаетесь обратиться к элементам массива forest
, который на самом деле имеет размеры [rows][colm]
, но используете его как если бы он был [x][102]
, вы выходите за пределы выделенной памяти, что может затереть значения других переменных (rows
, colm
и других) в стеке. Это и приводит к тому, что вы видите "гигантские" числа при выводе rows
и colm
.
Решение
-
Используйте правильный синтаксис: Для передачи многомерного массива в функции с динамическими размерами, вам нужно передать размер второго измерения как параметр функции. Например, вы можете изменить функцию
treeInput
следующим образом:void treeInput(char forest[][MAX_COL], int rows, int colm, int *totTrees);
Где
MAX_COL
— это максимальное значение числа колонн, которое ваше приложение может поддерживать (например, 102). -
Использовать указатели: Либо вы можете рассмотреть возможность использования указателей для передачи массива:
void treeInput(char **forest, int rows, int colm, int *totTrees);
При этом вам нужно будет динамически выделить память с использованием
malloc
, что усложняет код, но полностью исключает проблему с фиксированными размерами. - Пример использования
malloc
:
Если вы выберете динамическую аллокацию, то ваш код будет выглядеть примерно так:char **forest = malloc(rows * sizeof(char *)); for (int i = 0; i < rows; i++) forest[i] = malloc(colm * sizeof(char));
Заключение
Таким образом, основная причина вашей проблемы в том, что вы неправильно обращаетесь к многомерному массиву с различными размерами, что приводит к перезаписи данных. Исправление объявления массивов и/или обращение к ним будет решать вашу проблему. Убедитесь, что размеры массива совпадают везде, где он используется!