Использование одного и того же объекта потока для записи в файловый или строковый поток

Я пытаюсь использовать объект ostream для записи либо в файловый поток пользовательского ввода на основе строкового потока (аналогично fmemopen в Linux).

Я понял, что ostream не принимает объекты stringstream или fstream, а вместо этого принимает stringbug или filebuf.

Я попробовал следующий код:

    char content[] = "This is a test";
    if (isFile)
    {
        filebuf fp;
        fp.open(filename, ios::out);
        ostream os(&fp);
        os << content;
        fp.close();
    }
    else
    {
        stringbuf str;
        ostream os(&str);
        os << content;
    }

Это отлично работает в условии if else, но я хотел бы использовать ostream os как os << content вне условия if else. Однако проблема в том, что я не могу глобально определить ostream os, поскольку для ostream нет такого конструктора.

Есть ли способ обойти это?

Отделите запись данных от настройки механизма вывода. Напишите функцию, которая вставляет данные в поток. Эта функция должна принимать std::ostream по ссылке и записывать туда данные. Когда вы вызываете функцию, передайте std::ofstream или std::ostringstream, в зависимости от ситуации.

Pete Becker 12.04.2019 03:02

Это то, с чем я могу работать. Есть ли способ по умолчанию инициализировать insertdata(ostream& os), чтобы сказать insertdata(ostream& os = ofstream("temp.txt",ios::out)? Это дает мне ошибку. Это работает, если я делаю const ostream& os, но тогда os.write выдает ошибку компиляции.

Trancey 12.04.2019 06:43

@Trancey, неконстантная ссылка не может быть привязана к временному объекту. Кроме того, это не тот сценарий, в котором имеет смысл использовать значение по умолчанию. Вызывающий должен указать, в какой тип потока функция должна писать.

Remy Lebeau 12.04.2019 11:43
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
3
591
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

С этим можно справиться несколькими способами.

Использование вспомогательной функции:

void write(ostream &os, const char *content)
{
    os << content
}

...

char content[] = "This is a test";
if (isFile)
{
    ofstream ofs(filename);
    write(ofs, content);
}
else
{
    ostringstream oss;
    write(oss, content);
    string s = oss.str();
    // use s as needed...
}

В качестве альтернативы, используя лямбда:

char content[] = "This is a test";
auto write = [](ostream &os, const char *content){ os << content; }

if (isFile)
{
    ofstream ofs(filename);
    write(ofs, content);
}
else
{
    ostringstream oss;
    write(oss, content);
    string s = oss.str();
    // use s as needed...
}

Вместо этого используйте указатель:

char content[] = "This is a test";
std::unique_ptr<ostream> os;

if (isFile)
    os = std::make_unique<ofstream>(filename);
else
    os = std::make_unique<ostringstream>();

*os << content;

if (!isFile)
{
    string s = static_cast<ostringstream*>(os.get())->str(); // or: static_cast<ostringstream&>(*os).str()
    // use s as needed...
}

Это помогает! *os << content для ostringstream, можно ли это записать в объект ostringstream? Кажется, я могу получить его из указателя rdbuf streambuf, но я не могу поместить его в стандартную строку или stringstream.

Trancey 12.04.2019 22:05

Моя ошибка, *oss << content должно было быть *os << content. И да, это может написать ostringstream, так как это потомок ostream. Чтобы впоследствии получить string, вы можете привести ostream обратно к ostringstream, чтобы вызвать его метод str(). Я обновил свой ответ, чтобы показать, что

Remy Lebeau 12.04.2019 22:31

Другие вопросы по теме