Язык программирования C++. Пятое издание - Стенли Липпман
Шрифт:
Интервал:
Закладка:
// подразумевается, что оно принадлежит пространству имен std
using std::cin;
int main() {
int i;
cin >> i; // ok: теперь cin - синоним std::cin
cout << i; // ошибка: объявления using нет; здесь нужно указать
// полное имя
std::cout << i; // ok: явно указано применение cout из
// пространства имен std
return 0;
}
Для каждого имени необходимо индивидуальное объявление usingКаждое объявление using применяется только к одному элементу пространства имен. Это позволяет жестко задавать имена, используемые в каждой программе. Например, программу из раздела 1.2 можно переписать следующим образом:
#include <iostream>
// объявления using для имен из стандартной библиотеки
using std::cin;
using std::cout;
using std::endl;
int main() {
cout << "Enter two numbers:" << endl;
int v1, v2;
cin >> v1 >> v2;
cout << "The sum of " << v1 << " and " << v2
<< " is " << v1 + v2 << endl;
return 0;
}
Объявления using для имен cin, cout и endl означают, что их можно теперь использовать без префикса std::. Напомню, что программы С++ позволяют поместить каждое объявление using в отдельную строку или объединить в одной строке несколько объявлений. Важно не забывать, что для каждого используемого имени необходимо отдельное объявление using, и каждое из них должно завершаться точкой с запятой.
Заголовки не должны содержать объявлений usingКод в заголовках (см. раздел 2.6.3) обычно не должен использовать объявления using. Дело в том, что содержимое заголовка копируется в текст программы, в которую он включен. Если в заголовке есть объявление using, то каждая включающая его программа получает то же объявление using. В результате программа, которая не намеревалась использовать определенное библиотечное имя, может случайно столкнуться с неожиданным конфликтом имен.
Примечание для читателяНачиная с этого момента подразумевается, что во все примеры включены объявления using для имен из стандартной библиотеки. Таким образом, в тексте и примерах кода далее упоминается cin, а не std::cin.
Кроме того, для экономии места в примерах кода не будем показывать далее объявления using и необходимые директивы #include. В табл. А.1 приложения А приведены имена и соответствующие заголовки стандартной библиотеки, которые использованы в этой книге.
Читатели не должны забывать добавить соответствующие объявления #include и using в свои примеры перед их компиляцией.
Упражнения раздела 3.1Упражнение 3.1. Перепишите упражнения из разделов 1.4.1 и 2.6.2, используя соответствующие объявления using.
3.2. Библиотечный тип string
Строка (string) — это последовательность символов переменной длины. Чтобы использовать тип string, необходимо включить в код заголовок string. Поскольку тип string принадлежит библиотеке, он определен в пространстве имен std. Наши примеры подразумевают наличие следующего кода:
#include <string>
using std::string;
В этом разделе описаны наиболее распространенные операции со строками; а дополнительные операции рассматриваются в разделе 9.5.
Кроме определения операций, предоставляемых библиотечными типами, стандарт налагает также требования на эффективность их конструкторов. В результате библиотечные типы оказались весьма эффективны в использовании.
3.2.1. Определение и инициализация строк
Каждый класс определяет, как могут быть инициализированы объекты его типа. Класс может определить много разных способов инициализации объектов своего типа. Каждый из способов отличается либо количеством предоставляемых инициализаторов, либо типами этих инициализаторов. Список наиболее распространенных способов инициализации строк приведен в табл. 3.1, а некоторые из примеров приведены ниже.
string s1; // инициализация по умолчанию; s1 - пустая строка
string s2 = s1; // s2 - копия s1
string s3 = "hiya"; // s3 - копия строкового литерала
string s4(10, 'c'); // s4 - cccccccccc
Инициализация строки по умолчанию (см. раздел 2.2.1) создает пустую строку; т.е. объект класса string без символов. Когда предоставляется строковый литерал (см. раздел 2.1.3), во вновь созданную строку копируются символы этого литерала, исключая завершающий нулевой символ. При предоставлении количества и символа строка содержит указанное количество экземпляров данного символа.
Таблица 3.1. Способы инициализации объекта класса string
string s1 Инициализация по умолчанию; s1 — пустая строка string s2(s1) s2 — копия s1 string s2 = s1 Эквивалент s2(s1), s2 — копия s1 string s3("value") s3 — копия строкового литерала, нулевой символ не включен string s3 = "value" Эквивалент s3("value"), s3 — копия строкового литерала string s4(n, 'c') Инициализация переменной s4 символом 'c' в количестве n штук Прямая инициализация и инициализация копиейВ разделе 2.2.1 упоминалось, что язык С++ поддерживает несколько разных форм инициализации. Давайте на примере класса string начнем изучать, чем эти формы отличаются друг от друга. Когда переменная инициализируется с использованием знака =, компилятор просят скопировать инициализирующий объект в создаваемый объект, т.е. выполнить инициализацию копией (copy initialization). В противном случае без знака = осуществляется прямая инициализация (direct initialization).
Когда имеется одиночный инициализатор, можно использовать и прямую форму, и инициализацию копией. Но при инициализации переменной несколькими значениями, как при инициализации переменной s4 выше, следует использовать прямую форму инициализации.
string s5 = "hiya"; // инициализация копией
string s6("hiya"); // прямая инициализация
string s7(10, 'c'); // прямая инициализация; s7 - сссссссссс
Если необходимо использовать несколько значений, можно применить косвенную форму инициализации копией при явном создании временного объекта для копирования.
string s8 = string(10, 'c'); // инициализация копией; s8 - сссссссссс
Инициализатор строки s8 — string(10, 'c') — создает строку заданного размера, заполненную указанным символьным значением, а затем копирует ее в строку s8. Это эквивалентно следующему коду:
string temp(10, 'c'); // temp - сссссссссс
string s8 = temp; // копировать temp в s8
Хотя используемый для инициализации строки s8 код вполне допустим, он менее читабелен и не имеет никаких преимуществ перед способом, которым была инициализирована переменная s7.
3.2.2. Операции со строками
Наряду с определением способов создания и инициализации объектов класс определяет также операции, которые можно выполнять с объектами класса. Класс может определить обладающие именем операции, такие как функция isbn() класса Sales_item (см. раздел 1.5.2). Класс также может определить то, что означают различные символы операторов, такие как << или +, когда они применяются к объектам класса. Наиболее распространенные операции класса string приведены в табл. 3.2.
Таблица 3.2. Операции класса string
os << s Выводит строку s в поток вывода os. Возвращает поток os is >> s Читает разделенную пробелами строку s из потока is. Возвращает поток is getline(is, s) Читает строку ввода из потока is в переменную s. Возвращает поток is s.empty() Возвращает значение true, если строка s пуста. В противном случае возвращает значение false s.size() Возвращает количество символов в строке s s[n] Возвращает ссылку на символ в позиции n строки s; позиции отсчитываются от 0 s1 + s2 Возвращает строку, состоящую из содержимого строк s1 и s2 s1 = s2 Заменяет символы строки s1 копией содержимого строки s2 s1 == s2 s1 != s2 Строки s1 и s2 равны, если содержат одинаковые символы. Регистр символов учитывается <, <=, >, >= Сравнение зависит от регистра и полагается на алфавитный порядок символов Чтение и запись строкКак уже упоминалось в главе 1, для чтения и записи значений встроенных типов, таких как int, double и т.д., используется библиотека iostream. Для чтения и записи строк используются те же операторы ввода и вывода.