Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекция.docx
Скачиваний:
37
Добавлен:
28.03.2016
Размер:
2.79 Mб
Скачать
  1. Функции работы со строками из библиотеки обработки строк

Библиотека обработки строк обеспечивает много полезных функций для работы со строковыми данными, сравнения строк, поиска в строках сим­волов и других подстрок, разметки строк (разделения строк на логические куски) и определения длины строк. В этом разделе представлены некоторые типовые функции работы со строками из библиотеки обработки строк (из стандартной библиотеки С). Сведения об этих функциях сведены в таблицу 2.1.

Некоторые функции из таблицы 2.1. имеют параметры с типом данных size_t. Этот тип определяется в заголовочном файле stddef.h (из стандартной библиотеки С) как беззнаковый целый тип, такой, как unsigned int или unsigned long.

Типичная ошибка программирования. Забывают включить заголовочный файл <string.h> при использовании функций из библиотеки обработки строк.

Таблица 2.1.

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

Прототип функции

Описание функции

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

Копирует строку s2 в массив символов s1. Возвращает значение s1.

char *strncpy(char *s1, const char *s2, size_t n)

Копирует не более п сиволов из строки s2 в массив символов s1. Возвращает значение s1.

char *strcat(char s1, const char *s2)

Добавляет строку s2 к строке s1. Первый символ строки s2 записывается поверх завершающего нулевого символа строки s1. Возвращает значение s1.

strncat(char *s1, const char *s2, size_t n)

Добавляет не более n символов строки s2 в строку s1. Первый символ из s2 записывается поверх завершающего нулевого символа в s1. Возвращает значение s1.

char * strcmp (const char *s1, const char *s2)

Сравнивает строки s1 и s2. Функция возвращает значение 0, меньшее, чем 0 или большее, чем 0, если s1 соответственно равна, меньше или больше, чем s2.

char * strcmp (const char *s1, const char *s2, size_t n)

Сравнивает до n символов строки s1 со стокой s2. функция возвращает значение 0, меньшее, чем 0 или большее, чем 0, если s1 соответственно равна, меньше или больше, чем s2.

char *strtok(char s1, const char *s2)

Последовательность вызовов strtok разбивает строку s1 на «лексемы» - логические куски, такие, как слова в строке текста -разделенные символами, содержащимися в строке s2. Первый вызов содержит в качестве первого аргумента s1, а последующие вызовы для продолжения обработки той же строки, содержат в качестве первого аргумента NULL. При каждом вызове возвращается указатель на текущую лексему. Если при вызове функции лексем больше нет, возвращается NULL.

size_t strlen(const char *s)

Определяет длину строки s. Возвращает количество символов, предшествующих завершающему нулевому символу.

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

Функция strncpy эквивалентна strcpy за исключением того, что strncpy указывает количество символов, которое должно быть скопировано из строки в массив. Функция strncpy не обязательно должна копировать завершающий нулевой символ своего второго аргумента; завершающий нулевой символ записывается только в том случае, если количество символов, которое должно быть скопировано, по крайней мере на один больше, чем длина строки. Например, если второй аргумент – "test", завершающий нулевой символ записывается только в случае, если третий аргумент strncpy по меньшей мере равен 5 (четыре символа в "test" плюс один завершающий нулевой символ). Если третий аргумент больше пяти, завершающий нулевой символ добавляется к массиву до тех пор, пока не будет записано общее количество символов, указанное третьим аргументом.

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

В программе (см. ниже) strcpy используется для копирования полной строки в массиве x в массив у и strncpy – для копирования первых 14 символов массива x в массив z. Нулевой символ ('\0') добавляется в массив z, потому что вызов strncpy в программе не записывает завершающий нулевой символ (третий аргумент меньше, чем длина строки второго аргумента).

//Использование strcpy и strncpy

#include <iostream.h>

#include <string.h>

main() {

char x[ ] = "Поздравляю Вас с днем рождения";

char y[35], z [15];

cout << "Строка в массиве x: "<< x << endl

<<"Строка в массиве у: " <<strcpy(x, у) << endl;

strncpy(z, x, 14);

z[14] - '\0';

cout << "Строка в массиве z: " << z << endl;

return 0;

}

Строка в массиве x: Поздравляю Вас с днем рождения

Строка в массиве у: Поздравляю Вас с днем рождения

Строка в массиве z: Поздравляю Вас

Функция strcat добавляет свой второй аргумент – строку к своему пер­вому аргументу – массиву символов, содержащему строку. Первый символ второго аргумента замещает нулевой символ ('\0'), который завершал строку в первом аргументе. Программист должен быть уверен, что массив, исполь­зуемый для хранения первой строки, достаточно велик для того, чтобы хра­нить комбинацию первой строки, второй строки и завершающего нулевого символа (скопированного из второй строки). Функция strncat добавляет ука­занное количество символов из второй строки в первую. К результату до­бавляется завершающий нулевой символ. Программа (см. ниже) демон­стрирует функцию strcat и функцию strncat.

// Использование strcat и strncat.

#include <iostream.h>

#include <string.h>

main() {

char s1[25] = "Счастливого ";

char s2[ ] = "Нового Года ";

char s3 [40] = " ";

cout << "s1 = " << s1 << endl << "s2 = " << s2 << endl;

cout << "strcat(s1, s2) = " << strcat(sl, s2) << endl;

cout << "strncat(s3, s1, 12) = " << strncat(s3, s1, 12) << endl;

cout << "strcat(s3, s1) = " << strcat(s3, sl) << endl;

return 0;

}

sl = Счастливого

s2 = Нового Года

strcat(sl, s2) = Счастливого Нового Года

strncat(s3, sl, 12) = Счастливого

strcat(s3, sl) = Счастливого Счастливого Нового Года

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

Чтобы понять, что означает, что одна строка «больше» или «меньше», чем другая строка, рассмотрим процесс расстановки имен по алфавиту. Чи­татель, без сомнения, поставил бы «Jones» перед «Smith», потому что в ал­фавите первая буква имени «Jones» стоит раньше первой буквы имени «Smith». Но алфавит – это больше, чем просто список из 26 букв – он упорядочивает список символов. Каждая буква занимает внутри списка оп­ределенную позицию. «Z» – это больше, чем просто буква алфавита; «Z» – это двадцать шестая буква алфавита.

Типичная ошибка программирования. Предположение, что strcmp и strncmp возвращают 1, если их аргументы равны. При равенстве обе функции возвращают 0 (значение «ложь» в С++). Поэтому при проверке двух строк на равенство результаты функции strcmp или strncmp должны для определения равенства строк сравниваться с 0.

// Использование strcmp и strncmp

#include <iostream.h>

#include <iomanip.h>

#include <string.h>

main() {

char *s1 = "Счастливого Нового Года ";

char *s2 = " Счастливого Нового Года";

char *s3 = "Счастливого Праздника";

cout << "sl = " << sl << endl << "s2 = " << s2 <<endl

<< "s3 = " << s3 << endl << endl

<< "strcmp(sl, s2)= " <<setw(2) << strcmp(sl, s2) << endl

<< "strcmp(sl, s3) = " << setw(2) << strcmp(sl, s3) << endl

<< "strcmp(s3, sl) = " << setw(2) << strcmp(s3, sl) << endl << endl;

cout << "strncmp(sl, s3, 12) = " << setw(2) << strncmp(sl, s3, 12) << endl

<< "strcmp(sl, s3, 13) = " << setw(2) << strncmp(sl, s3, 13) << endl

<< "strcmp(s3, sl, 13) = " << setw(2) << strncmp(s3, sl, 13) << endl;

return 0;

}

sl = Счастливого Нового Года

s2 = Счастливого Нового Года

s3 = Счастливого Праздника

strcmp(sl, s2) = 0

strcmp(sl, s3) = -2

strcmp(s3, sl) = 2

strncmp(sl, s3, 12) = 0

strncmp(sl, s3, 13) = -2

strncmp(s3, sl, 13) = 2

Как компьютер узнает о порядке следования букв? Все символы пред­ставляются внутри компьютера как численные коды; когда компьютер срав­нивает две строки, он на самом деле сравнивает численные коды символов в строке. (Замечание: коды символов упорядочены по алфавиту только для латинских букв, а к кириллице это, к сожалению, не относится.)

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

В попытке стандартизации представления символов большинство производителей компьютеров спроектировало свои машины так, чтобы использовать одну из двух популярных кодирующих схем – ASCII или EBCDIC. ASCII означает «Американский стандартный код для информационного обмена» («American Standard Code for Information Interchange»), а EBCDIC означает «Расширенный двоичный код закодированного десятичного обмена» («Extended Binary Coded Decimal Interchange Code»). Существуют и другие схемы кодирования, но эти две наиболее популярны.

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

Функция strtok используется для превращения строки в последователь­ность лексем. Лексема – это последовательность символов, отделенная сим­волами разделителям (обычно пробелами или знаками пунктуации). Напри­мер, в строке текста каждое слово может рассматриваться как лексема, а пробелы, отделяющие слова друг от друга, можно рассматривать как разде­лители.

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

tokenPtr = strtok(string, " ");

присваивает tokenPtr указатель на первую лексему в string. Второй аргумент strtok, " " указывает, что лексемы в string разделяются пробелами. Функция strtok отыскивает первый символ в string, не являющийся разделителем (пробелом). Это начало первой лексемы. Затем функция находит следующий разделительный символ в строке и заменяет его нулевым символом ('\0'). Этим заканчивается текущая лексема. Функция strtok сохраняет указатель на следующий символ, стоящий в string за данной лексемой, и возвращает указатель на текущую лексему.

//Использование strtok

#include <iostream.h>

#include <string.h>

main () {

char string[] = "Это предложение содержит пять лексем";

char *tokenPtr;

cout <<"Строка, разбиваемая на лексемы:" << endl << string << endl

<< endl << "Лексемы:" << endl;

tokenPtr = strtok(string, " ");

while (tokenPtr != NULL) {

cout << tokenPtr << endl;

tokenPtr = strtok(NULL, " ");

}

return 0;

}

Строка, разбиваемая на лексемы:

Это предложение содержит пять лексем

Лексемы:

Это

предложение

содержит

пять

лексем

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

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

Функция strlen получает в качестве аргумента строку и возвращает ко­личество символов в строке – завершающий нулевой символ в длину не включается. Программа (см. ниже) демонстрирует функцию strlen.

//Использование strlen

#include <iostream.h>

#include <string.h>

main() {

char *string1 = "abcdefghijklmnopqrstuvwxyz";

char *string2 = "три";

char *string3 = "Бостон";

cout << "Длина строки \"" << string1

<< "\" - " « strlen(stringl) << endl

<< "Длина строки \"" << string2

<< "\" - " « strlen(string2) << endl

<< "Длина строки \"" << string3

<< "\" - " << strlen(string3) << endl;

return 0;

}

Длина строки "abcdefghijklmnopqrstuvwxyz" - 26

Длина строки "три" – 3

Длина строки "Бостон" – 6