Стенли Липпман - Язык программирования C++. Пятое издание Страница 37
- Категория: Компьютеры и Интернет / Программирование
- Автор: Стенли Липпман
- Год выпуска: -
- ISBN: -
- Издательство: -
- Страниц: 297
- Добавлено: 2019-05-29 10:29:11
Стенли Липпман - Язык программирования C++. Пятое издание краткое содержание
Прочтите описание перед тем, как прочитать онлайн книгу «Стенли Липпман - Язык программирования C++. Пятое издание» бесплатно полную версию:Лучшее руководство по программированию и справочник по языку, полностью пересмотренное и обновленное под стандарт С++11!Вы держите в руках новое издание популярного и исчерпывающего бестселлера по языку программирования С++, которое было полностью пересмотрено и обновлено под стандарт С++11. Оно поможет вам быстро изучить язык и использовать его весьма эффективными и передовыми способами. В соответствии с самыми передовыми и современными методиками изложения материала авторы демонстрируют использование базового языка и его стандартной библиотеки для разработки эффективного, читабельного и мощного кода.С самого начала этой книги читатель знакомится со стандартной библиотекой С++, ее самыми популярными функциями и средствами, что позволяет сразу же приступить к написанию полезных программ, еще не овладев всеми нюансами языка. Большинство примеров из книги было пересмотрено так, чтобы использовать новые средства языка и продемонстрировать их наилучшие способы применения. Эта книга — не только проверенное руководство для новичков в С++, она содержит также авторитетное обсуждение базовых концепций и методик языка С++ и является ценным ресурсом для опытных программистов, особенно желающих побыстрей узнать об усовершенствованиях С++11.Стенли Б. Липпман работал старшим консультантом в Jet Propulsion Laboratory, архитектором группы Visual С++ корпорации Microsoft, техническим сотрудником Bell Laboratories и главным инженером- программистом по анимации в кинокомпаниях Disney, DreamWorks, Pixar и PDI.Жози Лажойе, работающий ныне в кинокомпании Pixar, был членом канадской группы разработчиков компилятора C/C++ корпорации IBM, а также возглавлял рабочую группу базового языка С++ в составе международной организации по стандартизации ANSI/ISO.Барбара Э. Му имеет почти тридцатилетний опыт программирования. На протяжении пятнадцати лет она работала в компании AT&T, сотрудничая с Бьярне Страуструпом, автором языка С++, и несколько лет руководила группой разработчиков С++.• Узнайте, как использовать новые средства языка С++11 и стандартной библиотеки для быстрого создания надежных программ, а также ознакомьтесь с высокоуровневым программированием• Учитесь на примерах, в которых показаны передовые стили программирования и методики проектирования• Изучите принципы и узнайте почему язык С++11 работает именно так• Воспользуйтесь множеством перекрестных ссылок, способных помочь вам объединить взаимосвязанные концепции и проникнуть в суть• Ознакомьтесь с современными методиками обучения и извлеките пользу из упражнений, в которых подчеркиваются ключевые моменты, позволяющие избежать проблем• Освойте лучшие методики программирования и закрепите на практике изученный материалИсходный код примеров можно загрузить с веб-страницы книги на сайте издательства по адресу: http://www.williamspublishing.com
Стенли Липпман - Язык программирования C++. Пятое издание читать онлайн бесплатно
Доступ к элементам вектора осуществляется таким же способом, как и к символам строки: по их позиции в векторе. Например, для обработки все элементов вектора можно использовать серийный оператор for (раздел 3.2.3).
vector<int> v{1,2,3,4,5,6,7,8,9};
for (auto &i : v) // для каждого элемента вектора v
// (обратите внимание: i - ссылка)
i *= i; // квадрат значения элемента
for (auto i : v) // для каждого элемента вектора v
cout << i << " "; // вывод элемента
cout << endl;
В первом цикле управляющая переменная i определяется как ссылка, чтобы использовать ее для присвоения новых значений элементам вектора v. Используя спецификатор auto, позволим вывести ее тип автоматически. Этот цикл использует новую форму составного оператора присвоения (раздел 1.4.1). Как известно, оператор += добавляет правый операнд к левому и сохраняет результат в левом операнде. Оператор *= ведет себя точно так же, но перемножает левый и правый операнды, сохраняя результат в левом операнде. Второй серийный оператор for отображает каждый элемент.
Функции-члены empty() и size() вектора ведут себя так же, как и соответствующие функции класса string (раздел 3.2.2): функция empty() возвращает логическое значение, указывающее, содержит ли вектор какие-нибудь элементы, а функция size() возвращает их количество. Функция-член size() возвращает значение типа size_type, определенное соответствующим типом шаблона vector.
Чтобы использовать тип size_type, необходимо указать тип, для которого он определен. Для типа vector всегда необходимо указывать тип хранимого элемента (раздел 3.3).
vector<int>::size_type // ok
vector::size_type // ошибка
Операторы равенства и сравнения вектора ведут себя как соответствующие операторы класса string (раздел 3.2.2). Два вектора равны, если у них одинаковое количество элементов и значения соответствующих элементов совпадают. Операторы сравнения полагаются на алфавитный порядок: если у векторов разные размеры, но соответствующие элементы равны, то вектор с меньшим количеством элементов меньше вектора с большим количеством элементов. Если у элементов векторов разные значения, то их отношения определяются по первым отличающимся элементам.
Сравнить два вектора можно только в том случае, если возможно сравнить элементы этих векторов. Некоторые классы, такие как string, определяют смысл операторов равенства и сравнения. Другие, такие как класс Sales_item, этого не делают. Операции, поддерживаемые классом Sales_item, перечислены в разделе 1.5.1. Они не включают ни операторов равенства, ни сравнения. В результате нельзя сравнить два вектора объектов класса Sales_item.
Вычисление индекса вектораИспользуя оператор индексирования (раздел 3.2.3), можно выбрать указанный элемент. Подобно строкам, индексирование вектора начинаются с 0; индекс имеет тип size_type соответствующего типа; и если вектор не константен, то в возвращенный оператором индексирования элемент можно осуществить запись. Кроме того, как было продемонстрировано в разделе 3.2.3, можно вычислить индекс и непосредственно обратиться к элементу в данной позиции.
Предположим, имеется набор оценок степеней в диапазоне от 0 до 100. Необходимо рассчитать, сколько оценок попадает в кластер по 10. Между нулем и 100 возможна 101 оценка. Эти оценки могут быть представлены 11 кластерами: 10 кластеров по 10 оценок каждый плюс один кластер для наивысшей оценки 100. Первый кластер подсчитывает оценки от 0 до 9, второй — от 10 до 19 и т.д. Заключительный кластер подсчитывает количество оценок 100.
Таким образом, если введены следующие оценки:
42 65 95 100 39 67 95 76 88 76 83 92 76 93
результат их кластеризации должен быть таким:
0 0 0 1 1 0 2 3 2 4 1
Он означает, что не было никаких оценок ниже 30, одна оценка в 30-х, одна в 40-х, ни одной в 50-х, две в 60-х, три в 70-х, две в 80-х, четыре в 90-х и одна оценка 100.
Используем для содержания счетчиков каждого кластера вектор с 11 элементами. Индекс кластера для данной оценки можно определить делением этой оценки на 10. При делении двух целых чисел получается целое число, дробная часть которого усекается. Например, 42/10=4, 65/10=6, а 100/10=10.
Как только индекс кластера будет вычислен, его можно использовать для индексирования вектора и доступа к счетчику, значение которого необходимо увеличить.
// подсчет количества оценок в кластере по десять: 0--9,
// 10--19, ... 90--99, 100
vector<unsigned> scores(11, 0); // 11 ячеек, все со значением 0
unsigned grade;
while (cin >> grade) { // читать оценки
if (grade <= 100) // обрабатывать только допустимые оценки
++scores[grade/10]; // приращение счетчика текущего кластера
Код начинается с определения вектора для хранения счетчиков кластеров. В данном случае все элементы должны иметь одинаковое значение, поэтому резервируем 11 элементов, каждый из которых инициализируем значением 0. Условие цикла while читает оценки. В цикле проверяется допустимость значения прочитанной оценки (т.е. оно меньше или равно 100). Если оценка допустима, то увеличиваем соответствующий счетчик.
Оператор, осуществляющий приращение, является хорошим примером краткости кода С++:
++scores[grade/10]; // приращение счетчика текущего кластера
Это выражение эквивалентно следующему:
auto ind = grade/10; // получить индекс ячейки
scores[ind] = scores[ind] + 1; // приращение счетчика
Индекс ячейки вычисляется делением значения переменной grade на 10. Полученный результат используется для индексирования вектора scores, что обеспечивает доступ к соответствующему счетчику для этой оценки. Увеличение значения этого элемента означает принадлежность текущей оценки данному диапазону.
Как уже упоминалось, при использовании индексирования следует позаботиться о том, чтобы индексы оставались в диапазоне допустимых значений (см. раздел 3.2.3). В этой программе проверка допустимости подразумевает принадлежность оценки к диапазону 0-100. Таким образом, можно использовать индексы от 0 до 10. Они расположены в пределах от 0 до scores.size() - 1.
Индексация не добавляет элементовНовички в С++ иногда полагают, что индексирование вектора позволяет добавлять в него элементы, но это не так. Следующий код намеревается добавить десять элементов в вектор ivec:
vector<int> ivec; // пустой вектор
for (decltype(ivec.size()) ix = 0; ix != 10; ++ix)
ivec[ix] = ix; // катастрофа: ivec не имеет элементов
Причина ошибки — вектор ivec пуст; в нем нет никаких элементов для индексирования! Как уже упоминалось, правильный цикл использовал бы функцию push_back():
for (decltype(ivec.size()) ix = 0; ix != 10; ++ix)
ivec.push_back(ix); // ok: добавляет новый элемент со значением ix
Оператор индексирования вектора (и строки) лишь выбирает существующий элемент; он не может добавить новый элемент.
Внимание! Индексировать можно лишь существующие элементы!Очень важно понять, что оператор индексирования ([]) можно использовать для доступа только к фактически существующим элементам. Рассмотрим пример.
vector<int> ivec; // пустой вектор
cout << ivec[0]; // ошибка: ivec не имеет элементов!
vector<int> ivec2(10); // вектор из 10 элементов
cout << ivec2[10]; // ошибка: ivec2 имеет элементы 0...9
Попытка обращения к несуществующему элементу является серьезной ошибкой, которую вряд ли обнаружит компилятор. В результате будет получено случайное значение.
Попытка индексирования несуществующих элементов, к сожалению, является весьма распространенной и грубой ошибкой программирования. Так называемая ошибка переполнения буфера (buffer overflow) — результат индексирования несуществующих элементов. Такие ошибки являются наиболее распространенной причиной проблем защиты приложений.
Наилучший способ гарантировать невыход индекса из диапазона — это избежать индексации вообще. Для этого везде, где только возможно, следует использовать серийный оператор for.
Упражнения раздела 3.3.3Упражнение 3.16. Напишите программу, выводящую размер и содержимое вектора из упражнения 3.13. Проверьте правильность своих ответов на это упражнение. При неправильных ответах повторно изучите раздел 3.3.1.
Жалоба
Напишите нам, и мы в срочном порядке примем меры.