Операции над строковыми данными

Для обработки строк, представленных одномерными символьными массивами, в библиотеке системных функций предусмотрено довольно много различных операций. Прототипы этих функций сгруппированы в заголовочном файле string.h и большинство их названий начинается с префикса str (от string). Условимся о некоторых обозначениях аргументов и их типах, чтобы не повторять их в приведенной таблице:

S, S1,S2 – указатель на символьный массив (как правило, имя массива);

CS – указатель типа const char * (т.е. неизменяемый массив или строковая константа – источник данных);

ch – код символа, обычно числовое значение типа int;

k – количество символов.

Таблица 5.2

Функция Выполняемое действие
Определение длины строки
strlen(CS) Возвращает количество символов в строке S
Формирование строк
strdup(CS) Запрашивает память, копирует туда содержимое CS и возвращает указатель типа chr* на новую строку
strcpy(S1,CS2) Копирует содержимое CS2 в S1, возвращает указатель на S1
strncpy(S1,CS2,k) Копирует первые k символов из CS2 в S1, возвращает указатель на S1
stpcpy(S1,CS2) Копирует CS2 в S1, возвращает указатель на конец S1
strset(S,ch) Расписывает строку S символом ch, возвращает указатель на S1
strnset(S,ch,k) Повторяет k раз символ ch в строке S, возвращает указатель на S1
Конкатенация строк
strcat(S1,CS2) Приписывает содержимое CS2 в конец S1, возвращает указатель на S1 (длина массива S1 должна предусматривать такое расширение)
strncat(S1,CS2,k) Присоединяет первые k символов CS2 к содержимому S1, возвращает указатель на S1
Смена регистра
strlwr(S) замена символов строки S кодами малых букв, действует только на буквы латинского алфавита
strupr(S) замена символов строки S кодами больших букв, действует только на буквы латинского алфавита
Переворот строки
strrev(S) Перестановка символов строки S в обратном порядке
Преобразование в числовые данные
strtol(CS,ptr,r) Число, представленное в символьном виде в CS и записанное в системе счисления с основанием r, преобразуется в машинный формат числа типа long. В указатель ptr заносится адрес символа, прервавшего преобразования. Возвращаемое значение – результат преобразования.
strtoul(CS,ptr,r) Аналогичное преобразование в длинное целое число без знака
strtod(CS,ptr) Преобразование вещественного числа из символьного представления в машинный формат числа типа double.
Сравнение строк
strcmp(CS1,CS2) Возвращаемое значение равно 0, если CS1=CS2, больше 0, если CS1>CS2, и меньше 0, если CS1<CS2
strncmp(CS1,CS2,k) Сравниваются только первые k символов строк CS2 и CS2
stricmp(CS1,CS2) При сравнении игнорируется разница между кодами больших и малых букв
strcmpi(CS1,CS2) Аналогичная операция, разница только в названии функций
strnicmp(CS1,CS2,k) Сравнение первых k символов с игнорированием разницы между кодами больших и малых букв
strncmpi(CS1,CS2,k) Аналогичная операция, разница только в названии функций
Поиск символа
strchr(CS,ch) Строка CS сканируется слева направо до обнаружения символа ch. Если он найден, возвращаемый указатель "смотрит" на этот символ в строке CS, если такого символа нет, то возвращаемый указатель равен null (т.е. 0)
strrchr(CS,ch) Аналогичный поиск с конца строки CS.
Поиск строки
strstr(CS1,CS2) Поиск первого вхождения строки CS2 в строку CS1. Если поиск завершен успешно, возвращается указатель на первый символ найденной подстроки. В противном случае возвращается null
Специальный поиск
strpbrk(CS1,CS2) В строке CS1 ищется первый символ, содержащийся в CS2. Возвращается указатель на найденный символ или null.
strspn(CS1,CS2) Определяется длина начального фрагмента CS1, целиком состоящая из символов CS2 (порядок символов роли не играет)
strcspn(CS1,CS2) Определяется длина начального фрагмента CS1, который не содержит ни одного символа из CS2
strtok(S1,CS2) Поиск в строке S1 лексем, разделенных символами CS2

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

В функциях strtol и strtoul, выполняющих преобразование символьного представления числа в соответствующий машинный формат, допускается задание r=0. В этом случае основание системы определяется символьной записью числа. Если строка начинается с символа '0', за которым следуют символы цифр, не превосходящих 7, то число считается восьмеричным. Если строка начинается с комбинации '0x' или '0X', вслед за которой располагаются шестнадцатеричные цифры, то считается, что r=16.

В функции strtok лексемой считается цепочка символов, завершающаяся одним из предусмотренных символов-разделителей. При первом обращении к этой функции в строке S1 находится начальная лексема и возвращаемое значение является указателем на ее начальный символ. Одновременно в строку S1 на место обнаруженного символа-разделителя заносится нулевой байт. Это позволит в дальнейшем работать с найденной лексемой как со строкой. Для поиска следующих лексем в повторных обращениях к функции strtok вместо первого аргумента нужно задавать нулевой аргумент. Функция будет искать следующую лексему, расположенную правее принудительно вставленного нулевого байта. И так можно последовательно обнаружить все лексемы, содержавшиеся в строке S1. Для пояснения приведем следующий пример:

#include <stdio.h>

#include <conio.h>

#include <string.h>

void main()

{ char *ptr;

ptr=strtok("FEB.14,2006",".,-/");

while(ptr!=NULL)

{ printf("ptr=%s\n",ptr);

ptr=strtok(NULL, ".,-/");

}

getch();

}

//=== Результат работы ===

ptr=FEB

ptr=14

ptr=2006

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

Операции над строковыми данными - student2.ru

Отображаемые символы в таблице ASCII начинаются с кода 32 (0x20), которому соответствует символ "пробел". Коды больших русских букв начинаются с кода 128 (0x80), однако буква 'Ё' расположена не на своем месте.

Наблюдается разрыв в числовой последовательности кодов малых букв – после буквы 'п' расположена группа кодов псевдографики. С их помощью в текстовом режиме работы дисплея строятся одинарные и двойные контуры таблиц. Малая буква 'ё' также расположена не в алфавитном порядке. Все эти нюансы приходится учитывать при построении программы перекодировки русских текстов из кодовой страницы 1251 (т.е. из кодировки Windows) в кодировку MS-DOS

Сложность заключается в том, что под управлением MS-DOS в нашей стране используется кодовая страница с номером 866, а в операционных системах Windows 98/NT/2000/XP отечественная кодовая страница имеет номер 1251. У обеих кодовых страниц первые половины идентичны стандарту IBM. Здесь находятся коды управляющих символов (группа кодов от 0x00 до 0x1F), различные разделители (точки, запятые, скобки и т.п.) и знаки операций, большие и малые буквы латинского алфавита. А вот вторые половины этих кодовых страниц устроены по-разному и из-за этого тексты на русском языке, подготовленные в среде Windows, отображаются консольными приложениями BCB в виде некоторой абракадабры.

2.Функции, возвращающие и не возвращающие значение. Оператор return. Прототипы функций и их назначение

Описание любой функции начинается с ее заголовка, имеющего вид:

trv namef(type1 par1,type2 par2,...)

Здесь trv – тип возвращаемого значения;

namef – имя функции;

par1 – имя первого аргумента функции, имеющего тип type1;

par2 – имя второго аргумента функции, имеющего тип type2;

………………………………………………………….

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

Возврат значения функции

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

int Fib(int n)

{ if(n<3) return 1;

return Fib(n-2)+Fib(n-1);

}

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

namef(a1,a2,...);

Здесь namef – имя вызываемой функции;

a1, a2, … – список фактических параметров

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

y=a*fin1(x,-2)+b;

В этом случае сначала будет вычислено значение операнда fin1(x,-2), которое затем будет использовано при подсчете значения выражения.

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

k=scanf("%d %s",&x,str);

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

Пример 4. Заголовки функций вынесены в список прототипов.

double mid(double x, double y);

void swap1(double *x,double *y);

void swap2(double &x,double &y);

void main()

{ double a=1.5, b=-2.5,c;

c=mid(a,b);

swap1(&a,&b);

swap2(b,c);

.............

}

double mid(double x, double y)

{ return (x+y)/2.0; }

void swap1(double *x,double *y)

{ double tmp;

tmp=*x;*x=*y;*y=tmp;

}

void swap2(double&x,double&y)

{ double tmp;

tmp=x;x=y;y=tmp;

}

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

double mid(double, double);

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

int intersect(double&,double&,double&,double&,double&,double&);

В каком из параметров, – в первой паре или в последней, – надо указывать ссылки на координаты точки пересечения. Очевидно, что более информативным был бы прототип следующего вида:

int intersect( double &x1, double &y1, double &x2, double &y2,

double &x, double &y);

Билет 8

Наши рекомендации