Продолжая комментарии, если в упражнении используется массив переменной длины, его следует записать на C, поскольку стандарт C ++ не предоставляет VLA (и они были сделаны необязательными, начиная с C11 после добавления с C99)
Основная проблема с вашим кодом (за исключением полного сбоя при распределении входных данных) заключается в том, что он вызывает неопределенное поведение , поскольку int tmp_arr[tmp]
выходит из области видимости в конце цикла for
. То, что вы назначаете с помощью p_arr[i] = tmp_arr;
, больше не существует вне цикла, потому что tmp_arr
больше не существует. Любая попытка получить доступ к значению после его выхода из области действия вызывает неопределенное поведение , см. неопределенное, неопределенное и определяемое реализацией поведение
Каждый раз, когда вы обрабатываете ввод, вы должны проверять , ввод успешен, и полученное значение находится в допустимом диапазоне. Например, n
и q
должны быть положительными значениями. Используя scanf
вы можете сделать (минимально)
if (scanf("%d%d", &n, &q) != 2 || n <= 0 || q <= 0) {
fputs ("error: invalid format or value.\n", stderr);
return 1;
}
Вышеприведенное подтверждает, что 2 входа были получены и оба являются положительными значениями.
Чтобы сохранить указатель, назначенный с помощью p_arr[i] = tmp_arr;
, tmp_arr
должен быть выделенным типом для обработки неизвестного числа tmp
элементов, или он должен быть объявлен вне цикла (и достаточно большим, чтобы обрабатывать все ожидаемые значения). Значения - которые учитывая, что tmp
читается как ввод - не похоже на предполагаемый подход). Вы также не можете объявить tmp_arr
статическим, поскольку будет только один экземпляр, и при многократном присвоении ему p_arr[i]
все элементы p_arr[i]
будут указывать на одно и то же место.
Просто выделите tmp_arr
, и тогда присвоение p_arr[i]
сохранится в течение всей жизни программы или до ее освобождения, например,
int *tmp_arr = calloc (tmp, sizeof *tmp_arr); /* allocate */
if (!tmp_arr) { /* validate every allocation */
perror ("calloc-tmp_arr");
return 1;
}
p_arr[i] = tmp_arr;
( примечание: calloc
использовалось выше для обнуления новой выделенной памяти. Вместо этого можно использовать malloc
, поскольку код присваивается каждому элементу)
Сложив все это и добавив (минимальную) проверку, вы можете сделать что-то похожее на:
#include <stdio.h>
#include <stdlib.h>
int main (void) {
int n, q; /* validate EVERY input */
if (scanf("%d%d", &n, &q) != 2 || n <= 0 || q <= 0) {
fputs ("error: invalid format or value.\n", stderr);
return 1;
}
int *p_arr[n]; /* array of n-pointers to int */
for (int i = 0; i < n; i++) {
int tmp;
if (scanf("%d", &tmp) != 1 || tmp <= 0) { /* validate! */
fputs ("error: invalid input - tmp.\n", stderr);
return 1;
}
int *tmp_arr = calloc (tmp, sizeof *tmp_arr); /* allocate */
if (!tmp_arr) { /* validate every allocation */
perror ("calloc-tmp_arr");
return 1;
}
p_arr[i] = tmp_arr;
for (int j = 0; j < tmp; j++) {
int value;
if (scanf("%d", &value) != 1) { /* validate! */
fputs ("error: invalid input - value.\n", stderr);
return 1;
}
p_arr[i][j] = value;
printf ("%d ", p_arr[i][j]);
}
putchar ('\n'); /* no need to printf a single-character */
}
for (int i = 0; i < q; i++) {
int row, col; /* validate! */
if (scanf ("%d%d", &row, &col) != 2 || row < 0 || col < 0) {
fputs ("error: invalid input, row or col.\n", stderr);
return 1;
}
printf ("%d %d\n%d\n", row, col, p_arr[row][col]);
}
for (int i = 0; i < n; i++)
free (p_arr[i]);
return 0;
}
( Примечание: не проверено, поскольку ввод хакерранка не был предоставлен)
Посмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.