Указатели и массивы в языке С
Задание 5
- Промежуточный размер k примите за 5*Х, где Х – номер компьютера, за которым выполняется лабораторная работа. Предусмотрите корректный вывод результата перемножения двух матриц.
- Вывод результата перемножения выполните на основе операции разыменования.
- Напишите программу умножения матриц с обычной индексацией элементов массивов, т.е. без использования указателей.
- Включите нумерацию строк и столбцов (слева от матрицы и вверху над ней).
- Проверьте работу программы без предварительного обнуления.
Пример 6. Напишите программу формирования трех массивов, состоящих из матриц размерностей 4 8, и заполненных натуральными числами. Заполнение матриц выполнить по строкам последовательно для каждого из массивов. Предусмотрите вывод всех трех массивов на консоль и вывод одного из массивов, номер которого задается пользователем с клавиатуры.
Для решения примера сформируем трехмерный массив размером 3 4 8 с помощью указателя, в котором левый размер будет равен 3, центральный размер равен 4, а крайний правый размер равен 8, например *PTR[3*4*8].
Программный код решения примера:
#include <stdio.h> #include <conio.h> #define p 3 // Количество "подшитых" матриц #define n 4 // Число строк матрицы #define m 8 // Число столбцов матрицы int main (void){ int i, j, k, r; int *PTR[p*n*m], *M2[n*m]; // Заполнение одномерного массива for (i = 0; i < p*n*m; ++i) PTR[i] = (int*)(i + 1); printf("\n An array of dimension %dx%dx%d:\n", p, n, m); puts("==========================================="); // Разбивка массива for (k = 0; k < p; ++k){ printf("\n"); for (i = 0; i < n; ++i) { printf(" "); for (j = 0; j < m; ++j){ printf(" %3d ",PTR[k*n*m + i*m + j]); } printf("\n"); } } puts("==========================================="); printf("\n Select the number of arrays of a series of numbers (%d...%d): ",1, p); scanf_s("%d", &r); printf("\n Matrix number %d from three-dimensional array:\n", r); // Выбор матрицы из 3-мерного массива for (k = 0; k < p; ++k) for (i = 0; i < n; ++i) for (j = 0; j < m; ++j) if ( k == (r-1)) {M2[i*m + j] = PTR[k*n*m + i*m + j];} for (i = 0; i < n; ++i) { printf("\n "); for (j = 0; j < m; ++j) printf(" %3d ", M2[i*m + j]); } printf("\n\n Press any key: "); _getch(); return 0; }
Трехмерный массив можно рассматривать как книгу с заданным количеством страниц (размер p = 3 ), размер которых определяется как матрица с заданным числом строк (размер n = 4 ) и с заданным количеством столбцов (размер m = 8 ). Страницы (матрицы) "сшиваются". С помощью указателя *PTR сначала формируется одномерный массив, а затем он разбивается на заданное количество матриц. В функциях puts() допускается перевод на новую строку с помощью символа форматирования \n.
Результат выполнения программы показан на рис. 8.6.
Задание 6
- В программу включите проверку вводимого номера матрицы, т.е. чтобы число r [1;3].
- В программу введите указатели с многоуровневой адресацией, например ***ptr3, **ptr2. Проверьте работу программы.
- Количество строк матрицы примите n = 2*Х, где Х – номер компьютера, за которым выполняется лабораторная работа.
- Трехмерный массив заполните вещественными числами, равномерно распределенными в интервале [–3*X; 3*X], где Х – номер компьютера, за которым выполняется лабораторная работа.
- С учетом предыдущего пункта определите минимальный и максимальный элементы трехмерного массива. Определите также индексы (k,i,j) этих элементов. Результаты выведите на консоль.
Пример 7.Напишите программу поиска подстроки в строке, сформированной по случайному закону из 15 букв латинского алфавита, с помощью функции strstr(). В качестве подстроки принять первые три буквы своей фамилии.
Для работы с функцией strstr() требуется подключение заголовочного файла string.h.
Программный код решения примера:
#include <stdio.h> #include <conio.h> #include <string.h> #include <stdlib.h> #include <time.h> int main (void) { int i, k = 0, n, in; int numSTR; int N = 1000; int numA, numZ; char str[16]; char sub[4]; char *ptr; srand((unsigned)time(NULL)); numA = (int)'a'; numZ = (int)'z'; printf("\n Enter the three letters: "); in = scanf_s("%s", sub, sizeof(sub)); if (in == 0) { printf("\n Error input. Press any key: "); _getch(); exit(1); } printf("\n\t substring is \"%s\"\n", sub); for (n = 0; n < N; n++) { for (i = 0; i < 15; i++) str[i] = numA + rand() % (numZ - numA) + 1; str[i] = '\0'; ptr = strstr(str, sub); if (ptr != NULL) { numSTR = (int)(ptr - str +1); k++; break; } } if (k == 0) printf("\n\t Substring \"%s\" not found", sub); else printf("\n\t Substring \"%s\" found at positions %d, %d, %d", \ sub, numSTR, numSTR+1, numSTR+2); puts("\n"); for (i = 0; i < 15; i++) printf(" %3d)", i+1); puts(""); for (i = 0; i < 15; i++) printf(" %3c ", str[i]); printf("\n\n ... Press any key: "); _getch(); return 0; }
Подобный пример рассматривался в предыдущей работе. Видно, что применение указателя и функции strstr() существенно привело к уменьшению программного кода.
Возможный положительный результат работы программы показан на рис. 8.7.
Задание 7
- Объясните процесс вычисления правой части выражения с переменной numSTR.
- Примените вместо операторов цикла for операторы цикла while.
- Подсчитайте количество итераций формирования строки (из 15 символов), когда в ней будет найдена задаваемая подстрока (например, три латинские буквы вашей фамилии).
- Включите допустимо возможное для вашего компилятора количество итераций поиска подстроки в строке.
- Напишите программу имитации взлома пароля, состоящего из трех букв латинского алфавита. Если при трехкратном ручном вводе пароля, он не будет разгадан, то включите автоматический поиск.
Контрольные вопросы
- Как рассматривает имя массива компилятор языка С?
- На какое место в памяти компьютера указывает имя массива?
- Какая связь между указателями и массивами в языке С?
- Как формируется массив указателей в языке С?
- Как следует организовать посимвольное формирование строки символов с помощью указателя?
- Как с помощью одного указателя произвести инициализацию и вывод результата на консоль двухмерного (трехмерного) числового массива?
- Как изменяется значение типизированного указателя при применении к нему операции адресного сложения?
- Как производится вычитание указателей?