Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / Проверка потока / 12 сообщений из 12, страница 1 из 1
11.06.2013, 11:44
    #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
11.06.2013, 12:32
    #38293819
sherzod_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверка потока
Compositum,

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

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

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

И всё же интересно, зачем Беарне Стровструп так "завернул" проверку...
...
Рейтинг: 0 / 0
11.06.2013, 14:46
    #38294125
egorych
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверка потока
CompositumИ всё же интересно, зачем Беарне Стровструп так "завернул" проверку... 14290140 это же ваша тема, по моему. Anatoly Moskovsky вроде там всё разъяснял доходчиво
...
Рейтинг: 0 / 0
11.06.2013, 14:53
    #38294148
Compositum
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверка потока
egorychCompositumИ всё же интересно, зачем Беарне Стровструп так "завернул" проверку... 14290140 это же ваша тема, по моему. Anatoly Moskovsky вроде там всё разъяснял доходчиво
я в курсе о преобразованиях и не спрашивал о них. мой вопрос о другом.
...
Рейтинг: 0 / 0
11.06.2013, 16:17
    #38294352
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверка потока
Compositumпришлось перегружать Windows (ибо всё насмерть зависло),
Вероятно у вас в коде где-то возник бесконечный цикл с выделением памяти внутри него.
Или просто очень много памяти выделяется.
Других причин, чтобы винда повисла нет. Это вам не ДОС какой-то.
Но в любом случае причина не в операторе, т.к. он тривиален и там никаких ошибок не видно.
Ищите проблему в другом месте.
...
Рейтинг: 0 / 0
11.06.2013, 16:27
    #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
11.06.2013, 16:32
    #38294372
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверка потока
Anatoly Moskovskyесли рассматривать стандарт
Речь про стандарт C++03.
В C++11 внесены изменения. Какие - не помню.
...
Рейтинг: 0 / 0
11.06.2013, 16:44
    #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
11.06.2013, 18:30
    #38294538
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверка потока
CompositumПочему пишете про void*? Это же оператор неявного преобразования в bool (я о варианте Стровструпа)...
По стандарту С++03 должен быть void*.
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / Проверка потока / 12 сообщений из 12, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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