ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ В C++ (4-Е ИЗДАНИЕ) (часть 7) онлайн

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

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

// salemon.cpp

// показ графика продаж

#include <iostream>

#include <iomanip>

using namespace std;

 

const int DISTRICTS = 4;

const int MONTHS = 3;

///////////////////////////////////////////////////////////

int main ( )

{

  int d, m;

  double sales [ DISTRICTS ][ MONTHS ];

 

  cout << endl;

  for ( d = 0; d < DISTRICTS; d++ )

    for ( m = 0; m < MONTHS; m++ )

    {

      cout << "Введите объем продаж для отдела " << d + 1;

      cout << ", за месяц " << m + 1 << ": ";

      cin >> sales [ d ][ m ];

    }

 

  cout << "\n\n";

  cout << "                        Месяц\n";

  cout << "                1         2         3";

  for ( d = 0; d < DISTRICTS; d++ )

  {

    cout << "\nОтдел " << d + 1;

    for ( m = 0; m < MONTHS; m++ )

      cout << setiosflags ( ios::fixed )

           << setiosflags ( ios::showpoint )

           << setprecision ( 2 )

           << setw ( 10 )

           << sales [ d ][ m ];

  }

  cout << endl;

 

  return 0;

}

 

Эта программа принимает от пользователя данные о продажах и затем выво- дит их в виде таблицы.

Введите объем продаж для отдела 1, за месяц 1: 3964.23 Введите объем продаж для отдела 1, за месяц 2: 4135.87 Введите объем продаж для отдела 1, за месяц 3: 4397.98 Введите объем продаж для отдела 2, за месяц 1: 867.75

Введите              объем  продаж               для        отдела 2,            за           месяц   2:            923.59

Введите              объем  продаж               для        отдела 2,            за           месяц   3:            1037.01

Введите              объем  продаж               ДЛЯ       отдела 3,            за           месяц   1:            12.77

Введите              объем  продаж               для        отдела 3,            за           месяц   2:            378.32

Введите              объем  продаж               для        отдела 3,            за           месяц   3:            798.22

Введите              объем  продаж               для        отдела 4,            за           месяц   1:            2983.53

Введите              объем  продаж               для        отдела 4,            за           месяц   2:            3983.73

Введите              объем  продаж               ДЛЯ       отдела 4,            за           месяц   3:            9494.98

                        Месяц

                1         2         3

Отдел 1   1432.07    234.50    654.01

Отдел 2    322.00  13838.32  17589.88

Отдел 3   9328.34    934.00   4492.30

Отдел 4  12838.29   2332.63     32.93

Определение многомерного массива

Массив определяется двумя размерами, которые заключены в квадратные скобки:

double sales [ DISTRICTS ][ MONTHS ];

Вы можете считать sales двумерным массивом, похожим на шахматную дос- ку. Иными словами можно сказать, что этот массив является массивом масси- вов. Это массив элементов DISTRICTS, каждый из которых является массивом элементов MONTHS. На рис. 7.4 показано, как это выглядит.

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

elem = dimen3 [ x ][ у ][ z ];

Аналогично обстоит дело с одно- и двумерными массивами.

Доступ к элементам многомерного массива

Элементы двумерного массива требуют двух индексов:

sales [ d ][ m ];

Заметим, что каждый индекс заключается в отдельные квадратные скобки. Запятые не используются. Нельзя писать sales[d, m]; это работает в некоторых языках, но не в C++.

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

Программа SALEMON выводит таблицу денежных значений. Важно, чтобы такие значения были правильно отформатированы. Давайте отступим от нашей темы и рассмотрим, как это делается в C++. Для денежных значений обычно использу- ют два знака после запятой. Мы хотим выровнять значения в столбце. Также хо- рошо бы выводить последний ноль, то есть 79.50, а не 79.5.

Убедимся, что не потребуется много работы, чтобы реализовать это все с по- мощью потоков ввода/вывода C++. Вы уже видели, как использовался метод setw() для установки ширины выводимого поля. Форматирование десятичных чисел требует нескольких добавочных методов.

Рис. 7.4. Двумерный массив

Вот строка, которая печатает числа с плавающей точкой, именованные как fpn, в поле шириной в 10 символов с двумя знаками после запятой:

cout << setiosflags ( ios::fixed )  // нормальный неэкспоненциальный вид

<< setiosflags ( ios::showpoint )  // всегда показывать десятичную точку << setprecision ( 2 )               // два знака после запятой << setw ( 10 )                      // ширина вывода в 10 символов << fpn;                             // само число

Группа битовых форматирующих флагов в long int класса ios определяет, как должно быть выполнено форматирование. При этом нам не нужно знать, что та- кое класс ios или каковы причины использования существующего синтаксиса этого класса для осуществления работы выражений.

Мы коснемся только двух флагов: ios::fixed и ios::showpoint. Для их уста- новки используйте метод setiosflags с именем флага в качестве аргумента. Имя должно предшествовать имени класса ios и отделяться от него операцией разре- шения (::).

В первых двух строках оператора cout устанавливаются флаги ios (если вам нужно убрать флаги в более поздней точке программы, вы можете использовать метод resetiosflags). Флаг fixed предотвращает печать числа в экспоненциальной форме, например 3.45е3. Флаг showpoint определяет положение десятичной точ- ки, даже если число не имеет дробной части: 123.00 вместо 123.

Для установки точности до двух знаков после запятой используйте метод setprecision с числом в качестве аргумента. Мы уже знаем, как установить шири- ну поля, используя метод setw. При установке всех этих параметров для cout вы сможете получить желаемый формат вывода числа.

 

Подробнее мы поговорим о флагах форматирования ios в главе 12 «Потоки и файлы».

Инициализация многомерных массивов

Как вы могли ожидать, вы можете инициализировать многомерные массивы. Толь- ко предварительно подготовьтесь к тому, что придется напечатать много скобок и запятых. Вот вариант программы SALEMON, которая использует инициализацию массива вместо запроса пользователя о вводе. Эта программа называется SALEINIT.

// saleinit.cpp

// показ графика продаж по данным массива

#include <iostream>

#include <iomanip>

using namespace std;

const int DISTRICTS = 4; // размеры массива

const int MONTHS = 3;

///////////////////////////////////////////////////////////

int main ( )

{

  int d, m;

 

  double sales [ DISTRICTS ][ MONTHS ] =

  {

    {  1432.07,   234.50,   654.01 },

    {   322.00, 13838.32, 17589.88 },

    {  9328.34,   934.00,  4492.30 },

    { 12838.29,  2332.63,    32.93 }

  };

  cout << "\n\n";

  cout << "                        Месяц\n";

  cout << "                1         2         3";

  for ( d = 0; d < DISTRICTS; d++ )

  {

    cout << "\nОтдел " << d + 1;

    for ( m = 0; m < MONTHS; m++ )

    {

      cout << setw ( 10 ) << setiosflags ( ios::fixed )

           << setiosflags ( ios::showpoint ) << setprecision ( 2 )

           << sales [ d ] [ m ];

    }

  }

  cout << endl;

  return 0;

}

 

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

{ 1432.07, 234.50, 654.01 }.

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

 

9