- •Основы алгоритмизации и программирования, язык Си
- •Введение
- •Блок-схема алгоритма Общие требования к блок-схеме алгоритма
- •Линейные и разветвляющиеся процессы
- •Циклические процессы
- •Итерационные процессы
- •Комментарии
- •Типы данных
- •Данные целого типа
- •Данные вещественного типа
- •Модификатор const
- •Переменные перечисляемого типа
- •Константы
- •Описание переменных
- •Локальные переменные
- •Операции и выражения
- •Операция присваивания
- •Арифметические операции
- •Операции поразрядной арифметики
- •Логические операции
- •Операции отношения
- •Инкрементные и декрементные операции
- •Операция sizeof
- •Порядок выполнения операций
- •Приоритет операций
- •Преобразование типов
- •Операция приведения
- •Операция запятая
- •Ввод и вывод информации
- •Директивы препроцессора Директива #include
- •Директива #define
- •Понятие пустого и составного операторов
- •Условные операторы
- •Операторы организации цикла
- •Оператор цикла for
- •Оператор цикла while
- •Оператор цикла do … while
- •Вложенные циклы
- •Операторы перехода (break, continue, return, goto)
- •Примеры программ
- •Массивы Одномерные массивы
- •Примеры программ
- •Многомерные массивы (матрицы)
- •Примеры программ
- •Указатели Понятие указателя
- •Описание указателей
- •Операции с указателями
- •Связь между указателями и массивами
- •Массивы указателей
- •Многоуровневые указатели
- •Примеры программ
- •Символьные строки
- •Ввод/вывод строк.
- •Функции работы со строками.
- •Примеры программ
- •Функции
- •Прототип функции.
- •Определение функции.
- •Параметры функции
- •Параметры по умолчанию
- •Передача массива в функцию
- •Inline функции
- •Класс памяти
- •Автоматические переменные
- •Статические переменные
- •Регистровые переменные
- •Блочная структура
- •Примеры программ
- •Указатели на функции
- •Примеры программ
- •Рекурсия
- •Примеры программ
- •Аргументы в командной строке
- •Функции с переменным числом параметров
- •Примеры программ
- •Сортировка
- •Пузырьковая сортировка.
- •Шейкер сортировка
- •Сортировка вставкой
- •Сортировка выбором
- •Метод Шелла
- •Метод Хора
- •Структуры
- •Доступ к элементам структуры
- •Инициализация структур
- •Указатели на структуры.
- •Структуры и функции
- •Примеры программ
- •Поля бит
- •Объединения
- •Переменные с изменяемой структурой
- •Примеры программ
- •Организация списков и их обработка
- •Операции со списками при связном хранении
- •Построение обратной польской записи
- •Односвязный линейный список, очередь
- •Двусвязный линейный список
- •Циклический список, кольцо
- •Двусвязный циклический список
- •Примеры программ
- •Деревья
- •Потоки и файлы
- •Файлы Основные сведения о файловой системе
- •Организация посимвольного ввода и вывода
- •Определение конца файла feof()
- •Организация ввода и вывода строк
- •Удаление файлов
- •Дозапись потока
- •Позиционирование в файле
- •Текстовые и двоичные файлы
- •Функции fread() и fwrite()
- •Примеры программ
- •Хеширование
- •Схемы хеширования
- •Метод открытой адресации с линейным опробыванием
- •Метод цепочек
- •Машинное представление графов
- •Примеры программ
- •Литература
Многомерные массивы (матрицы)
В языке С(C++) определены только одномерные массивы, но поскольку элементом массива может быть массив, можно определить и многомерные массивы. Многомерный массив – это массив элементами которого являются массивы. Размерность массива – это количество индексов, используемых для доступа к конкретному элементу массива. Пример объявления двухмерного массива:
int mas[5][15];
Константное выражение, определяющее одну из размерностей массива, не может принимать нулевое значение:
int mas[0][7]; // ошибка
Можно инициализировать и многомерные массивы. Инициализация выполняется построчно, то есть в порядке возрастания самого правого индекса. Именно в таком порядке элементы многомерных массивов располагаются в памяти компьютера, например:
int mas[2][3]={2, 14, 36, 23, 1, 9};
Проинициализированный массив будет выглядеть так:
2 14 36
23 1 9
Многомерные массивы могут инициализироваться и без указания одной (самой левой) из размерностей массива. В этом случае количество элементов компилятор определяет по количеству членов в списке инициализации. Например, для массива mas будет получен тот же, что и в предыдущем примере результат:
int mas[][3]={ 34, 23, 67,
38, 56, 73,
37, 94, 28 };
Если необходимо проинициализировать не все элементы строки, а только несколько первых элементов, то в списке инициализации можно использовать фигурные скобки, охватывающие значения для этой строки, например:
int mas[][3]={{ 0 },
{ 10, 11},
{ 21, 21, 22} };
Если в какой-то группе {…} отсутствует значение, то соответствующему элементу присваивается 0. Предыдущий оператор будет эквивалентен следующему определению:
int mas[][3]={{ 0, 0, 0 },
{ 10, 11, 0 },
{ 21, 21, 22} };
Отличие в работе с многомерными массивами от работы с одномерными. состоит в том, что для доступа к элементу многомерного массива необходимо указать все его индексы:
n= mas[i][j]; // работа с элементом расположенным на i-ой
mas[i][j]=n; // строке и в j-ом столбце матрицы mas
В языке С(С++) можно использовать сечения массива, однако на использование сечений накладывается ряд ограничений. Сечения формируются вследствие опускания одной или нескольких пар квадратных скобок. Пары квадратных скобок можно отбрасывать только справа налево и строго последовательно. Сечения массивов используются при организации вычислительного процесса в функциях. Например:
int s[2][3];
Если при обращении к некоторой функции написать s[0], то будет передаваться нулевая строка массива s.
int b[2][3][4];
При обращении к массиву b можно написать, например, b[1][2] и будет передаваться вектор из четырех элементов, а обращение b[1] даст двухмерный массив размером 3 на 4. Нельзя написать b[2][4], подразумевая, что передаваться будет вектор, потому что это не соответствует ограничению наложенному на использование сечений массива.
Примеры программ
Рассмотрим некоторые примеры программ с использованием многомерных матриц.
Пример . Транспонировать матрицу относительно главной диагонали.
#include <stdio.h>
#define nn 3
void main()
{ int mas[nn][nn],i,j,kk;
printf("\n‚Введите матрицу");
for(i=0;i<nn;i++) // цикл по строкам матрицы
for(j=0;j<nn;j++) // цикл по столбцам матрицы
{ printf("\n‚введите элемент mas[%d][%d] = ",i,j);
scanf("%d",&mas[i][j]);
}
clrscr();
printf("\nИсходная матрица "); // Вывод матрицы на экран
for(i=0;i<nn;i++) // цикл по строкам матрицы
{ printf("\n");
for(j=0;j<nn;j++) // цикл по столбцам матрицы
printf("%5d",mas[i][j]);
}
// пример транспонирования используя оператор for
for(i=0;i<nn;i++)
for(j=i+1;j<nn;j++)
{ kk=mas[i][j];
mas[i][j]=mas[j][i];
mas[j][i]=kk;
}
// пример транспонирования используя оператор do while
i=0;
do
{ j=i+1;
do
{ kk=mas[i][j];
mas[i][j]=mas[j][i];
mas[j][i]=kk;
} while(++j<nn);
} while(+i<nn);
// пример транспонирования используя оператор while
i=0;
while(i<nn)
{ j=i+1;
while(j<nn)
{ kk=mas[i][j];
mas[i][j]=mas[j][i];
mas[j++][i++]=kk;
}
}
printf("\nИсходная матрица "); // Вывод матрицы на экран
for(i=0;i<nn;i++) // цикл по строкам матрицы
{ printf("\n");
for(j=0;j<nn;j++) // цикл по столбцам матрицы
printf("%5d",mas[i][j]);
}
}
Пример . Разработать программу выявления седловой точки в матрице размерности п х п. Седловой точкой в матрице называют элемент, одновременно наибольший в своей строке и наименьший в своем столбце.
#include<stdio.h>
#define n 4
void main()
{ int ms[n][n],i,i1,i2,j,j1,k,kk;
clrscr();
printf("\n‚Введите матрицу");
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{ printf("\ms[%2d][%2d]= ",i,j);
scanf("%d",&ms[i][j]);
}
clrscr();
printf("\nВведенный массив MS");
for(i=0;i<n;i++)
{ printf("\n");
for(j=0;j<n;j++)
printf("%3d",ms[i][j]);
}
// блок поиска седловой точки
for(i=0;i<n;i++)
{ k=ms[i][0]; i1=0; j1=0; // начальное значение координат в матрице
// для поиска седловой точки
for(j=0;j<n;j++) // цикл анализа i-ой строки
if (ms[i][j]>k) // найдено новое максимальное в строке
{ k=ms[i][j]; // запоминаем найденное значение
i1=i; j1=j; // и его координаты в матрице
}
kk=0;
for(i2=0;i2<n;i2++)
if(ms[i1][j1]>=ms[i2][j1] && i1!=i2) kk=1;
if(kk==0)
printf("\nседловая точка = %d \nкоординаты : MS[%d][%d] ",
ms[i1][j1],i1,j1);
}
}
Пример . Разработать программу умножения двух целочисленных матриц чисел.
#include<stdio.h>
void main()
{ int i,j,k,n,t;
int a[3][4],b[4][2],c[3][2];
printf("\nВведите матрицу a");
for(i=0;i<3;i++)
for(j=0;j<4;j++)
{ printf("\na[%d][%d]=",i,j);
scanf("%3d",&a[i][j]);
}
printf("\n Введите матрицу b");
for(i=0;i<4;i++)
for(j=0;j<2;j++)
{ printf("\nb[%d][%d]=",i,j);
scanf("%3d",&b[i][j]);
}
// умножение матриц используя оператор while
i=0;
while(i<3)
{ j=0;
while(j<2)
{ c[i][j]=0;
k=0;
while(k<4)
{ c[i][j]+=a[i][k]*b[k][j];
k++;
}
j++;
}
i++;
}
// умножение матриц используя оператор do while
i=0;
do
{ j=0;
do
{ c[i][j] = 0;
k = 0;
do
{ c[i][j] += a[i][k] * b[k][j];
k++;
} while( k < 3 );
j++;
} while( j < 3);
i++;
} while( i < 3);
puts("\nРезультирующая матрица c");
for(i=0;i<3;i++)
{ printf("\n");
for(j=0;j<2;j++)
printf("%3d",c[i][j]);
}
}
Пример . Построить спираль Улама в квадрате из N N клеток. В клетку в центре ставится 1, затем справа от единицы ставится 2, ниже – 3 и т.д., по ходу часовой стрелки ставятся последовательные числа натурального ряда. Результирующая матрица выводится на экран, при этом все простые числа заменяются звездочкой '*'.
#include<stdio.h>
#include<conio.h>
#define n 5
int main()
{
int i,i1,i2,j,j1,j2,
k=0, // направление движения
s=1; // значение заносимое в матрицу
static int mt[n][n];
i1=i2=j1=j2=n/2; // координаты середины матрицы
mt[i1][j1]=1; // 1 ставится в центр матрицы
while(s<n*n)
{ switch(k)
{ case 0: // движение вправо
if(j2<n-1) j2++; // изменение правой границы
for(j=j1+1; j<=j2; j++)
if(mt[i1][j]==0) mt[i1][j]=++s;
k=1; // изменение направления движения вниз
break;
case 1: // движение вниз
if(i2<n-1) i2++; // изменение нижней границы
for(i=i1+1; i<=i2; i++)
if(mt[i][j2]==0) mt[i][j2]=++s;
k=2; // изменение направления движения влево
break;
case 2: // движение влево
if(j1>0) j1--; // изменение левой границы
for(j=j2-1; j>=j1; j--)
if(mt[i2][j]==0) mt[i2][j]=++s;
k=3; // изменение направления движения вверх
break;
case 3: // движение вверх
if(i1>0) i1--; // изменение верхней границы
for(i=i2-1; i>=i1; i--)
if(mt[i][j1]==0) mt[i][j1]=++s;
k=0; // изменение направления движения вправо
break;
}
}
clrscr();
puts("spiral Ylama");
for(i=0;i<n;i++)
{ printf("\n");
for(j=0;j<n;j++)
{ k=0;
for(s=2; s<mt[i][j]-1;s++) // цикл проверки является ли mt[i][j]
if(mt[i][j] % s==0) // простым числом
{ k=1;
break;
}
if(k==0 && mt[i][j]!=1) printf("%s"," * ");
else printf("%3d",mt[i][j]);
}
}
return 0;
}