Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Язык программирования Сpp 25.09.11 (2).doc
Скачиваний:
16
Добавлен:
19.08.2019
Размер:
10.09 Mб
Скачать

10. Строки

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

cout<<"Привет!";

В данном случае текст, заключенный в двойные кавычки это и есть строка. Теперь вспомним, что базовые типы могут быть константами и переменными. Строка из рассмотренного примера похожа на константу, поскольку ее значение уже трудно изменить. Сразу возникает вопрос, а существуют ли такие строки, символы в которых могут изменяться? Ответ положительный: да, такие строки вполне можно сделать. Для этого просто нужно задать символьный массив элементы которого можно изменять. Например, объявим массив:

char myString[20]={'П','р','и','в','е','т'};

Здесь мы объявили массив, состоящий из 20 элементов, хотя использовали только 6. Важно отметить, что в отличие от числового массива, где неиспользованные позиции массива остаются неизменными (т.е. в них находится то, что осталось в памяти от предыдущей программы), неиспользованные символы в строковом массиве автоматически заполняются пробелами. Для символьных массивов существуют и другие исключения. Так для вывода на экран всей строки можно использовать оператор cout<<, а для ввода cin>> без указания на вывод каждого элемента массива. В последнем случае нужно иметь в виду, что все пробельные символы (пробелы и символы новой строки) пропускаются. Например, программа

#include <iostream>

using namespace std;

void main()

{

char myString[20]=”Privet”; // объявление

// и инициализация массива

cout<< myString; // массив символов выводится не поэлементно,

// а как одна величина

}

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

#include <iostream>

using namespace std;

void main()

{

char myString[20]= ”Privet”;

for(int i=0;i<20;i++)

cout<< myString[i];

}

также выводит Privet , но курсор останавливается на 20-ой позиции. Все незанятые символами позиции заполняются пробелами.

Рассмотрим еще один пример с использованием оператора ввода.

#include <iostream>

using namespace std;

void main()

{

char a[100],b[100];

cout<<"Input anithing"<<endl;

cin>>a>>b;

cout<<a<<b<<"\nTHE END";

}

Результате выполнения программы следующий: начала на экране появится сообщение

Input anithing

Мигающий курсор говорит о том, что выполняемая программа готова к вводу. После ввода какого-либо слова введите один или несколько побелов, нажмите Enter, что означает конец ввода в массив a, и теперь введите слово в массив b. В итоге получится нечто одна строка без пробелов, которая будет выглдядеть так:

Слово1Слово2

THE END

Если вы хотите ввести текст на кириллице, то не забудьте подключить библиотеку windows.h и установить кодировку для ввода SetConsoleCP(1251) и вывода SetConsoleOutputCP(1251).

Этот пример показывает, что оператор ввода cin не учитывает символ пробела.

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

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

#include <iostream>

using namespace std;

void main()

{

char a[100];

cout<<"Input anithing"<<endl;

cin.getline(a,80);//количество вводимых символов ограничено

cout<<a<<"THE END";

}

В данном случае результат будет таков:

Input anithing

Вводятся отдельные слова через пробел. После нажатия на Enter на экране появится

Слово1 Слово2THE END

Если количество введенных символов превысит значение, указанное во втором аргументе функции getline то чтение прекращается. Строго говоря, количество вводимых символов даже на единицу меньше чем число во втором аргументе. Это объясняется тем, что последнюю позицию занимает так называемый нуль-символ, информирующий о конце строки, но об этом мы поговорим чуть позднее.

Вероятно, сейчас не вполне понятен вызов функции getline. О , почему вызов осуществляется именно так, мы расскажем тогда, когда познакомимся с классами и потоками ввода-вывода.

Вернемся к первому примеру. Обратим внимание, что наше приветствие выводится без восклицательного знака. Исправим эту ошибку. С этой целью добавим оператор ввода элемента на 6-ой позиции, и с его помощью введем восклицательный знак.

#include <iostream>

using namespace std;

void main()

{

char myString[20]=”Privet”;

cout<< myString;

cin>>myString[6]; //Здесь нужно ввести восклицательный знак

cout<< myString;

}

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

Символьный массив можно инициализировать при объявлении

char myString[20]="Privet";

В этом случае после последней буквы компилятор автоматически добавит символ '\0' означающий конец строки. Для рассмотренного примера это будет 6-я позиция. Этот символ используется во многих функциях работающих со строковыми переменными, поэтому это способ предпочтительнее. Однако следует иметь в виду, что если мы теперь введем восклицательный знак, то символ '\0' будет замещен знаком '!'. С другой стороны, если не удалить символ '\0', то все свободные элементы массива будут недоступны. Например, после инициализации можно заменить любой символ массива с myString[0] до myString[5],но начиная с myString[7] до myString[20] элементы массива недоступны. Недоступность означает, что эти символы невозможно прочитать.

Строковые значения и строковые переменные не похожи на значения и переменные других типов, поэтому обычные операторы с ними не работают. Например, для строковых переменных знак присвоения работает только при объявлении переменной, т.е. код

char myString[10];

myString="Privet!";

является неверным в силу того, что myString это массив и, следовательно, указанный код должен выглядеть так:

char myString[10];

myString[0]='P';

myString[1]='r';

myString[2]='i';

myString[3]='v';

myString[4]='e';

myString[5]='t';

myString[6]='!';

myString[7]='\0';

Хотя ввод с клавиатуры можно выполнить, т.е.

#include<iostream>

using namespace std;

void main(){

char myString[20];

cin>>myString; //ввод с клавиатуры

cout<<myString;

}

Наиболее распространенной ошибкой при работе со строками является применение ператора равенства «», кне справедлив, ведь строка это массив. Строки можно сравнивать лишь поэлементно.

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

Функция

Описание

Замечания

strcpy(str1,str2)

Копирует str2 в str1

Не проверяет достаточно ли места в str1 для копирования

strcat(str1,str2)

Присоединяет str2 к окончанию str1

Не проверяет достаточно ли места в str1 для присоединения str2.

strlen(str)

Возвращает целое число равное длине строки без учета нуль-символа.

strcmp(str1,str2)

Сравнивает строки. Поочередно сравниваются коды символов двух строк. Если они совпадают, возвращает 0. Если значение кода символа str1 меньше str2, возвращает отрицательное число. Если значение кода символа str1 больше str2, возвращает положительное число

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

#include <cstring>

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

Очень часто перед программистом стоит задача перевода строк в числа. Например, строка "12345" и число 12345 это совершенно разные типы. Для перевода строки в число используется функция atoi(str). По-русски название функции произносится как "эй ту ай" ("A" to "I" - alphabetic to integer). Функция atoi возвращает целое число, соответствующее символам строки. Если невозможно установить соответствие символов аргумента с целым числом, то функция возвращает значение 0. Например:

atoi("12345")возвращает 12345

atoi("#12345") возвращает 0, потому, что символ # не является цифрой.

Функция atoi находится в библиотеке с заголовочным файлом cstdlib, поэтому в программах в которых используется эта функция должна присутствовать директива

#include <cstdlib>

В эту библиотеку входит также функция atol, которая возвращает значение типа long. Кроме того, в библиотеку входит функция atof, которая возвращает значение типа double если строка содержит только цифры и точку. В противном случае возвращается 0.0, что говорит о том, что число не определено.

В качестве примера рассмотрим программу, с помощью которой можно из вводимых букв и цифр выделить цифры. Правда, количество цифр не должно превосходить пяти, но читатель без труда может изменить это количество, поняв суть программы. В программе используется новая библиотечная функция isdigit(char), которая возвращает значение true, если аргумент является десятичной цифрой. В противном случае возвращается false. Кроме того, используется функция cin.get(char), которая в отличие от cin читает все символы, включая пробелы и символ возврата строки '\n'. Обращаться с этой функцией следует аккуратно, т.к. применение ее два раза подряд может привести к ошибке. Например, введя в первый раз число и нажав клавишу "Enter" автоматически повлечет ввод символа '\n' с помощью второй записи функции. В силу этих причин в предлагаемом ниже примере специально применена вспомогательная функция newLine.

#include <iostream>

#include <cstdlib>

#include <cctype>

using namespace std;

void read(int& n); /* Читает строку, отбрасывая все символы кроме цифр. Преобразует строку в целое число и присваивает его переменной n. */

void newLine(); /* Отбрасывает все символы оставшиеся в текущей строке, в том числе символ \n. */

void main(){

int n;

char answer;

do {

cout<<endl<<"Input sum and click Enter"<<endl;

read(n);

cout<<"The number equal "<<n<<" is'n it?"<<endl;

cout<<"Once more? (yes/no): ";

cin>>answer;

newLine();

}while((answer !='n')||(answer !='N'));

}// конец main

//*****************************************************

void read(int& n){

char digitString[6]; //массив для формирования числа

char next;

int index=0;

cin.get(next); //вводит символ включая пробелы

while (next !='\n')

{

if ((isdigit(next))&&(index<5))

{

digitString[index]=next;

index++;

}

cin.get(next);

} //конец while

digitString[index]='\0'; // ввод символа конца строки

n=atoi(digitString); //перевод символов в число

} //конец функции read()

//------------------------------------------

// Функция ввода строки

void newLine()

{char symbol;

do

{

cin.get(symbol);

}while(symbol !='\n');

}

Вот результат