Уважаемые Гуру!
Перечитываю Страупструпа.
Пытаюсь честно делать все примеры. Когда-то в VC6 уже их реализовывал и точно помню, что удалалось добиться работоспособности кода. Но теперь в VS2005/2008 многие вещи из стандартных библиотек, похоже, поменялись. В частности, пример:
int main(int argc, char* argv[])
{
switch(argc) {
case 1: // считывать из стандартного входного потока
break;
case 2: // считывать из строки параметров
cin = *new istream(argv[1],strlen(argv[1]));
break;
default:
error("слишком много параметров");
return 1;
}
// дальше прежний вариант main
}
cin = *new istream(argv[1],strlen(argv[1]));
Вызывает ошибку: нет легального доступа к приватному оператору "="!
Начал копать, оказалось, что istream теперь лишь алиас сложного шаблонного класса basic_istream, описание которого в MSDN сильно упрощено.
Пожалуйста, помогите:
1)как нужно переделать пример Страупструпа?
2)как вообще создать свой аналог cin (ввод потока из консоли!) с помощью STL?
То есть, это аналог подмены потока cin, который у Страупструпа выглядит как cin=*new ..... ?
В новой версии библиотек мы не можем напрямую присваивать cin другому istream'у? Теперь можно только буфер подменить?
ОК, а как теперь просто создать свой собственный поток ввода из консоли? istream my_cin; — не работает. Как правильно конструктор вызывать (можно ссылку на документацию, ибо я не нашел).
Спасибо!
Здравствуйте, ND322, Вы писали:
ND>ОК, а как теперь просто создать свой собственный поток ввода из консоли? istream my_cin; — не работает. Как правильно конструктор вызывать (можно ссылку на документацию, ибо я не нашел).
Не понял вопроса, ты откуда собираешься вводить? В комментарии у тебя было "считывать из строки параметров".
Пожалуйста, помогите:
1)как нужно переделать пример Страупструпа?
2)как вообще создать свой аналог cin (ввод потока из консоли!) с помощью STL?
По первому теперь понятно, переделал, заработало. Остался второй вопрос: как вообще в новой версии STL создать свой поток ввода с консоли?
Стандартный cin сейчас есть объект класса istream, который есть алиас от basic_istream. В MSDN конструктор класса basic_istream выглядит так:
explicit basic_istream(basic_streambuf<Elem, Tr> *_Strbuf, bool _Isstd = false);
То есть, нужен еще объект класса basic_streambuf. У него по MSDN конструктор без параметров. Я пробовал его создавать и указатель передавать в конструктор basic_istream. Но при запуске вылетал AV. Ну хоть бы пример в MSDN дали что-ли...
Да, про файловый и строковый я тоже знаю — эти примеры есть в МСДН, а вот с консоли как?
Самое смешное, для работы он мне нафиг не нужен — сколько лет программирую, обхожусь scanf\printf, а тут почитал тесты по С++, понял, что плохо знаю язык, решил подучиться у классиков, и теперь вижу, что совсем его не знаю ))))))))))))
Здравствуйте, ND322, Вы писали:
ND>Да, про файловый и строковый я тоже знаю — эти примеры есть в МСДН, а вот с консоли как?
Консоль в Windows это и есть (как бы) файл с именем "CON".
ND>Самое смешное, для работы он мне нафиг не нужен — сколько лет программирую, обхожусь scanf\printf, а тут почитал тесты по С++, понял, что плохо знаю язык, решил подучиться у классиков, и теперь вижу, что совсем его не знаю ))))))))))))
Здравствуйте, igna, Вы писали:
I>Здравствуйте, ND322, Вы писали:
ND>>Да, про файловый и строковый я тоже знаю — эти примеры есть в МСДН, а вот с консоли как?
I>Консоль в Windows это и есть (как бы) файл с именем "CON".
ND>>Самое смешное, для работы он мне нафиг не нужен — сколько лет программирую, обхожусь scanf\printf, а тут почитал тесты по С++, понял, что плохо знаю язык, решил подучиться у классиков, и теперь вижу, что совсем его не знаю ))))))))))))
I>А сколько лет ты программируешь, если не секрет?
Всего, или конкретно, на С++?
Вообще, начинал еще на Spectrum'е в начале 90-х (BASIC), потом году в 96-м собрал свой первый PC — сначала QBasic, потом TP, потом в институте начал MSVC учить, всякие транспортные задачи, комивояжеры, матрицы и прочие нехитрые SDI-шки, MDI-шки на нем писать. Потом работать пошел, пришлось перейти на Delphi, потом вообще несколько лет сам почти не кодил, теперь вот снова за C++ сел, и снова предпочел MS. Для прикладных задач знаний хватает, но книжки умные тоже читать надо.
Возвращаясь к примеру. Хочу таки докопаться.
С fstream заработало. Но ведь "родной" cin не от fstream унаследован? Они общего предка имеют, но cin сделан по-другому. Как?
Здравствуйте, ND322, Вы писали:
ND>Но ведь "родной" cin не от fstream унаследован?
Нет, хотя бы потому, что объекты не наследуются, наследуются классы (, экземплярами которых являются объекты).
Но даже если скорректировать твой вопрос заменив "cin" на "класс, экземпляром которого является cin", то тоже нет, поскольку в стандарте тип cin определен как istream. Причем именно istream, а не какой-либо производный от него тип. Как конкретно это сделано для конкретного компилятора, не знаю; но вот тебе пример, как под Windows можно получить объект типа istream для чтения с консоли:
#include <fstream>
#include <iostream>
#include <istream>
using namespace std;
int main()
{
filebuf fb;
fb.open("CON", ios_base::in);
istream in(&fb);
int i;
in >> i;
cout << i << '\n';
}
Да, вы правы! Причем, на самом деле (я о конкретной реализации в MSVС 2005 говорю), все еще хитрее.
cin объявлен как переменная типа istream.
__PURE_APPDOMAIN_GLOBAL extern _CRTDATA2 istream cin;
Сам тип istream это "ребрендинг" шаблонного класса basic_istream:
typedef basic_istream<char, char_traits<char> > istream;
И уже этот класс наследуется от basic_ios, который, как я догадываюсь, базовый для всех классов потоков:
template<class _Elem,class _Traits> class basic_istream: virtual public basic_ios<_Elem, _Traits>
У basic_istream два конструктора:
explicit __CLR_OR_THIS_CALL basic_istream(_Mysb *_Strbuf, bool _Isstd = false)
__CLR_OR_THIS_CALL basic_istream(_Uninitialized)
Второй работать отказывается, при попытке ввода через оператор >> объекта данного класса (созданного в статической или динамической памяти), он вылетает с АV. Первый вариант конструктора требует указатель на объект класса _Strbuf, у которого тоже своя богатая иерархия и весьма скудное описание в MSDN. Я так понимаю, в вашем крайнем примере, filebuf это синоним класса basic_filebuf, который в свою очередь, наследуется от basic_streambuf. Кажется, так. Осталось понять, какие еще потомки есть у basic_streambuf, и нет ли какого-то более элегантного решения, чем файл с именем "CON"...
Доделал пример из Страуструпа воспользовавшись идеей igna, посмотрите пожалуйста, буду благодарен за полезные замечания и идеи как это можно сделать лучше.
#include <iostream>
#include <sstream>
#include <string.h>
/.../
int main(int argc, char* argv[])
{
istringstream* in;
switch (argc)
{
case 1:
break;
case 2:
in = new istringstream(argv[1], ios_base::in); // ссылка на строковый поток, созданный по значению первого параметра вызова программы
cin.rdbuf((*in).rdbuf()); // используем новый буфер в качестве буфера потока cinbreak;
default:
cout << "Too many arguments\n";
return 1;
}
while (cin)
{
/.../
}
return no_of_errors;
}
У меня линукс, использую gcc-c++-4.5.1-4
Re[3]: istream:: Страупструп не пашет!
От:
Аноним
Дата:
21.11.11 21:49
Оценка:
Здравствуйте, rivest,
Вообще ничего не понимаю cin и (*in) к ссылке одного типа не приводятся, по всякому пробовал то мимо while проскакивает сразу или не читая вывод сразу циклится с какимто мусором. А "con" на 99.txt" заменил , один раз 99 выводит.
int main(int argc, char* argv[])
{
istringstream* in;
in = new istringstream("99.txt", ios_base::in); // ссылка на строковый поток, созданный по значению первого параметра вызова программы
cin.rdbuf((*in).rdbuf()); //// используем новый буфер в качестве буфера потока cin#define xin cin
#define xin (*in)
while (xin)
{ int i;
xin >> i;
cout << i << '\n';
}
return 0;
}
Считывается целое цисло 99 и выводится, среди следующих символов целых нет. Помоему все правильно. Попробуй считать char. Про почитать из актуального ничего кроме cplusplus.com — не знаю.
А>Здравствуйте, rivest, А>Вообще ничего не понимаю cin и (*in) к ссылке одного типа не приводятся, по всякому пробовал то мимо while проскакивает сразу или не читая вывод сразу циклится с какимто мусором. А "con" на 99.txt" заменил , один раз 99 выводит. А>
int main(int argc, char* argv[])
А>{
А> istringstream* in;
А> in = new istringstream("99.txt", ios_base::in); // ссылка на строковый поток, созданный по значению первого параметра вызова программы
А> cin.rdbuf((*in).rdbuf()); //// используем новый буфер в качестве буфера потока cin
А> #define xin cin
А> #define xin (*in)
А> while (xin)
А> { int i;
А> xin >> i;
А> cout << i << '\n';
А> }
А> return 0;
А>}
А>
Здравствуйте, rivest, Вы писали:
R>Считывается целое цисло 99 и выводится,
я потом догнал ( думал задача перенаправить ввод на файл — freopen(_args[1],"rt", stdin); )
R>из актуального ничего кроме cplusplus.com — не знаю.
Заметил MSDN тоже неплохим языком написан ( только в нем найти чет сложно ) редактор codeLobster за справкой по javascript на MSDN отправляет. Учить буду STL — на интервю его строго спрашивают