Как найти среднее арифметическое в строке массива

0 / 0 / 0

Регистрация: 13.04.2020

Сообщений: 3

1

В двумерном массиве вычислить среднее арифметическое значение элементов каждой строки

13.04.2020, 10:14. Показов 8285. Ответов 4


Студворк — интернет-сервис помощи студентам

Помогите пожалуйста написать в с++. Дали доп задание , сегодня до вечера нужно скинуть, а сама не могу ((

В двумерном массиве вычислить среднее арифметическое значение элементов каждой строки и записать результаты в одномерный массив.



0



Максим 1994

115 / 72 / 48

Регистрация: 16.11.2012

Сообщений: 257

13.04.2020, 11:25

2

Лучший ответ Сообщение было отмечено Lenka2001 как решение

Решение

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
using namespace std;
const int n = 3, m = 3;
 
int main() 
{
    setlocale(0, "RUS");
    int arr[n][m];
    double res[n] = { 0 };
 
    cout << "Задайте двумерный массив размером " << n << "X" << m <<endl;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            cin >> arr[i][j];
            res[i] += arr[i][j];
        }
        res[i] /= n;
    }
    
    for (int i = 0; i < n; i++)
    {
        cout << "Cреднее арифметическое " << i << " строки: ";
        cout << res[i] << " "<<endl;
    }
 
    cout << endl;
    
    cout << "Одномерный массив: ";
    for (int i = 0; i < n; i++)
    {
        cout << res[i] << " ";
    }
 
    cout << endl;
    system("pause");
    return 0;
}



2



Модератор

Эксперт С++

13100 / 10373 / 6206

Регистрация: 18.12.2011

Сообщений: 27,739

13.04.2020, 11:34

3

Lenka2001, А почему Вы не воспользовались
Образцы (шаблоны) программ для типовых задач
Почти Ваша задача (поделить значения элементов результата на количество столбцов m, надеюсь, вы в состоянии).



0



0 / 0 / 0

Регистрация: 13.04.2020

Сообщений: 3

13.04.2020, 12:09

 [ТС]

4

Максим, большое спасибо!



0



7427 / 5021 / 2891

Регистрация: 18.12.2017

Сообщений: 15,694

13.04.2020, 13:03

5

Цитата
Сообщение от Максим 1994
Посмотреть сообщение

res[i] /= n;

res[i] /= m;



0



Методы итерирования массивов похожи на «стартовые наркотики» (это, конечно, не наркотики; и я не говорю, что наркотики — это хорошо; это — просто фигура речи). Из-за них многие «подсаживаются» на функциональное программирование. Всё дело в том, что они невероятно удобны. Кроме того, большинство этих методов очень просто понять. Методы наподобие .map() и .filter() принимают всего один аргумент-коллбэк и позволяют решать простые задачи. Но возникает такое ощущение, что метод .reduce() у многих вызывает определённые затруднения. Понять его немного сложнее.

Я уже писал о том, почему я думаю, что .reduce() создаёт множество проблем. Отчасти это происходит из-за того, что многие руководства демонстрируют использование .reduce() только при обработке чисел. Поэтому я и писал о том, как много задач, не подразумевающих выполнение арифметических операций, можно решать с помощью .reduce(). Но что если вам совершенно необходимо работать именно с числами?

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

  1. Общая сумма значений элементов массива.
  2. Длина массива.

Выяснить всё это довольно просто. А вычисление средних значений для числовых массивов — тоже операция не из сложных. Вот элементарный пример:

function average(nums) {
    return nums.reduce((a, b) => (a + b)) / nums.length;
}

Как видите, особых непонятностей тут не наблюдается. Но задача становится тяжелее в том случае, если работать приходится с более сложными структурами данных. Что если у нас имеется массив объектов? Что если некоторые объекты из этого массива нужно отфильтровать? Как быть, если из объектов нужно извлечь некие числовые значения? При таком раскладе вычисление среднего значения для элементов массива — это уже задача немного более сложная.

Для того чтобы с этим разобраться мы решим учебную задачу (она основана на этом задании с FreeCodeCamp). Решим мы её пятью разными способами. У каждого из них есть собственные преимущества и недостатки. Разбор этих пяти подходов к решению данной задачи покажет то, каким гибким может быть JavaScript. И я надеюсь, что анализ решений даст вам пищу для размышлений о том, как использовать .reduce() в реальных проектах.

Обзор задачи

Предположим, что у нас есть массив объектов, описывающих сленговые выражения викторианской эпохи. Нужно отфильтровать те выражения, которые не встречаются в Google Books (свойство found соответствующих объектов равно false), и найти среднюю оценку популярности выражений. Вот как могут выглядеть подобные данные (они взяты отсюда):

const victorianSlang = [
    
        term: 'doing the bear',
        found: true,
        popularity: 108,
    },
    
        term: 'katterzem',
        found: false,
        popularity: null,
    },
    
        term: 'bone shaker',
        found: true,
        popularity: 609,
    },
    
        term: 'smothering a parrot',
        found: false,
        popularity: null,
    },
    
        term: 'damfino',
        found: true,
        popularity: 232,
    },
    
        term: 'rain napper',
        found: false,
        popularity: null,
    },
    
        term: 'donkey’s breakfast',
        found: true,
        popularity: 787,
    },
    
        term: 'rational costume',
        found: true,
        popularity: 513,
    },
    
        term: 'mind the grease',
        found: true,
        popularity: 154,
    },

];

Рассмотрим 5 способов нахождения среднего значения оценки популярности выражений из этого массива.

1. Решение задачи без использования .reduce() (императивный цикл)

В нашем первом подходе к решению задачи метод .reduce() использоваться не будет. Если вы раньше не сталкивались с методами для итерирования массивов, тогда, надеюсь, разбор этого примера немного прояснит для вас ситуацию.

let popularitySum = 0;
let itemsFound = 0;
const len = victorianSlang.length;
let item = null;
for (let i = 0; i < len; i++) {
    item = victorianSlang[i];
    if (item.found) {
        popularitySum = item.popularity + popularitySum;
        itemsFound = itemsFound + 1;
    
}
const averagePopularity = popularitySum / itemsFound;
console.log("Average popularity:", averagePopularity);

Если вы знакомы с JavaScript, то вы без особого труда поймёте этот пример. Собственно говоря, здесь происходит следующее:

  1. Мы инициализируем переменные popularitySum и itemsFound. Первая переменная, popularitySum, хранит общую оценку популярности выражений. А вторая переменная, itemsFound, (вот уж неожиданность) хранит количество найденных выражений.
  2. Затем мы инициализируем константу len и переменную item, которые пригодятся нам при обходе массива.
  3. В цикле for счётчик i инкрементируется до тех пор, пока его значение не достигнет значения индекса последнего элемента массива.
  4. Внутри цикла мы берём элемент массива, который хотим исследовать. К элементу обращаемся с помощью конструкции victorianSlang[i].
  5. Затем мы выясняем, встречается ли данное выражение в коллекции книг.
  6. Если выражение в книгах встречается — мы берём значение его рейтинга популярности и прибавляем к значению переменной popularitySum.
  7. При этом мы ещё и увеличиваем счётчик найденных выражений — itemsFound.
  8. И, наконец, мы находим среднее значение, деля popularitySum на itemsFound.

Итак, с задачей мы справились. Возможно, решение у нас получилось не особенно красивое, но своё дело оно делает. Использование методов для итерирования массивов позволит сделать его немного чище. Давайте взглянем на то, удастся ли нам, и правда, «почистить» это решение.

2. Простое решение №1: .filter(), .map() и нахождение суммы с помощью .reduce() 

Давайте, перед первой попыткой воспользоваться методами массивов для решения задачи, разобьём её на небольшие части. А именно, вот что нам нужно сделать:

  1. Отобрать объекты, представляющие выражения, которые имеются в коллекции Google Books. Тут можно воспользоваться методом .filter().
  2. Извлечь из объектов оценки популярности выражений. Для решения этой подзадачи подойдёт метод .map().
  3. Вычислить сумму оценок. Здесь мы можем прибегнуть к помощи нашего старого друга .reduce().
  4. И, наконец, найти среднее значение оценок.

Вот как это выглядит в коде:

// Вспомогательные функции
// ----------------------------------------------------------------------------
function isFound(item) {
    return item.found;
};

function getPopularity(item) {
    return item.popularity;
}

function addScores(runningTotal, popularity) {
    return runningTotal + popularity;
}

// Вычисления
// ----------------------------------------------------------------------------

// Отфильтровываем выражения, которые не были найдены в книгах.
const foundSlangTerms = victorianSlang.filter(isFound);

// Извлекаем оценки популярности, получая массив чисел.
const popularityScores = foundSlangTerms.map(getPopularity);

// Находим сумму всех оценок популярности. Обратите внимание на то, что второй параметр
// указывает на то, что reduce нужно использовать начальное значение аккумулятора, равное 0.
const scoresTotal = popularityScores.reduce(addScores, 0);

// Вычисляем и выводим в консоль среднее значение.
const averagePopularity = scoresTotal / popularityScores.length;
console.log("Average popularity:", averagePopularity);

Приглядитесь к функции addScore, и к той строке, где вызывается .reduce(). Обратите внимание на то, что addScore принимает два параметра. Первый, runningTotal, известен как аккумулятор. Он хранит сумму значений. Его значение изменяется каждый раз, когда мы, перебирая массив, выполняем оператор return. Второй параметр, popularity, представляет собой отдельный элемент массива, который мы обрабатываем. В самом начале перебора массива оператор return в addScore ещё ни разу не выполнялся. Это значит, что значение runningTotal ещё не устанавливалось автоматически. Поэтому, вызывая .reduce(), мы передаём этому методу то значение, которое нужно записать в runningTotal в самом начале. Это — второй параметр, переданный .reduce().

Итак, мы применили для решения задачи методы итерирования массивов. Новая версия решения получилась гораздо чище, чем предыдущая. Другими словами, решение получилось более декларативным. Мы не сообщаем JavaScript о том, как именно нужно выполнить цикл, не следим за индексами элементов массивов. Вместо этого мы объявляем простые вспомогательные функции маленького размера и комбинируем их. Всю тяжёлую работу делают за нас методы массивов .filter(), .map() и .reduce(). Такой подход к решению подобных задач оказывается более выразительным. Эти методы массивов гораздо полнее, чем это может сделать цикл, сообщают нам о намерении, заложенном в код.

3. Простое решение №2: использование нескольких аккумуляторов

В предыдущей версии решения мы создали целую кучу промежуточных переменных. Например — foundSlangTerms и popularityScores. В нашем случае такое решение вполне приемлемо. Но что если мы поставим перед собой более сложную цель, касающуюся устройства кода? Хорошо было бы, если мы могли бы использовать в программе шаблон проектирования «текучий интерфейс» (fluent interface). При таком подходе мы смогли бы объединять в цепочку вызовы всех функций и смогли бы обойтись без промежуточных переменных. Однако тут нас поджидает одна проблема. Обратите внимание на то, что нам необходимо получить значение popularityScores.length. Если мы собираемся объединить всё в цепочку, тогда нужен какой-то другой способ нахождения количества элементов в массиве. Количество элементов в массиве играет роль делителя при вычислении среднего значения. Посмотрим — сможем ли мы так изменить подход к решению задачи, чтобы всё можно было бы сделать путём объединения вызовов методов в цепочку. Мы сделаем это, отслеживая при переборе элементов массива два значения, то есть — используя «двойной аккумулятор».

// Вспомогательные функции
// ---------------------------------------------------------------------------------
function isFound(item) {
    return item.found;
};

function getPopularity(item) {
    return item.popularity;
}

// Для представления нескольких значений, возвращаемых return, мы используем объект.
function addScores({totalPopularity, itemCount}, popularity) {
    return {
        totalPopularity: totalPopularity + popularity,
        itemCount:       itemCount + 1,
    };
}

// Вычисления
// ---------------------------------------------------------------------------------

const initialInfo    = {totalPopularity: 0, itemCount: 0};
const popularityInfo = victorianSlang.filter(isFound)
    .map(getPopularity)
    .reduce(addScores, initialInfo);

// Вычисляем и выводим в консоль среднее значение.
const {totalPopularity, itemCount} = popularityInfo;
const averagePopularity = totalPopularity / itemCount;
console.log("Average popularity:", averagePopularity);

Здесь мы, для работы с двумя значениями, воспользовались в функции-редьюсере объектом. При каждом проходе по массиву, выполняемом с помощью addScrores, мы обновляем общее значение рейтинга популярности и количество элементов. Важно обратите внимание на то, что эти два значения представлены в виде одного объекта. При таком подходе мы можем «обмануть» систему и хранить две сущности внутри одного возвращаемого значения.

Функция addScrores получилась немного более сложной, чем функция с таким же именем предыдущего примера. Но теперь оказывается так, что мы можем использовать единственную цепочку вызовов методов для выполнения всех операций с массивом. В результате обработки массива получается объект popularityInfo, который хранит всё, что нужно для нахождения среднего. Это делает цепочку вызовов аккуратной и простой.

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

4. Композиция функций без использования точечной нотации

Если вы — новичок в функциональном программировании, или если вам кажется, что функциональное программирование — это слишком сложно, вы можете пропустить этот раздел. Его разбор принесёт вам пользу в том случае, если вы уже знакомы с curry() и compose(). Если вы хотите углубиться в данную тему — взгляните на этот материал о функциональном программировании на JavaScript, и, в частности, на третью часть серии, в которую он входит.

Мы — программисты, которые придерживаются функционального подхода. Это значит, что мы стремимся к тому, чтобы строить сложные функции из других функций — маленьких и простых. До сих пор мы, в ходе рассмотрения разных вариантов решения задачи, уменьшали количество промежуточных переменных. В результате код решения становился всё проще и проще. Но что если довести эту идею до крайности? Что если попытаться избавиться от всех промежуточных переменных? И даже попробовать уйти от некоторых параметров?

Можно создать функцию для вычисления среднего значения с использованием одной лишь функции compose(), без использования переменных. Мы называем это «программированием без использования точеной нотации» или «неявным программированием». Для того чтобы писать подобные программы понадобится множество вспомогательных функций.

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

Итак, вернёмся к нашей задаче по построению системы вычисления средних значений. Ради экономии места мы перейдём здесь на использование стрелочных функций. Обычно, как правило, лучше использовать именованные функции. Вот хорошая статья на эту тему. Это позволяет получить более качественные результаты трассировки стека в случае возникновения ошибок.

// Вспомогательные функции
// ----------------------------------------------------------------------------
const filter  = p => a => a.filter(p);
const map     = f => a => a.map(f);
const prop    = k => x => x[k];
const reduce  = r => i => a => a.reduce(r, i);
const compose = (...fns) => (arg) => fns.reduceRight((arg, fn) => fn(arg), arg);

// Это - так называемый "blackbird combinator".
// Почитать о нём можно здесь: https://jrsinclair.com/articles/2019/compose-js-functions-multiple-parameters/
const B1 = f => g => h => x => f(g(x))(h(x));

// Вычисления
// ----------------------------------------------------------------------------

// Создадим функцию sum, которая складывает элементы массива.
const sum = reduce((a, i) => a + i)(0);

// Функция для получения длины массива.
const length = a => a.length;

// Функция для деления одного числа на другое.
const div = a => b => a / b;

// Мы используем compose() для сборки нашей функции из маленьких вспомогательных функций.
// При работе с compose() код надо читать снизу вверх.
const calcPopularity = compose(
    B1(div)(sum)(length),
    map(prop('popularity')),
    filter(prop('found')),
);

const averagePopularity = calcPopularity(victorianSlang);
console.log("Average popularity:", averagePopularity);

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

В данном случае основная работа идёт в функции compose(). Если прочесть её содержимое снизу вверх, то окажется, что вычисления начинаются с фильтрации массива по свойству его элементов found. Затем мы извлекаем свойство элементов popularity с помощью map(). После этого мы используем так называемый «blackbird combinator». Эта сущность представлена в виде функции B1, которая используется для выполнения двух проходов вычислений над одним набором входных данных. Для того чтобы лучше в этом разобраться, взгляните на эти примеры:

// Все строки кода, представленные ниже, эквивалентны:
const avg1 = B1(div)(sum)(length);
const avg2 = arr => div(sum(arr))(length(arr));
const avg3 = arr => ( sum(arr) / length(arr) );
const avg4 = arr => arr.reduce((a, x) => a + x, 0) / arr.length;

Опять же, если вы снова ничего не поняли — не беспокойтесь. Это — просто демонстрация того, что на JavaScript можно писать очень разными способами. Из таких вот особенностей и складывается красота этого языка.

5. Решение задачи за один проход с вычислением кумулятивного среднего значения

Все вышеприведённые программные конструкции хорошо справляются с решением нашей задачи (включая императивный цикл). Те из них, в которых используется метод .reduce(), имеют кое-что общее. Они основаны на разбиении проблемы на небольшие фрагменты. Эти фрагменты потом различными способами компонуются. Анализируя эти решения, вы могли заметить, что в них мы обходим массив три раза. Возникает такое чувство, что это неэффективно. Хорошо было бы, если бы существовал способ обработки массива и выдачи результата за один проход. Такой способ существует, но его применение потребует прибегнуть к математике.

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

Среднее значение n чисел можно найти, воспользовавшись такой формулой:

Для того чтобы узнать среднее n + 1 чисел подойдёт та же формула, но в другой записи:

Эта формула представляет собой то же самое, что вот это:

И то же самое, что это:

Если немного это преобразовать, то получится следующее:

Если вы не видите во всём этом смысла — ничего страшного. Итог всех этих преобразований сводится к тому, что с помощью последней формулы мы можем рассчитывать среднее значение в процессе однократного обхода массива. Для этого нужно знать значение текущего элемента, среднее значение, вычисленное на предыдущем шаге, и число элементов. Кроме того, большинство вычислений можно вынести в функцию-редьюсер:

// Функция для вычисления среднего значения
// ----------------------------------------------------------------------------

function averageScores({avg, n}, slangTermInfo) {
    if (!slangTermInfo.found) {
        return {avg, n};
    
    return {
        avg: (slangTermInfo.popularity + n * avg) / (n + 1),
        n:   n + 1,
    };
}

// Вычисления
// ----------------------------------------------------------------------------

// Вычисляем и выводим в консоль среднее значение.
const initialVals       = {avg: 0, n: 0};
const averagePopularity = victorianSlang.reduce(averageScores, initialVals).avg;
console.log("Average popularity:", averagePopularity);

Благодаря использованию этого подхода необходимое значение можно найти, обойдя массив всего один раз. Другие подходы используют один проход для фильтрации массива, ещё один — для извлечения из него нужных данных, и ещё один — для нахождения суммы значений элементов. Здесь же всё укладывается в один проход по массиву.

Обратите внимание на то, что это необязательно делает вычисления более эффективными. При таком подходе приходится выполнять больше вычислений. Мы, при поступлении каждого нового значения, выполняем операции умножения и деления, делая это для поддержания текущего значения среднего в актуальном состоянии. В других вариантах решения этой задачи мы делим одно число на другое лишь один раз — в конце программы. Но такой подход гораздо эффективнее в плане использования памяти. Промежуточные массивы здесь не используются, в результате нам приходится хранить в памяти лишь объект с двумя значениями.

Однако такая вот эффективность использования памяти имеет определённую цену. Теперь в одной функции мы выполняем три действия. Мы в ней фильтруем массив, извлекаем число и пересчитываем результат. Это усложняет функцию. В результате, взглянув на код, уже не так просто его понять.

Что выбрать?

Какой же из рассмотренных выше пяти подходов к решению задачи можно назвать самым лучшим? На самом деле, это зависит от многих факторов. Возможно, вам нужно обработать по-настоящему длинный массив. Или, возможно, вашему коду нужно выполняться на платформе, на которой доступно не особенно много памяти. В подобных случаях имеет смысл воспользоваться тем решением задачи, где обработка массива выполняется за один проход. Но если системные ограничения роли не играют, тогда можно с успехом пользоваться более выразительными подходами к решению задачи. Программисту нужно проанализировать собственную ситуацию и принять решение о том, что лучше всего подходит его приложению, что наиболее целесообразно использовать в его обстоятельствах.

Возможно, у кого-то сейчас возникнет вопрос о том, есть ли способ объединения преимуществ разных подходов к решению подобной задачи. Можно ли разбить задачу на мелкие части, но выполнять все вычисления за один проход по массиву? Сделать это можно. Для этого понадобится применить концепцию трансдьюсеров. Это — отдельная большая тема.

Итоги

Мы рассмотрели пять способов вычисления среднего для элементов массива:

  1. Без использования .reduce().
  2. С использованием методов .filter() и .map(), а также — метода .reduce() в роли механизма для нахождения суммы чисел.
  3. С использованием аккумулятора, являющегося объектом и хранящего несколько значений.
  4. С применением методики неявного программирования.
  5. С вычислением кумулятивного среднего при однократном проходе по массиву.

Что же, всё-таки, стоит выбрать для практического применения? На самом деле — вам решать. Но если вы хотите найти какую-то подсказку — поделюсь своим мнением о том, как можно принять решение о наиболее подходящем способе решения задачи:

  1. Начните с использования подхода, который вы понимаете лучше всего. Если он позволяет достичь цели — остановитесь на нём.
  2. Если существует некий подход, который вы не понимаете, но хотите изучить — решите задачу с его помощью.
  3. И, наконец, если вы столкнулись с проблемой нехватки памяти — попробуйте тот вариант, где массив обходится один раз.

Уважаемые читатели! Как вы чаще всего обрабатываете массивы в JavaScript-проектах?

И снова здравствуйте! В прошлой части мы рассмотрели что такое одномерный массив в C++, узнали для чего он необходим, а так же порешали некоторые типовые академические задачи. В этот раз примеры программ будут написаны в среде Visual Studio 2017, но вы можете использовать любой другой инструмент, например Code::Blocks или онлайн компиляторы. Сегодня мы рассмотрим двумерный массив. Это также простейшая структура данных как и одномерный массив, к данным все также возможно обращаться по индексу, но есть некоторая особенность. Давайте рассмотрим ее так же на примере контейнера с яблоками:

Article
Article

Получается, что у нас теперь многоэтажный контейнер, в каждой ячейке которой находятся яблоки (ячейка так же может быть пустой, для ссылочных типов это значение null и ноль для значимых типов). Для того что бы взять  или положить яблоки из определенной ячейки необходимо сначала выбрать строку, а затем столбец, после чего мы возьмем необходимые нам яблоки, или наоборот положим.  Обратите внимание, что нумерация ячеек строк и столбцов начинается с 0! Это важно, так как индексация массива начинается всегда с 0 а не 1. Т.е что бы обратиться к первой ячейке контейнера, нам необходимо достать яблоки из нулевой ячейки на пересечении двух координат (вспомнили игру Морской бой? =) ). Идем на нулевую строку и ищем нулевой столбец где находится нужная нам ячейка. 

Здесь у нас лежат два яблока. Так же не забываем, что С++ строго типизированный язык программирования, поэтому мы не можем в целочисленный массив записать вещественное число (float или double) или символ (char) и наоборот. Но существуют языки в которых такое возможно, например PHP и Java Script.  Итак для работы с нашим контейнером и ячейками, нам предварительно нужно его создать и заполнить ячейки яблоками. Кладем в ячейку с координатами [0][0] два яблока, [0][1] — три яблока, [0][2] — одно яблоко и так далее до координат ячейки с индексом [4][4]. Что мы сделали? Правильно, инициализировали массив! В коде это будет выглядеть следующим образом:

#include<iostream> // Стандартная библиотека ввода вывода
#include<iomanip>// Библиотека манипуляторов для форматирования потока
#define ROWS 5      // Обозначаем длину строки нашего контейнера(массива) для яблок
#define COLUMNS 5   // Обозначаем длину столбца нашего контейнера(массива) для яблок
using namespace std; // используем стандартное пространство имен библиотеки iostream

int main(int argc, char* argv[])
{
	// Русский язык в консольном приложении
	setlocale(LC_ALL, "Rus");
	// наш контейнер с яблоками в каждой из
	// секций которой лежит определенное количество яблок
	int apples[ROWS][COLUMNS] = {
									{ 2, 3, 1, 1, 0 },
									{ 0, 1, 2, 2, 0 },
									{ 1, 1, 1, 1, 1 },
									{ 3, 4, 1, 2, 3 },
									{ 2, 2, 0, 2, 1 }
	};

	cout << "Выводим массив на экран: " << endl;
	// Это цикл, в котором мы идем и заглядываем в каждую секцию
	// по пересечениям строк и столбцов
	// для этого необходим вложенный цикл for в основной цикл
	// после чего печатаем количество каждой секции на экран
	// строк у нас 5, это макрос ROWS
	// столбцов у нас 5, это макрос COLUMNS
	// setw(4) это манипулятор для форматирование строки на экране, 4 - это примерно
	// 4 пробела между символами.
	for (size_t i = 0; i < ROWS; i++) {
		for (size_t j = 0; j < COLUMNS; j++) {
			cout << setw(4) << apples[i][j];
		}
		cout << endl;
	}
	cout << endl;
	system("pause"); // Задержка.
	return 0;
}

Вот так мы реализовали программу заполнения массивы и вывода его на пользовательский экран в консоли. Результат на картинке:

1

Как и в одномерные массивы по ходу написания программы и ее исполнения мы можем изменять количество яблок в секциях контейнера нашего двумерного массива, например в ячейку с индексом[0][2] поместить восемь яблок, а в [2][4] сто яблок (размер каждой секции зависит от типа контейнера, он у нас int, а в C++ размер этого типа равен от -2 147 483 648 до 2 147 483 648). А вот размер самого контейнера и количества ячеек ( строки и колонки) мы пока изменять не можем. Для этой цели служит отдельный вид массивов, именуемый — динамическим.

В массив мы можем записать вещественные числа, символы и строки:

#include<iostream> // Стандартная библиотека ввода вывода
#include<iomanip>// Библиотека манипуляторов для форматирования потока

#define ROWS 3      // Обозначаем длину строки нашего контейнера(массива) для яблок
#define COLUMNS 3   // Обозначаем длину столбца нашего контейнера(массива) для яблок
using namespace std; // используем стандартное пространство имен библиотеки iostream

int main(int argc, char* argv[])
{
	// Русский язык в консольном приложении
	setlocale(LC_ALL, "Rus");
	// наш контейнер с яблоками в каждой из
	// секций которой лежит определенное количсетво яблок
	// Можно и без указания размера при инициализации,
	// компилятор автоматически создаст массив с необходимым размером
	int apples[][COLUMNS] = {
								{ 2, 1, 3 },
								{ 100, 21, 32 }
	};

	char chars[ROWS][COLUMNS] = {
									{ 'a', 'b', 'c' },
									{ 'd', 'e', 'f' }
	};

	float reals[ROWS][COLUMNS] = {
									{ 2.1, 1.3, 3.4 },
									{ 6.8, 0.2, 8.3 }
	};

	double doubleReals[ROWS][COLUMNS] = {
										{ 2.14, 1.333, 3.45 },
										{ 6.882, 0.223, 8.123}
	};
	string strings[ROWS][COLUMNS] = {
										{ "Вася", "Иван", "Петя" },
										{ "Вадим", "Curtis", "Gucci Mane"},
	};
	return 0;
}

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

#include<iostream> // Стандартная библиотека ввода вывода
#include<iomanip>// Библиотека манипуляторов для форматирования потока

#define ROWS 5      // Обозначаем длину строки нашего контейнера(массива) для яблок
#define COLUMNS 5   // Обозначаем длину столбца нашего контейнера(массива) для яблок
using namespace std; // используем стандартное пространство имен библиотеки iostream

int main(int argc, char* argv[])
{
	// Русский язык в консольном приложении
	setlocale(LC_ALL, "Rus");
	// наш контейнер с яблоками в каждой из
	// секций которой лежит определенное количество яблок
	int apples[ROWS][COLUMNS];

	cout << "Введите числа, что бы заполнить массив: " << endl;
	// Это цикл, в котором мы заполняем наш двумерный массив вручную
	// для этого необходим вложить еще один цикл for в основной цикл

	for (size_t i = 0; i < ROWS; i++)
	{
		for (size_t j = 0; j < COLUMNS; j++)
		{
			cin >> apples[i][j];
		}
	}
	cout << endl;

	// Печатаем наш заполненый массив
	cout << "Выводим массив на экран: " << endl;
	for (size_t i = 0; i < ROWS; i++) {
		for (size_t j = 0; j < COLUMNS; j++) {
			cout << setw(4) << apples[i][j];
		}
		cout << endl;
	}
	cout << endl;
	system("pause"); // Задержка.
	return 0;
}

Давайте теперь попробуем заполнить массив случайными числами от 0 до 10. Для этого мы будем использовать знакомую из предыдущей статьи технику. Подключим header time.h  или  ctime:

#include<iostream> // Стандартная библиотека ввода вывода
#include<iomanip>// Библиотека манипуляторов для форматирования потока
#include<time.h> // Стандартная библиотека ввода вывода

#define ROWS 5      // Обозначаем длину строки нашего контейнера(массива) для яблок
#define COLUMNS 5   // Обозначаем длину столбца нашего контейнера(массива) для яблок
using namespace std; // используем стандартное пространство имен библиотеки iostream

int main(int argc, char* argv[])
{
	// Русский язык в консольном приложении
	setlocale(LC_ALL, "Rus");
	// наш контейнер с яблоками в каждой из
	// секций которой лежит определенное количество яблок
	int apples[ROWS][COLUMNS];

	cout << "Заполнение массива случайными числами от 1 до 10: " << endl;
	// Это цикл, в котором мы вручную заполняем наш двумерный массив
	// для этого необходим вложить еще один цикл for в основной цикл

	for (size_t i = 0; i < ROWS; i++) {
		for (size_t j = 0; j < COLUMNS; j++) {
			apples[i][j] = rand() % 11;
		}
	}

	// Печатаем наш заполненый массив
	cout << "Выводим массив на экран : " << endl;
	for (size_t i = 0; i < ROWS; i++) {
		for (size_t j = 0; j < COLUMNS; j++) {
			cout << setw(4) << apples[i][j];
		}
		cout << endl;
	}
	cout << endl;
	system("pause"); // Задержка.
	return 0;
}

И получаем результат (у вас результат может отличаться, функция rand(); может сгенерировать другие значения).:

3

Заполнить случайными числами наш двумерный массив позволила функция rand() % 11; Но в этом примере существует такая же проблема как и в случае с примером, когда мы заполняли одномерный массив случайными числами. Данный код генерирует случайные числа только один раз. При следующих запусках программы, в наш двумерный массив будут записаны те же случайные числа, что и в самый первый раз. Что бы уййти от этой проблемы, необходимо применить специальную функцию srand();.

Она на позволяет  устанавливать начало последовательности, генерируемой функцией rand() (функция rand() возвращает псевдослучайные числа). Функция srand() позволяет запускать программу несколько раз с различными последователь­ностями псевдослучайных чисел.

Добавим необходимую функцию в наш код:

#include<iostream> // Стандартная библиотека ввода вывода
#include<iomanip>// Библиотека манипуляторов для форматирования потока
#include<time.h> // Стандартная библиотека ввода вывода

#define ROWS 5      // Обозначаем длину строки нашего контейнера(массива) для яблок
#define COLUMNS 5   // Обозначаем длину столбца нашего контейнера(массива) для яблок
using namespace std; // используем стандартное пространство имен библиотеки iostream

int main(int argc, char* argv[])
{
	// Русский язык в консольном приложении
	setlocale(LC_ALL, "Rus");
	srand(time(NULL)); //  устанавливает в качестве базы текущее время. Этот прием часто используется для того,
	// чтобы при разных запусках генератора псевдослучайных чисел была всякий раз разная база и,
	// соответственно, разный ряд получаемых значений.

	// наш контейнер с яблоками в каждой из
	// секций которой лежит определенное количество яблок
	int apples[ROWS][COLUMNS];

	cout << "Заполнение массива случайными числами от 0 до 10: " << endl;
	// Это цикл, в котором мы вручную заполняем наш двумерный массив
	// для этого необходим вложить еще один цикл for в основной цикл

	for (size_t i = 0; i < ROWS; i++) {

		for (size_t j = 0; j < COLUMNS; j++) {
			apples[i][j] = rand() % 11;
		}
	}

	// Печатаем наш заполненый массив
	cout << "Выводим массив на экран : " << endl;
	for (size_t i = 0; i < ROWS; i++) {

		for (size_t j = 0; j < COLUMNS; j++) {
			cout << setw(4) << apples[i][j];
		}
		cout << endl;
	}
	cout << endl;
	system("pause"); // Задержка.
	return 0;
}

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

Давайте мы теперь попробуем заполнить контейнер случайным количеством яблок и найдем, сколько ячеек, в которых находится четное количество яблок (наш двумерный массив заполним случайными числами и посчитаем все четные элементы). Для этого необходимо завести отдельную переменную и в отдельном вложенном цикле for проделать операцию с остатком от деления на 2 и проверить также на ноль.

for (int i = 0; i < ROWS; i++)
{
for (int j = 0; j < COLUMNS; j++)
{
if (apples[i][j] % 2 == 0 && apples[i][j] != 0)
{
counter++;
}
}
}
Screenshot_1

Запустим и увидим результат (у вас результат может отличаться, так как если вы помните, мы используем функцию srand();):

Исходный текст программы:

#include<iostream> // Стандартная библиотека ввода вывода
#include<iomanip>// Библиотека манипуляторов для форматирования потока
#include<time.h> // Стандартная библиотека ввода вывода

#define ROWS 5      // Обозначаем длину строки нашего контейнера(массива) для яблок
#define COLUMNS 5   // Обозначаем длину столбца нашего контейнера(массива) для яблок
using namespace std; // используем стандартное пространство имен библиотеки iostream

int main(int argc, char* argv[])
{
	// Русский язык в консольном приложении
	setlocale(LC_ALL, "Rus");
	srand(time(NULL)); //  устанавливает в качестве базы текущее время. Этот прием часто используется для того,
	// чтобы при разных запусках генератора псевдослучайных чисел была всякий раз разная база и,
	// соответственно, разный ряд получаемых значений.

	// наш контейнер с яблоками в каждой из
	// секций которой лежит определенное количество яблок
	int apples[ROWS][COLUMNS];
	int counter = 0;

	cout << "Заполнение массива случайными числами от 0 до 10: " << endl;
	// Это цикл, в котором мы вручную заполняем наш двумерный массив
	// для этого необходим вложить еще один цикл for в основной цикл

	for (size_t i = 0; i < ROWS; i++) {

		for (size_t j = 0; j < COLUMNS; j++) {
			apples[i][j] = rand() % 11;
		}
	}

	// Печатаем наш заполненый массив
	cout << "Выводим массив на экран : " << endl;
	for (size_t i = 0; i < ROWS; i++) {

		for (size_t j = 0; j < COLUMNS; j++) {
			cout << setw(4) << apples[i][j];
		}
		cout << endl;
	}
	cout << endl;

	for (int i = 0; i < ROWS; i++)
	{
		for (int j = 0; j < COLUMNS; j++)
		{
			if (apples[i][j] % 2 == 0 && apples[i][j] != 0)
			{
				counter++;
			}
		}
	}

	cout << "Количество четных элементов в массиве : " << counter << endl; 
	// Задержка.
	system("pause");
	return 0;
}

Давайте теперь попробуем подсчитать среднее арифметическое содержимого нашего контейнера с яблоками (среднее арифметическое всех элементов двумерного массива). Для этого нам необходимо завести отдельную переменную, в которую будем складывать все яблоки (сумму всех элементов массива), после чего, полученную переменную разделим на количество элементов в массиве (а это у нас размерность массива).

#include<iostream> // Стандартная библиотека ввода вывода
#include<iomanip>// Библиотека манипуляторов для форматирования потока
#include<time.h> // Стандартная библиотека ввода вывода

#define ROWS 5      // Обозначаем длину строки нашего контейнера(массива) для яблок
#define COLUMNS 5   // Обозначаем длину столбца нашего контейнера(массива) для яблок
using namespace std; // используем стандартное пространство имен библиотеки iostream

int main(int argc, char* argv[])
{
	// Русский язык в консольном приложении
	setlocale(LC_ALL, "Rus");
	srand(time(NULL)); //  устанавливает в качестве базы текущее время. Этот прием часто используется для того,
	// чтобы при разных запусках генератора псевдослучайных чисел была всякий раз разная база и,
	// соответственно, разный ряд получаемых значений.

	// наш контейнер с яблоками в каждой из
	// секций которой лежит определенное количество яблок
	int apples[ROWS][COLUMNS];
	float buffer = 0; // наша переменная, куда мы будем складывать сумму наших яблок

	cout << "Заполнение массива случайными числами от 0 до 10: " << endl;
	// Это цикл, в котором мы вручную заполняем наш двумерный массив
	// для этого необходим вложить еще один цикл for в основной цикл

	for (size_t i = 0; i < ROWS; i++) {
		for (size_t j = 0; j < COLUMNS; j++) {
			apples[i][j] = rand() % 11;
		}
	}

	// Печатаем наш заполненый массив
	cout << "Выводим массив на экран : " << endl;
	for (size_t i = 0; i < ROWS; i++) {
		for (size_t j = 0; j < COLUMNS; j++) {
			cout << setw(4) << apples[i][j];
		}
		cout << endl;
	}
	cout << endl;

	for (int i = 0; i < ROWS; i++) {
		for (int j = 0; j < COLUMNS; j++) {
			buffer += apples[i][j];
		}
	}

	cout << "Среднее арифметическое массива : " << buffer / (ROWS * COLUMNS) << endl;
	// Задержка.
	system("pause");
	return 0;
}

Получаем результат (у вас результат может отличаться, так как если вы помните, мы используем функцию srand();).

Screenshot_1

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

#include<iostream> // Стандартная библиотека ввода вывода
#include<iomanip>// Библиотека манипуляторов для форматирования потока
#include<time.h> // Стандартная библиотека ввода вывода

#define ROWS 5      // Обозначаем длину строки нашего контейнера(массива) для яблок
#define COLUMNS 5   // Обозначаем длину столбца нашего контейнера(массива) для яблок
using namespace std; // используем стандартное пространство имен библиотеки iostream

int main(int argc, char* argv[])
{
	// Русский язык в консольном приложении
	setlocale(LC_ALL, "Rus");
	srand(time(NULL)); //  устанавливает в качестве базы текущее время. Этот прием часто используется для того,
	// чтобы при разных запусках генератора псевдослучайных чисел была всякий раз разная база и,
	// соответственно, разный ряд получаемых значений.

	// наш контейнер с яблоками в каждой из
	// секций которой лежит определенное количество яблок
	int apples[ROWS][COLUMNS];
	int MAS_REZ[ROWS];
	int max;
	cout << "Заполнение массива случайными числами от 0 до 10: " << endl;
	// Это цикл, в котором мы вручную заполняем наш двумерный массив
	// для этого необходим вложить еще один цикл for в основной цикл

	for (size_t i = 0; i < ROWS; i++) {
		for (size_t j = 0; j < COLUMNS; j++) {
			apples[i][j] = rand() % 120;
		}
	}

	// Печатаем наш заполненый массив
	cout << "Выводим массив на экран : " << endl;
	for (size_t i = 0; i < ROWS; i++) {
		for (size_t j = 0; j < COLUMNS; j++) {
			cout << setw(4) << apples[i][j];
		}
		cout << endl;
	}
	cout << endl;

	// В этом блоке будем искать максимальное количество  яблок в каждой секции
	// И выводить на экран пользователю.

	for (size_t i = 0; i < ROWS; i++) {
		max = apples[i][0];

		for (size_t j = 0; j < COLUMNS; j++) {
			if (apples[i][j] > max)
			{
				max = apples[i][j];
			}
		}
		cout << "Максимальный элемент строки в матрице apples : " << max << endl;
	}

	// Задержка.
	system("pause");
	return 0;
}

И вот что получаем на выходе программы (у вас результат может отличаться, так как если вы помните, мы используем функцию srand();).:

Screenshot_1

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

#include<iostream> // Стандартная библиотека ввода вывода
#include<iomanip>// Библиотека манипуляторов для форматирования потока
#include<time.h> // Стандартная библиотека ввода вывода

#define ROWS 5      // Обозначаем длину строки нашего контейнера(массива) для яблок
#define COLUMNS 5   // Обозначаем длину столбца нашего контейнера(массива) для яблок
using namespace std; // используем стандартное пространство имен библиотеки iostream

int main(int argc, char* argv[])
{
	// Русский язык в консольном приложении
	setlocale(LC_ALL, "Rus");
	srand(time(NULL)); //  устанавливает в качестве базы текущее время. Этот прием часто используется для того,
	// чтобы при разных запусках генератора псевдослучайных чисел была всякий раз разная база и,
	// соответственно, разный ряд получаемых значений.

	int apples[ROWS][COLUMNS];   // наш контейнер с яблоками в каждой из
	// секций которой лежит определенное количество яблок

	//Заполняем массив случайными числами (случайным количеством яблок в каждой ячейки)
	for (int i = 0; i < ROWS; i++) {
		for (int j = 0; j < COLUMNS; j++) {
			apples[i][j] = rand() % 120;
		}
	}
	// Печатаем наш массив на экран пользователю
	for (int i = 0; i < ROWS; i++) {
		for (int j = 0; j < COLUMNS; j++) {
			cout << setw(4) << apples[i][j];
		}

		cout << endl;
	}
	cout << endl;

	//Запускаем цикл сравнения, в котором будем искать максимальное количество яблок в столбцах
	int maxValue;

	//Запускаем цикл сравнения
	for (int i = 0; i < 5; i++)
	{
		//Определяем переменную внутри цикла специально, чтобы при переходе на следующий стобик(т.е. новую итеррацию цикла)- она обнулялась
		int maxValue = 0;
		//Пробегаем циклом по каждому элементу столбика, каждый раз сравниваем исходный элемент со следующим, и с максимальным на данный момент. Если проверяемый
		//элемент больше последующего и больше максимального - то пересохраняем это значение в переменную
		for (int j = 0; j < ROWS; j++)
		{
			if ((apples[j][i] > apples[j + 1][i]) && (apples[j][i] > maxValue))
			{
				maxValue = apples[j][i];
			}
		}
		//Выводим на экран
		cout << "Элемент " << i + 1 << " максимальный в столбце: " << maxValue << endl;
	}

    // Задержка.
	system("pause");
	return 0;
}

После компиляции программы посмотрим результат (как вы уже понимаете, результаты в вашем случае могут быть другими):

Screenshot_1

Ффух, идем дальше. И я приведу пример очередной задачки, которая часто может встречаться на тернистом пути программиста. Среднее арифметическое мы уже находили, правда во всем нашем двумерном массиве. Давайте теперь попробуем найти среднее арифметическое каждой строки, после чего все эти числа поместить в одномерный массив.

#include<iostream> // Стандартная библиотека ввода вывода
#include<iomanip>// Библиотека манипуляторов для форматирования потока
#include<time.h> // Стандартная библиотека ввода вывода

#define ROWS 5      // Обозначаем длину строки нашего контейнера(массива) для яблок
#define COLUMNS 5   // Обозначаем длину столбца нашего контейнера(массива) для яблок
#define SIZE 5
using namespace std; // используем стандартное пространство имен библиотеки iostream

int main(int argc, char* argv[])
{
	// Русский язык в консольном приложении
	setlocale(LC_ALL, "Rus");
	srand(time(NULL)); //  устанавливает в качестве базы текущее время. Этот прием часто используется для того,
	// чтобы при разных запусках генератора псевдослучайных чисел была всякий раз разная база и,
	// соответственно, разный ряд получаемых значений.

	int apples[ROWS][COLUMNS];   // наш контейнер с яблоками в каждой из
	// секций которой лежит определенное количество яблок
	float buffer, averageApples[ROWS];
	//Заполняем массив случайными числами (случайным количеством яблок в каждой ячейки)
	for (size_t i = 0; i < ROWS; i++) {

		for (int j = 0; j < COLUMNS; j++) {
			apples[i][j] = rand() % 15;
		}

	}
	// Печатаем наш массив на экран пользователю
	for (size_t i = 0; i < ROWS; i++) {

		for (size_t j = 0; j < COLUMNS; j++) {
			cout << setw(4) << apples[i][j];
		}

		cout << endl;
	}
	cout << endl;

	//Запускаем цикл в котором будем искать среднее арифметическое
	int maxValue;

	for (size_t i = 0; i < ROWS; i++) {

		buffer = 0;
		for (size_t j = 0; j < COLUMNS; j++) {

			buffer += apples[i][j];
		}

		buffer = buffer / ROWS;
		// Заполняем наш одномерный массив полученными значениями ср. арифметического
		averageApples[i] = buffer;
		cout << "Среднее значение " << i << " строки: " << buffer << endl;
	}

	cout << "nОдномерный массив со средними арифметическими каждой строкиn"  << endl;
	// Выводим на экран наш одномерныый массив
	for (size_t i = 0; i < SIZE; i++) 
		cout << averageApples[i] << setw(2);

	system("pause");
	return 0;
}

Соответственно, после запуска приложения, проверим результат:

Screenshot_1

А давайте теперь попробуем поработать с диагоналями матрицы! В матрице существует главная и побочная диагональ. На рисунке ниже, в контейнере с права зеленым показана линия главной диагонали. Соответственно справа — побочная диагональ.

Article

Очень часто встречаются задачи, где необходимо перебирать элементы диагоналей, ниже или выше этих диагоналей и тд. Рассмотрим такой вариант задачи:  «Создайте двумерный массив 5*5. Метод заполнения произвольный.
Выведите его. Все элементы главной диагонали занесите в одномерный массив и выведите его».

#include<iostream> // Стандартная библиотека ввода вывода
#include<iomanip>// Библиотека манипуляторов для форматирования потока
#include<time.h> // Стандартная библиотека ввода вывода

#define ROWS 5      // Обозначаем длину строки нашего контейнера(массива) для яблок
#define COLUMNS 5   // Обозначаем длину столбца нашего контейнера(массива) для яблок
#define SIZE 5
using namespace std; // используем стандартное пространство имен библиотеки iostream

int main(int argc, char* argv[])
{
	// Русский язык в консольном приложении
	setlocale(LC_ALL, "Rus");
	srand(time(NULL)); //  устанавливает в качестве базы текущее время. Этот прием часто используется для того,
	// чтобы при разных запусках генератора псевдослучайных чисел была всякий раз разная база и,
	// соответственно, разный ряд получаемых значений.

	int apples[ROWS][COLUMNS];   // наш контейнер с яблоками в каждой из
	// секций которой лежит определенное количество яблок
	int mainDiagonal[SIZE];      // одномерный массив, куда мы занесем все элементы главной диагонали матрицы apples
	//Заполняем массив случайными числами (случайным количеством яблок в каждой ячейки)
	for (size_t i = 0; i < ROWS; i++) {

		for (int j = 0; j < COLUMNS; j++) {
			apples[i][j] = rand() % 15;
		}

	}
	// Печатаем наш массив на экран пользователю
	cout << "Текущий массив : " << endl;

	for (size_t i = 0; i < ROWS; i++) {

		for (size_t j = 0; j < COLUMNS; j++) {
			cout << setw(4) << apples[i][j];
		}

		cout << endl;
	}
	cout << endl;

	//Запускаем цикл в котором будем искать элементы главной диагонали
	for (size_t i = 0; i < ROWS; i++) {

		for (size_t j = 0; j < i + 1; j++) {

			mainDiagonal[i] = apples[i][j];
		}
	}
	cout << endl;
	cout << "Массив с элементами главной диагонали" << endl;

	for (size_t i = 0; i < SIZE; i++) {

		cout << mainDiagonal[i] << setw(4);
	}

	// Задержка.
	system("pause > NULL");
	return 0;
}

Запустим нашу программу и посмотрим результат:

Screenshot_1

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

А теперь найдем все элементы побочной диагонали.

#include<iostream> // Стандартная библиотека ввода вывода
#include<iomanip>// Библиотека манипуляторов для форматирования потока
#include<time.h> // Стандартная библиотека ввода вывода

#define ROWS 5      // Обозначаем длину строки нашего контейнера(массива) для яблок
#define COLUMNS 5   // Обозначаем длину столбца нашего контейнера(массива) для яблок
#define SIZE 5
using namespace std; // используем стандартное пространство имен библиотеки iostream

int main(int argc, char* argv[])
{
	// Русский язык в консольном приложении
	setlocale(LC_ALL, "Rus");
	srand(time(NULL)); //  устанавливает в качестве базы текущее время. Этот прием часто используется для того,
	// чтобы при разных запусках генератора псевдослучайных чисел была всякий раз разная база и,
	// соответственно, разный ряд получаемых значений.

	int apples[ROWS][COLUMNS];   // наш контейнер с яблоками в каждой из
	// секций которой лежит определенное количество яблок
	int sideDiagonal[SIZE];      // одномерный массив, куда мы занесем все элементы главной диагонали матрицы apples
	//Заполняем массив случайными числами (случайным количеством яблок в каждой ячейки)
	for (size_t i = 0; i < ROWS; i++) {
		for (int j = 0; j < COLUMNS; j++) {
			apples[i][j] = rand() % 15;
		}
	}
	// Печатаем наш массив на экран пользователю
	cout << "Текущий массив : " << endl;

	for (size_t i = 0; i < ROWS; i++) {
		for (size_t j = 0; j < COLUMNS; j++) {
			cout << setw(4) << apples[i][j];
		}

		cout << endl;
	}
	cout << endl;

	//Запускаем цикл в котором будем искать элементы побочной диагонали
	for (size_t i = 0; i < ROWS; i++) {
		for (size_t j = 0; j < COLUMNS; j++) {
			if (j == ROWS - (i + 1)) {
				sideDiagonal[i] = apples[i][j];
			}
		}
	}
	cout << endl;
	cout << "Массив с элементами побочной диагонали" << endl;

	for (size_t i = 0; i < SIZE; i++) {
		cout << sideDiagonal[i] << setw(4);
	}

	// Задержка.
	system("pause > NULL");
	return 0;
}

Screenshot_1

Запускаем программу и проверяем получившийся результат:

Вообще удобно запомнить или держать шпаргалку с методикой обработки двумерных массивов, я приведу некоторую из них:

  • В первом цикле мы бегаем по строкам двумерного массива;
  • Во втором (вложенном цикле for) мы бегаем по столбцам;
  • Элементы на главной диагонали — row = col;
  • Элементы ниже главной диагонали — col > row;
  • Элементы выше главной диагонали — col < row;
  • Элементы на побочной диагонали — col = Rows — row;
  • Элементы ниже побочной диагонали —  col > Rows — row;
  • Элементы выше побочной диагонали — col < Rows — row;

На этой ноте завершаю эту статью. Мы еще вернемся к массивам и матрицам. Но только после того, как научимся оперировать непосредственно с памятью и пощупаем указатели. Так что следующий этап у нас, да да — указатели =) До встречи!

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

#include <iostream>
#include <time.h>
#include <windows.h>
using namespace std;

int main(void)
{
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
    int N;
    int M;
    int  sum = 0;

    cout << "Введите количество строк матрицы: " << endl;
    cin >> N;

    cout << "Введите количество столбцов матрицы: " << endl;
    cin >> M;


    /*_____________________________*/

    int **arr = new int*[N];
    for (int i = 0; i < N; i++)
    {
        arr[i] = new int[M];
    }

    /*_____________________________*/

    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < M; j++)
        {
            arr[i][j] = rand() % 20;
        }
    }

    /*_____________________________*/

    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < M; j++)
        {
            cout << arr[i][j] << "t";
        }
        cout << endl;
    }

    /*_____________________________*/

    /*_____________________________*/

    for (int i = 0; i < N; i++)
    {
        delete[] arr[i];
    }


    delete[] arr;

    return 0;
} 

задан 15 ноя 2021 в 11:41

SomeBodyLite's user avatar

Среднеарифметическое — сумма всех членов множества деленная на их кол-во. Исходя из этого:

float averageRow;
for (int i = 0; i < N; i++)
{
    averageRow = 0;
    for (int j = 0; j < M; j++)
    {
        averageRow += arr[i][j];
    }
    averageRow /=M;
    cout <<"Average row " << i <<": " << averageRow <<  endl;
 }

ответ дан 15 ноя 2021 в 11:57

Alexey Vesker's user avatar

Alexey VeskerAlexey Vesker

5812 серебряных знака11 бронзовых знаков

Перейти к содержанию

Функция, вычисляющая среднее арифметическое элементов массива

Просмотров 12к. Обновлено 15 октября 2021

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

Среднее арифметическое определяется как сумма элементов, деленная на их количество.

Параметром функции является целочисленный массив, возвращает она вещественное число.

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

Pascal

паскаль среднее арифметическое чисел


const N = 10;
type
arrtype = array[1..N] of integer;
var
arr: arrtype;
i: byte;
avrg: real;

procedure fill_array(var a: arrtype);
begin
for i:=1 to N do a[i]:=random(50)+1;
end;

function average(a:arrtype):real;
var sum:integer;
begin
sum := 0;
for i:=1 to N do sum:=sum+a[i];
average := sum / n;
end;

begin
randomize;
fill_array(arr);
for i:=1 to N do write(arr[i]:4);
writeln;
avrg := average(arr);
writeln(avrg:3:2);
end.



3 31 24 25 42 5 26 39 27 43
26.50

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

Язык Си


#include < stdio.h>
#define N 10
float average(int arr[]);

main() {
int a[N];
int i, min1, min2, buff;
srand(time(NULL));
for (i=0; i< N; i++) {
a[i] = rand() % 100;
printf("%3d", a[i]);
}
printf("n %.2fn", average(a));
}

float average(int arr[]) {
int sum, i;
sum = 0;
for (i=0; i< N; i++) sum += arr[i];
return sum/N;
}



82 35 2 32 56 55 33 41 99 45
48.00

Python

среднее арифметическое python


from random import random
N = 10

def average(a):
s = 0
for i in range(N):
s += a[i]
return s/N

arr = [0] * N
for i in range(N):
arr[i] = int(random() * 100)

b = average(arr)
print(arr)
print(b)



[30, 63, 67, 29, 29, 54, 30, 29, 41, 0]
37.2

В языке Python есть встроенная функция sum(), которая возвращает сумму элементов переданного ей списка. Поэтому код

s = 0
for i in range(N):
s += a[i]
можно заменить на

s = sum(a)

Понравилась статья? Поделить с друзьями:
  • Как составить осв по офр
  • Как правильно спать чтобы исправить осанку
  • Как найти координаты равнобедренный треугольник
  • Как найти контакт в ватсапе без номера
  • Как составить выкройку на штаны