C++ для начинающих - Липпман 3 стр.


Прочитано слово: and

Прочитано слово: Adam's

Все слова прочитаны!

(В главе 6 мы рассмотрим вопрос о том, как убрать знаки препинания из вводимых слов.)

1.5.1. Файловый ввод/вывод

Библиотека iostream поддерживает и файловый ввод/вывод. Все операции, применимые в стандартному вводу и выводу, могут быть также применены к файлам. Чтобы использовать файл для ввода или вывода, мы должны включить еще один заголовочный файл:

#include fstream

Перед тем как открыть файл для вывода, необходимо объявить объект типа ofstream:

ofstream outfile("name-of-file");

Проверить, удалось ли нам открыть файл, можно следующим образом:

if ( ! outfile ) // false, если файл не открыт

cerr "Ошибка открытия файла.\n"

Так же открывается файл и для ввода, только он имеет тип ifstream:

ifstream infile("name-of-file");

if ( ! infile ) // false, если файл не открыт

cerr "Ошибка открытия файла.\n"

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

#include iostream

#include fstream

#include string

int main()

{

ifstream infile("in_file");

ofstream outfile("out_file");

if ( ! infile ) {

cerr "Ошибка открытия входного файла.\n";

return -1;

}

if ( ! outfile ) {

cerr "Ошибка открытия выходного файла.\n";

return -2;

}

string word;

while ( infile word )

outfile word ' ';

return 0;

}

В главе 20 библиотека ввода/вывода будет рассмотрена подробно. А в следующих разделах мы увидим, как можно создавать новые типы данных, используя механизм классов и шаблонов.

2014-04-07 23:08:15 Андрей

Клас дякую все зрозумыло ы легко запам`ятовується

2014-01-06 16:23:31 adil

thank you спасибо тебе хорошая статья думаю что все сдесь понятно с++ это самая стандартный Язык программирование спасибо за статию

2014-01-05 20:54:54 Djo

Зачётная глава! Решил c php перейти на c++. Всё понятно и без флуда.

2013-10-31 19:48:46 Дима

Почему в двух последних программах нет строчки namespace std;????? Я, как начинающий, никогда бы не понял как написать эти программы, если бы не пользовался другими источниками.

2012-09-05 09:19:51 Вася

Вот http://www.microsoft.com/ru-ru/download/details.aspx?id=12187 Или вот вебинсталлер http://download.microsoft.com/download/4/0/6/4067968E-5530-4A08-B8EC-17D2B3F02C35/vs_ultimateweb.exe

2012-09-04 18:28:41 Daulet

Кто-нибудь подскажите где можно скачать Microsoft Visual c++?

2012-08-29 10:51:01 Noisee

Спасибо за описание. Уважаемый автор, дополните примеры строкой using namespace std; Без этого собираться не будет.. Влад, поставь себе виртуалбокс, установи туда линукс (к примеру дебиан 6.05 - на данный момент последний). Потом погугли "c++ helloworld linux" и "с++ makefile". Думаю многие вопросы сами собой отпадут, когда сделаешь это. Удачи!

2012-07-19 01:21:35 Мишуил

Грамотно написано. Очень приятно, что есть еще хорошие статьи и авторы. Все доходчиво и понятно. 5+

2012-07-19 01:19:03 Мишуил

Влад, это не для тебя. Не заморачивайся этой тупой фигнёй - иди лучше дом2 посмотри.

2012-07-10 16:33:42 влад

я нихера не понял...и потскажите с++ надо скачивать иль он уже есть и если есть то как его найти и запустить

2012-06-17 14:05:38 RUSLAN

Какие книги предлогаете для начинающих? Иногда у меня не хватает логики для решении задач. Чтобы понимать и логику развивать в этой программирвание что надо делать?

2012-05-29 23:09:10 Иван

Как написать программу для поиска телефонных номеров на странице интернет версии газеты Aviso и других?У меня есть Exel файл с номерами,которые нужно исключить(выделить).

2012-03-11 18:28:36 Стёпа

Всё ништяк, хороший учебник ! мне понравился всё работает (если чтото-когдато не понимаешь погугли)

2012-02-29 10:31:39 Владимир

Хорошая статья Народ,у кого все получается и все примеры работают выложите пжлста проги которыми сами пользуетесь

2012-02-15 08:54:21 Павел

К сожалению, у меня почему-то не работает пример простой законченной программы из пункта 1.5. При пошаговой отладке выяснилось, что программа зацикливается в цикле while. После полного прочтения строки она заново предлагает ввести строку, а не выводит сообщение, что все слова прочитаны. Использую Visual C++ 2008 Express edition

2012-01-11 22:25:59 Артур

Чётко но пока поучу еще php

2011-11-08 10:36:18 Николай

Дмитрий, после подключения include объявите стандартное пространство имён: using namespace std;

2011-10-19 15:37:14 Дмитрий

у меня visual C++ express edition, не работает cout пишет не обьявленный идентификатор, iostream был подключен

2011-10-18 03:34:20 ииисус

почему после инклудов нет using namespace std; ? qt, например, ругается при определении string

2011-09-28 18:36:04 Дмитриц

В последней программе две ошибки. Строки, в которых используется cerr не закрыты, не стоит ";".

2. Краткий обзор С++

Эту главу мы начнем с рассмотрения встроенного в язык С++ типа данных "массив". Массив – это набор данных одного типа, например массив целых чисел или массив строк. Мы рассмотрим недостатки, присущие встроенному массиву, и напишем для его представления свой класс Array, где попытаемся избавиться от этих недостатков. Затем мы построим целую иерархию подклассов, основываясь на нашем базовом классе Array. В конце концов мы сравним наш класс Array с классом vector из стандартной библиотеки С++, реализующим аналогичную функциональность. В процессе создания этих классов мы коснемся таких свойств С++, как шаблоны, пространства имен и обработка ошибок.

2.1. Встроенный тип данных "массив"

Как было показано в главе 1, С++ предоставляет встроенную поддержку для основных типов данных – целых и вещественных чисел, логических значений и символов:

// объявление целого объекта ival

// ival инициализируется значением 1024

int ival = 1024;

// объявление вещественного объекта двойной точности dval

// dval инициализируется значением 3.14159

double dval = 3.14159;

// объявление вещественного объекта одинарной точности fval

// fval инициализируется значением 3.14159

float fval = 3.14159;

К числовым типам данных могут применяться встроенные арифметические и логические операции: объекты числового типа можно складывать, вычитать, умножать, делить и т.д.

int ival2 = ival1 + 4096; // сложение

int ival3 = ival2 - ival; // вычитание

dval = fval * ival; // умножение

ival = ival3 / 2; // деление

bool result = ival2 == ival3; // сравнение на равенство

result = ival2 + ival != ival3; // сравнение на неравенство

result = fval + ival2 dval; // сравнение на меньше

result = ival ival2; // сравнение на больше

В дополнение к встроенным типам стандартная библиотека С++ предоставляет поддержку для расширенного набора типов, таких, как строка и комплексное число. (Мы отложим рассмотрение класса vector из стандартной библиотеки до раздела 2.7.)

Промежуточное положение между встроенными типами данных и типами данных из стандартной библиотеки занимают составные типы – массивы и указатели. (Указатели рассмотрены в разделе 2.2.)

Массив – это упорядоченный набор элементов одного типа. Например, последовательность

0 1 1 2 3 5 8 13 21

представляет собой первые 9 элементов последовательности Фибоначчи. (Выбрав начальные два числа, вычисляем каждый из следующих элементов как сумму двух предыдущих.)

Для того чтобы объявить массив и проинициализировать его данными элементами, мы должны написать следующую инструкцию С++:

int fibon[9] = { 0, 1, 1, 2, 3, 5, 8, 13, 21 };

Здесь fibon – это имя массива. Элементы массива имеют тип int, размер (длина) массива равна 9. Значение первого элемента – 0, последнего – 21. Для работы с массивом мы индексируем (нумеруем) его элементы, а доступ к ним осуществляется с помощью операции взятия индекса. Казалось бы, для обращения к первому элементу массива естественно написать:

int first_elem = fibon[1];

Однако это не совсем правильно: в С++ (как и в С) индексация массивов начинается с 0, поэтому элемент с индексом 1 на самом деле является вторым элементом массива, а индекс первого равен 0.Таким образом, чтобы обратиться к последнему элементу массива, мы должны вычесть единицу из размера массива:

fibon[0]; // первый элемент

fibon[1]; // второй элемент

...

fibon[8]; // последний элемент

fibon[9]; // ... ошибка

Девять элементов массива fibon имеют индексы от 0 до 8. Употребление вместо этого индексов 1-9 является одной из самых распространенных ошибок начинающих программистов на С++.

Для перебора элементов массива обычно употребляют инструкцию цикла. Вот пример программы, которая инициализирует массив из десяти элементов числами от 0 до 9 и затем печатает их в обратном порядке:

int main()

{

int ia[10];

int index;

for (index=0; index10; ++index)

// ia[0] = 0, ia[1] = 1 и т.д.

ia[index] = index;

for (index=9; index=0; --index)

cout ia[index] " ";

cout endl;

}

Оба цикла выполняются по 10 раз. Все управление циклом for осуществляется инструкциями в круглых скобках за ключевым словом for. Первая присваивает начальное значение переменной index. Это производится один раз перед началом цикла:

index = 0;

Вторая инструкция:

index 10;

представляет собой условие окончания цикла. Оно проверяется в самом начале каждой итерации цикла. Если результатом этой инструкции является true, то выполнение цикла продолжается; если же результатом является false, цикл заканчивается. В нашем примере цикл продолжается до тех пор, пока значение переменной index меньше 10. На каждой итерации цикла выполняется некоторая инструкция или группа инструкций, составляющих тело цикла. В нашем случае это инструкция

ia[index] = index;

Третья управляющая инструкция цикла

++index

выполняется в конце каждой итерации, по завершении тела цикла. В нашем примере это увеличение переменной index на единицу. Мы могли бы записать то же действие как

index = index + 1

но С++ дает возможность использовать более короткую (и более наглядную) форму записи. Этой инструкцией завершается итерация цикла. Описанные действия повторяются до тех пор, пока условие цикла не станет ложным.

Вторая инструкция for в нашем примере печатает элементы массива. Она отличается от первой только тем, что в ней переменная index уменьшается от 9 до 0. (Подробнее инструкция for рассматривается в главе 5.)

Несмотря на то, что в С++ встроена поддержка для типа данных "массив", она весьма ограничена. Фактически мы имеем лишь возможность доступа к отдельным элементам массива. С++ не поддерживает абстракцию массива, не существует операций над массивами в целом, таких, например, как присвоение одного массива другому или сравнение двух массивов на равенство, и даже такой простой, на первый взгляд, операции, как получение размера массива. Мы не можем скопировать один массив в другой, используя простой оператор присваивания:

int array0[10]; array1[10];

...

array0 = array1; // ошибка

Вместо этого мы должны программировать такую операцию с помощью цикла:

for (int index=0; index10; ++index)

array0[index] = array1[index];

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

Упражнение 2.1

Как вы думаете, почему для встроенных массивов не поддерживается операция присваивания? Какая информация нужна для того, чтобы поддержать эту операцию?

Упражнение 2.2

Какие операции должен поддерживать "полноценный" массив?

2.2. Динамическое выделение памяти и указатели

Прежде чем углубиться в объектно-ориентированную разработку, нам придется сделать небольшое отступление о работе с памятью в программе на С++. Мы не сможем написать сколько-нибудь сложную программу, не умея выделять память во время выполнения и обращаться к ней.

В С++ объекты могут быть размещены либо статически – во время компиляции, либо динамически – во время выполнения программы, путем вызова функций из стандартной библиотеки. Основная разница в использовании этих методов – в их эффективности и гибкости. Статическое размещение более эффективно, так как выделение памяти происходит до выполнения программы, однако оно гораздо менее гибко, потому что мы должны заранее знать тип и размер размещаемого объекта. К примеру, совсем не просто разместить содержимое некоторого текстового файла в статическом массиве строк: нам нужно заранее знать его размер. Задачи, в которых нужно хранить и обрабатывать заранее неизвестное число элементов, обычно требуют динамического выделения памяти.

До сих пор во всех наших примерах использовалось статическое выделение памяти. Скажем, определение переменной ival

int ival = 1024;

заставляет компилятор выделить в памяти область, достаточную для хранения переменной типа int, связать с этой областью имя ival и поместить туда значение 1024. Все это делается на этапе компиляции, до выполнения программы.

С объектом ival ассоциируются две величины: собственно значение переменной, 1024 в данном случае, и адрес той области памяти, где хранится это значение. Мы можем обращаться к любой из этих двух величин. Когда мы пишем:

int ival2 = ival + 1;

то обращаемся к значению, содержащемуся в переменной ival: прибавляем к нему 1 и инициализируем переменную ival2 этим новым значением, 1025. Каким же образом обратиться к адресу, по которому размещена переменная?

С++ имеет встроенный тип "указатель", который используется для хранения адресов объектов. Чтобы объявить указатель, содержащий адрес переменной ival, мы должны написать:

int *pint; // указатель на объект типа int

Существует также специальная операция взятия адреса, обозначаемая символом . Ее результатом является адрес объекта. Следующий оператор присваивает указателю pint адрес переменной ival:

int *pint;

pint = ival; // pint получает значение адреса ival

Мы можем обратиться к тому объекту, адрес которого содержит pint (ival в нашем случае), используя операцию разыменования, называемую также косвенной адресацией. Эта операция обозначается символом *. Вот как можно косвенно прибавить единицу к ival, используя ее адрес:

*pint = *pint + 1; // неявно увеличивает ival

Это выражение производит в точности те же действия, что и

ival = ival + 1; // явно увеличивает ival

В этом примере нет никакого реального смысла: использование указателя для косвенной манипуляции переменной ival менее эффективно и менее наглядно. Мы привели этот пример только для того, чтобы дать самое начальное представление об указателях. В реальности указатели используют чаще всего для манипуляций с динамически размещенными объектами.

Основные отличия между статическим и динамическим выделением памяти таковы:

* статические объекты обозначаются именованными переменными, и действия над этими объектами производятся напрямую, с использованием их имен. Динамические объекты не имеют собственных имен, и действия над ними производятся косвенно, с помощью указателей;

Назад Дальше