Смекни!
smekni.com

Основы программирования на языке Си (стр. 16 из 27)

декса. Например, чтобы изменить значение 2-го пиксела слева в 4-й строке надо запи-

сать оператор:

bitmap[3][1] = true;

Все сказанное во 2-м параграфе относительно одномерных массивов как пара-

метров функций верно и для двумерных массивов, но у них есть еще одна особен-

ность. В прототипах и заголовках функций можно опускать первую размерность мно-

гомерного массива-параметра (т.е. записывать пустые квадратные скобки "[]"), но все

остальные размерности надо обязательно указывать. Далее в качестве примера приве-

дена функция, заполняющая битовую карту черными пикселами.

void clear_bitmap( bool bitmap[][BITMAP_WIDTH],

int bitmap_height )

{

for ( int row = 0; row < bitmap_height; row++ )

70

for ( int column = 0; column < BITMAP_WIDTH; column++ )

bitmap[row][column] = false;

}

5. Символьные строки

Во многих уже рассматривавшихся программах для вывода на экран часто ис-

пользовались символьные строки, например, ""Введите возраст:"". В Си++ строки

хранятся и обрабатываются в виде символьных массивов, на которые накладывается

дополнительное ограничение (см. п.5.1).

5.1 Завершающий нуль-символ '&bsol;0'

Символьный массив для хранения строки должен иметь длину на 1 символ

больше, чем длина строки. В последнем элементе массива хранится специальный

нуль-символ (символ с кодом 0, часто обозначается '&bsol;0'). Этот служебный символ

обозначает конец строки, и это общепринятое правило представления строк, которое

соблюдают все библиотечные функции для работы со строками.

На рис. 6 показаны два массива, в которых хранятся символы строки ""Введите

возраст:"", но из них только массив "phrase" является правильным представлением

строки. Хотя и "phrase", и "list" являются символьными массивами, но только

"phrase" имеет достаточную длину для хранения символьной строки ""Введите воз-

раст:"" вместе с завершающим символом "'&bsol;0'".

Рис. 6.. Правильное ("phrase") и неправильное ("list") представление сим-

вольной строки.

5.2 Объявление и инициализация символьных строк

Символьные строки описываются как обычные массивы:

char phrase[17];

Массивы можно полностью или частично проинициализировать непосредст-

венно в операторе описания. Список значений элементов массива заключается в фи-

гурные скобки "{}" (это правило верно для любых массивов, а не только для сим-

вольных). Например, оператор

char phrase[17] = { 'В','в','е','д','и','т','е',' ',

'в','о','з','р','а','с','т',

':', '&bsol;0' };

71

одновременно и объявляет массив "phrase", и присваивает его элементам значения

согласно рис. 6. То же самое делает оператор:

char phrase[17] = "Введите возраст:";

Если не указывать размер "17", то размер массива будет выбран в соответствии

с количеством инициализирующих значений (с учетом завершающего нуль-символа).

Т.е. строку можно описать с помощью любого из двух следующих операторов:

char phrase[] = { 'В','в','е','д','и','т','е',' ',

'в','о','з','р','а','с','т',

':', '&bsol;0' };

char phrase[] = "Введите возраст:";

Очень важно запомнить, что символьные строки хранятся в виде массивов. По-

этому их нельзя приравнивать и сравнивать с помощью операций "=" и "==". Напри-

мер, нельзя записать оператор присваивания:

phrase = "Вы напечатали строку:";

Для копирования и сравнения строк следует применять специальные библио-

течные функции.

5.3 Библиотечные функции для работы с символьными строками

В стандартном библиотечном файле "string.h" хранятся прототипы большо-

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

что в рассматриваемые далее программы этот заголовочный файл включается с по-

мощью директивы препроцессора:

#include <string.h>

Если в программе есть строковая переменная "a_string", то скопировать в нее

содержимое другой строки можно с помощью функции "strcpy(...)":

strcpy( a_string, "Вы напечатали строку:" );

Этот оператор скопирует в массив a_string символы константной строки ""Вы

напечатали строку:"" и добавит в конец массива (т.е. присвоит 21-му элементу) за-

вершающий нуль-символ "'&bsol;0'". Вызов оператора

strcpy( a_string, another_string );

приведет к копированию строки, хранящейся в массиве "another_string", в массив

"a_string". При копировании строк важно, чтобы длина массива-приемника

("a_string") была, как минимум, (L+1), где L длина копируемой строки

("another_string"). В противном случае вызов функции приведет к ошибке выхода за

пределы массива, которая не обнаруживается компилятором, но может привести к

серьезным сбоям во время выполнения программы.

Для вычисления длины строки предназначена функция "strlen(...)". Вызов

"strlen(another_string)" возвращает длину строки "another_string" (без учета нуль-

символа).

Функция "strcmp(...)" выполняет сравнение двух переданных ей строк. Если

строки одинаковы, то эта функция возвратит 0 (т.е. "false"), а если строки различа-

ются, то функция возвратит ненулевое значение.

Функция конкатенации (соединения) строк "strcat(...)" получает два пара-

метра-строки и копирует вторую строку в конец первой. При работе с "strcat(...)",

как и с функцией "strcpy(...)", надо обязательно следить за размером массива-

приемника. Си++ не проверяет, достаточен ли размер первого массива, переданного

72

этой функции, для хранения соединенных строк. При малом размере массива про-

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

Работа с библиотечными строковыми функциями продемонстрирована в про-

грамме 5.1.

5.4 Чтение символьных строк из потока ввода с помощью функции "getline(...)"

Для ввода строк (например, с клавиатуры) пригоден оператор ">>", но его при-

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

пустим, в программе содержатся операторы:

...

...

cout << "Введите имя: ";

cin >> a_string;

...

...

После сеанса работы со следующими экранными сообщениями:

...

...

Введите имя: Вася Иванов

...

...

Переменной "a_string" будет присвоено значение ""Вася"", т.к. оператор ">>"

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

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

"getline(...)", имеющая 2 параметра. Например, оператор:

cin.getline(a_string, 80);

позволяет получить от пользователя строку с пробелами длиной до 79 символов (по-

следний, 80-й символ строки служебный нуль-символ).

В программе 5.1 демонстрируется действие функций "getline(...)",

"strcmp(...)", "strcpy(...)" и "strcat(...)".

#include <iostream.h>

#include <string.h>

const int MAXIMUM_LENGTH = 80;

int main()

{

char first_string[MAXIMUM_LENGTH];

char second_string[MAXIMUM_LENGTH];

cout << "Введите первую строку: ";

cin.getline(first_string,MAXIMUM_LENGTH);

cout << "Введите вторую строку: ";

cin.getline(second_string,MAXIMUM_LENGTH);

cout << "До копирования строки были ";

if ( strcmp(first_string,second_string) )

cout << "не ";

cout << "одинаковыми.&bsol;n";

73

strcpy( first_string, second_string );

cout << "После копирования строки стали ";

if ( strcmp(first_string,second_string) )

cout << "не ";

cout << "одинаковыми.&bsol;n";

strcat( first_string, second_string);

cout << "После конкатенации первая строка равна: ";

cout << first_string;

return 0;

}

Программа 5.1.

Программа 5.1 в типичном сеансе работы выводит сообщения: