Опубликован: 14.12.2010 | Уровень: для всех | Доступ: свободно
Лекция 9:

Указатели и массивы в языке С

< Лекция 8 || Лекция 9: 1234 || Лекция 10 >

Задание 5

  1. Промежуточный размер k примите за 5*Х, где Х – номер компьютера, за которым выполняется лабораторная работа. Предусмотрите корректный вывод результата перемножения двух матриц.
  2. Вывод результата перемножения выполните на основе операции разыменования.
  3. Напишите программу умножения матриц с обычной индексацией элементов массивов, т.е. без использования указателей.
  4. Включите нумерацию строк и столбцов (слева от матрицы и вверху над ней).
  5. Проверьте работу программы без предварительного обнуления.

Пример 6. Напишите программу формирования трех массивов, состоящих из матриц размерностей 4 \times 8, и заполненных натуральными числами. Заполнение матриц выполнить по строкам последовательно для каждого из массивов. Предусмотрите вывод всех трех массивов на консоль и вывод одного из массивов, номер которого задается пользователем с клавиатуры.

Для решения примера сформируем трехмерный массив размером 3 \times 4 \times 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.

Пример вывода данных трехмерного массива

Рис. 8.6. Пример вывода данных трехмерного массива

Задание 6

  1. В программу включите проверку вводимого номера матрицы, т.е. чтобы число r \in [1;3].
  2. В программу введите указатели с многоуровневой адресацией, например ***ptr3, **ptr2. Проверьте работу программы.
  3. Количество строк матрицы примите n = 2*Х, где Х – номер компьютера, за которым выполняется лабораторная работа.
  4. Трехмерный массив заполните вещественными числами, равномерно распределенными в интервале [–3*X; 3*X], где Х – номер компьютера, за которым выполняется лабораторная работа.
  5. С учетом предыдущего пункта определите минимальный и максимальный элементы трехмерного массива. Определите также индексы (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.

Результат поиска подстроки в строке

Рис. 8.7. Результат поиска подстроки в строке

Задание 7

  1. Объясните процесс вычисления правой части выражения с переменной numSTR.
  2. Примените вместо операторов цикла for операторы цикла while.
  3. Подсчитайте количество итераций формирования строки (из 15 символов), когда в ней будет найдена задаваемая подстрока (например, три латинские буквы вашей фамилии).
  4. Включите допустимо возможное для вашего компилятора количество итераций поиска подстроки в строке.
  5. Напишите программу имитации взлома пароля, состоящего из трех букв латинского алфавита. Если при трехкратном ручном вводе пароля, он не будет разгадан, то включите автоматический поиск.

Контрольные вопросы

  1. Как рассматривает имя массива компилятор языка С?
  2. На какое место в памяти компьютера указывает имя массива?
  3. Какая связь между указателями и массивами в языке С?
  4. Как формируется массив указателей в языке С?
  5. Как следует организовать посимвольное формирование строки символов с помощью указателя?
  6. Как с помощью одного указателя произвести инициализацию и вывод результата на консоль двухмерного (трехмерного) числового массива?
  7. Как изменяется значение типизированного указателя при применении к нему операции адресного сложения?
  8. Как производится вычитание указателей?
< Лекция 8 || Лекция 9: 1234 || Лекция 10 >
Мухаммадюсуф Курбонов
Мухаммадюсуф Курбонов