Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Alexandrov_E_E__Afonin_V_V_-_Programmirovani

.pdf
Скачиваний:
222
Добавлен:
11.03.2015
Размер:
6.21 Mб
Скачать

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

{

printf("\n");

for (j = 0; j < n; j++) printf(" %4d", C[i][j]);

}

printf("\n\n ... Press any key: ");

_getch(); return 0;

}

В программе используются три цикла по формированию произведения двух матриц. Первый цикл (переменная i) связан с количеством строк первой матрицы (матрицы А), второй (переменная j) – с количеством столбцов второй матрицы (матрица В), третий (переменная k) – со смежной размерностью матриц, которая исчезает в результирующей матрице С. Матрицы А и В определены как неизменяемые типы (const int). Приведенный программный метод (метод «ijk») можно назвать первым методом.

Результат выполнения программы показан на рис. 5.7.

Рис. 5.7. Результат произведения двух матриц

Задание 7

1.Измените программу, чтобы циклы были организованы в порядке «jki». Это можно назвать вторым методом программного перемножения двух матриц.

2.Измените программу, чтобы циклы были организованы в порядке «kji». Это можно назвать третьим методом программного перемножения двух матриц.

3.Примените тип float для заданных матриц. Предусмотрите форматированный вывод результата на консоль, когда элементы столбцов выравниваются по правому краю, а между столбцами фиксированное число позиций (между числами с наибольшим количеством цифр).

91

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

1.Как организуются многомерные числовые массивы в языке С?

2.Как организуется индексирование числовых массивов в языке С?

3.На кого или на что возлагается контроль границ числовых массивов в языке программирования С?

4.В какой очередности и как происходит заполнение многомерных числовых массивов в программах на языке С?

5.Для чего применяется начальная инициализация числовых массивов при дальнейшем их использовании?

6.Сколько потребуется операторов цикла для вывода на консоль двухмерного числового массива (матрицы чисел)?

7.Почему при определении размерности массива с помощью препроцессорной директивы define не используется точка с запятой после числового значения?

БИБЛИОГРАФИЧЕСКИЙ СПИСОК

1.Кочан С. Программирование на языке С : пер. с англ./С. Кочан. –

3-е изд. – М. : Вильямс, 2007. – 496 с.

2.Шилдт Г. Полный справочник по С : пер. с англ./Г. Шилдт. – 4-е изд. –

М. : Вильямс, 2007. – 704 с.

3.Хусаинов Б. С. Структуры и алгоритмы обработки данных. Примеры на языке Си (+CD) : учеб. пособие / Б. С. Хусаинов. – М. : Финансы и стати-

стика, 2004. – 464 с.

92

Тема 6

СИМВОЛЬНЫЕ МАССИВЫ В ЯЗЫКЕ С. РАБОТА СО СТРОКАМИ

Изучаются задание и инициализация символьных массивов в языке программирования С, решение задач с символьными массивами, базовые функции для работы со строками.

ТЕОРЕТИЧЕСКАЯ ЧАСТЬ

Как уже отмечалось, в языке программирования С заложены средства для задания последовательностей упорядоченных данных – массивов. Рассмотрим массивы символов, которые определяются типом char. Одномерный массив наиболее часто применяется в виде строки символов. Строка – это одномерный массив символов, заканчивающийся нулевым символом – '\0' [1; 2], который служит признаком окончания строки. При объявлении массива символов, предназначенного для хранения строки, необходимо отвести одно место для нуля. Например, если дана строка qwerty, в которой 6 символов, каждый из которых занимает в памяти 1 байт, то при инициализации такой строки необходимо отвести 1 байт для нулевого символа. Поэтому следует сделать объявление строки для семи символов:

char str[7] = "qwerty";

Альтернативным объявлением может служить безразмерная инициализа-

ция:

char str[ ] = "qwerty";

При этом в случае определения длины строки результатом будет число 6. Размер строки не изменится, если в ней указать символ ее окончания:

char str[ ] = "qwerty\0";

Аналогично числовым массивам в языке С могут использоваться массивы строк, т. е. набор одномерных массивов символов. Например, сервер базы данных сверяет команды пользователей с массивом допустимых команд [2]. В качестве массива строк будет служить двухмерный символьный массив. Размер левого измерения определяет количество строк, а правого – максимальную длину каждой из них [2]. Например:

char str[30][80];

Число 30 – это количество строк массива, а 80 – максимальная длина каждой строки с учетом нулевого символа ее завершения. Чтобы обратиться к отдельной строке двухмерного символьного массива, достаточно указать только левый индекс объявленного массива.

Многомерные символьные массивы образуются как и числовые: char str[n][m] [N];

93

В объявлении массива n – первая размерность, m – вторая размерность, , N N-я (последняя) размерность. Значения размерностей – целые неотрицательные числа.

6.1. Одномерные символьные массивы – строки

Одномерный массив – это список связанных однотипных переменных. Общая форма записи [2]:

тип имя_массива[размер];

В приведенной записи элемент тип объявляет базовый тип массива. Количество элементов, которые будут храниться в массиве с именем имя_массива, определяется элементом размер.

В языке С индексация массива (символьного или числового) начинается с

нуля.

Доступ к отдельному элементу массива осуществляется с помощью индекса, описывающего позицию элемента внутри массива.

Все массивы занимают смежные ячейки памяти, т. е. элементы массива в памяти расположены последовательно друг за другом. Ячейка памяти с наименьшим адресом относится к первому элементу массива, а с наибольшим – к последнему.

Для массива символов при инициализации массива необходимо резервировать место для символа окончания строки, т. е. '\0'.

Символьная константа – это набор символов, заключенных в двойные апострофы, например "hello".

В конец символьной строки не требуется обязательно добавлять нуль, компилятор языка С делает это автоматически. При инициализации символьной строки как одномерного массива необходимо предусмотреть место для нулевого символа, например:

char str[7] = "hello";

Для одномерных массивов общий размер массива в байтах вычисляется по формуле

всего байт = размер типа в байтах × количество элементов.

6.2. Двухмерные символьные массивы

Двухмерный массив представляет собой список одномерных массивов. Общая форма его записи выглядит так:

тип имя_массива[размер1] [размер2];

В приведенной записи размер1 означает число строк двухмерного массива, а размер2 – количество столбцов. При этом размерность размер2 определяет максимальную длину для заданного массива. Обычно размер2 задают с некоторым запасом.

94

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

Место хранения для всех элементов массива определяется во время компиляции. Память, выделенная для хранения массива, используется в течение всего времени его существования.

Для двухмерных массивов заданного типа общий размер в байтах вычисляется по формуле

всего байт = количество строк × количество столбцов × размер в байтах.

Инициализация двухмерного символьного массива может быть определена либо посимвольно, либо построчно, например

char str[3][80] = {

{'1','2','3','4','5'},

{'x','y','z'},

{'A','B','C','D'}

};

char str2[3][80] = { "0123456789",

"x_y_z",

"A B C D" };

Число 80 взято с запасом для возможной длины строки. Число 3 – это количество строк двухмерного массива. В обоих случаях может быть добавлен символ окончания строки ('\0'), который не выводится на экран дисплея и не передается в файл, например в текстовый. В то же время необходимо помнить, что каждая строка заканчивается нулевым символом.

6.3. Многомерные символьные массивы

Общая форма записи многомерного массива:

тип имя_массива[размер1] [размер2] [размерN];

Индексация каждого размера начинается с нуля. Элементы массива располагаются в памяти в порядке возрастания самого правого индекса. Поэтому правый индекс будет изменяться быстрее, чем левый (левые). В конце каждой строки подразумевается нулевой символ.

При обращении к многомерным массивам компьютер много времени затрачивает на вычисление адреса, так как приходится учитывать значение каждого индекса [2]. Следовательно, доступ к элементам многомерного массива происходит значительно медленнее, чем к элементам одномерного. В связи с этим многомерные массивы используются значительно реже, чем одноили двухмерные.

Для многомерных массивов общий размер в байтах вычисляется по фор-

муле

всего байт = размер1× размер2× × размерN ×размер типа в байтах.

95

Очевидно, многомерные массивы способны занять большой объем памяти, а программа, которая их использует, может очень быстро столкнуться с проблемой нехватки памяти.

Для определения размера типа в байтах применяется функция sizeof(), которая возвращает целое число. Например, sizeof(char).

При инициализации многомерных массивов необходимо указать все данные (размерности), за исключением крайней слева размерности. Это нужно для того, чтобы компилятор смог определить длину подмассивов, составляющих массив, и выделить необходимую память.

ПРАКТИЧЕСКАЯ ЧАСТЬ

Пример 1. Написать программу определения длины заданных строк и их распечатки, а также определения размера строк в байтах.

Для решения поставленной задачи применим библиотечную функцию strlen() и оператор sizeof.

Программный код решения примера

#include <stdio.h>

#include <conio.h>

#include <string.h>

int main (void) {

char str[] = {'A','B','C','D','\0'}; char str2[] = "hello, world\0"; printf("\n\t The lines are:\n\n\t ");

puts(str);

printf("\t "); // Для отступа от края дисплея puts(str2);

printf("\n\t The length of the 1st line (%s) is: %i\n", str, strlen(str));

printf("\t The size of the memory of the 1st line (%s) is: %i\n", str, sizeof str);

printf("\n\t The length of 2-nd line (%s) is: %i\n", str2, strlen(str2));

printf("\t Memory size 2-nd line (%s) is: %i\n", str2, sizeof str2);

printf("\n Press any key: "); _getch();

return 0;

}

В программе функция strlen() возвращает длину строки, причем последняя должна заканчиваться символом окончания строки [2], который не учитывается. Для работы с функцией strlen() необходимо подключить заголовок <string.h>. Оператор sizeof во время компиляции программы по-

96

лучает размер типа или значения. Для определения размера типа он применяется со скобками, например sizeof(char), а для определения размера конкретного значения скобки могут необязательны.

В программе использована функция puts(), которая записывает строку, адресуемую, например, параметром str, в стандартное выходное устройство – дисплей. Символ конца строки преобразуется в разделитель строк.

Результат выполнения программы показан на рис.6.1.

Рис. 6.1. Определение длины и размерности строк

Задание1

1.В строке str2[] уберите символ завершения строки. Проанализируйте и объясните результат.

2.Вместо функций puts() примените функции printf().

3.Задайте явную инициализацию строк как одномерных массивов. Сравните результаты длины и размерности строк.

4.При явной инициализации одномерных массивов в заданных строках не указывайте символы конца строки. Проанализируйте результат выполнения программы.

5.Напишите программу циклического заполнения символьного массива, соответствующего фамилии пользователя (студента).

6.Определите размерности типов char, int, float, double, long int, long double.

Пример 2. Написать программу копирования одной заданной строки в другую. При решении используем библиотечную функцию strcpy_s(), для ко-

торой подключим заголовок <string.h>. Программный код решения примера

#include <stdio.h>

#include <conio.h>

#include <string.h>

int main (void)

{

char str1[] = "123456789"; char str2[] = "qwerty";

97

printf("\n\t The length of the line \"%s\" is: %d\n", str1, strlen(str1));

// Копирование с учетом размера str1 strcpy_s(str1, strlen(str1), str2);

printf("\t After copying: "); puts(str1);

printf("\n\t The length of the line \"%s\" is: %d\n", str1, strlen(str1));

printf("\n Press any key: "); _getch();

return 0;

}

Результат выполнения программы показан на рис.6.2.

Рис.6.2. Пример копирования строк

Задание2

1.В программе для строк добавьте символ окончания строки. Проанализируйте результат выполнения программы.

2.Скопированную строку выведите на экран дисплея с разрядкой (с пробелами) между символами.

3.Произведите копирование одной строки в другую при их задании через клавиатуру.

4.Введите с клавиатуры две строки, различающиеся одним символом. Напишите программу по определению индексов двух различных символов для введенных строк. Длину строк возьмите не менее 7 символов.

5.Произведите копирование одной строки в другую без применения функ-

ции strcpy().

6.С клавиатуры введите свою фамилию (буквами латинского алфавита), выведите ее на консоль в прямом и обратном порядке, например Ivanov, vonavI.

Пример 3. Написать программу преобразования десятичной системы счисления в двоичную. Исходное десятичное число считать целым без знака.

98

Программный код решения примера

#include <stdio.h>

#include <conio.h>

int main (void)

{

const char D[] = {

'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};

int newNumber[80]; long int inputNumber; int i = 0, base = 2;

printf("\n\t Enter a positive integer: "); scanf_s("%ld", &inputNumber);

// Прямой процесс преобразования десятичного числа в двоичное do {

newNumber[i] = inputNumber % base;

++i;

inputNumber /= base;

} while ( inputNumber != 0 );

//Запись преобразованного числа в обратном порядке printf("\n\t Result after conversion: ");

for (--i; i >= 0; --i)

printf("%d", newNumber[i]);

printf("\n\n Press any key: "); _getch();

return 0;

}

В программе использован квалификатор (спецификатор) типа const, который указывает компилятору, что символьный массив не может изменяться в программе.

Результат выполнения программы приведен на рис.6.3.

Рис. 6.3. Перевод десятичного числа в двоичное

Задание3

1.Проверьте работу программы с помощью инженерного калькулятора (см. calc через Пуск Выполнить).

99

2.Подсчитайте число итераций цикла для преобразования числа 13 в двоичное число.

3.Вместо цикла do – while примените цикл while.

4.Напишите программу преобразования двоичного числа в десятичное число. Проверьте работу программы с помощью инженерного калькулятора.

5.Напишите программу для преобразования десятичных чисел в числа с основанием 3 и 8.

Пример 4. С помощью функции strcat() присоединить одну строку к другой с пробелом и без.

Пусть имеются строки str1 и str2. Функция strcat() присоединяет к строке str1 копию строки str2 и завершает строку str1 нулевым символом [2]. Процесс присоединения называется конкатенацией.

Программный код решения примера

#include <stdio.h>

#include <conio.h>

#include <string.h>

#define N 79

int main (void)

{

char str1[N+1], str2[N+1];

printf("\n\t Print 1 string of characters: "); gets_s(str1, N); // для MS Visual Studio

printf("\t Print 2 string of characters: "); gets_s(str2, N); // для MS Visual Studio

strcat_s(str1, N, str2); // для MS Visual Studio printf("\n\t Result after concatenation: %s\n", str1);

printf("\n Press any key: "); _getch();

return 0;

}

Возможный результат выполнения программы представлен на рис.6.4.

Рис. 6.4. Результат конкатенации двух строк

100