ТОП 10:

Строковый тип или стандартный класс string



Язык С++ включает в себя стандартный класс, называемый string. Этот класс во многом улучшает традиционный строковый тип char[], поскольку он более эффективен и безопасен в использовании. Например, не нужно заботиться о создании массива нужного размера для содержания строковых переменных. Тип данных string берет на себя всю ответственность за управление памятью. Он позволяет изменять строку динамически в соответствии с потребностями. Основные действия со строками выполняются в нём с помощью операций и методов. Для использования типа string необходимо подключить заголовочный файл <string> или (если vcl.h) <cstring.h>. Строка типа string не имеет и не содержит нуль-символа.

Для объектов типа string разрешены следующие операции: =, +, ==, !=, <, <=, >, >=, [], <<, >>, +=.

Рассмотрим пример:

#include <string>

int main() {

string s1, s2("sotrudnik"), s3;

s1 = "Privet";

cout << "\n Vvedite imya: "; cin >> s3;

s1 = s1+ " " + s2 + " " + s3; // или cout << s1 + " " + s2 + " " + s3;

cout << s1;

getch(); return 0;

}

Данный пример показывает способы инициализации объектов типа string, а так же использование операций присваивания и конкатенации. Ввод и вывод для объектов класса string осуществляется путём, схожим с применяемым для строкового типа. Операции << и >> перегружены для использования с объектами типа string и работают так же как с char. Таким образом, если потребуется считывать строку, имеющую пробелы, то необходимо пользоваться методом getline(). Рассмотрим пример: //если в строке предполагаются пробелы

int main() {

string fio, address;

cout << "Vvedite FIO: "; getline(cin, fio);

cout << "Vashe FIO: " << fio;

cout << "\nVvedite vash adress v neskolko strok:\n";

getline(cin, address, '$');

cout << "Vash adress: " << address << endl;

getch(); return 0;

}

Метод getline (); позволяет считать полное имя, которое возможно содержит внутренние пробелы. Первым аргументом этого метода является потоковый объект, из которого будет приниматься ввод (cin), а вторым аргументом - объект типа string, куда будет помещён текст. Если функция не имеет третьего аргумента, то предполагается, что завершающим символом строки будет '\n', представляющий клавишу Enter (вернее переход на следующую строку).

Имеются различные методы для поиска строк и фрагментов строк в объектах класса string:

– find() – для поиска строки, переданной в качестве аргумента, в строке для которой был вызван метод. Если поиск удачен, то возвращает номер позиции, с которой начинается найденная строка, иначе возвращает -1, например:

string s1, s2; //пример 1

s1 = "Privet mir";

s2 = "mir";

int p = s1.find(s2);

cout << p; // строка s2 начинается в строке s1 c 7 позиции

 

string s1, s2; //пример 2

s1 = "Privet miru";

s2 = "miro";

int p=s1.find(s2, 5); //искать с пятого символа

if(p < 0 ) cout << "s2 v s1 ne naidena";

else cout << p;

 

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

string s1;

s1 = "Privet miru";

int p=s1.find_first_of("abvgde", 0); //поиск серии с нулевой позиции

if(p<0)

cout << "Bukvy a, b, v, g, d, e ne naideny!";

else

cout << p; // âûâåäåò 3, òàê êàê s1[3]=='v'

 

– find_first_not_of() ищет первый символ в строке, который не входит в определённую группу символов и возвращает его позицию;

– и т.д. ...

Имейте ввиду, что для каждой функции существует вариант, позволяющий исакть в заданной строке подстроки типа char.

Существуют различные способы модификации объектов класса string, с помощью следующих наиболее часто используемых методов:

– erase(позиция первого символа фрагмента, длина фрагмента) удаляет фрагмент из строки, например:

string s1;

s1 = "Privet mir";

s1.erase(1, 7);

cout << s1; //óâèäèì Pir

– replace(позиция начала замены , кол-во символов исх. строки, которое должно быть заменено , строка для замены) заменяет часть строки на другую строку, например:

s1 = "Privet mir";

s1.replace(1, 5, "oka");

cout << s1; // óâèäèì Poka mir

– insert() вставляет строку, определённую во втором аргументе, на место, определённое в первом аргументе, например:

string s1;

s1 = "Privet mir";

s1.insert(6, "ik");

cout << s1; //óâèäèì Privetik mir

– size() и length() возвращают количество символов в объекте класса string;

– clear() очищает (обнуляет) строку, например:

s1 = "Privet mir";

s1.clear();

cout << s1.length(); //увидим 0

– append(кол-во символов, которое будет добавлено в конец , символы, которые будут добавлены) эквивалентна +.

Для сравнения объектов класса string обычно используют перегруженные операции (==, <, …) или следующие методы:

– compare(начальная позиция, число символов, которые надо сравнить , строка используемая для сравнения , начальная позиция , количество символов) сравнивает символы одной строки с другой строкой;

– substr(позиция фрагмента , кол-во символов) возвращает фрагмент строки, для которой этот метод был вызван.

Для доступа к символам в объектах класса string можно использовать классическую запись s[i]. Для приведения объекта типа string к строковой переменной типа char имеется функция c_str(), добавляющая в конец строки нуль символ. Рассмотрим пример преобразования из string в char:

string s1;

s1 = "Privet mir";

int N = s1.length();

char* s2 = new char [N];

strncpy(s2, s1.c_str(), N); // или for(int i=0; i<N; i++) s2[i]=s1[i];

cout << s2;

Выделенный жирным шрифтом текст можно заменить одним оператором:

const char *s2 = s1.c_str(); //обязательно const преобразовывает из строки в char

 

Кроме рассмотренных нами методов класса string существует множество других, с которыми вы должны ознакомиться самостоятельно.

 

Тип строк AnsiString – строки с 0 символом в конце. Индексация начинается не с 0 , а с 1.

В С++Builder многие компоненты работают с типом строк AnsiString, объявленным в заголовочном файле vcl.h. Это строки с нулевым символом в конце. При объявлении переменные типа AnsiString инициализируются пустыми строками. Для AnsiString определены операции отношения ==, !=, >, <, >=, <= и операции +, =, +=. Сравнение происходит с учётом регистра. Определена также операция индексации []. Индексы начинаются с 1.

Тип AnsiString не рекомендуется использовать в консольных приложениях, поскольку он не перегружен для операций cin >> и cout <<(т.е лучше использовать стринг в консольных). Он предназначен для визуального программирования. У этого типа имеются такие же методы как и у класса string (только пишутся с большой буквы). Перечислим основные методы класса AnsiString:

– Insert(…str, int…) вставляет в вызывающую строку подстроку str на место, начинающиеся с индекса, указанного во втором аргументе;

– Length() возвращают количество символов в строке;

– AnsiCompare(str) сравнивает символы вызывающей строки со строкой, указанной в качестве аргумента. Возвращает 0 при равенстве строк;

– AnsiCompareIC(str) осуществляет сравнение без учёта регистра;

– AnsiPos(str) возвращает индекс первого символа первого вхождения подстроки str в вызывающей строке. Возвращает 0 при неудаче.

– substr(позиция фрагмента , кол-во символов) возвращает фрагмент строки, для которой этот метод был вызван;

– Delete(int, int) удаляет из вызывающей строки число символов, указанное во втором параметре, начиная с позиции, указанной в первом параметре;

– SubString(int , int ) возвращает подстроку, начинающуюся с символа в позиции, указанной в первом аргументе, и содержащую количество символов, указанное во втором аргументе.

Преобразование строки AnsiString в строку типа char осуществляется с помощью функции c_str(), например:

AnsiString s1;

s1 = "Privet mir";

char *s2 = s1.c_str();

cout << s2;

Обратное преобразование выполняется с помощью функции AnsiString(char *s).

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

 

Лекция 6(10,5 стр.)

Перегрузка операций

 

Перегрузка операций – это одна из самых интересных возможностей ООП. Использование перегрузки операций может превратить сложный и малопонятный текст программы в интуитивно понятный. Например, не очень понятная строка d3=d1.plus(d2) может быть заменена на более читаемую и привычную d3=d1+d2 с помощью перегрузки операций. Такие операции, как +, -, *, /, <=, += и т.п., обычно работают только с основными типами данных. Для использования этих операций с определёнными программистом типами данных необходимо применять перегрузку.

Любая операция, определённая в С++ (за исключением :: , ?: , . , .* , #), может быть перегружена для созданного вами класса. Это делается с помощью операторных функций специального вида:

возвращаемый_тип operator знак_перегружаемой_операции (список параметров) { тело функции } . (см. «ВОТ»)

Если операторная функция реализована как функция класса, то количество параметров у этой функции на единицу меньше, так как первым операндом при этом считается сам объект, вызвавший данную операцию !!!

Перегрузка подчиняется следующим правилам:

· при перегрузке операций сохраняется количество аргументов, приоритеты операций и правила ассоциации, используемые в стандартных типах данных;

· для стандартных типов данных переопределять операции нельзя;

· операторные функции не могут иметь аргументов по умолчанию;

· операторные функции наследуются (за исключением =);

· операторные функции не могут определяться как static.

Рассмотрим пример перегрузки унарных операций. Создадим класс для хранения значения счётчика.

class Count {

private:

unsigned int c; // çíà÷åíèå ñ÷åò÷èêà

public:

Count() { c = 0; } // êîíñòðóêòîð

unsigned int get() { // ìåòîä: ïîëó÷èòü çíà÷åíèå

return c;

}

void operator++() { // «ВОТ»

++c;

}

};

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

int main( ) {

Count c1, c2; // два объекта

cout << "\nc1 = " << c1.get(); // âûâîäèì íà ýêðàí (ñ1=0)

cout << "\nc2 = " << c2.get(); // âûâîäèì íà ýêðàí (ñ2=0)

 

++c1; // метод ++ вызывается для с1

++c2; ++c2; // óâåëè÷èâàåì c2

 

cout << "\nc1 = " << c1.get(); // ñíîâà ïîêàçûâàåì çíà÷åíèÿ (ñ1=1)

cout << "\nc2 = " << c2.get() << endl; // ñ2=2

getch(); return 0;

}

В данной программе в методе, увеличивающем значение объекта, использовано ключевое слово operator для перегрузки операции ++. В этом методе сначала указывается возвращаемый тип, затем ключевое слово operator, за которым стоит операция, которую мы перегружаем, а затем (список аргументов). Такой синтаксис говорит компилятору о том, что если операнд принадлежит классу Count, то нужно вызывать функцию с таким именем тогда, когда в программе встретится операция ++. Перегруженные операции компилятор отличает по типу данных их операндов. Это означает, что если в программе используется какая то переменная целого типа (int var; ++var;), то для её инкрементирования компилятор использует встроенную процедуру увеличения, а если унарная операция увеличения применяется к объекту, то компилятор вызовет функцию программиста.

Обратите внимание на то, что в методе void operator++( ) нет аргументов в связи с тем, что методы класса всегда имеют доступ к объектам класса, для которых они были вызваны.

Вопрос:

Как надо изменить метод void operator++( ), чтобы появилась возможность использовать строку с1=++с2 ?

Count operator++() { //новый метод вместо войд

++c; Count temp; temp.c=c; //временная переменная

return temp;

}

};

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

int main( ) {

Count c1, c2;

++c1;

++c2; ++c2;

c1 = ++c2; //эту строчку добавили

cout << "\nc1 = " << c1.get(); // ñ1=3

cout << "\nc2 = " << c2.get() << endl; // ñ2=3

getch(); return 0;

}

Здесь мы создаём новый временный объект класса для использования его в качестве возвращаемого значения. В данном методе единственной целью объекта temp является хранение возвращаемого значения для операции ++.

Рассмотрим 2-ой вариант решения этой задачи:

Count(int t) { c = t; }

Count operator++() { // метод: увеличить значение

++c;

return Count(c); // или return c;

}

};

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

int main( ) {

}

Здесь, в строке return Count(c); происходят все те же действия, которые в предыдущем варианте занимали три строки. Здесь создаётся объект типа Count, который не имеет имени и инициализируется значением, полученным в виде параметра c. Чтобы этот метод работал, мы создали дополнительно конструктор с одним аргументом, способствующий возвращению функцией объекта, инициализированного значением c.

Рассмотрим пример перегрузки постфиксной записи, где переменная увеличивается после того, как её значение было использовано в выражении. Определим два варианта перегрузки операции ++.

class Count {

Count operator++() {

++c;

return Count(c); // èëè return c;

}

Count operator++(int) {

c++;

return Count(c); // èëè return c;

}

};

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

int main( ) {

Count c1, c2, c3;

++c1;

++c2; ++c2;

c1 = ++c2;

c3++;

cout << "\nc1 = " << c1.get(); // ñ1=3

cout << "\nc2 = " << c2.get() << endl; // ñ2=3

cout << "\nc3 = " << c3.get() << endl; // ñ3=1

getch(); return 0;

}

Для реализации постфиксной записи операции ++ используется функция Count operator++(int), в которой int не играет роли аргумента и не означает целое число. Это просто сигнал для компилятора, чтобы использовалась постфиксная версия операции инкрементирования.

 







Последнее изменение этой страницы: 2016-04-08; Нарушение авторского права страницы

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.231.167.166 (0.019 с.)