powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Проверка потока
12 сообщений из 12, страница 1 из 1
Проверка потока
    #38293715
Фотография Compositum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Доброго времени суток.

У меня есть вопрос по следующему простому коду:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
/*
test.cpp
© BS.
Пример создания класса потока, для которого можно назначать дополнительные символы, интерпретируемые
как разделители.
11/06/2013, Раздел 11.7
*/
//--------------------------------------------------------------------------------------------------
#include <iostream>
#include <sstream>
#include <algorithm>
#include <exception>
#include <string>
#include <vector>
using namespace std;
//--------------------------------------------------------------------------------------------------
class Punct_stream
// аналогичен потоку istream, но пользователь может самостоятельно задавать разделители.
{
private:
	istream& source; // источник символов
	istringstream buffer; // буфер для форматирования
	string white; // символы-разделители
	bool sensitive; // является ли поток чувствительным к регистру
public:
	Punct_stream(istream& is): source(is), sensitive(true) {}
	void whitespace(const string& s) { white = s; } // создаёт строку разделителей
	void add_white(char c) { white += c; } // добавить символ в набор разделителей
	void case_sensitive(bool b) { sensitive = b; }
	bool is_case_sensitive() { return sensitive; }
	bool is_whitespace(char c); // является ли 'c' одним из заданных разделителей?
	Punct_stream& operator >> (string& s);
	operator bool(); // проверка результата ввода значения из потока
};
//--------------------------------------------------------------------------------------------------
bool Punct_stream::is_whitespace(char c)
// проверка символа на то, является ли он разделителем
{
	for(int i = 0; i < white.size(); ++i) if(c == white[i]) return true;
	return false;
}
//--------------------------------------------------------------------------------------------------
Punct_stream::operator bool()
// проверка результата ввода значения из потока
{
	return !(source.fail() || source.bad()) && source.good();
}
//--------------------------------------------------------------------------------------------------
Punct_stream& Punct_stream::operator >> (string& s){
	while(!(buffer >> s)){ // попытка прочитать данные из потока buffer
		if(buffer.bad() || !source.good()) return *this;
		buffer.clear();
		
		string line;
		getline(source,line); // считать строку line из потока source
		
		// при необходимости заменяем символы
		for(int i = 0; i < line.size(); ++i)
			if(is_whitespace(line[i])) line[i] = ' '; // в пробел
			else if(!sensitive) line[i] = tolower(line[i]); // в нижний регистр
			buffer.str(line); // записываем строку в поток
	}
	return *this;
}
//==================================================================================================
int main()
// точка входа
try{
	Punct_stream ps(cin);
	ps.whitespace(";:,.?!()\"{}<>/&$@#%^*|~");
	ps.case_sensitive(false);
	cout << "Enter the words, please: ";
	vector<string> vs;
	string word;
	while(ps >> word) vs.push_back(word); // ввод слов
	sort(vs.begin(), vs.end()); // сортировка в лексикографическом порядке
	// удаляем дубликаты
	for(int i = 0; i < vs.size(); ++i) if(i == 0 || vs[i] != vs[i-1]) cout << vs[i] << endl;
}
catch(exception& e){
	cerr << e.what() << endl;
	return 1;
}
catch(...){
	cerr << "Unknown exception." << endl;
	return 2;
}


Мне не понятна проверка в функции Punct_stream::operator bool() :
Код: plaintext
1.
return !(source.fail() || source.bad()) && source.good();



1. Для чего автор проверяет fail и bad ? Почему он не ограничился лишь проверкой good ? Разве положительный good автоматически не подразумевает, что fail и bad установлены в false ?

2. Кроме того, часто в коде пишут такую конструкцию:
Код: plaintext
1.
2.
3.
while(cin >> x){
    //...
}


Почему в функции Punct_stream::operator bool() автор не написал по аналогии так:
Код: plaintext
1.
2.
3.
4.
5.
6.
Punct_stream::operator bool()
// проверка результата ввода значения из потока
{
	// return !(source.fail() || source.bad()) && source.good();
        return source;
}


Показанный мною альтернативный вариант у меня не работает (кладёт на лопатки Windows), хотелось бы понять, почему, что я упустил?

Спасибо.
...
Рейтинг: 0 / 0
Проверка потока
    #38293819
sherzod_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Compositum,

return !(source.fail() || source.bad()) && source.good() -- оптимизация под fail и bad (likely/unlikely), видимо это состояние частое. ios::good еще проверяет eof.
...
Рейтинг: 0 / 0
Проверка потока
    #38293840
Фотография Compositum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sherzod_,

Спасибо. А почему второй вариант не работает так, как я ожидал?
...
Рейтинг: 0 / 0
Проверка потока
    #38293884
sherzod_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Compositum,

не знаю:). Винду можно по разному на лопатки класть :D. Возможно из-за eof, стандартный оператор приведения к void* или bool не проверяет этот флаг, а возвращает !fail().
...
Рейтинг: 0 / 0
Проверка потока
    #38294001
Фотография Compositum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хм... Сейчас снова попробовал свой вариант проверки - отработал нормально. В прошлый раз, когда пришлось перегружать Windows (ибо всё насмерть зависло), я в качестве исходных данных программе скормил произвольный текст с какой-то web-странички, с сайта http://www.cplusplus.com...

И всё же интересно, зачем Беарне Стровструп так "завернул" проверку...
...
Рейтинг: 0 / 0
Проверка потока
    #38294125
egorych
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CompositumИ всё же интересно, зачем Беарне Стровструп так "завернул" проверку... 14290140 это же ваша тема, по моему. Anatoly Moskovsky вроде там всё разъяснял доходчиво
...
Рейтинг: 0 / 0
Проверка потока
    #38294148
Фотография Compositum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
egorychCompositumИ всё же интересно, зачем Беарне Стровструп так "завернул" проверку... 14290140 это же ваша тема, по моему. Anatoly Moskovsky вроде там всё разъяснял доходчиво
я в курсе о преобразованиях и не спрашивал о них. мой вопрос о другом.
...
Рейтинг: 0 / 0
Проверка потока
    #38294352
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Compositumпришлось перегружать Windows (ибо всё насмерть зависло),
Вероятно у вас в коде где-то возник бесконечный цикл с выделением памяти внутри него.
Или просто очень много памяти выделяется.
Других причин, чтобы винда повисла нет. Это вам не ДОС какой-то.
Но в любом случае причина не в операторе, т.к. он тривиален и там никаких ошибок не видно.
Ищите проблему в другом месте.
...
Рейтинг: 0 / 0
Проверка потока
    #38294364
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CompositumПочему в функции Punct_stream::operator bool() автор не написал по аналогии так:
Вообще-то по аналогии (если рассматривать стандарт) то оператор должен выглядеть так
Код: plaintext
1.
2.
3.
4.
Punct_stream::operator void*()
{
    return fail() ? 0 : (void*)this;
}


Ну а fail() реализовать через делегирование во вложенный объект.
fail() включает в себя bad() поэтому нет смысла отдельно вызывать bad().
...
Рейтинг: 0 / 0
Проверка потока
    #38294372
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly Moskovskyесли рассматривать стандарт
Речь про стандарт C++03.
В C++11 внесены изменения. Какие - не помню.
...
Рейтинг: 0 / 0
Проверка потока
    #38294390
Фотография Compositum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyВообще-то по аналогии (если рассматривать стандарт) то оператор должен выглядеть так
Код: plaintext
1.
2.
3.
4.
Punct_stream::operator void*()
{
    return fail() ? 0 : (void*)this;
}



Ну а fail() реализовать через делегирование во вложенный объект.
fail() включает в себя bad() поэтому нет смысла отдельно вызывать bad().
Почему пишете про void*? Это же оператор неявного преобразования в bool (я о варианте Стровструпа)...
...
Рейтинг: 0 / 0
Проверка потока
    #38294538
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CompositumПочему пишете про void*? Это же оператор неявного преобразования в bool (я о варианте Стровструпа)...
По стандарту С++03 должен быть void*.
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / Проверка потока
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]