Перейти к содержимому

Как вывести двумерный массив c

  • автор:

Вывод двумерного массива си

Массив у вас располагается одним куском, так что обращение к array[i][j] осуществляется просто как к j -му элементу после i строк, т.е. к элементу номер i*(число столбцов)+j , т.е. в вашем варианте — array[i*n+j], где n` — число элементов в строке.

Заметим, что у вас строк — m , так что вы фактически заполняете массив по столбцам, и точно так же пытаетесь его выводить.

Вот так будет лучше:

int rows, cols; printf("Rows pls:"); scanf_s("%d", &rows); printf("columns pls:"); scanf_s("%d", &cols); arrayl = (int*)malloc(rows * cols * sizeof(int)); for (i = 0; i < rows; i++) < for (j = 0; j < cols; j++) < printf("arrayl (%d)(%d) = ", i, j); scanf_s("%d", &arrayl[i*cols+j]); >> for (i = 0; i < rows; i++) < for (j = 0; j < cols; j++) < printf("%5d ",arrayl[i*cols+j]); >printf("\n"); > 

Обратите внимание, что имена переменных — rows и cols (columns) не дают возможности спутать, что есть число строк (кстати, строка в таблице по-английски — row, но не string. ), что — столбцов. Я бы даже i и j поменял на r и c . Выбор имен переменных — куда важнее, чем кажется начинающим.

Двумерные массивы

Объявление int A[n] создает в памяти одномерный массив: набор пронумерованных элементов, идущих в памяти последовательно. К каждому элементу массива можно обратиться, указав один индекс — номер этого элемента. Но можно создать и двумерный массив следующим образом: int A[n][m] . Данное объявление создает массив из n объектов, каждый из которых в свою очередь является массивом типа int [m] . Тогда A[i] , где i принимает значения от 0 до n-1 будет в свою очередь одним из n созданных обычных массивов, и обратиться к элементу с номером j в этом массиве можно через A[i][j] .

Подобные объекты (массивы массивов) также называют двумерными массивами. Двумерные массивы можно представлять в виде квадратной таблицы, в которой первый индекс элемента означает номер строки, а второй индекс – номер столбца. Например, массив A[3][4] будет состоять из 12 элементов и его можно записать в виде

A[0][0] A[0][1] A[0][2] A[0][3] A[1][0] A[1][1] A[1][2] A[1][3] A[2][0] A[2][1] A[2][2] A[2][3]

Для считывания, вывода на экран и обработки двумерных массивов необходимо использовать вложенные циклы. Первый цикл – по первому индексу (то есть по всем строкам), второй цикл – по второму индексу, то есть по всем элементам в строках (столбцам). Например, вывести на экран двумерный массив в виде таблицы, разделяя элементы в строке одним пробелом можно следующим образом:

int A[n][m]; for (int i = 0; i < n; ++i) < // Выводим на экран строку i for (int j = 0; j < m; ++j) < cout cout 

А считать двумерный массив с клавиатуры можно при помощи еще более простого алгоритма (массив вводится по строкам, то есть в порядке, соответствующему первому примеру):

for (i = 0; i < n; ++i) < for (j = 0; j < m; ++j) < cin >> A[i][j]; > >

Обработка двумерного массива

Обработка двумерных массивов производится аналогичным образом. Например, если мы хотим записать в массив таблицу умножения, то есть присвоить элементу A[i][j] значение i * j , это можно сделать следующим образом при помощи вложенных циклов:

for (i = 0; i < n; ++i) < for (j = 0; j < m; ++j) < A[i][j] = i * j; >>

Рассмотрим более сложную задачу и несколько способов ее решения. Пусть дан квадратный двумерный массив int A[n][n] . Необходимо элементам, находящимся на главной диагонали проходящей из левого верхнего угла в правый нижний (то есть тем элементам A[i][j] , для которых i == j ) присвоить значение 1 , элементам, находящимся выше главной диагонали – значение 0, элементам, нахощящимся ниже главной диагонали – значение 2. То есть получить такой массив (пример для n == 4 ):

1 0 0 0 2 1 0 0 2 2 1 0 2 2 2 1

Рассмотрим несколько способов решения этой задачи. Элементы, которые лежат выше главной диагонали – это элементы A[i][j] , для которых i < j , а для элементов ниже главной диагонали i >j . Таким образом, мы можем сравнивать значения i и j и по ним определять значение A[i][j] . Получаем следующий алгоритм:

for (i = 0; i < n; ++i) < for (j = 0; j < n; ++j) < if (i < j) < A[i][j] = 0; >else if (i > j) < A[i][j] = 2; >else < A[i][j] = 1; >> >

Данный алгоритм плох, поскольку выполняет одну или две инструкции if для обработки каждого элемента. Если мы усложним алгоритм, то мы сможем обойтись вообще без условных инструкций.

Сначала заполним главную диагональ, для чего нам понадобится один цикл:

for (i = 0; i

Затем заполним значением 0 все элементы выше главной диагонали, для чего нам понадобится в каждой из строк с номером i присвоить значение элементам A[i][j] для j = i+1 , . n-1 . Здесь нам понадобятся вложенные циклы:

for (i = 0; i < n; ++i) < for (j = i + 1; j < n; ++j) < A[i][j] = 0; >>

Аналогично присваиваем значение 2 элементам A[i][j] для j = 0 , . i-1 :

for (i = 0; i < n; ++i) < for (j = 0; j < i; ++j) < A[i][j] = 2; >>

Можно также внешние циклы объединить в один и получить еще одно, более компактное решение:

for (i = 0; i < n; ++i) < // Заполняем строку с номером i for (j = 0; j < i; ++j) < A[i][j] = 2; // Сначала пишем 2 ниже диагонали >A[i][j] = 1; // После завершения предыдущего цикла i==j, пишем 1 for (++j; j < n; ++j) // Цикл начинаем с увеличения j на 1 < A[i][j] = 0; // Записываем 0 выше диагонали >>

Многомерные массивы

Можно объявлять не только двумерные массивы, но и массивы с большим количеством измерений. Например, объявление int A[n][m][l] создает трехмерный массив из n*m*l элементов. Для обращения к каждому элементу такого массива необходимо указать три индекса: A[i][j][k] , при этом 0

Передача двумерных массивов в функцию

В функцию можно передавать двумерный массив в качестве параметра, если размер этого массива фиксирован и объявлен в описании функции. То есть если заранее известен размер массива, то можно определить функцию, получающую в качестве параметра двумерный массив такого размера:

void f (int A[10][10]) < . >int main()

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

Чтобы использовать массивы произвольного размера, нам на помощь прийдут указатели. Для начала разберемся, как представлять двумерный массив в виде указателей.

Одномерный массив int A[n] это почти то же самое, что указатель на переменную типа int : int * A .

Тогда двумерный массив - это массив, каждый из элементов которого является одномерным массивом, то есть указателем на какой-то адрес целого числа в памяти. То есть двумерный массив - это массив элементов типа int * или же это указатель на переменную типа int * , то есть это переменная типа int ** .

Итак, двойной указатель можно объявить так:

int ** A;

Теперь выделим память для массива A . Если мы хотим, чтобы в массиве A было n элементов, каждый из которых является указателем на тип int , то сделаем это при помощи операции new :

A = new int * [n];

Теперь A указывает на область памяти, содержащей n элементов, каждый из которых имеет тип int * и указывает на некоторую область памяти, пока еще не выделенную. Выделим эту память - сделаем все A[i] указателями на область памяти из m элементов типа int :

for (int i = 0; i

Функцию, получающую в качестве параметра двумерный массив, можно объявлять так:

void f (int ** A, int n, int m)

Как и в случае с одномерным массивом, передаваемым как указатель, нам нужно одновременно передавать размеры массива - количество строк n и количество столбцов m .

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

Форматирование чисел при выводе

Допустим, мы заполним массив таблицей умножения: A[i][j]=i*j как в примере в начале раздела. Если мы теперь попробуем вывести этот массив на экран, разделяя элементы в строке одним пробелом, то из-за того, что числа имеют различную длину столбцы таблицы окажутся неровными:

0 0 0 0 0 0 0 0 0 0 0 1 2 3 4 5 6 7 8 9 0 2 4 6 8 10 12 14 16 18 0 3 6 9 12 15 18 21 24 27

Для того, чтобы получить ровные столбцы необходимо, выводить числа так, чтобы одно выводимое число имело ширину, например, ровно в 3 символа, а “лишние” позиции были бы заполнены пробелами. Тогда получится следующая таблица:

0 0 0 0 0 0 0 0 0 0 0 1 2 3 4 5 6 7 8 9 0 2 4 6 8 10 12 14 16 18 0 3 6 9 12 15 18 21 24 27

Для того, чтобы выводимое число или строка имело ровно заданную ширину, необходимо перед выводом его на экран для потока cout вызвать метод width с параметром 3 . Данный метод устанавливает ширину поля для выводимого значения. Получим следующую программу для вывода:

for(int i = 0; i < n; ++i) < for(int j = 0; j < m; ++j) < cout.width(3); cout cout

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

Внимание! Если выводимое число или строка имеет большую длину, чем это было установлено функцией width , то это число или строка будут выведены полностью, а не будет обрезано до указанного значения. То есть предпочтительней вывести результат некрасиво, нежели неверно.

Упражнения

Общие требования к оформлению программ.

Считывание данных осуществляется функцией void Read (int **& A, int & n, int & m) . Эта функция считывает размер массива в переменные n и m , передаваемые по ссылке, выделяет память под хранение массива.

Решение задачи осуществляется функцией, получающей в качестве параметра массив (типа int ** ), его размеры, дополнительные параметры при необходимости.

Вывод массива на экран осуществляется отдельной функцией Print , получающей в качестве параметров массив и его размеры.

Типичный вид программы на примере задачи A:

void Read (int **& A, int & n) < . >void Fill (int ** A, int n) < . >void Print (int ** A, int n) < . >int main()

A: Максимум

Найдите индексы первого вхождения максимального элемента. Выведите два числа: номер строки и номер столбца, в которых стоит наибольший элемент в двумерном массиве. Если таких элементов несколько, то выводится тот, у которого меньше номер строки, а если номера строк равны то тот, у которого меньше номер столбца.

Программа получает на вход размеры массива n и m , затем n строк по m чисел в каждой.

3 4
0 3 2 4
2 3 5 5
5 1 2 3

B: Снежинка

Дано нечетное число n . Создайте двумерный массив из n × n элементов, заполнив его символами "." (каждый элемент массива является строкой из одного символа). Затем заполните символами "*" среднюю строку массива, средний столбец массива, главную диагональ и побочную диагональ. В результате единицы в массиве должны образовывать изображение звездочки. Выведите полученный массив на экран, разделяя элементы массива пробелами.

C: Шахматная доска

Даны два числа n и m . Создайте двумерный массив размером n×m и заполните его символами "." и "*" в шахматном порядке. В левом верхнем углу должна стоять точка.

D: Диагонали параллельные главной

Дано число n . Создайте массив размером n×n и заполните его по следующему правилу. На главной диагонали должны быть записаны числа 0. На двух диагоналях, прилегающих к главной, числа 1. На следующих двух диагоналях числа 2, и т.д.

0 1 2 3 4
1 0 1 2 3
2 1 0 1 2
3 2 1 0 1
4 3 2 1 0

E: Побочная диагональ

Дано число n . Создайте массив размером n×n и заполните его по следующему правилу:

Числа на диагонали, идущей из правого верхнего в левый нижний угол равны 1.

Числа, стоящие выше этой диагонали, равны 0.

Числа, стоящие ниже этой диагонали, равны 2.

Полученный массив выведите на экран. Числа в строке разделяйте одним пробелом.

0 0 0 1
0 0 1 2
0 1 2 2
1 2 2 2

F: Поменять строки

Дан двумерный массив. Поменяйте в нем первую и последнюю строку. Полученный массив выведите на экран.

Программа получает на вход два числа: количество строк n в массиве и количество столбцов m . Далее идет n строк, каждая из которых содержит m чисел - элементы массива.

Выведите массив на экран разделяя числа в строке одним пробелом.

Решение оформите в виде функции void SwapRows (int ** A, int n, int m) .

3 4
11 12 13 14
21 22 23 24
31 32 33 34
31 32 33 34
21 22 23 24
11 12 13 14

G: Поменять столбцы

Дан двумерный массив и два числа: i и j . Поменяйте в массиве столбцы с номерами i и j и выведите результат.

Программа получает на вход размеры массива n и m , затем элементы массива, затем числа i и j .

Решение оформите в виде функции void SwapColumns (int ** A, int n, int m, int i, int j) .

3 4
11 12 13 14
21 22 23 24
31 32 33 34
0 1
12 11 13 14
22 21 23 24
32 31 33 34

H: Симметричен ли массив?

Дано число n и массив размером n×n . Проверьте, является ли этот массив симметричным относительно главной диагонали. Выведите слово “ YES ”, если массив симметричный, и слово “ NO ” в противном случае.

Решение оформите в виде функции bool IsSymmetric (int ** A, int n) .

3
0 1 2
1 2 3
2 3 4

I: k-я диагональ

Дан квадратный двумерный массив размером n×n и число k . Выведите элементы k -й по счету диагонали ниже главной диагонали (т.е. если k == 1 , то нужно вывести элементы первой диагонали, лежащей ниже главной, если k == 2 , то второй диагонали и т.д.).

Значение k может быть отрицательным, например, если k == -1 , то нужно вывести значение первой диагонали лежащей выше главной. Если k == 0 , то нужно вывести элементы главной диагонали.

Программа получает на вход число n , затем массив размером n×n , затем число k .

4
1 2 3 4
5 6 7 8
0 1 2 3
4 5 6 7
1
5 1 6
4
1 2 3 4
5 6 7 8
0 1 2 3
4 5 6 7
-2

J: Транспонировать прямоугольную матрицу

Дан двумерный массив размером n×m . Симметричный ему относительно главной диагонали массив называется транспонированным к данному. Он имеет размеры m×n : строки исходного массива становятся столбцами транспонированного, столбцы исходного массива становятся строками транспонированного.

Для данного массива постройте транспонированный массив и выведите его на экран. Решение оформите в виде функции void Transpose (int ** Src, int ** Dst, int n, int m) .

3 4
11 12 13 14
21 22 23 24
31 32 33 34
11 21 31
12 22 32
13 23 33
14 24 34

K: Транспонировать квадратную матрицу

Дан двумерный массив размером n×n . Транспонируйте его и результат запишите в этот же масссив. Вспомогательный массив использовать нельзя.

Решение оформите в виде функции void Transpose (int ** Src, int n) .

3
1 2 3
4 5 6
7 8 9
1 4 7
2 5 8
3 6 9

L: Поменять две диагонали

Дан квадратный массив. Поменяйте местами элементы, стоящие на главной и побочной диагонали, при этом каждый элемент должен остаться в том же столбце (то есть в каждом столбце нужно поменять местами элемент на главной диагонали и на побочной диагонали).

Решение оформите в виде функции void SwapDiagonals (int ** Src, int n) .

3
1 2 3
4 5 6
7 8 9
7 2 9
4 5 6
1 8 3

M: Кинотеатр

В кинотеатре n рядов по m мест в каждом. В двумерном массиве хранится информация о проданных билетах, число 1 означает, что билет на данное место уже продано, число 0 означает, что место свободно. Поступил запрос на продажу k билетов на соседние места в одном ряду. Определите, можно ли выполнить такой запрос.

Программа получает на вход числа n и m. Далее идет n строк, содержащих m чисел (0 или 1), разделенных пробелами. Затем дано число k.

Программа должна вывести номер ряда, в котором есть k подряд идущих свободных мест. Если таких рядов несколько, то выведите номер наименьшего подходящего ряда. Если подходящего ряда нет, выведите число 0.

3 4
0 1 0 1
1 0 0 1
1 1 1 1
2
3 3
0 1 0
1 0 0
1 1 1
3

N: Прямоугольник Паскаля

Даны два числа n и m. Создайте массив n×m и заполните его по следующим правилам:

Числа, стоящие в строке 0 или в столбце 0 равны 1 ( A[0][j] = 1 , A[i][0] = 1 ). Для всех остальных элементов массива A[i][j] = A[i-1][j] + A[i][j-1] , то есть каждый элемент равен сумме двух элементов, стоящих слева и сверху от него.

Выведите данный массив на экран, отводя на вывод каждого элемента массива ровно 6 символов (см. пример).

1 1 1 1 1 1 
1 2 3 4 5 6
1 3 6 10 15 21
1 4 10 20 35 56

O: Ходы коня

На шахматной доске стоит конь. Отметьте положение коня на доске и все клетки, которые бьет конь.

Программа получает на вход координаты коня на шахматной доске в шахматной нотации (то есть в виде “e4”, где сначала записывается номер столбца (буква от “a” до “h”, слева направо), затем номеру строки (цифра от 1 до 8, снизу вверх).

Клетку, где стоит конь, отметьте буквой “K”, клетки, которые бьет конь, отметьте символами “*”, остальные клетки заполните точками.

Выведите на экран изображение доски.

P: Ходы ферзя

Решите предыдущую задачу для ферзя. Ферзь обозначается буквой “Q”.

Q: Заполнение змейкой

По данным числам n и m заполните двумерный массив размером n×m числами от 1 до n×m “змейкой”, как показано в примере. Выведите полученный массив, отводя на вывод каждого элемента ровно 4 символа.

1 2 3 4 5 
10 9 8 7 6
11 12 13 14 15

R: Заполнение диагоналями

По данным числам n и m заполните двумерный массив размером n×m числами от 1 до n×m “диагоналями”, как показано в примере. Выведите полученный массив, отводя на вывод каждого элемента ровно 4 символа.

1 2 4 7 10 
3 5 8 11 13
6 9 12 14 15

S: Поворот прямоугольного массива

Дан прямоугольный массив размером n×m. Поверните его на 90 градусов по часовой стрелке, записав результат в новый массив размером m×n.

Выведите получившийся массив. Числа при выводе разделяйте одним пробелом.

3 4
11 12 13 14
21 22 23 24
31 32 33 34
31 21 11
32 22 12
33 23 13
34 24 14

T: Поворот квадратного массива

Дан квадратный массив. Поверните его на 90 градусов по часовой стрелке. Результат запишите в этот же массив, вспомогательный массив использовать нельзя.

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

3
1 2 3
4 5 6
7 8 9
7 4 1
8 5 2
9 6 3

U: Таблица умножения

Даны числа n и m. Создайте двумерый массив размером n×m и заполните его таблицей умножения по формуле A[i][j] = i * j . При заполнении массива нельзя использовать вложенные циклы.

Выведите получившийся массив на экран (при выводе можно использовать вложенные циклы), отводя на вывод каждого числа ровно 4 символа.

0 0 0 0 0 0 
0 1 2 3 4 5
0 2 4 6 8 10
0 3 6 9 12 15

V: Заполнение в шахматном порядке

Даны числа n и m. Заполните массив размером n×m в шахматном порядке: клетки одного цвета заполнены нулями, а другого цвета - заполнены числами натурального ряда сверху вниз, слева направо. В левом верхнем углу записано число 1.

Выведите полученный массив на экран, отводя на вывод каждого элемента ровно 4 символа.

1 0 2 0 3 
0 4 0 5 0
6 0 7 0 8

W: Заполнение спиралью

По данным числам n и m заполните двумерный массив размером n×m числами от 1 до n×m по спирали, выходящей из левого верхнего угла и закрученной по часовой стрелке, как показано в примере. Выведите полученный массив, отводя на вывод каждого элемента ровно 4 символа.

Тесты к этой задаче закрытые.

1 2 3 4 5 
14 15 16 17 6
13 20 19 18 7
12 11 10 9 8

X: Сапер

На поле для игры в сапер клеточки с минами обозначаются символом “*”, а в каждой пустой клеточке записано число от 0 до 8, равное количеству мин в 8 клетках, соседних с данной.

Дан список мин на поле. Постройте по данному списку изображение поля.

Программа получает на вход числа N и M - количество строк и столбцов на поле, а также количество мин на поле K. Далее идет K пар чисел - координат мин. Первое число - номер строки, второе число - номер столбца.

Выведите изображение поля на экран, клетки при выводе разделяйте одним пробелом.

Тесты к этой задаче закрытые.

3 2 2 1 1 2 2
* 2 2 * 1 1
2 2 0
0 0
0 0

Y: Крестики-нолики

Напишите программу, которая по изображению поля для игры в «Крестики-нолики» определит, могла ли такая ситуация возникнуть в результате игры с соблюдением всех правил.

Напомним, что игра в «Крестики-нолики» ведется на поле 33. Два игрока ходят по очереди. Первый ставит крестик, а второй – нолик. Ставить крестик и нолик разрешается в любую еще не занятую клетку поля. Когда один из игроков поставит три своих знака в одной горизонтали, вертикали или диагонали, или когда все клетки поля окажутся заняты, игра заканчивается.

Вводится три строки по три числа в каждой, описывающих игровое поле. Число 0 обозначает пустую клетку, 1 – крестик, 2 – нолик. Числа в строке разделяются пробелами.

Требуется вывести слово YES, если указанная ситуация могла возникнуть в ходе игры, и NO в противном случае.

Тесты к этой задаче закрытые.

1 1 1 1 1 1 1 1 1
2 1 1 1 1 2 2 2 1
1 1 1 2 0 2 0 0 0
0 0 0 0 1 0 0 0 0
1 1 1 2 2 2 0 0 0

Z: Городской план

План города представляет собой прямоугольник, разбитый на \(n\times m\) квадратиков. Каждый квадратик может быть занят зданием или быть свободным. Если два соседних (по стороне) квадратика заняты зданием, то это — оно и то же здание.

Программа получает на вход два числа \(n\) и \(m\), затем идет \(n\) строк по \(m\) символов в каждой — план города. Символ “ . ” обозначает свободную клетку, символ “ # ” обозначает здание.

Выведите число зданий на плане.

Тесты к этой задаче закрытые.

unixforum.org

Ввод и вывод двумерного(динамического) массива. (Не могу понять в чем дело.)

scriper Сообщения: 25 ОС: FreeBSD 7.0-STABLE Контактная информация:

Ввод и вывод двумерного(динамического) массива.

Сообщение scriper » 14.10.2007 15:26

Нужно ввести двумерный массив с неопределенной заранее размерностью(NxM) для решения некоторой задачи.

#include int main() < int N,M; //N- количество строк, M-количество стобцов. printf("Введи количество строк матрицы A:"); scanf("%d",&N); printf("Введи количество столбцов матрицы A:"); scanf("%d",&M); int** A; A= new int*[N]; //Ввод матрицы int i,j; for (i=0;i> //Вывод введенной матрицы printf("Введенная матрица:"); for (i=0;i printf("\n"); > delete []A; return 0; >

Резальтат выполнения

scriper@scriper.ate.loc: /usr/home/scriper/proj/labs2> g++ lab1_2.cpp scriper@scriper.ate.loc: /usr/home/scriper/proj/labs2> ./a.out Введи количество строк матрицы A:2 Введи количество столбцов матрицы A:2 1 2 3 4 Введенная матрица:-1515870811 -1515870811 -1515870811 -1515870811

Где ошибка?
Спасибо сказали:
Liksys Сообщения: 2910

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение Liksys » 14.10.2007 15:50

Сначала отформатируй по человечески код
Спасибо сказали:
scriper Сообщения: 25 ОС: FreeBSD 7.0-STABLE Контактная информация:

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение scriper » 14.10.2007 16:01

14.10.2007 15:50
Сначала отформатируй по человечески код

Что ты имеешь ввиду? Это как то повлияет на работаспособность програмы?
Спасибо сказали:
scriper Сообщения: 25 ОС: FreeBSD 7.0-STABLE Контактная информация:

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение scriper » 14.10.2007 16:13

Все, разбрался
Спасибо сказали:
Liksys Сообщения: 2910

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение Liksys » 14.10.2007 16:19

Понял, как повлияет?
Спасибо сказали:
sergio Сообщения: 436 Статус: Интересующийся новичок ОС: Debian GNU/Linux 4 & 5

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение sergio » 14.10.2007 16:28

14.10.2007 16:19
Понял, как повлияет?

Debian GNU/Linux 4 -- AMD Athlon64 3000+ / Asus 7600GS -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome

Спасибо сказали:
azrael Сообщения: 73 ОС: KUbuntu 8.04 Hardy Heron

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение azrael » 22.10.2007 21:13

Гениальное решение темы, 5 баллов
Спасибо сказали:
apacho Сообщения: 110 ОС: MOPSLinux 5.1

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение apacho » 29.10.2007 12:32

А для чего собственно нужна строка 23?У меня без неё всё отлично работает!
bash-3.1$ ./a.out
Введи количество строк матрицы A:2
Введи количество столбцов матрицы A:2
1
2
3
4
Введенная матрица:1 2
3 4

Окошки не нужны, нужны ПИНГВИНЫ.
Слака рулит.
Спасибо сказали:

drBatty Сообщения: 8735 Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит. ОС: Slackware-current Контактная информация:

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение drBatty » 29.10.2007 13:06

29.10.2007 12:32
А для чего собственно нужна строка 23?У меня без неё всё отлично работает!

ну и код у вас, господа. 23я строка это которая с new? А как же у вас с ней работало.
Это кстати не двухмерный массив, это массив указателей на одномерные массивы, и если их удалять, надо сначала удалить все эти одномерные массивы, а затем массив указателей. В Си нет многомерных массивов. Т.е. окончание должно выгладеть примерно так:

//Вывод и удаление введенной матрицы printf("Введенная матрица:"); for (i=0;i printf("\n"); delete[] A[i]; > delete[] A; return 0; >

И вообще, раз оператор new выполнился 1+N раз(в данном случае), значит оператор delete должен выполнится ровно столько же раз.

Скоро придёт
Осень

Спасибо сказали:
sergio Сообщения: 436 Статус: Интересующийся новичок ОС: Debian GNU/Linux 4 & 5

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение sergio » 29.10.2007 14:52

29.10.2007 12:32
А для чего собственно нужна строка 23?У меня без неё всё отлично работает!

А с ней?
В ней и заключалась "неисправность".

Debian GNU/Linux 4 -- AMD Athlon64 3000+ / Asus 7600GS -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome

Спасибо сказали:
apacho Сообщения: 110 ОС: MOPSLinux 5.1

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение apacho » 29.10.2007 17:24

А вот так нельзя сделать?

#include
int main() int N,M; //N- количество строк, M-количество стобцов.
printf("Введи количество строк матрицы A:");
scanf("%d",&N);
printf("Введи количество столбцов матрицы A:");
scanf("%d",&M);
int A[N][M];
//Ввод матрицы
int i,j;
for (i=0;i <
for(j=0;j scanf("%d",&A[i][j]);
>
>

Окошки не нужны, нужны ПИНГВИНЫ.
Слака рулит.
Спасибо сказали:
sergio Сообщения: 436 Статус: Интересующийся новичок ОС: Debian GNU/Linux 4 & 5

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение sergio » 29.10.2007 17:50

29.10.2007 17:24
А вот так нельзя сделать?

Почему низзя?

Debian GNU/Linux 4 -- AMD Athlon64 3000+ / Asus 7600GS -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome

Спасибо сказали:
apacho Сообщения: 110 ОС: MOPSLinux 5.1

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение apacho » 29.10.2007 19:10

Значит и надо так сделать!А то с этими указателями мозг перегреется!
Окошки не нужны, нужны ПИНГВИНЫ.
Слака рулит.
Спасибо сказали:
Liksys Сообщения: 2910

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение Liksys » 29.10.2007 19:23

А на старых компилерах нииибуууудет работать
Спасибо сказали:

drBatty Сообщения: 8735 Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит. ОС: Slackware-current Контактная информация:

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение drBatty » 29.10.2007 19:25

29.10.2007 17:24
А вот так нельзя сделать?

Нет, сам попробуй:

int N,M; int A[N][M];

Это ж не бейсик, всё ж. можно int A[N][M];тогда и только тогда, когда N,M целочисленные константы, а у тебя переменные.

Скоро придёт
Осень

Спасибо сказали:
Attila Сообщения: 125 Статус: Тролль-Лѣсовичокъ ОС: Свободная aka ArchLinux

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение Attila » 29.10.2007 19:35

Нет, ну совсем недавно же эта тема поднималась По стандарту С99 массивы переменной длины допустимы
Эван, эвое!
Поэтический Форум любителей и почитателей Э. Т. А. Гофмана (О системах * NIX)
Спасибо сказали:

drBatty Сообщения: 8735 Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит. ОС: Slackware-current Контактная информация:

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение drBatty » 29.10.2007 19:40

29.10.2007 19:35
Нет, ну совсем недавно же эта тема поднималась По стандарту С99 массивы переменной длины допустимы

. многомерные?
темы что-то не нашёл.

Скоро придёт
Осень

Спасибо сказали:
apacho Сообщения: 110 ОС: MOPSLinux 5.1

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение apacho » 29.10.2007 19:46

Ну тогда вот так:
#include
int main() int i; //N- количество строк, M-количество стобцов.
printf("Введи количество строк матрицы A:");
scanf("%d",&i);
const int N=i;
printf("Введи количество столбцов матрицы A:");
scanf("%d",&i);
const int M=i;
int A[N][M];
>

Окошки не нужны, нужны ПИНГВИНЫ.
Слака рулит.
Спасибо сказали:
Liksys Сообщения: 2910

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение Liksys » 29.10.2007 19:59

Многомерные!

[liksys@max ~]$ cat > test.c int main() < int a = 5; int b = 10; if ( a == 5 ) b = 10; int arr[a][b]; return 0; >[liksys@max ~]$ gcc -std=c9x -o test test.c [liksys@max ~]$ ./test

Но лучше использовать malloc()/free()
Спасибо сказали:

drBatty Сообщения: 8735 Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит. ОС: Slackware-current Контактная информация:

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение drBatty » 29.10.2007 20:04

29.10.2007 19:46
Ну тогда вот так:
const int M=i;
int A[N][M];

тоже не пойдёт. M - константная переменная типа const int. Ну хотя бы потому, что компилятору надо выделить памяти под A[][], а он не знает сколько именно. Когда используют new, вопрос стоит по другому: память выделяет не компилятор, а операционная система. Можно сделать так:

int main() < int A[10][10]; do< //ввод N, M так же >while(!(N

Скоро придёт
Осень

Спасибо сказали:
Attila Сообщения: 125 Статус: Тролль-Лѣсовичокъ ОС: Свободная aka ArchLinux

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение Attila » 29.10.2007 20:05

Liksys, может, прикрутите где-нить здесь описание массивов в С? Многомерных, переменной длины и т.п. Раз уж такой вопрос возникает у людей с завидным постоянством?

Эван, эвое!
Поэтический Форум любителей и почитателей Э. Т. А. Гофмана (О системах * NIX)
Спасибо сказали:

drBatty Сообщения: 8735 Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит. ОС: Slackware-current Контактная информация:

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение drBatty » 29.10.2007 20:20

29.10.2007 19:59
Многомерные!

Больше эксплойтов, хороших и разных. Сначала один неизвестно сколько new понаставил, а вместо того, чтоб прибраться - ещё столькоже new. Дык система у нас самая лучшая, и по стандарту обязана за нами какашки подбирать! А за памятью можно и магазин сбегать. А теперь умные люди и стандарт переписали, пущай программа сколько хошь места в стеки возьмёт, стек большой, на всех хватит. Отстал я от жизни.

Но лучше использовать malloc()/free()

А какая разница, всё равно никто не проверяет, что там malloc вернёт. На исключение надеются, что-ли?

Скоро придёт
Осень

Спасибо сказали:
Liksys Сообщения: 2910

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение Liksys » 29.10.2007 20:25

Кто не проверяет, а кто проверяет.
Любую мою программу посмотри, у меня любая функция, которая потенциально может вернуть код об ошибке, заключается в if.

Спасибо сказали:

drBatty Сообщения: 8735 Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит. ОС: Slackware-current Контактная информация:

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение drBatty » 29.10.2007 20:32

29.10.2007 20:25
Кто не проверяет, а кто проверяет.
Любую мою программу посмотри,

Ну в примерах, имхо, допустимо. Чтобы код не заграмождать. Хотя в этой теме наверное и нужно(в смысле . Для начинающих). Вот только как проверить что там с переменным массивом? Мне интерестно, как туда впихнуть проверку?

Скоро придёт
Осень

Спасибо сказали:
Liksys Сообщения: 2910

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение Liksys » 29.10.2007 20:33

Вот и фиг, что никак, если только реагировать на сигналы, но это кастыль
Спасибо сказали:

drBatty Сообщения: 8735 Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит. ОС: Slackware-current Контактная информация:

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение drBatty » 29.10.2007 20:42

29.10.2007 20:33
Вот и фиг, что никак, если только реагировать на сигналы, но это кастыль

значит никогда не надо так делать. Да и malloc, имхо, тоже не лучший вариант. Никогда мне не приходило в голову его использовать. А такие костыли - давить. Си это не ассемблер.

Скоро придёт
Осень

Спасибо сказали:
Liksys Сообщения: 2910

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение Liksys » 29.10.2007 21:07

Ну на malloc() глупо катить бочку
А такие массивы - это да. Мало ли что в стандарте написано
Спасибо сказали:

drBatty Сообщения: 8735 Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит. ОС: Slackware-current Контактная информация:

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение drBatty » 30.10.2007 12:47

29.10.2007 21:07
Ну на malloc() глупо катить бочку

она как goto, когда человек точно знает что делает - благо. А если он пишет "как в бейсике" - зло.
А такие массивы - это да. Мало ли что в стандарте написано

В стандарте и в правду очень много букв Только, имхо, бегинеру всё сразу не нужно, всё равно, всё он не осилит. В первом сообщении приводилась распостронённая задача про двухмерный массив. И данные там были представленны правильно: ввиде массива указателей на массивы. Такой подход наиболее естественнен в си(да навероное и в с++).

Скоро придёт
Осень

Спасибо сказали:
Iroln Сообщения: 201 ОС: openSUSE 10.3

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение Iroln » 13.06.2008 01:47

Подытоживая и структурируя все вышесказанное.
Я это делал так:

/* Ввод и вывод двумерного динамического массива */ #include #include int main(void) < int i, j, m, n, tmp; int status; double **array; printf("Количество строк (q-выход): "); status = scanf("%d",&m); if (status!=1) return 0; printf("Количество столбцов (q-выход): "); status = scanf("%d",&n); if (status!=1) return 0; // Динамическое выделение памяти под двумерный массив array = (double**) malloc(m * sizeof(double*)); if (array==NULL) < fprintf(stderr,"Не удалось выделить память\n"); exit(EXIT_FAILURE); >for (i=0; i > fprintf(stderr,"Выделено памяти под массив: %zd байт(а)\n", (sizeof **array)*m*n); // Ввод массива printf("Введите мaссив размерностью %d x %d (q-выход):\n", m, n); for (i=0; i > > // Вывод массива for (i=0; i printf("\n\n"); for (i=0; i free(array); return 0; >
iroln@iroln:~/debug> ./io_dyn_arr2 Количество строк (q-выход): 4 Количество столбцов (q-выход): 3 Выделено памяти под массив: 96 байт(а) Введите массив размерностью 4 x 3 (q-выход): (1,1) 1 (1,2) 4 (1,3) 2 (2,1) 5 (2,2) 2 (2,3) 5 (3,1) 3 (3,2) 6 (3,3) 5 (4,1) 3 (4,2) 5 (4,3) 3 1.0 4.0 2.0 5.0 2.0 5.0 3.0 6.0 5.0 3.0 5.0 3.0 iroln@iroln:~/debug>

Задание на дом для начинающих
Напишите кусок кода для динамического выделения памяти под массив размерностью n (ну то бишь больше двух).

Тайною мир держится
Спасибо сказали:

drBatty Сообщения: 8735 Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит. ОС: Slackware-current Контактная информация:

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение drBatty » 01.11.2008 03:06

// Динамическое выделение памяти под двумерный массив array = (double**) malloc(m * sizeof(double*)); for (i=0; i

неверно. если памяти в первом malloc не хватит - программа рухнет после второго(даже если ему хватит, при попытке записать по адресу (NULL + i) <= NULL, а если в цикле - тоже рухнет.
видимо так надо:

// Динамическое выделение памяти под двумерный массив array = (double**) malloc(m * sizeof(double*)); for (i=0; array && i else fprintf(stderr,"Выделено памяти под массив: %zd байт(а)\n", (sizeof **array)*m*n);

тут цикл вообще не начнётся если первый malloc вернёт ноль, а если не вернёт, вылетит из цикла после первого же ошибочного второго malloc'а.
размер массива ИМХО логичнее записать как m*sizeof(double**) + m * (n * sizeof(double))

free(array);

Эх блин. Столько распинался. А вы так ничего не поняли.
ну не вернётся память обратно. вернётся только массив из m указателей на указатели. А m массивов doublе так и останется висеть оторванным ладно было бы C++, мы бы деструктор к элементам array написали, он m раз выполнился и m массивов удалил. А так. Эх.

Скоро придёт
Осень

Двумерные массивы

С позволяет создавать многомерные массивы. Простейшим видом многомерного массива является двумерный массив. Двумерный массив - это массив одномерных массивов. Двумерный массив объявляется следующим образом:

тип имя_массива[размер второго измерения][размер первого измерения];

Следовательно, для объявления двумерного массива целых с размером 10 на 20 следует написать:

Посмотрим внимательно на это объявление. В противоположность другим компьютерным языкам, где размерности массива отделяются запятой, С помещает каждую размерность в отдельные скобки.

Для доступа к элементу с индексами 3, 5 массива d следует использовать

В следующем примере в двумерный массив заносятся числа от 1 до 12, после чего массив выводится на экран.

#include
int main(void)
int t,i, num[3][4];
/* загрузка чисел */
for(t=0; t for (i=0; i num[t][i] = (t*4)+i+1;

В данном примере num[0][0] имеет значение 1, num[0][1] имеет значение 2, num[0][2] - 3 и так далее. num[2][3] имеет значение 12.

Двумерные массивы сохраняются в виде матрицы, где первый индекс отвечает за строку, а второй -за столбец. Это означает, что правый индекс изменяется быстрее левого, если двигаться по массиву в порядке расположения элементов в памяти. На рис. показано графическое представление двумерного массива в памяти. Левый индекс можно рассматривать как указатель на строку.

Число байт в памяти, требуемых для размещения двумерного массива, вычисляется следующим образом:

число байт = размер второго измерения * размер первого измерения * sizeof (базовый тип)

Предполагая наличие в системе 2-байтных целых, целочисленный массив с размерностями 10 на 5 будет занимать 10 * 5 * 2, то есть 100 байт.

Когда двумерный массив используется как аргумент функции, передается указатель на первый элемент. Функция, получающая двумерный массив, должна, как минимум, определять размер первого измерения, поскольку компилятору необходимо знать длину каждой строки для корректной индексации массива. Например, функция, получающая двумерный целочисленный массив с размерностями 5, 10, будет объявляться следующим образом:

Можно определить размер второго измерения, но это не обязательно. Компилятору нужно знать размер первого измерения для правильного выполнения операторов типа

в функции. Если длина строки не известна, невозможно узнать, где начинается следующая строка.

Краткая программа, приведенная ниже, использует двумерный массив для хранения оценок каждого студента в классах учителя. Программа предполагает, что учитель имеет три класса и в каждом классе может быть максимум 30 студентов. Обратим внимание, как осуществляется доступ к grade из каждой функции:

#include
#include
#include
#include
#define CLASSES 3
#define GRADES 30
int grade[CLASSES][GRADES];
void disp_grades(int g[] [GRADES]), enter_grades(void);
int get_grade(int num);
int main(void) /* программа для хранения оценок */
char ch;
for (;;) do printf("(E)nter grades\n");
printf("(R)eport grades\n");
printf("(Q) uit\n");
ch = toupper(getche());
>
while(ch!='E' && ch!='R' && ch!='Q');
switch(ch)
case 'E':
enter_grades();
break;
case 'R':
disp_grades(grade);
break;
case 'Q':
return 0;
>
>
>

/* ввод каждой оценки студентов */
void enter_grades(void)
int t, i;
for(t=0; t for(i=0; i grade[t][i] = get_grade (i);
>
>

/* реальный ввод оценки */
int get_grade(int num) char s [80];
printf("enter grade for student # %d:\n", num+1);
gets (s);
return(atoi(s));
>

/* вывод оценок класса */
void disp_grades(int g[] [GRADES])
int t, i;
for(t=0; t printf("Class # %d:\n", t+1);
for(i=0; i printf("grade for student #%d is %d\n", i+1, g[t][i]);
>
>

Рисунок. Размещение двумерного массива в памяти

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *