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

Главная

СТРОКИ

Для представления символьной информации можно использовать символы, символьные переменные и символьные константы.

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

Встроенный строковый тип

Встроенный строковый тип перешел в С++ от С. Строка символов хранится в памяти как массив, и доступ к ней осуществляется при помощи указателя типа char*. Количество элементов в таком массиве на один элемент больше, чем изображение строки, т.к. в конец строки добавлен '\0' (нулевой байт или нуль-терминатор:

АА \0

„A‟ “A”

символ(1 байт)

строка (2 байта)

Объявление и инициализация строк

Поместить строку в массив можно либо при вводе, либо с помощью инициализаций:

char str1[] = "STRING";

char str2[20] = { 'S','t','r','i','n','g','\0' }; const char *str3 = "STRING\n";

char str4[20];

cin >> str4;

//строка не должна превышать 19 симв. + 0 символ

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

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

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

1

можно использовать функцию С++ cin.getline. Она требует три аргумента – массив символов, в котором должна храниться строка текста, длина и символ-ограничитель:

char str1[80]; cin.getline(str1, 80, '\n');

Функция прекращает считывать символы если встречается символ-ограничитель '\n' и если количество считанных символов оказывается на один меньше, чем указано во-втором аргументе. Третий аргумент имеет '\n' в качестве значения по умолчанию, так что в вызове функции его можно опустить.

Согласно общепринятым стандартом ASCII установлено соответствие между символами и кодами. Клавиатура (совместно с драйвером) кодирует нажатие любой клавиши с учетом регистровых и управляющих клавиш в соответствующий ей код (прил. 1 содержит список символьных кодов ASCII). Например:

' '

-

0x20,

'B'

-

0x42,

'*'

-

0x2A,

'Y'

-

0x59,

Манипуляции со строками и символами на самом деле подразумевают манипуляции с соответствующими численными кодами, а не с самими символами. Это объясняет взаимозаменяемость символов и малых целых в С++. Так как имеет смысл говорить, что один численный код больше, меньше или равен другому численному коду, можно сопоставлять различные строки и символы друг с другом.

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

'0' - '9' 0x30 - 0x39 'A' - 'Z' 0x41 - 0x5A 'a' - 'z' 0x61 - 0x7A

Тогда, для получения символа десятичной цифры из значения целой переменной, лежащей в диапазоне 0…9, а также значения целой переменной из символа десятичной цифры можно:

int

n = 5;

char

c;

c = n + '0';

if (c >= '0' && c <= '9') n = c - '0';

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

char c;

if (c >='a' && c <='z') c = c - 'a' + 'A';

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

2

Работа со строкой

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

while (*str1++ ) { ... }

str1 разыменовывается, и получившееся значение проверяется на истинность. Любое отличное от нуля значение считается истинным, и, следовательно, цикл заканчивается, когда будет достигнут символ с кодом 0. Операция инкремента ++ прибавляет 1 к указателю str1 и таким образом сдвигает его к следующему символу.

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

char st[] = "STRING";; int cnt = 0;

if ( st )

while ( *st++ ) ++cnt;

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

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

//pstr1 не адресует массива символов char *pstr1 = 0;

//pstr2 адресует нулевой символ const char *pstr2 = "";

При работе со строкой можно, также как и в массивах, использовать нотацию индексов:

for (int i = 0; (s1[i] = s2[i])!= '\0'; i++); //

а также нотацию указателей:

for (; (*s1 = *s2) != '\0'; s1++, s2++); // копирование

Использование строк встроенного типа чревато ошибками из-за слишком низкого уровня реализации и невозможности обойтись без адресной арифметики. Рассмотрим типичные ошибки. Например:

const char *str = "STRING\n"; int len = 0;

while ( str++ ) ++len; //ошибка,str не разыменовывается и изменяется

Указатель str не разыменовывается, следовательно, на равенство 0 проверяется не

3

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

Поскольку строка представляет собой последовательность символов, большинство программ, обрабатывающих строки, используют последовательный или посимвольный просмотр строки. Если же в процессе обработки строки предполагается изменение ее содержимого, то проще всего (но не всегда эффективно) организовать его в виде посимвольного переписывания входной строки в выходную. При этом нужно помнить, что каждой строке требуется отдельный индекс, если для входной строки он может изменяться в заголовке цикла посимвольного просмотра, то для выходной строки он меняется только в моменты добавления очередного символа. Кроме того, не нужно забывать «закрывать» выходную строку символом конца строки. В качестве примера рассмотрим пример удаления лишних пробелов из строки:

сhar str1[] = "STR ING"; сhar str2[10];

int i,j;

for (j = 0, i = 0; str1[i] != 0; i++) // Посимвольный просмотр строки

{

if (str1[i] != ' ') // Текущий символ – не пробел

{

if (i!=0 && str1[i-1] ==

' ')//

Первый в

слове -

str2[j++] = ' ';

//

добавить

пробел

str2[j++] = str1[i];

// Перенести символ слова

}

// в выходную строку

}

str2[j] = 0;

Рассмотрим еще один пример проверки правильности расстановки круглых скобок в строке:

4

char s[256];

int i, c; // с переменнаясчетчик cout << "Введите строку"; gets(s); // вводим строку

for(c = i = 0; s[i] != 0; i++)

{

if(s[i] == '(') // если скобка открывающая c++; // увеличить счетчик

if(s[i] == ')') // если скобка закрывающа c--; // уменьшить счетчик

}

if(!c)

//если с = 0, кол-во открывающих // и закрывающих скобок равно

cout << "Текст сбалансирован по скобкам\n";

else

cout << "Баланса скобок нет\n";

Функции работы со строками

Стандартная библиотека С предоставляет набор функций для манипулирования строками. Стандартная библиотека С является частью библиотеки С++. Для ее использования мы должны включить заголовочный файл #include <cstring>. Функции приведены в табл. 1.

Таблица 1

 

Набор функций манипулирования строками

 

 

Функция

Прототип и краткое описание функции

strcmp

int strcmp(const char *str1, const char *str2);

 

Сравнивает строки str1 и str2. Если str1 < str2, то результат

 

отрицательный, если str1 = str2, то результат равен 0, если str1 >

 

str2, то результат положительный

strcpy

char* strcpy(char*s1, const char *s2);

 

Копирует байты из строки s1 в строку s2

strdup

char *strdup (const char *str);

 

Выделяет память и переносит в нее копию строки str.

strlen

int strlen (const char *str);

 

Вычисляет длину строки str

strncat

char *strncat(char *s1, const char *s2, int

 

kol);

 

Приписывает kol символов строки s1 к строке s2

strncpy

char *strncpy(char *s1, const char *s2, int

 

kol);

 

Копирует kol символов строки s1 в строку s2

strnset

char *strnset(char *str, int c, int kol);

 

Заменяет первые kol символов строки s1 символом с

5

atoi

int atoi(char *str);

 

Преобразует строку в целое

atof

float atof(char *str);

Преобразует строку в число с плавающей точкой

 

Строки при передаче в функцию в качестве фактических параметров могут быть определены либо как одномерные массивы типа char[], либо как указатели типа char*. В отличие от массивов, в этом случае нет необходимости явно указывать длину строки.

Для указателя с типом указуемой переменной char допускаются различные интерпретации: указатель на отдельный байт; указатель на область памяти – массив байтов; указатель на отдельный символ; указатель на массив символов.

6

Соседние файлы в папке Теория