Урок №208. функционал класса istream

Inherited from std::basic_istream

Member functions

operator>> extracts formatted data (public member function of )
get extracts characters (public member function of )
peek reads the next character without extracting it (public member function of )
unget unextracts a character (public member function of )
putback puts character into input stream (public member function of )
getline extracts characters until the given character is found (public member function of )
ignore extracts and discards characters until the given character is found (public member function of )
read extracts blocks of characters (public member function of )
readsome extracts already available blocks of characters (public member function of )
gcount returns number of characters extracted by last unformatted input operation (public member function of )
tellg returns the input position indicator (public member function of )
seekg sets the input position indicator (public member function of )
sync synchronizes with the underlying storage device (public member function of )

Parts of the IO stream library

Standard Stream Objects for Console I/O: (cout, cin, cerr, clog, etc.)

These are declared in the <iostream> header and provide a consistent interface for console I/O. They allow you a lot of control about the exact way you want to read a value from the stream into the given variable (or write the variable to the stream).

File I/O

File I/O is done by manually declaring objects of the ifstream, ofstream or
fstream classes (from the <fstream> header) and then associating a file
with the stream by using the stream’s open method with the file’s name as an
argument. File I/O is particularly important because files are often used to
represent a large variety of media, such as the console, devices, disk files,
virtual memory, list of running processes and even the black hole ‘/dev/null’.
This is especially true on *nix systems where it is commonly said that
«Everything is a file».

Here is a very very simple example of writing to a file:

#include <iostream>
#include <fstream>

using namespace std;

int main()
{
        ofstream ofs("a.txt",ios::app);
        if(ofs.good())
        {
                ofs<<"Hello a.txt, I'm appending this on you.";
        }
        return 0;
}

String Streams

Strings are streams and streams are strings. Both are character arrays, but
each has a totally different interface (random access strings vs serial
stringstreams). By providing both std::string and stringstreams, the C++
standard library ensures that you have the flexibility to choose either
interface for your design.

By including the <sstream> header, you can make objects of the
istringstream, ostringstream and stringstream types. These objects make certain
kinds of string manipulations much easier.

You can, for example, open a string in a stringstream, extract a floating point number from it to do some operations, and put it back in the stream.

#include <iostream>
#include <sstream>

using namespace std;

int main()
{
        stringstream my_stream(ios::in|ios::out);
        std::string dat("Hey, I have a double : 74.79 .");

        my_stream.str(dat);
        my_stream.seekg(-7,ios::end);

        double val;
        my_stream>>val;

        val= val*val;

        my_stream.seekp(-7,ios::end);
        my_stream<<val;

        std::string new_val = my_stream.str();
        cout<<new_val;

        return 0;
}

The output is

Hey, I have a double : 5593.54

The lower level, where streams meet buffers

This is the most interesting and confusing part of this library, letting you
manipulate streams at their lowest levels, bytes and bits. This is accomplished
by the abstract class streambuf from which stringbuf and filebuf are derived.
Every stream object has one of those as their backbones. Their function rdbuf()
lets you access a pointer to the underlying stream buffer.

Here is a very simple example of copying a file efficiently with those buffers (thankfully, no ultra-complicated manipulation is involved here!).

#include <iostream>
#include <fstream>
using namespace std;

int main()
{
        ifstream ifs("a.txt");
        //ios::trunc means that the output file will be overwritten if exists 
        ofstream ofs("a.txt.copy", ios::trunc);  
        if (ifs &&  ofs )
        {
                ofs<<ifs.rdbuf();
        }

        return 0;
}

Popular pages

  • Jumping into C++, the Cprogramming.com ebook
  • How to learn C++ or C
  • C Tutorial
  • C++ Tutorial
  • 5 ways you can learn to program faster
  • The 5 most common problems new programmers face
  • How to set up a compiler
  • How to make a game in 48 hours

Базовые типы для работы с потоками

Последнее обновление: 25.10.2017

Все инструменты для работы с системой ввода-вывода и потоками в языке С++ определены в стандартной библиотеке.
Заголовочный файл iostream определяет следующие базовые типы для работы с потоками:

  • istream и wistream: читают данные с потока

  • ostream и wostream: записывают данные в поток

  • iostream и wiostream: читают и записывают данные в поток

Для каждого типа определен его двойник, который начинается на букву w и который предназначен для поддержки данных типа wchar_t.

Эти типы являются базовыми для других классов, управляющих потоками ввода-вывода.

Объект типа ostream получает значения различных типов, преобразует их в последовательность символов и
передает их через буфер в определенное место для вывода (консоль, файл, сетевые интерфейсы и т.д.)

Поток istream получает через буфер из определенного места последовательности символов (с консоли, из файла, из сети и т.д.)
и преобразует эти последовательности в значения различных типов. То есть когда мы вводим данные (с той же клавиатуры в консоли), сначала данные накапливаются в буфере и только
затем передаются объекту istream.

По умолчанию в стандартной библиотеке определены объекты этих классов — cout, cin,
cerr, которые работают с консолью.

Запись в поток

Для записи данных в поток ostream применяется оператор <<. Этот оператор получает два
операнда. Левый операнд представляет объект типа ostream, а правый операнд — значение, которое надо вывести в поток.

К примеру, по умолчанию стандартная библиотека C++ предоставляет объект cout, который представляет тип
ostream и позволяет выводить данные на консоль:

#include <iostream>

int main()
{
	std::cout << "Hello" << std::endl;
	return 0;
}

Так как оператор << возвращает левый операнд — cout, то с помощью цепочки операторов мы
можем передать на консоль несколько значений:

std::cout << "Hello" << " world" << std::endl;

Чтение данных

Для чтения данных из потока применяется оператор ввода >>, который принимает два операнда.
Левый операнд представляет поток istream, с которого производится считывание, а правый операнд — объект, в который считываются данные.

Для чтения с консоли применяется объект cin, который представляет тип istream.

#include <iostream>
 
int main()
{   
    int age;
    double weight;
    std::cout << "Input age: ";
    std::cin >> age;
    std::cout << "Input weight: ";
    std::cin >> weight;
    std::cout << "Your age: " << age << "\t your weight: " << weight << std::endl;
    return 0;
}

Однако такой способ не очень подходит для чтения строк с консоли особенно когда считываемая строка содержит пробельные символы. В этом случае
лучше использовать встроенную функцию getline(), которая в качестве параметра принимает поток istream и переменную типа string, в которую надо считать данные:

#include <iostream>
#include <string>

int main()
{
	std::string name;
	std::cout << "Input name: ";
	getline(std::cin, name);
	//std::cin >> name;
	std::cout << "Your name: " << name <<std::endl;
	return 0;
}

Консольный вывод данной программы:

Input name: Tom Smit
Your name: Tom Smit

Вывод ошибок

Для вывода сообщения об ошибке на консоль применяется объект cerr, который представляет объект типа ostream:

#include <iostream>

int main()
{
	std::cerr << "Error occured" << std::endl;
	return 0;
}

Потоки символов wchar_t

Для работы с потоками данных типов wchar_t в стандартной библиотеке определены объекты wcout
(тип wostream), wcerr (тип wostream) и wcin (тип wistream), которые являются аналогами
для объектов cout, cerr и cin и работают аналогично

#include <iostream>

int main()
{
	int age;
	double weight;
	std::wcout << "Input age: ";
	std::wcin >> age;
	std::wcout << "Input weight: ";
	std::wcin >> weight;
	if (age <= 0 || weight <= 0)
		std::wcerr << "Invalid data" << std::endl;
	else
		std::wcout << "Your age: " << age << "\t your weight: " << weight << std::endl;
	return 0;
}

НазадВперед

Conclusion

Common wisdom holds that streams are superior to stdio because they are
typesafe and extensible. In this article I showed that the extensibility
goes far beyond the addition of new types to the formatting layer. I added
a manipulator to convert printf formatting commands to their stream equivalents.
And I added a new stream class that displays output in a debug window
under Microsoft Windows, fully supporting all features of the ostream
class (including the new format manipulator). Both additions require very
little code, but the programmer must know where to hook into the streams
framework. This is, of course, characteristic of programming with frameworks.

Директива

Эта директива читается препроцессором и приказывает ему вставить в данную программу содержимое пользовательского или системного заголовочного файла. Эти файлы в основном импортируются из внешнего источника в текущую программу.

Процесс импортирования таких файлов, которые могут быть системными или пользовательскими, известен как File Inclusion (англ. — включение файлов). Этот тип директивы препроцессора указывает компилятору включить файл в исходный код программы.

Вот два типа файлов, которые могут быть включены с помощью :

1. Заголовочный файл или стандартный файл. Это файл, который содержит C/C++ объявления функций и макроопределения для совместного использования между несколькими исходными файлами.

Такие функции, как , , , и различные другие функции ввода-вывода или другие стандартные функции содержатся в различных заголовочных файлах. Поэтому для использования этих функций пользователям необходимо импортировать несколько заголовочных файлов, которые определяют требуемые функции.

2. Файлы, определяемые пользователем. Эти файлы похожи на заголовочные файлы, за исключением того, что они написаны и определены самим пользователем. Это избавляет пользователя от многократной записи определенной функции. После записи пользовательский файл может быть импортирован в любое место программы с помощью препроцессора .

8 ответов

10

Заменить

с

11 июнь 2014, в 23:00
Поделиться

6

Некоторые вещи, которые вы должны проверить:

  • Проверьте папку include в вашей версии VS (в «» проверьте файл, который вы включаете, , убедитесь, что он там).

  • Проверьте свои проекты Включить каталоги в — (это должно выглядеть так: )

  • Убедитесь, что вы выбрали правильный проект для этого кода
    ()

  • Убедитесь, что в ваших кодовых файлах нет , VS не поддерживает это (в том же проекте, проверьте ваши другие файлы кода,.cpp и .h файлы для и удалите его).

  • Убедитесь, что у вас не более одной функции в вашем
    файлы проекта кода (в том же проекте, проверьте свои другие файлы кода, файлы .cpp и .h для функции и удалите его или замените другим именем).

Некоторые вещи, с которыми вы могли бы попытаться построить:

  • Исключить из вашей функции и поместить ее
    после включения директивы.
  • Используйте без .

30 июль 2012, в 00:02
Поделиться

4

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

Выше работали для меня. Ниже не было:

Это также не удалось:

05 дек. 2015, в 21:09
Поделиться

1

Скорее всего, вам не хватает $(IncludePath) в свойствах → Каталоги VС++ → Включить каталоги. Добавление этого должно сделать iostream и другие видимыми снова. Вероятно, вы удалили его по ошибке при настройке своей программы.

10 дек. 2015, в 13:11
Поделиться

1

Возможно, ваш компилятор и ресурсы, установленные вокруг него, были как-то неполными. Я рекомендую повторно установить ваш компилятор: он должен работать после этого.

30 июль 2012, в 01:09
Поделиться

Microsoft Visual Studio забавна, когда вы используете установщик, вы ДОЛЖНЫ установить флажок в нескольких вариантах, чтобы обойти .netframework(несколько), чтобы сделать больше С++ вместо острых приложений, таких как параметры clr при разработке dekstop… в установщике визуальной студии…. разница — это проект консоли С++ win32 или консольный проект С++ CLR.
Так в чем разница? Ну, я не буду перечислять все файлы CLR, но так как большинство хороших ядер С++ находятся в Linux… поэтому CLR позволяет обойти много окон .netframework b/c visual studio действительно была для вас для приложений в C sharp.

Вот проект консоли С++ win32!

Теперь идет проект консоли С++ CLR!

Обе программы делают то же самое… CLR просто выглядит более структурированной методологией перегрузки классов, поэтому Microsoft может отличить обширную библиотеку, которую вы должны ознакомиться, если это так.
https://msdn.microsoft.com/en-us/library/2e6a4at9.aspx

другие вещи, которые вы узнаете из отладки, чтобы добавить для предотвращения ошибок

14 сен. 2017, в 05:10
Поделиться

Если ваши каталоги include правильно указаны в листе свойств проекта VС++ → Свойства конфигурации → Каталоги VС++- > Включить каталоги. Путь ссылается на макрос $(VC_IncludePath)
В моем VS 2015 это оценивается следующим образом:
«C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include»

Это сделало это для меня.

19 фев. 2017, в 22:29
Поделиться

У меня возникла эта ошибка, когда я создал консольное приложение «Пустое» в Visual Studio 2015. Я заново создал приложение, оставив флажок «Пусто», он добавил все необходимые библиотеки.

09 июнь 2016, в 00:20
Поделиться

Ещё вопросы

  • 2033В чем разница между #include <filename> и #include «filename»?
  • 1262Какое влияние оказывает extern «C» в C ++?
  • 808Какие типы POD в C ++?
  • 669Когда вы должны использовать класс против структуры в C ++?
  • 538Как автоматически генерировать трассировку стека при сбое моей программы
  • 442Правила аннулирования итераторов
  • 431Безымянное / анонимное пространство имен против статических функций
  • 420Каковы различия между структурой и классом в C ++?
  • 371Как вы очищаете переменную stringstream?
  • 364Как узнать текущее время и дату в C ++?

Точность, запись чисел и десятичная точка

Используя манипуляторы (или флаги), можно изменить точность и формат вывода значений типа с плавающей запятой.

Флаги группы форматирования floatfield:

   fixed — используется десятичная запись чисел типа с плавающей запятой;

   scientific — используется чисел типа с плавающей запятой;

   showpoint — всегда отображается десятичная точка и конечные нули для чисел типа с плавающей запятой.

Манипуляторы:

   fixed — используется десятичная запись значений;

   scientific — используется экспоненциальная запись значений;

   showpoint — отображается десятичная точка и конечные нули чисел типа с плавающей запятой;

   noshowpoint — не отображаются десятичная точка и конечные нули чисел типа с плавающей запятой;

   setprecision(int) — задаем точность для чисел типа с плавающей запятой.

Методы:

   precision() — возвращаем текущую точность для чисел типа с плавающей запятой;

   precision(int) — задаем точность для чисел типа с плавающей запятой.

Если используется десятичная или экспоненциальная запись чисел, то точность определяет количество цифр после запятой/точки

Обратите внимание, если точность меньше количества значащих цифр, то число будет округлено. Например:

#include <iostream>
#include <iomanip> // для setprecision()

int main()
{
std::cout << std::fixed;
std::cout << std::setprecision(3) << 123.456 << ‘\n’;
std::cout << std::setprecision(4) << 123.456 << ‘\n’;
std::cout << std::setprecision(5) << 123.456 << ‘\n’;
std::cout << std::setprecision(6) << 123.456 << ‘\n’;
std::cout << std::setprecision(7) << 123.456 << ‘\n’;

std::cout << std::scientific << ‘\n’;
std::cout << std::setprecision(3) << 123.456 << ‘\n’;
std::cout << std::setprecision(4) << 123.456 << ‘\n’;
std::cout << std::setprecision(5) << 123.456 << ‘\n’;
std::cout << std::setprecision(6) << 123.456 << ‘\n’;
std::cout << std::setprecision(7) << 123.456 << ‘\n’;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

#include <iostream>
#include <iomanip> // для setprecision()
 

intmain()

{

std::cout<<std::fixed;

std::cout<<std::setprecision(3)<<123.456<<‘\n’;

std::cout<<std::setprecision(4)<<123.456<<‘\n’;

std::cout<<std::setprecision(5)<<123.456<<‘\n’;

std::cout<<std::setprecision(6)<<123.456<<‘\n’;

std::cout<<std::setprecision(7)<<123.456<<‘\n’;

std::cout<<std::scientific<<‘\n’;

std::cout<<std::setprecision(3)<<123.456<<‘\n’;

std::cout<<std::setprecision(4)<<123.456<<‘\n’;

std::cout<<std::setprecision(5)<<123.456<<‘\n’;

std::cout<<std::setprecision(6)<<123.456<<‘\n’;

std::cout<<std::setprecision(7)<<123.456<<‘\n’;

}

Результат:

Если не используются ни десятичная, ни экспоненциальная запись чисел, то точность определяет, сколько значащих цифр будет отображаться. Например:

#include <iostream>
#include <iomanip> // для setprecision()

int main()
{
std::cout << std::setprecision(3) << 123.456 << ‘\n’;
std::cout << std::setprecision(4) << 123.456 << ‘\n’;
std::cout << std::setprecision(5) << 123.456 << ‘\n’;
std::cout << std::setprecision(6) << 123.456 << ‘\n’;
std::cout << std::setprecision(7) << 123.456 << ‘\n’;
}

1
2
3
4
5
6
7
8
9
10
11

#include <iostream>
#include <iomanip> // для setprecision()
 

intmain()

{

std::cout<<std::setprecision(3)<<123.456<<‘\n’;

std::cout<<std::setprecision(4)<<123.456<<‘\n’;

std::cout<<std::setprecision(5)<<123.456<<‘\n’;

std::cout<<std::setprecision(6)<<123.456<<‘\n’;

std::cout<<std::setprecision(7)<<123.456<<‘\n’;

}

Результат:

Используя манипулятор или флаг showpoint, мы можем заставить программу выводить десятичную точку и конечные нули. Например:

#include <iostream>
#include <iomanip> // для setprecision()

int main()
{
std::cout << std::showpoint;
std::cout << std::setprecision(3) << 123.456 << ‘\n’;
std::cout << std::setprecision(4) << 123.456 << ‘\n’;
std::cout << std::setprecision(5) << 123.456 << ‘\n’;
std::cout << std::setprecision(6) << 123.456 << ‘\n’;
std::cout << std::setprecision(7) << 123.456 << ‘\n’;
}

1
2
3
4
5
6
7
8
9
10
11
12

#include <iostream>
#include <iomanip> // для setprecision()
 

intmain()

{

std::cout<<std::showpoint;

std::cout<<std::setprecision(3)<<123.456<<‘\n’;

std::cout<<std::setprecision(4)<<123.456<<‘\n’;

std::cout<<std::setprecision(5)<<123.456<<‘\n’;

std::cout<<std::setprecision(6)<<123.456<<‘\n’;

std::cout<<std::setprecision(7)<<123.456<<‘\n’;

}

Результат:

Пример 1 — фильтруем цифры

uflowunderflowдонесколько раз подряд

Используем буферы

  • eback() (end back pointer) — указатель на первый элемент буфера
  • gptr() (get pointer) — указатель на на элемент буфера, который будет считан следующим
  • egptr() (end get pointer) — указатель на элемент, следующий за последним элементом буфера. Когда достигает его, это означает, что буфер исчерпан и его нужно снова заполнить

Наглядная иллюстрация с сайта mr-edd.co.uk

  • setg(eback, gptr, egptr) — устанавливает значения соответствующих указателей
  • gbump(offset) — сдвинуть указатель на позиций. Фактически, после выполнения функции примет значение
  • pbase() (put base pointer) — указатель на первый элемент буфера
  • pptr() (put pointer) — указатель на на элемент буфера, который будет записан следующим
  • epptr() (end put pointer) — указатель на элемент, следующий за последним элементом буфера.

Еще одна наглядная иллюстрация с сайта mr-edd.co.uk

setp(pbase, epptr) — устанавливает значения соответствующих указателей

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

устанавливается на начало буфера)

pbump(offset) — сдвинуть указатель на позиций. Фактически, после выполнения функции примет значение

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector