Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Конкатенация (сцепление) строк

Поиск

 

Конкатенация или сцепление строк может быть реализовано путем добавления одного массива в другой:

 

char Str1[10],Str2[10],Str3[20],Str4[11]=", and \0";

int I,J,K;

  printf("Input string: ");

  scanf("%s",Str1);

  printf("Input string too: ");

  scanf("%s",Str2);

  for (I=0;Str1[I]!=0;I++)

  Str3[I]=Str1[I];

  for (J=I,K=0;Str4[K]!=0;K++,J++)

  Str3[J]=Str4[K];

  for (I=J,K=0;Str2[K]!=0;K++,I++)

  Str3[I]=Str2[K];

  Str3[I]=0;

  printf("You input: %s\n",Str3);

 

Функция strcat() библиотеки string.h сцепляет строки точно также:

 

  char Str1[10],Str2[10],Str4[11]=", and \0";

  printf("Input string: ");

  scanf("%s",Str1);

  printf("Input string too: ");

  scanf("%s",Str2);

  strcat(Str1,Str4);

  strcat(Str1,Str2);

  printf("You input: %s\n",Str1);

 

Данный пример хорош только для англоязычных строк. Применение русских букв вызовет затруднения. Задать, например, русскоязычную константу не удастся, поскольку в инициализаторе нельзя применять функции. Поэтому следует использовать прямое обращение к массиву bufRus:

 

  char Str1[100],Str2[10];

  printf(RUS("Введите строку: "));

  scanf("%s",Str1);

  printf(RUS("Введите еще строку: "));

  scanf("%s",Str2);

   RUS(", а затем \0");

  strcat(Str1,bufRus);

  strcat(Str1,Str2);

  printf(RUS("Вы ввели: %s\n"),Str1);

 

Функция strncat() также осуществляет конкатенацию строк, однако, присоединяет лишь указанное в третьем параметре количество символов (беззнаковое целое):

char* strncat(char* strl, const char* str2, size_t num)

Функция возвращает указатель на начало сформированной строки strl.

 

Сравнение строк

 

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

 

char Str[21];

strcpy(Str, RUS("Проверка копирования"));

int i=0;bool PrEqu=false; //i - счетчик букв

RUS("Проверка копирования");//Занесение русского текста в bufRus

while (bufRus[i]!='\0') //Проверка на конец копируемого массива

{if (Str[i]!=bufRus[i])

{PrEqu=false;break;}//Если буквы не совпали выход из цикла

                                 // с отрицательным результатом PrEqu=false

i++;PrEqu=true;} //цикл сравнения

if (PrEqu) cout<<RUS("строки равны");

else cout<<RUS("строки не равны");

 

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

Функция strcmp () имеет синтаксис:

int strcmp(const char* strl, const char* str2)

После сравнения строк strl и str2 данная функция возвращает в результате одно из следующих значений:

• <0-еслистрока strl меньше, чем str2;

• =0 - если строки эквивалентны;

• >0 - если строка strl больше, чем str2. Эта функция производит сравнение, различая прописные и строчные буквы. Следующий пример иллюстрирует работу функции strcmp ():

char strl[]="Ошибка открытия базы";

char str2[]="Ошибка открытия Базы";

int i;

i = strcmp(strl, str2);

В результате переменной i будет присвоено положительное значение, так как строка из strl меньше, чем строка из str2, по той причине, что прописные буквы имеют код символов меньше, чем строчные (слово "базы " в первом случае начинается со строчной литеры, а во втором - с прописной).

Функция stricmp () имеет синтаксис:

int stricmp(const char* strl, const char* str2)

Данная функция сравнивает строки strl и str2, не различая регистра символов. Возвращается одно из следующих целочисленных значений:

• <0-еслистрока strl меньше, чем str2;

• =0 - если строки эквивалентны;

• >0 - если строка strl больше, чем str2.

Следующий фрагмент программы демонстрирует применение функции stricmp ():

char strl[]="Moon";

char str2[]="MOON";

int i;

i = stricmp(strl, str2);

В данном случае переменной i будет присвоено значение 0 (сигнализируя тем самым совпадение строк), так как strl и str2 отличаются только регистром.

Функция strncmp () проводит сравнение определенного числа первых символов двух строк. Регистр символов при этом учитывается. Функция имеет следующий прототип:

int strncmp(const char* strl, const char* str2, size_t num)

Данная функция сравнивает num первых символов двух строк, на которые указывают strl и str2, и возвращает одно из следующих значений:

• <0 - если строка strl меньше, чем str2;

• =0 - если строки эквивалентны;

• >0 - если строка strl больше, чем str2.

Рассмотрим пример использования функции strncmp ().

char strl[]="Ошибка открытия базы";

char str2[]="Ошибка Открытия базы";

int i;

i = strncmp(strl, str2, 12);

В результате сравнения первых 12-ти символов обеих строк переменная i получит положительное значение, так как подстроки "Ошибка откры" и "Ошибка Откры" отличаются одним символом и в первом случае код символа больше, чем во втором.

Функция strnicmp () производит сравнение определенного числа первых символов двух строк, не обращая внимания на регистр символов. Данная функция описана следующим образом:

int strnicmp(const char* strl, const char* str2, size_t num)

Функция возвращает целочисленное значение согласно правилу:

• <0 - если строка strl меньше, чем str2;

• =0 - если строки эквивалентны;

• >0 - если строка strl больше, чем str2. В следующем примере производится сравнение заданного числа символов подстрок:

char strl[]="Opening error";

char str2[]="Opening Error...";

int i;

i = strnicmp(strl, str2, 13);

В результате переменной i будет присвоено значение 0, так как первые 13 символов обеих подстрок отличаются только регистром.

 

 

1.6 Преобразование строк

 

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

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

char* _strlwr(char* str)

Следующий фрагмент показывает применение функции _strlwr():

char str[] = "ABRACADABRA";

_strlwr(str);

После вызова функции строка str будет преобразована в "abracadabra".

Функция _ strupr () объявлена следующим образом:

char* _strupr (char* str)

Данная функция преобразует строку символов, на которую указывает str, в прописные буквы (к верхнему регистру). В результате работы функции возвращается указатель на полученную строку.

Следующий пример переводит символы заданной строки в верхний регистр:

char str[]="pacific ocean";

_strupr(str);

cout << str;

В результате будет выведено: PACIFIC OCEAN

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

На практике довольно широко используются функции проверки принадлежности символов какому-либо диапазону, такие как isalnum(), isalpha(), isascii(), isdigit() и т.д. (см. табл. 8.2), объявленные в заголовочном файле ctype.h. Ниже рассматривается пример использования этого вида функций.

 

char str[4];

do

{

cout << RUS("Сколько тебе лет?\n");

cout << RUS("Введите 3 символа и нажмите Enter\n");

cin.getline(str,4);

if (isalpha(str[0]))

{

cout << RUS("Первый символ буква,");

cout << RUS("Введите заново\n");

continue;

}

if (iscntrl(str[0]))

{

cout << RUS("Первый символ управляющий,");

cout << RUS("Введите заново\n");

continue;

}

if (ispunct(str[0]))

{

cout << RUS("Первый символ знак пунктуации,");

cout << RUS("Введите заново\n");

continue;

}

for(int i=0; i<strlen(str);i++)

{

if (! isdigit (str [i])) continue;

else

{cout << RUS("Ваш возраст ") << str; goto end;}

}

}

while(true);

end:

 

Здесь пользователю предлагается ввести свой возраст. Функция cin.getline () помещает в строку str введенную последовательность (до трех) символов, после чего следует проверка первого введенного элемента массива на принадлежность к буквенной, управляющей последовательностей или символам пунктуации. Если результат соответствующей проверки положительный, пользователю предлагается ввести данные повторно. В противном случае все введенные элементы строки проверяются на принадлежность к цифровому набору данных. Если хотя бы один из символов не удовлетворяет проверяемому условию, цикл ввода повторяется сначала. После корректного ввода данных на экран выводится сообщение о возрасте пользователя.

 

Обращение строк

 

Функция обращения строки strrev() меняет порядок следования символов на обратный (реверс строки). Данная функция имеет прототип:

char* strrev(char* str)

Следующий пример демонстрирует работу функции strrev ().

char str [6];

strcpy(str, RUS("Привет"));

cout << strrev(str);

В результате на экране будет выведена строка "тевирП". Эта функция изменяет строку-оригинал.

 

Поиск символов

 

Одна из часто встречаемых задач при работе со строками - поиск отдельного символа или даже группы символов. Библиотека string.h предлагает следующий набор стандартных функций.

Функция нахождения символа в строке strс hr () имеет следующий прототип:

char* strchr(const char* string, int c)

Данная функция производит поиск символа с в строке string и в случае успешного поиска возвращает указатель на место первого вхождения символа в строку. Если указанный символ не найден, функция возвращает NULL. Поиск символа осуществляется с начала строки.

Ниже рассматривается фрагмент, осуществляющий поиск заданного символа в строке.

 

char str[6];

strcpy(str, "Привет");

char* pStr;

pStr = strchr(str,'и');

cout << RUS(pStr);

 

В результате работы программы указатель pStr будет указывать на подстроку "ивет", т.е. хранить адрес символа 'и'.

Функция strrchr () осуществляет поиск заданного символа с конца строки. Она имеет следующий синтаксис:

char* strrchr(const char* string, int c)

Данная функция возвращает указатель на последний, совпавший с заданным с, символ в строке string. Если символ не найден, возвращается значение NULL.

Функция strspn () проводит сравнение символов одной строки с символами другой и возвращает позицию (начиная с нуля), в которой строки перестают совпадать. Данная функция имеет следующий прототип:

size_t strspn(const char* string, const char* group)

Функция проверяет каждый символ строки string на соответствие каждому из символов строки group. В результате работы функции возвращается число совпавших символов.

Следующий пример демонстрирует использование данной функции:

char str[] = "Загрузка параметров БД";

char substr[] = "Загрузка параметррррр";

int index=0;

index = strspn(str, substr);

cout << index;

На экран будет выведено число 17, так как символы строки str и подстроки substr совпадают вплоть до 17-й позиции. Приведенная функция различает регистр символов.

Функция strcspn () имеет синтаксис:

size_t strcpn(const char* strl, const char* str2)

Эта функция сопоставляет символы строки strl и str2 и возвращает длину строки strl, не входящей в str2. Таким образом, можно определить, в какой позиции происходит пересечение двух символьных массивов:

char str[] = "abcdefghijk";

int index;

index = strcspn(str, "elf");

Переменная index получит значение 4, так как в этой позиции строки имеют первый общий элемент.

Функция strpbrk () объявлена следующим образом:

char* strpbrk(const char* strl, const char* str2)

Эта функция отыскивает место вхождения в строку strl любого из символов строки str2. Если символы найдены, возвращается место первого вхождения любого символа из str2 в строку strl. В противном случае функция возвращает NULL.

Ниже иллюстрируется использование функции strpbrk ():

char strl[]="abcdefghijk";

char str2[] = "ecb";

char* ptr;

ptr=strpbrk(strl, str2);

cout << ptr << ' \n';

В результате будет выведена подстрока "bcdefghijk", так как символ 'b' из строки str2 встречается в строке strl раньше других.

 

Поиск подстрок

 

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

Функция strstr () описана следующим образом:

char* strstr(const char* str, const char* substr)

Данная функция осуществляет сканирование строки str и находит место первого вхождения подстроки substr в строку str. В случае успешного поиска функция strstr возвращает указатель на первый символ строки str, начиная с которого следует точное совпадение части str обязательно со всей лексемой substr. Если подстрока substr не найдена в str, возвращается NULL.

Следующий пример показывает использование функции strstr ().

 

char strl[]="Производится поиск элемента";

char str2[] = "поиск";

char* ptr;

ptr=strstr(strl, str2);

cout << RUS(ptr);

 

На экран будет выведено "поиск элемента", так как подстрока, содержащаяся в str2, находится внутри строки strl и функция strstr () установит указатель ptr на соответствующий элемент символьного массива strl.

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

Функция strtok () имеет синтаксис:

char* strtok(char* str, const char* delim)

Эта функция выполняет поиск в строке str подстроки, обрамленной с обеих сторон любым символом-разделителем из строки delim. В случае успешного поиска данная функция обрезает строку str, помещая символ ' \0' в месте, где заканчивается найденная лексема. Таким образом, при повторном поиске лексемы в указанной строке str первым параметром следует указывать NULL. Так как strtok () модифицирует строку-оригинал, рекомендуется предварительно сохранять копию последней. Приведенный ниже пример иллюстрирует вышесказанное.

Предположим, необходимо разбить, имеющееся в строковом массиве предложение, по словам и вывести каждое из них на экран.

 

char str []="Язык программирования C++";

char *Delimiters = ".!?,;:\"'/0123456789@#$%^&*()<>{}[]~+-=";

char *ptr;

ptr = strtok(str, Delimiters);

if (ptr) {cout << RUS(ptr);cout<<"\n";}

while(ptr)

{

ptr = strtok(NULL, Delimiters);

if (ptr) {cout << RUS(ptr);cout<<"\n";}

}

 

В данной программе объявляется подлежащая анализу строка str, подстрока, содержащая набор разделителей Delimiters и указатель на символьный тип данных ptr. Вызов функции strtok (str, Delimiters) сканирует строку str и как только в ней встретится любой символ, входящий в подстроку Delimiters (в данном случае это символ пробела), указатель ptr станет ссылаться на начало исходной строки до найденного символа. То есть ptr будет содержать:

*ptr = "Язык"

Благодаря тому, что функция strtok () помещает в найденном месте нуль-терминатор '\0', исходная строка модифицируется. Таким образом, массив символов str примет значение:

"программирования C++"

Осуществив проверку указателя ptr на существование в операторе if (ptr), найденное слово выводится на экран. Далее в цикле с помощью функции strtok () находится последний нуль-терминатор строки str:

ptr = strtok (NULL, Delimiters);

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

 

1.10 Функции преобразования типа

 

Функции преобразования данных довольно часто используются, как следует из названия, для преобразования одного типа данных в другой тип. В приведенной ниже табл. 8.3 перечислены основные функции, их прототипы подключаются в заголовочном файле stdlib. h.

Таблица 8.3. Преобразование данных

Наименование Краткое описание
atof преобразует строку символов в число с плавающей точкой
atoi преобразует строку символов в строку типа int
atol преобразует строку символов в число типа long
ecvt преобразует число с плавающей точкой типа double в строку символов; десятичная точка и знак числа не включаются в полученную строку; позиция точки и знак числа возвращаются отдельно
fcvt идентично ecvt, но округляет полученное значение до заданного числа цифр
gcvt преобразует число с плавающей точкой типа double в строку символов, включая символ десятичной точки и используя специфицированное число цифр
itoa преобразует число типа int в строку символов
ltoa преобразует число типа long в строку символов
strtod преобразует строку символов в число с плавающей точкой типа double
strtol преобразует строку символов в число типа long
strtoul преобразует строку символов в число типа unsigned long
ultoa преобразует число типа unsigned long в строку символов

 

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

Функция atoi (), синтаксис которой

int atoi(const char* ptr)

преобразует ASCIIZ-строку символов, на которую указывает ptr, в число типа int. Если в строке встречается символ, который не может быть преобразован, данная функция возвращает 0. В случае если преобразуемое число превышает диапазон представления типа int, возвращается только два младших байта числа.

В отличие от нее, функция atol () преобразует заданное строковое число в тип long. Эта функция имеет аналогичный синтаксис:

int atol(const char* ptr)

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

Рассмотрим пример преобразования строки цифровых символов в целое и длинное целое.

 

char str[]="70000000";

long i = atol(str);

cout << i << '\n';

 

Функция atof (), определенная как

double atof(const char* ptr)

выполняет преобразование ASCIIZ-строки в число с плавающей точкой типа double. Строка символов должна быть представлена с учетом формата:

[пробелы] [знак] [цифры] [.] [цифры] [е|E[знак]цифры],

где

[пробелы] - последовательность пробелов или табуляторов; [знак] - символ ' + ' или '-'; [цифры] - десятичные цифры; [е | Е] - символ показателя степени.

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

Функции обратного преобразования itoa() и ltoa() производят конвертирование чисел типа int и long соответственно. Они имеют следующий синтаксис:

char *_ltoa(long num, char* str, int radix);

и

char* itoa(int num, char* str, int radix);

или

char* _itoa(int num, char *str, int radix);

Данные функции принимают в качестве аргумента число num и преобразуют его в строку str с учетом основания системы счисления, представленной в переменной radix. Следующий фрагмент программы преобразует целое число 98765 в строку, используя десятеричную систему счисления:

int numb = 98765;

char str[10];

itoa(numb, str, 10);

cout << numb << '\n' << str;

Функция strtod() преобразует строку символов в число с плавающей точкой. Ее синтаксис имеет следующий вид:

double strtod(const char *s, char **endptr);

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

Функция gcvt () имеет прототип:

char* gcvt(double val, int ndec, char *buf);

и осуществляет конвертирование числа val типа double в ASCIIZ-строку, помещая ее в буфер buf. Если число цифр, подлежащих преобразованию, больше целого числа, указанного в ndec, в преобразованном числе указываются символы знака и десятичной точки, при этом младшие разряды дробной части отбрасываются. В противном случае число преобразуется в экспоненциальную форму. Функция возвращает указатель на начало сформированной строки.

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

 

char str[10];

double num;

// Значащих цифр:

int sig = 4;

// Обычное представление числа

num = 3.547;

gcvt(num, sig, str);

cout << str << '\n';

// Отрицательное число

num = -843.7105;

gcvt(num, sig, str);

cout << str << '\n';

// Экспоненциальное представление

num = 0.135e4;

gcvt(num, sig, str);

cout << str << '\n';

 

В результате будет выведено:

3.547

-843.7

1350

 

Другие функции

 

Большинство функций работы со строками содержится в библиотеке string.h. Основные функции работы с символьными массивами сведены в таблицу I I I.1 (Приложение I I I).

 

Примеры программ

 

Выделение слов

 

Выделение слов организуется на основе поиска разделителей слов – пробелов, точек, запятых и т.п. Если разделители расположены до начала слова, они пропускаются. Указатель *ptr[i] (i – номер слова) устанавливается на первый неразделитель – начало слова (Таблица 3.1). Затем происходит поиск разделителя в конце слова. Он заменяется на ноль ‘\0’. Все изложенные процедуры по выделению следующего слова повторяются до тех пор, пока небудет достигнут конец обрабатываемой строки. Запись нулей в исходную строку модифицирует ее и, если строка нужна в оригинале, ее следует предварительно сохранить.

Таблица 3.1

Адрес   Ptr[0]         Ptr[1]     Ptr[2]    
Строка   q w e     t y   t t \0
Дополнение         \0       \0      

 

//Пример программы выделения слов

char St[21]="";// 20 символов и \0

int k,i=0;

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

gets(St);

k=strlen(St);

cout<<RUS("\nДлина строки = ")<<k;

char *Delimiters = ".!?,;:\"'/0123456789@#$%^&*()<>{}[]~+-=";

char *ptr[20];

int x=0;bool prDelim=true;

ptr[i]=St;

do

{do

   {

    while ((*ptr[i]!=Delimiters[x])&&(Delimiters[x]!='\0')) x++;

    if (Delimiters[x]!='\0') ptr[i]++;

   }

 while (Delimiters[x]!='\0');

i++;ptr[i]=ptr[i-1];//найдено начало слова

for(;;)

{ ptr[i]++;if (*ptr[i]=='\0') {prDelim=false;break;}//найден конец строки

x=0;

while ((*ptr[i]!=Delimiters[x])&&(Delimiters[x]!='\0')) x++;

if (Delimiters[x]!='\0')

{*ptr[i]='\0';ptr[i]++;prDelim=true;break;}//найден конец слова

}

}

while (prDelim);

for(int j=0;j<i;j++)cout<<'\n'<<ptr[j];//вывод массива слов

 

В библиотеке string.h есть функция выделения слова strtok(St, Delimiters). Она выделяет одно слово строки St по перечню разделителей Delimiters. Если нужно выделить последующие слова, функцию используют с параметром NULL вместо St. Тогда она продолжает выделять слова в строке St. По завершению всех слов функция возвращает ноль и это следует использовать для выхода из цикла выделения.

 

char St[21]="";// 20 символов и \0

int k,i=0;

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

gets(St);

strrev(St);

puts(St);

k=strlen(St);

cout<<RUS("\nДлина строки = ")<<k;

char *Delimiters = ".!?,;:\"'/0123456789@#$%^&*()<>{}[]~+-=";

char *ptr[20];

ptr[i] = strtok(St, Delimiters);//выделение первого слова

while(ptr[i])

{i++;

ptr[i] = strtok(NULL,Delimiters);// выделение следующего слова

}

for(int j=0;j<i;j++)cout<<'\n'<<ptr[j];//вывод массива

 

При выводе:

если обращение как ptr[j] – вывод слова полностью

если обращение как *ptr[j] – вывод 1-го символа слова

если обращение как *(ptr[j]+1) – вывод 2-го символа слова

если обращение как *(ptr[j] +n) – при n> длины слова выводятся буквы следующего слова

 



Поделиться:


Последнее изменение этой страницы: 2021-11-27; просмотров: 142; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.144.109.147 (0.008 с.)