Функции для работы со строками Для работы со строками используются библиотечные функции, прототипы которых находятся в заголовочных файлах stdlib.h и string.h. В программах, в зависимости от типа, вызовы функций для работы со строками задаются в виде: ИмяФ(СписокАргументов); или ИмяПерем=ИмяФ(СписокАргументов); где ИмяФ – имя функции; СписокАргументов – список аргументов, передаваемых в тело функции; ИмяПерем – идентификатор соответствующего типа. Например: y=strlen(st); /*переменной y присвоить значение длины строки st*/ При использовании библиотечных функций следует учитывать некоторые особенности их выполнения и представления символьных данных в памяти. - Функции, работающие с регистрами, распространяются только на латиницу.
- В С некоторые параметры функций обработки символов принадлежат типу int (unsigned), поэтому, если число станет больше 128 (255), функция будет работать некорректно.
- Перед первым обращением к строке она должна быть объявлена и проинициализирована. Во многих случаях в качестве начального значения строки необходимо бывает задать пустую строку. Такую инициализацию можно выполнить с помощью вызова функции strcpy(s, "");, но более эффективным будет присваивание *s=0;. Кроме того пустую строку можно инициализировать char s[10]=""; или char s[10]="\0";, но при этом размер строки должен быть задан.
- Функции копирования (кроме strncpy ) не проверяют длину строки. Размер строки-приемника должен быть больше, чем размер источника на 1 символ (для символа '\0' ).
При вызове функции strncpy следует помнить, что, если длина копируемой строки превосходит параметр kol, то строка-получатель не будет завершена символом '\0'. В этом случае такой символ надо дописывать в конец строки вручную. Функции для работы со строками – файл stdlib.h | Функция | Прототип | Краткое описание действий | atof | double atof (const char *str); | преобразует строку str в вещественное число типа double | atoi | int atoi (const char *str); | преобразует строку str в целое число типа int | atol | long atol (const char *str); | преобразует строку str в целое число типа long | itoa | char *itoa (int v, char *str, int baz); | преобразует целое v в строку str. При изображении числа используется основание baz (2<=baz<=36). Для отрицательного числа и baz =10 первый символ "минус" (–). | ltoa | char *ltoa (long v, char *str, int baz); | преобразует длинное целое v в строку str. При изображении числа используется основание baz (2<=baz<=36). | ultoa | char *ultoa (unsigned long v, char *str, int baz); | преобразует беззнаковое длинное целое v в строку str | Функции для работы со строками – файл string.h | Функция | Прототип | Краткое описание действий | strcat | char *strcat (char *sp, const char *si); | приписывает строку si к строке sp (конкатенация строк) | strchr | char *strchr (const char *str, int c); | ищет в строке str первое вхождение символа с | strcmp | int strcmp (const char *str1, const char *str2); | сравнивает строки str1 и str2. Результат отрицателен, если str1<str2 ; равен нулю, если str1==str2, и положителен, если str1>str2 (сравнение беззнаковое) | strcpy | char *strcpy (char *sp, const char *si); | копирует байты строки si в строку sp | strcspn | int strcspn (const char *str1, const char *str2); | определяет длину первого сегмента строки str1, содержащего символы, не входящие во множество символов строки str2 | strdup | char *strdup (const char *str); | выделяет память и переносит в нее копию строки str | strlen | unsigned strlen (const char *str); | вычисляет длину строки str | strlwr | char *strlwr (char *str); | преобразует буквы верхнего регистра в строке в соответствующие буквы нижнего регистра | strncat | char *strncat (char *sp, const char *si, int kol); | приписывает kol символов строки si к строке sp (конкатенация) | strncmp | int strncmp (const char *str1, const char *str2, int kol); | сравнивает части строк str1 и str2, причем рассматриваются первые kol символов. Результат отрицателен, если str1<str2 ; равен нулю, если str1==str2, и положителен, если str1>str2 | strncpy | char *strncpy (char *sp, const char *si, int kol); | копирует kol символов строки si в строку sp ("хвост" отбрасывается или дополняется пробелами) | strnicmp | int strnicmp (char *str1, const char *str2, int kol); | сравнивает не более kol символов строки str1 и строки str2, не делая различия регистров (см. функцию strncmp ) | strnset | char *strnset (char *str, int c, int kol); | заменяет первые kol символов строки str символом c | strpbrk | char *strpbrk (const char *str1, const char *str2); | ищет в строке str1 первое появление любого из множества символов, входящих в строку str2 | strrchr | char *strrchr (const char *str, int c); | ищет в строке str последнее вхождение символа с | strset | char *strset (char *str, int c); | заполняет строку str заданным символом c | strspn | int strspn (const char *str1, const char *str2); | определяет длину первого сегмента строки str1, содержащего только символы, из множества символов строки str2 | strstr | char *strstr (const char *str1, const char *str2); | ищет в строке str1 подстроку str2. Возвращает указатель на тот элемент в строке str1, с которого начинается подстрока str2 | strtod | double strtod (const char *str, char **endptr); | преобразует символьную константу str в число двойной точности. Если endptr не равен NULL, то *endptr возвращается как указатель на символ, при достижении которого прекращено чтение строки str | strtok | char *strtok (char *str1, const char *str2); | ищет в строке str1 лексемы, выделенные символами из второй строки | strtol | long strtol (const char *str, char **endptr, int baz); | преобразует символьную константу str к значению "длинное число" с основанием baz (2<=baz<=36). Если endptr не равен NULL, то *endptr возвращается как указатель на символ, при достижении которого прекращено чтение строки str | strupr | char *strupr (char *str); | преобразует буквы нижнего регистра в строке str в буквы верхнего регистра | Сравнение строк с помощью функции strcmp осуществляется побайтово в лексикографическом порядке, то есть в порядке следования соответствующих байтов строк в таблице кодировки. Именно поэтому значения элементов в строках зависят от регистра. При использовании библиотечных функций следует иметь в виду, что указатель на строку и имя массива символов указывают на адрес размещения строки в памяти. Это означает, что изменения значений элементов строки сохраняются после завершения работы функции. Чтобы не допустить изменений в строке используется указатель на константу, который не позволит модифицировать данные, хранящиеся по адресуемой области памяти. Пример 7. //Программа демонстрирует работу функций из файла stdlib.h #include "stdafx.h" #include <stdio.h> #include <stdlib.h> int main() { char sv[]="23.547", si[]="1234", sl[]="-112424", st1[15],st2[25],st3[15]; double v; int i; long l,t=457821; v=atof(sv); printf("Преобразование строки в вещественное число = %f\n",v); i=atoi(si); printf("Преобразование строки в целое число = %d\n",i); l=atol(sl); printf("Преобразование строки в длинное целое число = %ld\n",l); printf("Преобразование длинного целого числа в строку = %s\n", ultoa(t,st1,10)); printf("Преобразование длинного целого числа в строку = %s\n", ultoa(t,st2,2)); printf("Преобразование длинного целого числа в строку = %s\n", ultoa(t,st3,16)); system("pause"); return 0; } Пример 8. //Программа демонстрирует работу функций из файла string.h #include "stdafx.h" #include <stdio.h> #include <string.h> int main(void) { char st[50],sp[100],str[]="", si[]="qwerty", sl[]="qwerty", sw[]="qwertyu"; int len=0, sravn1, sravn2, sravn3, kol=5; printf("Введите строку: "); gets(st); len=strlen(st); printf("Длина строки = %d\n",len); printf("Конкатенация строк: %s\n",strcat(st,"12cdb")); sravn1=strcmp(si,sl); printf("Сравнение строк: %s==%s результат %d\n", si,sl,sravn1); sravn2=strcmp(si,sw); printf("Сравнение строк: %s<%s результат %d\n", si,sw,sravn2); sravn3=strcmp(sw,si); printf("Сравнение строк: %s>%s результат %d\n", sw,si,sravn3); printf("Копирование байтов: %s\n",strcpy(sp,st)); printf("Преобразование букв нижнего регистра в верхний: %s\n", strupr(st)); printf("Преобразование букв верхнего регистра в нижний: %s\n", strlwr(st)); printf("Копирование %d символов в другую строку: %s\n", kol,strncpy(str,st,kol)); printf("Поиск в строке первого появления символа из другой строки: %s\n",strpbrk(st,si)); printf("Поиск в строке последнее вхождение заданного символа: %s\n",strrchr(st,'t')); system("pause"); return 0; } Пример 9. //Поиск множества неповторяющихся символов строки #include "stdafx.h" #include <stdio.h> #include <string.h> int main(void) { char st[80]; int i,j,flag,len; printf("Введите строку: "); gets(st); len=strlen(st); //длина строки printf("Неповторяющиеся символы строки образуют множество: "); for (i=0;i<len;i++){ flag=0; //флаг проверки на совпадение for (j=0;j<i;j++) //сравнение символа с предыдущими if (st[i]==st[j]) flag=1; if (flag==0)printf("%c",st[i]); } system("pause"); return 0; } Пример 10. /*Удаление лишних левых и внутренних пробелов в строке при выводе*/ #include "stdafx.h" #include <stdio.h> #include <string.h> int main(void) { char st[80]; int i=0,len; printf("Введите строку: "); gets(st); len=strlen(st);//длина строки printf("Преобразованная строка: "); //Удалены лишние пробелы слева while (st[i++]==' '); //Удалены лишние пробелы внутри строки for (--i;i<len;i++) if ((st[i]!=' ')||(st[i+1]!=' ')) printf("%c",st[i]); //если рядом два пробела system("pause"); return 0; } Для выполнения описанных в этом подразделе функций необходимо включить в программу файл string.h командой #include <string.h> strcat - сцепить две строки. Определение: char *strcat(s1,s2) char *s1, *s2; Пример 11: /* сцепить две строки */ /* в головном файле conio.h содержится функция очистки экрана clrscr( ) */ #include <string.h> #include <stdio.h> #include <conio.h> int main(void) { clrscr(); char destination[25]; char *blank = " ", *c = "C++", *turbo = "Turbo"; strcpy(destination, turbo); strcat(destination, blank); strcat(destination, c); printf("%s\n", destination); getch(); return 0; } strncat - сцепить две строки, причем из второй строки копировать не более n символов. Определение: char *strncat(s1,s2,n) char *s1, *s2; int n; Пример 12: /* cцепить две строки, причем из второй строки копировать не более n символов */ #include <string.h> #include <stdio.h> #include <conio.h> int main(void) { clrscr(); char destination[25]; char *source = "structured "; strcpy(destination, "programming"); strncat(destination, source, 11); printf("%s\n", destination); getch(); return 0; } strcmp - сравнить две строки в лексикографическом порядке. Определение: int strcmp(s1,s2) char *s1, *s2; Пример 13: #include <string.h> #include <stdio.h> #include <conio.h> int main(void) { char *buf1 = "aaa", *buf2 = "bbb", *buf3 = "ccc"; int ptr; clrscr(); ptr = strcmp(buf2, buf1); if (ptr > 0) printf("buffer 2 is greater than buffer 1\n"); else printf("buffer 2 is less than buffer 1\n"); ptr = strcmp(buf2, buf3); if (ptr > 0) printf("buffer 2 is greater than buffer 3\n"); else printf("buffer 2 is less than buffer 3\n"); getch(); return 0; } strncmp - сравнить первые n символов двух строк. Определение: int strncmp(s1,s2, n) char *s1, *s2; int n; Пример 14: #include <string.h> #include <stdio.h> #include <conio.h> int main(void) { char *buf1 = "aaabbb", *buf2 = "bbbccc", *buf3 = "ccc"; int ptr; clrscr(); ptr = strncmp(buf2,buf1,3); if (ptr > 0) printf("buffer 2 is greater than buffer 1\n"); else printf("buffer 2 is less than buffer 1\n"); ptr = strncmp(buf2,buf3,3); if (ptr > 0) printf("buffer 2 is greater than buffer 3\n"); else printf("buffer 2 is less than buffer 3\n"); getch(); return(0); } strcpy - копировать строку s2 в строку s1. Определение: char *strcpy(s1,s2) char *s1, *s2; Пример 15: #include <stdio.h> #include <string.h> #include <conio.h> int main(void) { clrscr(); char string[10]; char *str1 = "abcdefghi"; strcpy(string, str1); printf("%s\n", string); getch(); return 0; } strncpy - копировать не более n символов строки s2. Определение: char *strncpy(s1,s2,n) char *s1, *s2; int n; Пример 6: #include <stdio.h> #include <string.h> #include <conio.h> int main(void) { clrscr(); char string[10]; char *str1 = "abcdefghi"; strncpy(string, str1, 3); string[3] = '\0'; printf("%s\n", string); getch(); return 0; } strlen - определить длину строки (число символов без завершающего нулевого символа). Определение: int strlen(s) char *s; Пример 17: #include <stdio.h> #include <string.h> #include <conio.h> int main(void) { clrscr(); char *string = "Borland International"; printf("%d\n", strlen(string)); getch(); return 0; } strchr - найти в строке первое вхождение символа n. Определение: char *strchr(s,n) char *s; int n; Пример 18: #include <string.h> #include <stdio.h> #include <conio.h> int main(void) { clrscr(); char string[20]; char *ptr, c = 'r'; strcpy(string, "This is a string"); ptr = strchr(string, c); if (ptr) printf("The character %c is at position: %d\n", c, ptr); else printf("The character was not found\n"); getch(); return 0; } strrchr - найти в строке последнее вхождение символа с. Определение: char *strrchr(s,c) char *s; int c; Пример 19: #include <string.h> #include <stdio.h> #include <conio.h> int main(void) { clrscr(); char string[20]; char *ptr, c = 'r'; strcpy(string, "This is a string"); ptr = strrchr(string, c); if (ptr) printf("The character %c is at position: %d\n", c, *ptr); else printf("The character was not found\n"); getch(); return 0; } strpbrk - найти в строке s1 любой из множества символов, входящих в строку s2. Определение: char *strpbrk(s1,s2) char *s1, *s2; Пример 20: #include <stdio.h> #include <string.h> #include <conio.h> int main(void) { clrscr(); char *string1 = "abcdefghijklmnopqrstuvwxyz"; char *string2 = "onm"; int *ptr; ptr = strpbrk(string1, string2); if (ptr) printf("strpbrk found first character: %c\n", *ptr); else printf("strpbrk didn't find character in set\n"); getch(); return 0; } strspn - определить длину отрезка строки s1, содержащего символы из множества, входящих в строку s2. Определение: int strspn(s1,s2) char *s1, *s2; Пример 21: #include <stdio.h> #include <string.h> #include <alloc.h> #include <conio.h> int main(void) { clrscr(); char *string1 = "1234567890"; char *string2 = "123DC8"; int length; length = strspn(string1, string2); printf("Character where strings differ is at position %d\n", length); getch(); return 0; } strcspn - определить длину отрезка строки s1, не содержащего символы cтроки s2. Определение: int strcspn(s1,s2) char *s1, *s2; Пример 22: #include <stdio.h> #include <string.h> #include <alloc.h> #include <conio.h> int main(void) { clrscr(); char *string1 = "1234567890"; char *string2 = "747DC8"; int length; length = strcspn(string1, string2); printf("Character where strings intersect is at position %d\n", length); getch(); return 0; } strtok - выделить из строки s1 лексемы, разделенные любым из множества символов, входящих в строку s2. Определение: char *strtok(s1,s2) char *s1, *s2; Пример 23: #include <string.h> #include <stdio.h> #include <conio.h> int main(void) { clrscr(); char input[16] = "abc,d"; char *p; p = strtok(input, ","); if (p) printf("%s\n", p); p = strtok(NULL, ","); if (p) printf("%s\n", p); getch(); return 0; } Строки и указатели Строки в языке С представляют собой массив символов. Поскольку имя массива без индексов является указателем на первый элемент этого массива, то при использовании функций обработки строк им будут передаваться не сами строки, а указатели на них. Так как все строки в языке С++ заканчиваются нулевым символом, который имеет значение <ложь>, то условие в операторе while(*str) будет истинным до тех пор, пока программа не достигнет конца строки. При работе со строками в большинстве случаев целесообразно применять указатели. Приведем примеры фрагментов программ: /*Пример копирования строки s2 в s1*/ char *s1, char *s2; char *ptrs1 = s1; //указатель инициализирован на начало строки while ((*s1++ = *s2++) != 0); Следующий пример демонстрирует, что использование нулевого ограничителя упрощает различные операции над строками. /*Пример пользовательской функции конкатенации*/ char *s1, char *s2; char *p1, *p2; p1 = s1; p2 = s2; while ( *p1 != '\0') p1++; //найти конец 1-ой строки. //или while ( *p1) p1++; while ((*p1 = *p2) != 0) { /*копировать строку р2, пока не будет скопирован нулевой Ограничитель*/ p1++; p2++; //Передвинуть указатели к следующему байту } //или while (( *p1++ = *p2++) != 0);/*. Пример 24. /*Демонстрация работы с указателями и с функциями для обработки строк*/ #include "stdafx.h" #include <stdio.h> #include <string.h> int main(void) { char string[100], temp[100], *result, simvol; int numresult, res; /*создает строку "computer program" посредством использования strcpy и strcat*/ strcpy(string, "computer"); result = strcat(string," program"); printf("1) создали строку\n%s\n",result); /*находит строку, в которой первый раз обнаружено 'a'*/ simvol='a'; result = strchr(string,simvol); printf("2) находим в строке первое вхождение символа \'%c\'\n %s\n",simvol,result); /* создает копию строки */ result = strcpy(temp,string); printf("3) создали копию строку\n%s\n",result); /* находит "a","b","c" в строке */ strcpy(string,"xyzabbc"); res = strcspn(string,"abc"); printf("4) определяем длину заданного сегмента \n%d\n",res); /*создает новый указатель на строку для дублирования строки*/ result = strdup(string); printf("5) создали новый указатель на строку \n%s\n",result); system("pause"); return 0; } В предыдущих примерах рассматривалось присваивание указателю адреса только первого элемента символьного массива. Однако это можно делать и с адресом любого отдельного элемента массива путем добавления символа '&' к индексированному имени. Особенно удобно пользоваться этим правилом при выделении подстроки. Например, следующая программа выводит на экран часть введенной строки после первого пробела: Пример 25. /*Вывести на экран часть строки после первого пробела*/ #include "stdafx.h" #include <stdio.h> int main(void) { char s[80], *p; int i; printf("ввести строку: "); gets(s); /*найти первый пробел или конец строки*/ for(i=0; s[i] && s[i]!=' '; i++); p = &s[i]; printf(p); system("pause"); return 0; } В этой программе p будет указывать либо на пробел, если он есть, либо на ноль, если в строке нет пробелов. Если p указывает на пробел, то программа выведет на экран его и затем остаток строки. Например, если ввести фразу <язык программирования С++>, функция printf() напечатает сначала пробел и затем <программирования С++>. Если p укажет на ноль, то на экран ничего не выводится. Пример 26: //Выводит каждое отдельное слово и подсчитывает его длину #include "stdafx.h" #include <stdio.h> #include <string.h> int main(void) { char text[100],*p, *razd=" .,"; int dlina; puts ("Введите текст "); gets(text); p=strtok(text,razd); // Выделение первого слова текста while (p) { // Пока можно выделить слово dlina=strlen(p); // Определение длины слова cout << "\n слово "<< p << " длина = " << dlina <<"\n"; p=strtok(NULL,razd); //Выделение второго, третьего, и т.д. слов } system("pause"); return 0; } При использовании строк или указателей на строки в качестве параметров функций следует учитывать некоторые особенности. При передаче строки как параметра функции не указывается длина, так как ограничителем является символ конца строки. Строки передаются в функции в качестве параметров как массивы символов или как указатели типа char. При побайтовом копировании строки или ее подстроки без использования стандартных функций формируемую строку следует завершить, дописав символ конца строки. В противном случае строка не воспринимается как единое целое, а при выходе за ее границы доступными становятся байты, содержащие "мусор", то есть непредсказуемую информацию. Обращение к строкам через указатели позволяет вносить и сохранять изменения, записанные в адресуемой области памяти. Для недопущения изменений в строке указатель на константу можно объявить с лексемой const следующим образом: const char *p;. В силу специфики представления строк в виде символьного массива сами строки, строковые константы, заключенные в кавычки, и указатели на строки обрабатываются эквивалентно. При этом каждый такой элемент адресует область памяти и передается в функции как адрес. При копировании строки или подстроки с использованием указателя не создается физической копии значений элементов. Объявленный новый указатель адресует то место в памяти, с которого начинается копируемая строка или подстрока. Например: char text[50]="Язык программирования"; char *p=text, *pp; //объявление и инициализация указателя р адресом строки text pp=p; //указатель рр адресует ту же строку text Адресация на тот же участок памяти объясняется, во-первых, неэффективностью повторного хранения уже имеющихся данных, во-вторых, относительной программной трудоемкостью копирования байтов, в-третьих, для хранения адреса строки требуется гораздо меньше места, чем для самой строки. В данном контексте понятие эффективности носит относительный характер, так как иногда в программе полезным бывает хранение резервной копии введенных данных. Пример 27 // Ввести строку, используя указатели и удалить из нее все вхождения символа а. # include <stdio.h> # include <conio.h> # include <stdlib.h> # include <locale.h> # include <string.h> int main(void) { //устанавливаем русско язычный вариант вывода информации на экран setlocale(LC_ALL,"Russian"); //описываем указатель на символьный тип данных //и сразу же выделяем область памяти размером 50 байт (предполагаемая //длина строки char *ptr=(char*)malloc(50*sizeof(char)); //Проверка выделения динамической области памяти if (!ptr) {printf("Память не выделена"); return 1;} char *ptr1; printf("Введите строку: "); gets(ptr); //переопределяем динамическую область памяти под истинный размер //введенной строки, т.к. функция strlen() определяет количество //видимых симолов, а необходимо учесть и символ конца строки ‘\0’, // strlen(ptr)+1 ptr=(char*)realloc(ptr,(strlen(ptr)+1)*sizeof(char)); if (!ptr) {printf("Память не выделена"); return 1;} while(ptr1=strchr(ptr,'a')) strcpy(ptr1,ptr1+1); //Переопределяем новый размер строки ptr=(char*)realloc(ptr,strlen(ptr)*sizeof(char)+1); printf(" Новая строка ->%s",ptr); //освобождаем динамическую память free(ptr); _getch(); return 0; } Пояснения к программе. while(ptr1=strchr(ptr,'a')) strcpy(ptr1,ptr1+1); ptr=(char*)realloc(ptr,strlen(ptr)*sizeof(char)+1); В данном цикле проверяем вхождения симола а в строке используя функцию strchr(). Если данный символ в строке ptr существует, то переменная ptr1 получит адрес первого вхождения данного символа в строке ptr. Если такого символа в строке нет, то переменная ptr1 получит значение адресного нуля, т.е. NULL и цикл прекратит свою работу. Используя strcpy(ptr1,ptr1+1), копируем последовательность байтов начиная с адреса ptr1+1 и заканчивая ‘\0’ в строку, начинающуюся с адреса ptr1. Таким образом, удаляем все вхождения символа а. Результат выполнения программы:  Рис. 11. 2 Результат выполнения программы к примеру 27 Ключевые термины Внутренние коды символов – целые числа, однозначно соответствующие символам во внутреннем представлении. Инициализация строки – определение значения строки. Размер строки – объем памяти, занимаемой строкой, выраженный в байтах. Символ конца строки – нулевой байт, являющийся признаком конца строки символов. Символьная константа – константа типа char. Символьная переменная – переменная типа char. Строка – это пронумерованная последовательность символов, заключенная в двойные кавычки. Конкатенация строк – это результат последовательного соединения строк. Лексикографический порядок – правило сравнения символов, основанное на величине кода внутреннего представления каждого символа. Пустая строка – это строка единичной длины, содержащая только символ конца строки. Сравнение строк – это результат проверки выполнения отношения "больше", "меньше" или "равно" над строками. Стандартные функции по работе со строками – это функции обработки строк, прототипы которых входят в стандартные библиотеки С Адрес строки – это указатель на блок непрерывной области памяти, с которого начинает располагаться массив символов. Строки как параметры функций – это описание передачи значений строк в функции как массив символов или указатель типа char. Указатель на строку – адрес начала расположения строки в памяти. Краткие итоги - Для представления текстовой информации в С используются символьные данные и строки.
- В С не определен строковый тип данных, и строка представляется как массив символов.
- Инициализировать строку можно как массив символов.
- Признаком конца строки является нулевой символ.
- Обратиться к элементу строки можно по индексу, который соответствует порядковому номеру элемента.
- Нумерация элементов строки начинается с нуля. Размер строки определяется количеством входящих в нее символов.
- В С предусмотрены различные способы ввода и вывода одиночных символов и строк: с помощью стандартных функций, с помощью потокового или форматированного ввода/вывода. При считывании строки с клавиатуры признак конца строки добавляется автоматически.
- Каждому символу однозначно соответствует его внутренний код.
- Для работы со строками в языке С предусмотрены стандартные функции, прототипы которых включены в стандартные библиотеки stdlib.h и string.h.
- При обращении к функциям для работы со строками следует учитывать, что изменение значений элементов строк сохраняются после завершения работы функции.
- Перед использованием строки в программном коде ее необходимо проинициализировать. Неинициализированные строки могут привести к некорректной работе программы.
- В некоторых стандартных функциях по работе со строками следует проводить контроль длин параметров.
- Результат работы некоторых функций требует принудительного добавления к строке символа конца строки.
- Значения элементов строк зависят от регистра.
- Изменение регистра символов кириллицы в программе может выполняться некорректно.
- В силу специфики представления строк в виде символьного массива сами строки, строковые константы, заключенные в кавычки, и указатели на строки обрабатываются эквивалентно.
- Строки передаются в функции в качестве параметров как массивы символов или как указатели типа char.
- Обращение к конкретному элементу строки можно осуществить посредством адресации индексированного имени строки.
- При формировании строки без использования стандартных функций требуется дописывать символ конца строки.
- С помощью указателей на константы можно защитить строку от изменений.
- Копирование строк с помощью указателей осуществляется через объявление нового указателя, адресующего область памяти, занимаемую строкой или подстрокой.
Контрольные вопросы - Почему в С не выполняется операция прямого присваивания значения строке?
- Почему символ и строка, состоящая из одного символа, занимают разный объем памяти?
- Почему в функции scanf("%s", string); не указывается обращение к переменной по адресу?
- Допустима ли операция сравнения над символами? Если да, то каким образом определены отношения "больше" и "меньше"?
- Какая из функций, gets или puts, заносит в поток управляющий символ '\n' и с какой целью?
- Можно ли выполнить присваивание символьной переменной числового значения? Почему?
- В чем различия результатов вывода символьной переменной со спецификаторами %d и %c?
- Что будет являться результатом работы функции побайтового копирования строк, если длина строки-источника превосходит допустимый размер строки-приемника?
- Что будет являться результатом работы функции побайтового копирования строк, если длина строки-источника меньше размера строки-приемника?
- Почему при сравнении строк важен регистр символов?
- Как сравниваются строки разной длины?
- Какие возможны последствия при обращении к неинициализированной строке?
- Почему функция изменения регистра символов строки может некорректно работать с кириллицей?
- Что будет являться результатом работы функции побайтового копирования строк, если длина строки-источника превосходит допустимый размер строки-приемника?
- Что будет являться результатом работы функции побайтового копирования строк, если длина строки-источника меньше размера строки-приемника?
- Почему при сравнении строк важен регистр символов?
- Как сравниваются строки разной длины?
- Какие возможны последствия при обращении к неинициализированной строке?
- Почему функция изменения регистра символов строки может некорректно работать с кириллицей?
- Почему обращения к строке через ее имя и через указатель эквивалентны?
- Почему в качестве параметра функции передается адрес строки, а не сама строка символов?
- Возможно ли применение операций инкремента и декремента к указателю на строку? Если да, то что будет адресовать полученный указатель?
- Почему при формировании строки без использования стандартных функций необходимо дописывать символ конца строки? Почему этого не требуется при считывании строк с клавиатуры?
- Какие возможны ошибки в программе при некорректной работе со строками?
- Для защиты строки от изменения объявляется указатель на константу или указатель-константа? Почему?
Задание. При выполнении данной лабораторной работы необходимо решать каждую задачу с использование указателей и функций для работы со строками. Не использовать символьные массивы с фиксированным количеством элементов. Максимально экономно подходить к использованию памяти. Вариант 1. Задание 1. Дана строка, состоящая из слов, разделенных пробелами и заканчивающаяся точкой. Подсчитать, сколько слов в строке. Задание 2. Дана строка, содержащая текст, заканчивающийся точкой. Вывести на экран слова, содержащие три буквы. Задание 3. Дана строка. Преобразовать ее, удалив каждый символ * и повторив каждый символ, отличный от *. Вариант 2. Задание 1. Дана строка, состоящая из слов, разделенных пробелами и заканчивающаяся точкой, содержащая английский текст. Найти количество слов, начинающихся с буквы b. Задание 2. Дана строка, состоящая из слов, разделенных пробелами и заканчивающаяся точкой. Вывести на экран слова, содержащие три буквы. Задание 3. Дана строка, состоящая из слов, разделенных пробелами и заканчивающаяся точкой. Удалить в каждом слове текста последнюю букву. Вариант 3. Задание 1. Дана строка. Подсчитать, сколько в ней букв r, k, t. Задание 2. Дана строка, состоящая из слов, разделенных пробелами и заканчивающаяся точкой. Определить, сколько раз входит в нее группа букв abc. Задание 3. Дана строка, состоящая из слов, разделенных пробелами и заканчивающаяся точкой. Удалить в каждом слове текста первую букву. Вариант 4. Задание 1. Дана строка. Определить, сколько в ней символов *, ;, :. Задание 2. Дана строка. Подсчитать, сколько различных символов встречается в ней. Вывести их на экран. Задание 3. Из строки Str1 удалить все символы, входящие в строку Str2. Вариант 5. Задание 1. Дана строка, состоящая из слов, разделенных пробелами и заканчивающаяся точкой. Найти длину самого длинного слова. Задание 2. Дана строка, состоящая из слов, разделенных пробелами и заканчивающаяся точкой Определить, сколько раз в строке встречается заданное слово. Задание 3. Дана строка, состоящая из слов, разделенных пробелами и заканчивающаяся точкой. В каждом слове продублировать последнюю букву. Вариант 6. Задание 1. Дана строка символов, среди которых есть двоеточие (:). Определить, сколько символов ему предшествует. Задание 2. Дана строка, состоящая из слов, разделенных пробелами и заканчивающаяся точкой. Указать те слова, которые содержат хотя бы одну букву k. Задание 3. Дана строка, состоящая из слов, разделенных пробелами и заканчивающаяся точкой. В тех словах, которые содержат хотя бы одну букву k продублировать первую букву. Вариант 7. Задание 1. Дана строка. Подсчитать самую длинную последовательность подряд идущих букв а. Задание 2. Дана строка, состоящая из слов, разделенных пробелами и заканчивающаяся точкой. Найти в ней те слова, которые начинаются и оканчиваются одной и той же буквой. Задание 3. Дана строка из символов латинского алфавита. Замените все вхождения слова "two" на символ '2'. Вариант 8. Задание 1. Дана строка. Преобразовать ее, удалив каждый символ * и повторив каждый символ, отличный от *. Задание 2. В записке слова зашифрованы — каждое из них записано наоборот. Расшифровать сообщение. Задание 3. Дана строка, состоящая из слов, разделенных пробелами и заканчивающаяся точкой. Заменить в ней слово he на she. Вариант 9. Задание 1. Дана строка. Определить, сколько раз входит в нее группа букв abc. Задание 2. Отредактировать заданное предложение, удаляя из него те слова, которые встречаются в предложении заданное число раз. Задание 3. Дана строка, состоящая из слов, разделенных пробелами и заканчивающаяся точкой. Заменить в ней заданное слово на другое заданное слово. Если первое слово встречается несколько раз, то произвести несколько замен. Вариант 10. Задание 1. Дана строка. Подсчитать количество букв k в последнем ее слове. Задание 2. Напечатать те слова, которые встречаются в каждом из двух заданных предложений. Задание 3. Дана строка, состоящая из слов, разделенных пробелами и заканчивающаяся точкой. Поменять в ней местами первое и последнее слово. Вариант 11. Задание 1. Дана строка символов, среди которых есть одна открывающаяся и одна закрывающаяся скобка. Вывести на экран все символы, расположенные внутри этих скобок. Задание 2. Отредактировать заданное предложение, удаляя из него все слова с нечетными номерами. Задание 3. Дана строка, состоящая из слов, разделенных пробелами и заканчивающаяся точкой. Перевернуть в ней все слова с четными номерами. Вариант 12. Задание 1. Имеется строка, содержащая буквы латинского алфавита и цифры. Вывести на экран длину наибольшей последовательности цифр, идущих подряд. Задание 2. Форматирование текста. Дан текст, состоящий из предложений, разделяемых точками. Напишите программу, производящую следующее форматирование: после каждой точки в конце предложения должен стоять хотя бы один пробел; первое слово в предложении должно начинаться с прописной буквы. Задание 3. Дана строка, состоящая из слов, разделенных пробелами и заканчивающаяся точкой. Заменить в ней все слова, начинающиеся с буквы m на mama. Вариант 13. Задание 1. Дан набор слов, разделенных точкой с запятой (;). Набор заканчивается двоеточием (:). Определить, сколько в нем слов, заканчивающихся буквой а. Задание 2. Лишние пробелы. Дана строка, состоящая из слов, разделенных пробелами. Напишите программу, удаляющую лишние пробелы. Пробел считается лишним, если он: • стоит в начале строки; • стоит в конце строки; • следует за пробелом. Задание 3. Дана строка, состоящая из слов, разделенных пробелами и заканчивающаяся точкой. В каждом слове оставить только первые вхождения каждой буквы. Вариант 14. Задание 1. В строке заменить все двоеточия (:) точкой с запятой (;). Подсчитать количество замен. Задание 2. Дана строка, состоящая из символов латинского алфавита, разделенных пробелами (одним или несколькими). Преобразовать каждое слово в строке, удалив из него все вхождения первой буквы этого слова (количество пробелов между словами не изменять). Задание 3. Дана строка, состоящая из слов, разделенных пробелами и заканчивающаяся точкой. Перед каждым четным по номеру слову вставить слово mama/ Вариант 15. Задание 1. В строке удалить символ «двоеточие» (:) и подсчитать количество удаленных символов. Задание 2. Дана строка, состоящая из символов латинского алфавита, разделенных пробелами (одним или несколькими). Определить количество слов, которые начинаются и заканчиваются одной и той же буквой. Задание 3. Дана строка, состоящая из слов, разделенных пробелами и заканчивающаяся точкой. Если слово в строке заканчивается буквой а, то следующее за ним слово удалить. Вариант 16. Задание 1. Дана строка, состоящая из слов, разделенных пробелами и заканчивающаяся точкой. Определить сколь слов в строке начинаются на заданную букву. Задание 2. Дана строка, состоящая из символов латинского алфавита, разделенных пробелами (одним или несколькими). Преобразовать каждое слово в строке, удалив из него все вхождения последней буквы этого слова (количество пробелов между словами не изменять). Задание 3. В строке между словами вставить вместо пробела запятую и пробел. Вариант 17. Задание 1. Удалить часть символьной строки, заключенной в скобки (вместе со скобками). Задание 2. Дана строка, состоящая из слов, разделенных пробелами и заканчивающаяся точкой. Заменить каждую первую букву слова со строчной на прописнуюю Задание 3. Предложение состоит из слов, разделенных одним или несколькими пробелами. Оставить в строке только те слова, которые заканчиваются на заданный символ. Вариант 18. Задание 1. В строке имеется одна точка с запятой (;). Подсчитать количество символов до точки с запятой и после нее. Задание 2. Дана строка-предложение из символов латинского алфавита. Вывести самое короткое слово в предложении (если таких слов несколько, то вывести первое из них). Задание 3. Дана строка, состоящая из слов, разделенных пробелами и заканчивающаяся точкой. Поменять местами первое слово со вторым, третье с четвертым и т.д. Вариант 19. Задание 1. Строка содержит одно слово. Проверить, будет ли оно читаться одинаково справа налево и слева направо (т.е. является ли оно палиндромом). Задание 2. Дана строка, состоящая из символов латинского алфавита, разделенных пробелами (одним или несколькими). Определить количество слов, которые содержат ровно три буквы ' А '. Задание 3. Дана строка, состоящая из слов, разделенных пробелами и заканчивающаяся точкой. Напечатать те слова данной строки, которые отличаются от слова hello. Вариант 20. Задание 1. Проверить, одинаковое ли число открывающихся и закрывающихся скобок в данной строке. Задание 2. В предложении, состоящем из слов, разделенных одним пробелом, заменить первую букву у слов, следующих за словами the, a, на прописную. Задание 3. Дана строка, состоящая из слов, разделенных пробелами и заканчивающаяся точкой. После каждой буквы q добавить букву u. Вариант 21. Задание 1. Дана строка-предложение из символов латинского алфавита. Преобразовать строку так, чтобы каждое слово начиналось с заглавной буквы. Задание 2. Дана строка-предложение из символов латинского алфавита. Вывести самое длинное слово в предложении (если таких слов несколько, то вывести последнее из них). Задание 3. Дана строка, состоящая из слов, разделенных пробелами и заканчивающаяся точкой. Заменить все вхождения ph на f? а все вхождения ed на ing. Вариант 22. Задание 1. Даны две строки А и В. Составьте программу, проверяющую, можно ли из букв, входящих в А, составить В (буквы можно использовать не более одного раза и можно переставлять). Например, А: ИНТЕГРАЛ; В: АГЕНТ — составить можно; В: ГРАФ — составить нельзя. Задание 2. Определить, сколько раз в строке встречается заданное слово. Задание 3. Дана строка, состоящая из слов, разделенных пробелами и заканчивающаяся точкой. Удалить из нее повторно встречающиеся слова. Вариант 23. Задание 1. Строка содержит произвольный русский текст. Проверить, каких букв в нем больше: гласных или согласных. Задание 2. Дана строка, состоящая из символов латинского алфавита, разделенных пробелами (одним или несколькими). Определить количество слов, которые содержат введенный символ. Задание 3. Дана строка, состоящая из слов, разделенных пробелами и заканчивающаяся точкой. Удалить из нее те слова, которые в ней встречаются по одному разу. Вариант 24. Задание 1. Строка состоит из слов, разделенных пробелами. Оставить между словами только по одному пробелу. Задание 2. Выясните, имеются ли среди введенных символов все буквы, входящие в слово "yandex". Задание 3. Дана строка, состоящая из слов, разделенных пробелами и заканчивающаяся точкой. Удалить из нее те слова, в которых первая буква встречается еще раз. Вариант 25. Задание 1. Дана строка, состоящая из символов латинского алфавита, разделенных пробелами (одним или несколькими). Определить длину самого длинного слова. Задание 2. Предложение состоит из слов, разделенных одним или несколькими пробелами. Написать программу, печатающую все слова, начинающиеся на введенный символ. Задание 3. В английском предложении слова разделены одним пробелом. Во всех словах, следующих за артиклями а и the, удалить первую букву. |