Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / из istream в ostream / 21 сообщений из 21, страница 1 из 1
12.06.2013, 19:31
    #38295346
Compositum
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
из istream в ostream
Доброго времени суток.

Существует ли более компактный способ перенаправления содержимого istream в ostream, минуя использование дополнительных переменных? Поясню на примере:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
void fconc(const string& f1, const string& f2, const string& rf)
// Объединить содержимое файлов f1 и f2, сохранив результат в файл rf.
{
	ofstream of(rf);	
	if(!of) error("Can't open file ", rf);
	int x;	
	{
		ifstream if1(f1);
		if(!if1) error("Can't open file ", f1);	
		while(if1 >> x) of << x << ' ';
		if(!if1.eof()) error("Reading error ", f1);
	} // здесь поток if1 уничтожается, дозаписывая в файл то, что осталось в буфере	
	ifstream if2(f2);
	if(!if2) error("Can't open file ", f2);
	while(if2 >> x) of << x << ' ';
	if(!if2.eof()) error("Reading error ", f2);
	if(!of) error("Writing error ", rf);
}


В приведённом выше коде я использовал переменную x, считывая значение сначала в неё, а потом читая из неё. Можно ли это промежуточное "колено" как-то исключить, написав код более компактно?

Спасибо.
...
Рейтинг: 0 / 0
12.06.2013, 19:45
    #38295357
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
из istream в ostream
CompositumМожно ли это промежуточное "колено" как-то исключить, написав код более
компактно?
Почему бы не так:
Код: sql
1.
of <<if1 <<if2;


Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
12.06.2013, 20:02
    #38295363
Compositum
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
из istream в ostream
Dimitry SibiryakovПочему бы не так:
Код: sql
1.
of <<if1 <<if2;


И что это означает? И что, если поток if1 достигнет конца раньше, чем if2?

Попробовал ваше предложение в двух вариантах.

1. В этом случае приложение зависает:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
void fconc(const string& f1, const string& f2, const string& rf)
// Объединить содержимое файлов f1 и f2, сохранив результат в файл rf.
{
	ofstream of(rf);	
	if(!of) error("Can't open file ", rf);		
	ifstream if1(f1);
	if(!if1) error("Can't open file ", f1);
	ifstream if2(f2);
	if(!if2) error("Can't open file ", f2);		
	while(of << if1 << if2);
	if(!if1.eof()) error("Reading error ", f1);
	if(!if2.eof()) error("Reading error ", f2);
	if(!of) error("Writing error ", rf);
}



2. Во втором варианте получаю неверный результат в файла, а так же сообщение об ошибке (ошибка чтения файла data1.txt):
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
void fconc(const string& f1, const string& f2, const string& rf)
// Объединить содержимое файлов f1 и f2, сохранив результат в файл rf.
{
	ofstream of(rf);	
	if(!of) error("Can't open file ", rf);		
	ifstream if1(f1);
	if(!if1) error("Can't open file ", f1);
	ifstream if2(f2);
	if(!if2) error("Can't open file ", f2);		
	of << if1 << if2;
	if(!if1.eof()) error("Reading error ", f1);
	if(!if2.eof()) error("Reading error ", f2);
	if(!of) error("Writing error ", rf);
}
...
Рейтинг: 0 / 0
12.06.2013, 20:06
    #38295366
Compositum
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
из istream в ostream
Пробовал и третий вариант, приводящий так же к зависанию приложения:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
void fconc(const string& f1, const string& f2, const string& rf)
// Объединить содержимое файлов f1 и f2, сохранив результат в файл rf.
{
	ofstream of(rf);	
	if(!of) error("Can't open file ", rf);		
	ifstream if1(f1);
	if(!if1) error("Can't open file ", f1);
	ifstream if2(f2);
	if(!if2) error("Can't open file ", f2);		
	while(if1) of << if1;
	while(if2) of << if2;
	if(!if1.eof()) error("Reading error ", f1);
	if(!if2.eof()) error("Reading error ", f2);
	if(!of) error("Writing error ", rf);
}
...
Рейтинг: 0 / 0
12.06.2013, 20:24
    #38295378
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
из istream в ostream
Попробуй заменить ifstream на filebuf. Для него есть перегруженный <<.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
13.06.2013, 01:06
    #38295537
Новый Год
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
из istream в ostream
a это точно нужно?

обычно это делают так
cat file1 file2 file3 > Outputfile

если нужно программно -- посмотрите исходники cat
...
Рейтинг: 0 / 0
13.06.2013, 08:05
    #38295611
v6y
v6y
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
из istream в ostream
Тут не совсем понятно что в итоге хочет получить автор топика. То ли скопировать содержимое файлов f1 и f2 в файл rf, то ли получить из этих файлов текстовые представления целых чисел с дальнейшей их записью в файл rf.

В общем случае

cat f1 f2 > rf

и

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
void fconc(const string& f1, const string& f2, const string& rf)
// Объединить содержимое файлов f1 и f2, сохранив результат в файл rf.
{
	ofstream of(rf);	
	if(!of) error("Can't open file ", rf);
	int x;	
	{
		ifstream if1(f1);
		if(!if1) error("Can't open file ", f1);	
		while(if1 >> x) of << x << ' ';
		if(!if1.eof()) error("Reading error ", f1);
	} // здесь поток if1 уничтожается, дозаписывая в файл то, что осталось в буфере	
	ifstream if2(f2);
	if(!if2) error("Can't open file ", f2);
	while(if2 >> x) of << x << ' ';
	if(!if2.eof()) error("Reading error ", f2);
	if(!of) error("Writing error ", rf);
}



выдадут разные результаты.
...
Рейтинг: 0 / 0
13.06.2013, 08:36
    #38295629
Compositum
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
из istream в ostream
Новый Годa это точно нужно?

обычно это делают так
cat file1 file2 file3 > Outputfile

если нужно программно -- посмотрите исходники catЯ не спрашивал о том, как перенаправлять потоки средствами командных оболочек.
v6yТут не совсем понятно что в итоге хочет получить автор топика. То ли скопировать содержимое файлов f1 и f2 в файл rf, то ли получить из этих файлов текстовые представления целых чисел с дальнейшей их записью в файл rf.Вы оба невнимательно читали мой вопрос.

Автор топика чётко обозначил вопрос, показав его суть на простом примере, который присутствует лишь для наглядности оного.
Сам вопрос достаточно чёток и ясен:
автор топикаСуществует ли более компактный способ перенаправления содержимого istream в ostream, минуя использование дополнительных переменных?
Поскольку это форум по программированию на C++, то очевидно, что вопрос задан в контексте использования этого языка.
...
Рейтинг: 0 / 0
13.06.2013, 08:54
    #38295641
v6y
v6y
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
из istream в ostream
CompositumАвтор топика чётко обозначил вопрос, показав его суть на простом примере, который присутствует лишь для наглядности оного.
Сам вопрос достаточно чёток и ясен:
автор топикаСуществует ли более компактный способ перенаправления содержимого istream в ostream, минуя использование дополнительных переменных?

Конкретно ваш пример есть не перенаправление содержимого istream в ostream, а именно форматированое чтение из одного потока и форматированная запись в другой. Это не совсем одно и тоже и поэтому позволяет неоднозначное интерпретирование того, что в конечном итоге нужно получить.

автор топикаСуществует ли более компактный способ перенаправления содержимого istream в ostream, минуя использование дополнительных переменных?
Насколько я знаю, нет.
...
Рейтинг: 0 / 0
13.06.2013, 10:20
    #38295741
Usman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
из istream в ostream
CompositumСуществует ли более компактный способ перенаправления содержимого istream в ostream, минуя использование дополнительных переменных?
Код: 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.
#include <algorithm>
#include <iostream>
#include <cstdarg>
#include <fstream>
using namespace std;

void fconc(const char *rf, ...) {
	va_list vargs;
	va_start(vargs, rf);
	ofstream fout(rf);
	while (char *name = va_arg(vargs, char*)) {
		ifstream fin(name);
		copy(
			istreambuf_iterator<char>(fin),
			istreambuf_iterator<char>(),
			ostreambuf_iterator<char>(fout)
		);
		fin.close();
	}
	fout.close();
	va_end(vargs);
}

int main() {
	fconc("C:\\1.txt", "C:\\boot.ini", "C:\\Windows\\system.ini", "C:\\Windows\\win.ini");
	return 0;
}
...
Рейтинг: 0 / 0
13.06.2013, 10:46
    #38295785
v6y
v6y
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
из istream в ostream
UsmanCompositumСуществует ли более компактный способ перенаправления содержимого istream в ostream, минуя использование дополнительных переменных?
Код: 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.
#include <algorithm>
#include <iostream>
#include <cstdarg>
#include <fstream>
using namespace std;

void fconc(const char *rf, ...) {
	va_list vargs;
	va_start(vargs, rf);
	ofstream fout(rf);
	while (char *name = va_arg(vargs, char*)) {
		ifstream fin(name);
		copy(
			istreambuf_iterator<char>(fin),
			istreambuf_iterator<char>(),
			ostreambuf_iterator<char>(fout)
		);
		fin.close();
	}
	fout.close();
	va_end(vargs);
}

int main() {
	fconc("C:\\1.txt", "C:\\boot.ini", "C:\\Windows\\system.ini", "C:\\Windows\\win.ini");
	return 0;
}



Я хотел предложить похожий вариант:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
ostream & sconc(const istream & is, ostream &os) {
 if (!is) throw string("Error");
 copy(
   istreambuf_iterator<char>(is.rdbuf()),
   istreambuf_iterator<char>(),
   ostreambuf_iterator<char>(os)
 );

 return os;
}

void fconc(const string& f1, const string& f2, const string& rf)  {
 ofstream of(rf);
 sconc(ifstream(f2), sconc(ifstream(f1),of));
 of.close();
}



Но меня смутило
авторминуя использование дополнительных переменных
...
Рейтинг: 0 / 0
13.06.2013, 10:48
    #38295788
Compositum
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
из istream в ostream
Usman,

Благодарю, интересный код. Я внёс в него небольшие косметические изменения и запустил, но получил сообщение: Can't open input file .
Код: 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.
/*
test.cpp
http://www.sql.ru/forum/1028906/iz-istream-v-ostream#14426593
Перенаправление нескольких потоков ввода в поток вывода, без использования промежуточных 
переменных.
*/
#include <algorithm>
#include <iostream>
#include <cstdarg>
#include <fstream>
using namespace std;
void fconc(const char *rf, ...)
// Объединение содержимого файлов в один, имя которого указано в rf.
{
	va_list vargs;
	va_start(vargs, rf);
	ofstream fout(rf);
	if(!fout) throw runtime_error("Can't open output file."); // обязательно проверяем состояние
	while (char *name = va_arg(vargs, char*)) {
		ifstream fin(name);
		if(!fin) throw runtime_error("Can't open input file."); // обязательно проверяем состояние
		copy(
			istreambuf_iterator<char>(fin),
			istreambuf_iterator<char>(),
			ostreambuf_iterator<char>(fout)
		);
		// fin.close(); // в этом нет необходимости
	}
	// fout.close();  // в этом нет необходимости
	va_end(vargs);
}
//==================================================================================================
int main()
try{
	fconc("C:\\bs\\1.txt", "C:\\boot.ini", "C:\\Windows\\system.ini", "C:\\Windows\\win.ini");	
}
catch(exception& e){
	cerr << e.what() << endl;
	return 1;
}
catch(...){
	cerr << "Unknown exception." << endl;
	return 2;
}
...
Рейтинг: 0 / 0
13.06.2013, 11:05
    #38295822
Usman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
из istream в ostream
Compositum,

Нужно проверить пути:

- C:\boot.ini
- C:\Windows\system.ini
- C:\Windows\win.ini

В Windows XP/2003 это стандартные системные файлы (должно работать).
В Seven - возможно уже по-другому.
...
Рейтинг: 0 / 0
13.06.2013, 11:09
    #38295831
Compositum
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
из istream в ostream
v6y,

Спасибо, попробовал и ваш код, немного подкорректировав его:
Код: 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.
/*
test.cpp
http://www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1028906&msg=14425267
Перенаправление нескольких потоков ввода в поток вывода, без использования промежуточных 
переменных.
*/
//--------------------------------------------------------------------------------------------------
#include <algorithm>
#include <iostream>
#include <cstdarg>
#include <fstream>
using namespace std;
//--------------------------------------------------------------------------------------------------
ostream& sconc(const istream& is, ostream& os) {
 if(!is) throw runtime_error("Can't open input file."); // обязательно проверяем состояние
 copy(
   istreambuf_iterator<char>(is.rdbuf()),
   istreambuf_iterator<char>(),
   ostreambuf_iterator<char>(os)
 );
 return os;
}
//--------------------------------------------------------------------------------------------------
void fconc(const string& f1, const string& f2, const string& rf)  {
 ofstream of(rf.c_str());
 if(!of) throw runtime_error("Can't open output file."); // обязательно проверяем состояние
 ifstream if2(f2.c_str());
 if(!if2) throw runtime_error("Can't open input file."); // обязательно проверяем состояние
 ifstream if1(f1.c_str());
 if(!if1) throw runtime_error("Can't open input file."); // обязательно проверяем состояние
 sconc(if2, sconc(if1,of));
 // of.close(); // в этом нет необходимости
}
//==================================================================================================
int main()
try{
	fconc("C:\\boot.ini", "C:\\Windows\\system.ini", "C:\\bs\\1.txt");	
}
catch(exception& e){
	cerr << e.what() << endl;
	return 1;
}
catch(...){
	cerr << "Unknown exception." << endl;
	return 2;
}


К сожалению, в результате получаю так же Can't open input file .
...
Рейтинг: 0 / 0
13.06.2013, 11:15
    #38295839
Compositum
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
из istream в ostream
UsmanCompositum,

Нужно проверить пути:

- C:\boot.ini
- C:\Windows\system.ini
- C:\Windows\win.ini

В Windows XP/2003 это стандартные системные файлы (должно работать).
В Seven - возможно уже по-другому.
опа... я проверил второй и третий, упустив проверку первого. :) Да, похоже, что в Windows 7 x64 отсутствует файл C:\boot.ini. Убрал его, и оба варианта кода (ваш и код v6y ) сразу заработал, спасибо!

А используя операторы "<<" и ">>", выполняя посимвольное перенаправление, можно написать более компактный вариант, чем указал я (даже если отбросить добавляемые мною символы пробелов)?

Спасибо.
...
Рейтинг: 0 / 0
13.06.2013, 11:41
    #38295893
Usman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
из istream в ostream
Compositum,

Без функции copy , но с буферизацией (считывает весь файл в строку):
Код: plaintext
1.
fout << string(istreambuf_iterator<char>(fin), istreambuf_iterator<char>()).c_str();
...
Рейтинг: 0 / 0
13.06.2013, 12:50
    #38296068
Usman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
из istream в ostream
Compositum,

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
ofstream& operator<<(ofstream& fout, ifstream& fin)
{
	copy(
		istreambuf_iterator<char>(fin),
		istreambuf_iterator<char>(),
		ostreambuf_iterator<char>(fout)
	);
	return fout;
}

void fconc(const char *rf, ...) {
	va_list vargs;
	va_start(vargs, rf);
	ofstream fout(rf);
	while (char *name = va_arg(vargs, char*)) {
		ifstream fin(name);
		fout << fin;
	}
	va_end(vargs);
}
...
Рейтинг: 0 / 0
13.06.2013, 14:12
    #38296230
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
из istream в ostream
А так что не подходит?

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
template <typename Ostream, typename Istream>
void copy_stream(Ostream& os, Istream& is)
{
    os << is.rdbuf();
}

int main()
{
    ifstream is("/etc/hosts");
    copy_stream(cout, is);
    return 0;
}
...
Рейтинг: 0 / 0
13.06.2013, 14:21
    #38296248
итераторы
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
из istream в ostream
может, использовать std::copy, std::ostream_iterator и std::istream_operator (детали по памяти не вспомню, но по идее должно делаться в 1 строчку)?
...
Рейтинг: 0 / 0
13.06.2013, 14:43
    #38296295
v6y
v6y
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
из istream в ostream
Anatoly MoskovskyА так что не подходит?

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
template <typename Ostream, typename Istream>
void copy_stream(Ostream& os, Istream& is)
{
    os << is.rdbuf();
}

int main()
{
    ifstream is("/etc/hosts");
    copy_stream(cout, is);
    return 0;
}



Тьфу блин, я чего то просмотрел что у ostream есть
Код: plaintext
1.
ostream& operator<< (streambuf* sb )



Вот и нагородил огород :)
...
Рейтинг: 0 / 0
13.06.2013, 15:53
    #38296419
Compositum
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
из istream в ostream
Благодарю всех за ответы. Как освобожусь - буду изучать предложенные варианты.
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / из istream в ostream / 21 сообщений из 21, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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