Использование типов vector и string
В качестве первого введения в стандартную библиотеку С++ рассмотрим востребованные на практике способы обработки массивов и строк с использованием типов vector и string. В данном разделе мы не ставим целью дать строгое определение таких понятий как классы, методы классов, шаблоны, итераторы и т.д. Вся эта проблематика будет изложена подробно в следующих разделах пособия. Но понять и оценить возможности стандартной библиотеки С++ при работе с массивами и строками можно уже и на этом этапе обучения.
Сначала дадим краткое введение в терминологию, чтобы в дальнейшем называть все понятия своими именами.
Класс – сложный тип данных, определяемый пользователем (разработчиком программы или библиотеки). Элементами класса как сложного типа данных являются переменные и функции. Функции, определённые внутри класса, называются методами класса, а переменные – полями. К методам класса обычно обращаются, используя составное имя:
Имя переменной класса. Имя метода
Шаблонный класс в С++ (его называют также параметризованным типом) служит основой для создания множества классов, которые отличаются только типом своих элементов.
Шаблонный класс vector
Шаблонный класс vector является шаблоном для формирования векторов с конкретными типами элементов. Синтаксис описания рассмотрим на примерах:
vector<int> x; // объявили вектор без указания размеров
vector<int> y(10);// вектор из 10 элементов, инициализированных нулями
vector<int> z(y); // вектор z – копия y
vector<int> z=y; // то же самое: вектор z – копия y
Работать с вектором можно так же, как с обычным массивом, т.е. доступ к элементам осуществляется по их индексам с использованием квадратных скобок. Несколько методов могут оказаться полезными.
push_back(значение) – помещает заданное значение в конец вектора
pop_back() – удаляет последний элемент из вектора
size() – возвращает размер вектора
empty() – проверяет вектор на пустоту
clear() – очищает вектор
begin() – возвращает указатель на начало вектора
end() – возвращает указатель на элемент, следующий за последним.
Если использовать метод push_back для заполнения вектора, то никаких проблем с памятью вообще не возникнет – она будет выделяться автоматически по мере необходимости.
В следующем примере вектор заполняется случайными числами с помощью функции random_shuffle, которая выполняет случайное перемешивание последовательности натуральных чисел 1,2,…,n. Затем выполняется сортировка при помощи стандартной функции sort.
// Пример 1.12 – демонстрация шаблонного типа vector
#include <iostream>
#include <vector> // содержит шаблон vector
#include <algorithm> //алгоритмы случ.перемешивания и сортировки
using namespace std;
int main() {
vector<int> v;
int n,i;
cout<<"n=?"; cin>>n;
for (i=0;i<n;i++) {
v.push_back(i+1);// заполнение числами 1,2,3,...,n
cout<<v[i];//к элементам вектора можно обращаться по индексу
} cout<<endl;
// случайное перемешивание
random_shuffle(v.begin(), v.end());
for (i=0;i<v.size();i++) cout<<v[i]; cout<<endl;
// а теперь - сортировка
sort(v.begin(), v.end());
for (i=0;i<v.size();i++) cout<<v[i]; cout<<endl;
system("pause"); return 0;
}
Класс string
Обрабатывать строки, используя класс string, пожалуй, проще и удобнее, чем использовать встроенные строки с завершающим нулём.
Для ввода переменных этого типа можно использовать функцию getline.
getline(cin, s);
Здесь s — имя вводимой переменной типа string.
При описании переменной типа string можно сразу её инициализировать.
Например: string v("Hello");
Доступ к элементам строки типа string осуществляется стандартным образом через индекс. Над строками типа string определены следующие операции:
· присваивания, например s1=s2;
· объединения строк (s1+=s2 или s1=s1+s2) — добавляет к строке s1 строку s2, результат сохранится в строке s1;
· сравнения строк на основе лексикографического порядка: s1=s2, s1!=s2, s1<s2, s1>s2, s1<=s2, s1>=s2 — результатом будет логическое значение;
При обработке строк типа string можно использовать следующие методы (методов у класса string много, поэтому здесь представлены, на наш взгляд, используемые наиболее часто). Пусть s–произвольная строка, тогда к каждому из методов обращаемся так:
s.имя_метода(параметры,_если_есть).
· substr(pos, length) — возвращает подстроку из строки s, начиная с позиции pos длиной length символов;
· empty() — возвращает значение true, если строка s пуста, false — в противном случае;
· size(), length() – количество символов в строке (длина строки);
· insert(pos, s1) — вставляет строку s1 в строку s, начиная с позиции pos;
· erase(pos, length) — удаляет из строки s подстроку длиной length символов, начиная с позиции pos ;
· find(s1, pos) — возвращает номер первого вхождения строки s1 в строку s, поиск начинается с номера pos, параметр pos может отсутствовать , в этом случае поиск идет с начала строки;
В качестве примера приведём последний (четвёртый!) вариант удаления пробелов из строки (примеры 1.7,1.8, 1.10). По лаконичности и наглядности текста, этот вариант, пожалуй, самый лучший. Но по эффективности безусловный лидер – вариант 1.8, в котором реализован собственный алгоритм обработки строки как массива символов.
//Пример 1.13 – удаление из строки пробелов
// с использованием типа string и его методов
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s; int n=0;
cout<<"?"; getline(cin, s);
while ((n=s.find(" "))>=0) s.erase(n,1);
cout << s << endl;
system("pause"); return 0;
}