Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Учебное пособие_С++2015

.pdf
Скачиваний:
179
Добавлен:
15.03.2016
Размер:
2.8 Mб
Скачать

Символьные данные могут использоваться и в операторах цикла 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

1 . Проверить,

else

printf("\nнет такой подстроки\n"); return 0;

}

Не надо искать смысл в написанных программах. Они написаны только для того, чтобы сравнить запись одних и тех же действий, средствами языка С и языка С++. Как видно из примера, выполнение любых действий со строками старого стиля менее наглядно. Кроме того, необходимо проверять, достаточно ли места в строке-приемнике при копировании, то есть фактически код работы со строками старого стиля должен быть еще более длинным.

Контрольные задания

Подготовить текст исходного предложения в соответствии с вариантом задачи, указанным в таблице (предложение должно заканчиваться точкой, разделитель слов в предложении - пробел). Составить программу и выполнить ее на ПК.

Вариант

Условие задачи

1Из заданного предложения, начиная с первой встретившейся буквы 'а', скопировать в подстроку все символы до первой встретившейся буквы ' к'.

2В исходном предложении все символы пробела заменить символами подчеркивания.

3Вывести символы, которые встречаются в исходном предложении по одному разу.

4В исходном предложении удалить все символы пробела. Вывести преобразованный текст и количество удаленных пробелов.

5Определить, сколько раз в заданном предложении встречается сочетание двух первых букв.

6В качестве исходного предложения задать арифметическое

3 ln sin x

выражение, записанное на языке С: e a b

соблюдается ли баланс открывающихся и закрывающихся скобок. Если равенство соблюдается, то вывести соответствующее сообщение, в противном случае вывести количества открывающихся и закрывающихся скобок.

130