Учебное пособие_С++2015
.pdfСимвольные данные могут использоваться и в операторах цикла for. Так, при выполнении операторов:
for( ch='a'; ch>='d'; ch++) printf("%с",ch);
в строку экрана выводится последовательность:
a b с d
Если значение символьной переменной вывести с помощью спецификатора для целых чисел %d, то на экране отобразится код символа. Например:
for(ch='a'; ch>='d'; ch++) printf("%d ",ch);
на экран будет выведено:
97 98 99 100
Над символьными данными можно выполнять арифметические операции сложения и вычитания. Так, например, операция ch++; из предыдущего примера увеличивает код символа, хранящегося в переменной ch на 1. Или, выполняя операцию ch='a'-'A'; будет получена разница кода большой (А) и маленькой буквы (а) латинского алфавита. Так, например, если в символьной переменной ch1 хранится маленькая буква алфавита, то, выполнив действия:
char ch,ch1,ch2; ch='a'-'A'; ch1='k'; ch2=ch1-сh;
printf("%c-%d %c-%d\n",ch1,ch1,ch2,ch2);
в переменную ch2 запишется та же буква, только большая, а на экран будет выведено
k-107 K-75
Строки
Значением строки является любая последовательность символов. Причем для компьютера – это набор байтов.
Строковая константа - это строка, заключенная в кавычки, например:
―Язык программирования‖
В С++ есть две возможности работы со строками: функции, унаследованные из библиотеки С (заголовочный файл <string.h> или <cstring>), и библиотечный класс С++ string. Рассмотрим обе эти возможности.
121
Наследие языка С: Строковая переменная или строка представляет собой массив символов, заканчивающийся нуль-символом, поэтому и объявляется она именно так:
сhar st[30];
В квадратных скобках указывается максимальное число символов в строке st.
Под значение строковой переменной в памяти компьютера отводится 30 байт, пронумерованных от 0 до 29, где 30 - объявленный размер строки.
Строка отличается от несимвольного массива тем, что она заканчивается кодом 0 - признаком окончания строки. По местоположению этого специального символа определяется фактическая длина строки.
Начальное значение строки можно задать при ее объявлении следующим образом:
char s[80] = "Язык программирования Си";
Символы в кавычках будут записаны в начало массива s, а затем - признак окончания строки '\0'.
При описании строки можно также написать так:
char s[] = "Язык программирования Си";
В этом случае компилятор подсчитает символы в кавычках, выделит памяти на 1 байт больше и занесет в эту область саму строку и завершающий ноль.
Ввод-вывод строковых данных
При вводе строк, как и символов, можно использовать функцию scanf(). При этом для форматного ввода и вывода строк используется спецификатор %s. Однако нажатие клавиши [Enter] или клавиши [пробел] не является значимым символом. При вводе строки с помощью функции scanf() нажатие одной из этих клавиш формирует символ конца строки. Таким образом надо помнить, что функция scanf() позволяет записать в строку только одно слово.
Пример. Организовать ввод ФИО студента.
char fam[20];
printf ("Введите фамилию и инициалы студента"); scanf("%s", fam);
На клавиатуре строка набирается без кавычек, например:
122
Андреева С.В. [Enter]
Одновременно с вводом строки в байт с индексом восемь запишется символ с кодом 0. Инициалы студента в эту строку записаны не будут, так как пробел после фамилии будет воспринят командой scanf как конец строки.
Для ввода текста, содержащего пробелы, следует использовать специальную функцию gets(). При вводе строки с помощью этой функции только нажатие клавиши [Enter] сформирует символ конца строки.
Так, например, в предыдущей задаче:
char fam[20];
printf("Введите фамилию и инициалы студента"); gets(fam);
использование функции gets() позволит записать в строку fam не только фамилию, но и инициалы.
Вывод строк осуществляется с помощью функции printf() или специальной функции puts(). Например, функция
printf("| %20s|",fam);
выведет на экран в правую часть поля из 20 позиций строку fam:
| Андреева С.В.|
Специальная функция puts() выводит содержимое строки и переводит курсор на следующую строку экрана. Например:
putchar('|’); puts(fam); putchar('|’);
приведет к получению следующего результата:
|Андреева С.В.
|
Последний символ | будет выводиться в следующей строке экрана.
Обработка строковых данных
К любому символу строки можно обратиться как к элементу одномерного массива, например, запись st[i] определяет i-ый символ в строке st. Поэтому при решении некоторых задач обработку строковых данных можно проводить посимвольно, организуя циклы для просмотра строки.
Например: Дано предложение. Определить количество слов в нем.
123
Решение:
Слова в предложении разделяются пробелами. Подсчитав количество пробелов, можно определить количество слов, учитывая, что между словами введен только один пробел.
#include "stdafx.h"
#include<string.h> int main()
{ char slova[120]; int i, n, k=1;
printf("Введите предложение\n"); gets(slova);
n= strlen(slova); // функция strlen() возвращает длину строки for(i=0;i<n; i++)
if(slova[i]==' ')k++; //поиск и подсчет пробела printf("k=%d\n",k);
return 0;
}
Стандартные функции обработки строк
Большинство действий над строками реализуется с помощью стандартных функций, унаследованных от языка С и описанных в заголовочном файле string.h. Рассмотрим некоторые из них.
Сравнение строк:
strcmp(str1,str2) – сравнивает две строки str1 и str2 и возвращает 0, если они одинаковы; результат отрицателен, если str1<str2 и положителен, если str1>str2.
strncmp(str1, str2, kol) – сравниваются части строк str1 и str2 из kol символов. Результат равен 0, если они одинаковы.
Сравнение двух строк выполняется последовательно слева направо с учетом кодировки символов. Например, сравнивая стоки st1 и st2
char st1[10]="Пример"; char st2[10]="ПPимер"; int a;
if (strcmp(st1,st2)>0) a=1;
else
a=2;
124
переменной а будет присвоено значение 1, так как код символа 'р' больше кода символа 'Р'.
Сцепление строк
strcat(str1,str2) - сцепление строк в порядке их перечисления. strncat(str1,str2,kol) – приписывает kol символов строки str2 к строке str1.
Функция служит для объединения двух строк в одну. Например, в результате выполнения операторов:
char fam[] = "Андреев С.В.";
char pr[17]= " -студент СИБГУТИ
";
strcat(fam ,pr); printf("|%32s|", fam);
на экран будет выведена строка:
|Андреев С.В. -студент СИБГУТИ |
Заметим, что строка вывода занимает поле в 32 позиции, а переменная fam располагается в левой части этого поля.
Определение длины строки
strlen(str) – определяет длину строки str. Пример. Определить длину строки
char fam[] = "Андреева С.В.";
printf("%d",strlen(fam));
функция strlen() вернѐт значение равное 13 (символов).
Копирование строк
strcpy(str1,str2) – копирует строку str2 в строку str1. strncpy(str1, str2, kol) – копирует kol символов строки str2 в строку str1.
Пример. Скопировать фамилию сотрудника в переменную fam и вывести на экран.
#include "stdafx.h" #include<string.h>
int main()
{ char fam[15];
char *str = " Андреева С.В.";
125
strcpy(fam, str); printf("|%s|\n", fam); return 0;
}
В результате выполнения данных операторов на экран будет выведена строка:
|Андреева С.В.|
Поиск символа в стоке
strchr(st, ch) - функция поиска адреса символа ch в строке st. Результатом выполнения поиска является адрес найденного символа в строке st, иначе возвращается нулевой адрес. Чтобы вычислить порядковый номер символа ch в строке, можно из найденного адреса вычесть адрес начала строки.
Пример. В заданной фамилии определить порядковый номер символа ‗n‘.
#include "stdafx.h"
#include<string.h> int main()
{ char fam[] = "Ivanov";//задание фамилии char faml[20];
char |
a='n';// искомый символ |
char |
*p; |
p=strchr(fam,a);//поиск символа в фамилии if(p)
printf("|%s|%d\n", fam, p-fam);/*вывод фамилии и порядкового номера символа n в ней */
else
printf("нет такого символа в фамилии!\n"); return 0;
}
Пример программы для задачи с текстовыми данными
Исходным текстом является предложение, заканчивающееся точкой. Слова в предложении отделяются друг от друга одним пробелом. Определить самое длинное слово в предложении.
#include "stdafx.h"
#include<string.h> int main()
{ char slovo[12],X[120]; // описание массивов для предложений int i,m=0,n,k=0,dl;
126
gets(X); |
|
// ввод исходного предложения в X |
|
dl= strlen(X);// определяем длину введенного предложения |
|||
for(i=0; i<dl; |
i++) //цикл от начала до конца строки X |
||
if(X[i]!=' ') |
k++; |
// считаем символы до пробела |
|
else |
// если дошли до пробела |
||
|
{ if (k>m) |
|
//поиск мах значения счетчика к |
|
{ m=k; // запоминаем длину текущего длинного слова |
n=i; // запоминаем номер пробела, идущего за длинным словом
}
k=0; //обнуляем счетчик для нового слова предложения Х
}
k=0;
for(i=n-m;i<n;i++)//выбор из строки X самого длинного слова в массив slovo
slovo[k++]=X[i];
slovo[k]=0; //ставим в массиве slovo признак конца текста
printf("%s\n",slovo); //вывод найденного длинного слова printf("%d\n",strlen(slovo));//вывод его длины
return 0;
}
Более полный перечень функций работы со строками и символами смотрите в приложении А. Эти функции позволяют достичь высокой эффективности работы программы, использующей их. Но они весьма неудобны и небезопасны в использовании, поскольку выход за границы строкового массива не проверяется.
Библиотека языка С++: Тип данных string стандартной библиотеки языка С++ лишен этих недостатков. С помощью операций и методов этой библиотеки длина строки может динамически меняться в соответствии с
потребностями. Для |
использования класса string к программе надо |
|
подключить заголовочный файл <string>. |
|
|
Для создания |
строки типа string определено |
несколько |
конструкторов. Приведем примеры создания строк: |
|
|
string s1; |
//создание пустой строки |
|
string s2("Привет"); //создание строки со значением Привет |
||
string s3(s2); //создание строки s3 со значением строки |
s2; |
К строке типа string можно применять операции старого стиля, например: s1=’X’; // присвоение строке s1 значения символа Х
127
s1="ура"; //запись в строку s1 слово ура.
s2=s1; //присвоение значения строке s2 значения строки s1
Над объектами класса string |
допустимы операции: |
|
|||
|
|
|
|
||
операция |
действие |
операция |
действие |
||
|
|
|
|
|
|
= |
присваивание |
> |
больше |
|
|
|
|
|
|
|
|
+ |
конкатенация |
>= |
больше |
либо |
|
|
|
|
|
равно |
|
|
|
|
|
|
|
= = |
сравнение |
на |
[ ] |
индексация |
|
|
равенство |
|
|
|
|
|
|
|
|
|
|
!= |
неравенство |
|
<< |
потоковый вывод |
|
|
|
|
|
|
|
< |
меньше |
|
>> |
потоковый ввод |
|
|
|
|
|
|
|
<= |
меньше |
либо |
+= |
добавление |
|
|
равно |
|
|
|
|
|
|
|
|
|
|
Для работы со строками этих операций недостаточно. Для работы со строками целиком и для обработки частей строк в классе string определено множество разнообразных методов (функций). Библиотека С++ содержит функции присваивания части одной строки другой строке (assing), добавления части одной строки к другой строке (append),вставки в одну строку части другой строки (insert), очистки строки (clear), выделения части строки (substr), поиск подстроки в строке (find), сравнение частей строк (compare), получение характеристик строк: определение количества элементов строки (size или length), максимальная длина строки (max_size), определение, является ли строка пустой (empty). Наиболее употребительные из них описаны в библиотеке <string> приложения А.
Рассмотрим пример обработки строк с использованием средств языка С и библиотеки языка С++.
Вариант использования средств языка С:
#include "stdafx.h" #include<string.h> #include "iostream"
128
using namespace std; int main()
{setlocale(0,"RUS");
char С1[50],С2[50],С3[50]= "";//строки с завершающим нулем char *flag;
//Заполняем массивы исходной информацией strcpy(С1,"Миру "); strcpy(С2,"Мир! ");
//Объединяем массивы С1 и С2 в массив С3 strcat(С3,С1); strcat(С3,С2);
cout<< С3<<endl;
// Сравниваем массив С1 с С2
if (strcmp(С1,С2) < 0 ) cout<< С1; else cout <<С2;
//поиск в строке С3 подстроки ‖Ми‖ flag=strstr(С3, "Ми"); if(flag)
printf("\nтакая подстрока есть\n");
else
printf("\nнет такой подстроки\n"); return 0;
}
Напишем эту же программу средствами библиотеки С++
#include "stdafx.h" #include<string> #include "iostream" using namespace std;
int main()
{ setlocale(0,"RUS"); string С1,С2,С3; //строки
С1="Миру ";
С2="Мир! ";
//объединение строк
С3=С1+С2;
cout << С3<<endl;
// Сравнение строк
if (С1 < С2) cout<< С1; else cout << С2;
// Поиск в строке С1 подстроки "Ми" int flag = С1.find("Ми"); if(flag>=0)
printf("\nтакая подстрока есть\n");
129
else
printf("\nнет такой подстроки\n"); return 0;
}
Не надо искать смысл в написанных программах. Они написаны только для того, чтобы сравнить запись одних и тех же действий, средствами языка С и языка С++. Как видно из примера, выполнение любых действий со строками старого стиля менее наглядно. Кроме того, необходимо проверять, достаточно ли места в строке-приемнике при копировании, то есть фактически код работы со строками старого стиля должен быть еще более длинным.
Контрольные задания
Подготовить текст исходного предложения в соответствии с вариантом задачи, указанным в таблице (предложение должно заканчиваться точкой, разделитель слов в предложении - пробел). Составить программу и выполнить ее на ПК.
Вариант |
Условие задачи |
1Из заданного предложения, начиная с первой встретившейся буквы 'а', скопировать в подстроку все символы до первой встретившейся буквы ' к'.
2В исходном предложении все символы пробела заменить символами подчеркивания.
3Вывести символы, которые встречаются в исходном предложении по одному разу.
4В исходном предложении удалить все символы пробела. Вывести преобразованный текст и количество удаленных пробелов.
5Определить, сколько раз в заданном предложении встречается сочетание двух первых букв.
6В качестве исходного предложения задать арифметическое
3 ln sin x
выражение, записанное на языке С: e a b
соблюдается ли баланс открывающихся и закрывающихся скобок. Если равенство соблюдается, то вывести соответствующее сообщение, в противном случае вывести количества открывающихся и закрывающихся скобок.
130