Исключение обработки ввода с использованием динамического массива на языке C
Столкнулся с проблемой обработки вводимых данных с использованием двумерного динамического массива. При вводе корректного значения в строке 55:
readCount = scanf_s("%d", &array[i][j]);
выскакивает сообщение:
Вызвано исключение по адресу 0x7BF49D4E (ucrtbased.dll) в laba5_3.exe: 0xC0000005: нарушение прав доступа при записи по адресу 0xCDCDCDCD.
Гуглил эту проблему, но ничего конкретного по С так и не нашел. Прошу помочь с решением данной проблемы.
#include <stdio.h>
#include <locale.h>
#include <stdlib.h>
#include <malloc.h>
int ClearStdin()
{
int rv = 1;
int ch;
while (1) {
ch = getchar();
if (ch == '\n' || ch == EOF) {
break;
}
rv = 0;
}
return rv;
}
int main() {
setlocale(LC_ALL, "");
int n, m, countzero = 0, countneg = 0, countpos = 0, readCount, isEmpty;
int **array;
printf("Введите размерность (n) и (m) массива \n");
//Проверка n
while (1) {
readCount = scanf_s("%d", &n);
isEmpty = ClearStdin();
if (readCount == 1 && isEmpty != 0 && n > 0) {
break;
}
printf("Неверный формат числа. Введите целое положительное число\n");
}
//Проверка m
while (1) {
readCount = scanf_s("%d", &m);
isEmpty = ClearStdin();
if (readCount == 1 && isEmpty != 0 && m > 0) {
break;
}
printf("Неверный формат числа. Введите целое положительное число\n");
}
array = (int*)malloc(n * m * sizeof(int));
//Ввод элементов матрицы
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++)
{
printf("Введите целый элемент в формате (a,b) [%d,%d]\n", i, j);
//Проверка
while (1) {
readCount = scanf_s("%d", &array[i][j]);
isEmpty = ClearStdin();
if (readCount == 1 && isEmpty != 0) {
break;
}
printf("Неверный формат числа. Введите целое положительное число\n");
}
}
}
//Вывод матрицы
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
printf("%d ", array[i][j]);
printf("\n");
}
//Поиск отрицательных,положительных и нулей
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (array[i][j] < 0) {
countneg++;
}
else if (array[i][j] == 0) {
countzero++;
}
else if (array[i][j] > 0) {
countpos++;
}
}
}
printf("Колво положительных :%d\nКолво нулей :%d\nКолво отрицательных :%d", countpos, countzero, countneg);
free(array);
return 0;
}
Ответы (3 шт):
Э нет, это так не работает...
Раз вы объявили
int **array;
то уже никаких
array = (int*)malloc(n * m * sizeof(int));
Компилятор же не знает, как обратиться к array[i][j].
Так что лучше всего
array = malloc(n * sizeof(int*));
for(int i = 0; i < n; ++i)
array[i] = malloc(m*sizeof(int));
Вот тогда
array[i][j]
имеет смысл...
Ну, и не забывайте потом освобождать память тоже - сначала в цикле, потом общий указатель.
А вообще посмотрите тут - там это все разобрано подробно...
P.S. Еще - как примечание - в С приведение результата malloc() к типу вашего указателя не нужно. Если компилятор ругается - значит, вы компилируете код не как С, а как С++.
Двумерный динамический массив A создается следующим образом:
int **A = (int **)malloc(N*sizeof(int *));
for(int i = 0; i < N; i++) {
A[i] = (int *)malloc(M*sizeof(int));
}
, где переменные N и M - строки и стобцы соответственно.
Касательно функциональности, дальше всё стандартно: объявление счетчиков i и j для строк и столбцов соответственно.
Очистка памяти для данного массива выглядит таким образом:
for(int i = 0; i < N; i++) {
free(A[i]);
}
free(A);
Итоговый вариант кода:
#include <stdio.h>
#include <locale.h>
#include <malloc.h>
#include <stdlib.h>
int ClearStdin()
{
int rv = 1;
int ch;
while (1) {
ch = getchar();
if (ch == '\n' || ch == EOF) {
break;
}
rv = 0;
}
return rv;
}
int main() {
setlocale(LC_ALL, "");
int N, M;
int readCount, isEmpty;
printf_s("Введите размерность N: "); //ввод N
while (1) {
readCount = scanf_s("%d", &N);
isEmpty = ClearStdin();
if (readCount == 1 && isEmpty != 0 && N > 0) {
break;
}
printf("Неверный формат числа. Введите целое положительное число\n");
}
printf_s("Введите размерность M: "); //ввод M
while (1) {
readCount = scanf_s("%d", &M);
isEmpty = ClearStdin();
if (readCount == 1 && isEmpty != 0 && M > 0) {
break;
}
printf("Неверный формат числа. Введите целое положительное число\n");
}
int** A = (int**)malloc(N * sizeof(int*));
for (int i = 0; i < N; i++) {
A[i] = (int*)malloc(M * sizeof(int));
}
//создание динамической матрицы N*M
int i, j;
for(i = 0; i < N; i++)
for (j = 0; j < M; j++) {
printf_s("A[%d][%d] = ", i + 1, j + 1);
//scanf_s("%d", &A[i][j]);
while (1) {
readCount = scanf_s("%d", &A[i][j]);
isEmpty = ClearStdin();
if (readCount == 1 && isEmpty != 0) {
break;
}
printf("Неверный формат числа. Введите целое положительное число\n");
}
}
//заполнение матрицы с клавиатуры
int countneg = 0, countzero = 0, countpos = 0;
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if (A[i][j] < 0) {
countneg++;
}
else if (A[i][j] == 0) {
countzero++;
}
else if (A[i][j] > 0) {
countpos++;
}
}
}
printf("Кол-во положительных :%d\nКол-во нулей :%d\nКол-во отрицательных :%d", countpos, countzero, countneg);
for (int i = 0; i < N; i++) {
free(A[i]);
}
free(A);
// очистка памяти
return 0;
}
Если n это количество строк матрицы, то для того способа ее представления (один кусок памяти), что вы используете, нельзя писать array[i][j] для доступа к ее элементам.
Объявить переменную для такой матрицы целых чисел придется вот так int *array (указатель на целые, а не указатель на указатель, как у вас написано).
Тогда для доступа к элементу [i][j] надо писать array[i * n + j].
И для ввода данных получится scanf("%d" &array[i * n + j]) или scanf("%d", array + i * n + j).
Кстати, память под матррицу array = (int*)malloc(n * m * sizeof(int)); вы выделили правильно.