
- •1. Введение
- •2. Элементы языка
- •2.1. Первые программы
- •2.2. Алфавит языка
- •2.3. Комментарии
- •2.4. Типы данных
- •2.5. Целые типы данных
- •2.6. Плавающие типы данных
- •2.7. Константы-строки, или литералы
- •2.8. Директива препроцессора define
- •2.9. Описания
- •2.10. Модификатор const
- •3. Выражения
- •3.1. Операция и выражение присваивания
- •3.2. Арифметические операции
- •3.3. Операции отношения
- •3.4. Логические операции
- •3.5. Побитовые операции
- •3.6. Сдвиги
- •?????3.8. Тернарная или условная операция
- •3.9. Операция следования
- •3.10. Приоритеты операций и порядок вычисления
- •4.6. Оператор выбора switch
- •4.7. Оператор цикла while
- •4.8. Цикл с постусловием do-while
- •4.9. Оператор for
- •4.10. Оператор безусловного перехода
- •4.11. Оператор break
- •4.12. Оператор continue
- •4.13. Оператор return
- •5. Указатели
- •5.1. Определение указателей
- •5.2. Указатели и массивы
- •5.3. Адресная арифметика
- •5.4. Символьные массивы и строки
- •5.5. Многомерные массивы
- •5.6. Указатели и многомерные массивы
- •6. Операция sizeof
- •7. Операции для работы с динамической памятью
- •7.1. Операция выделения памяти new
- •7.2. Операция освобождения памяти delete
- •8. Функции
- •8.1. Определение и вызов функции
- •8.2. Функции. Передача аргументов
- •8.3. Передача многомерных массивов
- •8.4. Указатели на функции
- •8.5. Ссылки
- •8.6. Ссылки в качестве параметров функций
- •8.7. Аргументы по умолчанию
- •8.8. Переопределение функций
- •8.9. Шаблоны функций
- •9. Объявления и определения
- •10. Область существования имени
- •11. Область видимости
- •Здесь будет напечатано
- •12. Классы памяти
- •13. Объявления объектов и типов
- •14. Имена типов
- •15. Синоним имени типа
- •16. Правила преобразования стандартных типов
- •16.1. Явные преобразования
- •16.2. Неявные преобразования стандартных базовых типов
- •16.3. Преобразование производных стандартных типов
- •17. Перечисления
- •18. Классы
- •18.1. Объявление классов
- •18.2. Конструкторы
- •18.3. Деструкторы
- •18.4. Статические члены класса
- •18.5. Указатель this
- •18.6. Статические функции-члены
- •18.7. Указатели на члены класса
- •18.8. Инициализация данных–членов класса
- •18.9. Конструктор копирования и операция присваивания
- •18.10. Дружественные функции
- •18.11. Конструктор и операция new
- •18.12. Вызов деструктора
- •19. Производные классы
- •19.1. Построение производного класса
- •19.2. Защищенные члены класса
- •19.3. Управление уровнем доступа к членам класса
- •19.4. Последовательность вызова конструктора и деструктора при построении производного класса на основе одного базового
- •19.5. Преобразования типов
- •20. Полиморфизм
- •20.1. Раннее и позднее связывание
- •20.2. Виртуальные функции
- •20.3. Абстрактные классы
- •21. Переопределение стандартных операций
- •21.1. Основные определения и свойства
- •21.2. Операции new и delete при работе с абстрактными типами
- •21.3. Использование new при создании динамического объекта абстрактного типа
- •21.4. Операция delete
- •21.5. Преобразование типов
- •22. Некоторые особенности переопределенных операций
- •22.2. Операция [ ]
- •23. Классы и шаблоны
- •24. Списки
- •24.1. Операции над односвязными списками
- •24.2. Двунаправленные и кольцевые списки
- •24.3. Операции над кольцевыми списками
- •25. Стеки
- •25.1. Реализация стека через массив
- •25.2. Реализация стека через динамическую цепочку звеньев
- •26. Двоичные деревья
- •26.1. Определение и построение
- •26.2.Таблицы
- •27. Список литературы
8.3. Передача многомерных массивов
Если функции передаётся двумерный массив, то описание соответствующего аргумента функции должно содержать количество столбцов; количество строк – несущественно, поскольку фактически передаётся указатель.
Рассмотрим пример функции, перемножающей матрицы А и В; результат – С.
Размер матриц – не более 10.
const nmax = 10;
void product (int a[ ][nmax], int b[ ][nmax], int c[ ][nmax],
int m, int n, int k){
/* m – число строк в матрице a;
n – число строк в матрице b (должно быть равно числу столбцов в матрице a);
k – число столбцов в матрице b.
*/
for (int i=0; i<m; i++)
for (int j=0; j<k; j++){
c[i][j]=0;
for (int l=0; l<n; l++) c[i][j] + = a[i][l]*b[l][j];
}
}
Если заданы,
например, квадратные матрицы а и в
размером
,
то получить их произведение с можно
так:
product (a, b, c, 5, 5, 5);
В приведённом примере есть недостаток – здесь заранее фиксируется максимальная размерность матриц. Обойти это можно различными способами, один из которых – использование вспомогательных массивов указателей на массивы.
Напишем функцию, транспонирующую квадратную матрицу произвольной размерности n.
void trans ( int n, double *p[ ] )
{double x;
for (int i=0; i<n-1; i++)
for (int j=i+1; j<n; j++)
{x=p[i][j]; p[i][j]=p[j][i]; p[j][i]=x;}
}
void main(){
double A[4][4]={ 10, 12, 14, 17
15, 13, 11, 0
-3, 5.1, 6, 6
2, 8, 3, 1};
double ptr[ ]={(double*)&A[0], (double*)&A[1],
(double*)&A[2], (double*)&A[3]};
int n=4;
trans (n, ptr);
for (int i=0; i<n; i++){ count<<”\n строка”<<(i+1)<<”:”;
for (int j; j<n; j++)
cout<<”\t”<<A[i][j];
cout<<\n”;
}
}
В функции main матрица представлена двумерным массивом double A[4][4]. Такой массив нельзя непосредственно использовать в качестве фактического параметра, соответствующего формальному double *p[]. Поэтому вводиться дополнительный вспомогательный массив указателей double *ptr[]. В качестве начальных значений элементам этого массива присваиваются адреса строк матрицы, преобразованные к типу double*.
Многомерный массив с переменными размерами может быть динамически сформирован внутри функции. В вызываемую функцию его можно передать как указатель на одномерный массив указателей на одномерные массивы с элементами известной размерности и заданного типа.
В качестве примера приведем функцию, формирующую единичную матрицу порядка n.
int** singl (int n){
int **p=new int*[n];
/* Тип int* [n] - массив указателей на целые.
Операция new возвращает указатель на выделенную память под этот массив и тип переменной p есть int**. Таким образом, р есть массив указателей на строки целых будущей матрицы. */
if (p = = NULL){cout<<”Динамический массив не создан!\n”;
exit(1);}
// цикл создания одномерных массивов – строк матрицы:
for (int i=0; i<n; i++){p[i]=new int[n];
if( !p[i] ){cout<<”Не создана динамическая строка!\n”; exit(1);}
for (int j=0; j<n; j++)
p[i][j]=(i = =j )? 1: 0;}
return p;}
void main(){
int n;
cout<<”\n Задайте порядок матрицы: ”;
cin>>n;
int** matr; //Указатель для формируемой матрицы
matr = singl(n);
for (int i=0; i<n; i++){cout<<”\n строка”;
cout.width(2);
cout<<i+1<<”: ”;
for (int j=0; j<n; j++){
cout.width(4);
cout<<matr[i][j];
}
}
for(i=0; i<n; i++) delete matr[i];
delete matr;
}
В этой программе обращение к функции cout.width(k) устанавливает ширину поля следующего вывода в k позиций, что позволяет выровнять вид полученной матрицы.