C ++ Insertion << перегрузка оператора

0

Как я могу (во внешней функции) различать cout << thingToShow и outfile << thingToWrite с различными форматами? У меня есть один файл, который, как я предполагаю, строит всю эту реализацию, не меняя ничего, и есть примеры

    cout << "\nx matrix is: \n";
    cout << x;
    cout << "\ny matrix is: \n";
    cout << y;

которые должны быть отформатированы как

x matrix is: 
         ---              ---
        |       30  50      |
        |                   |
        |       25  40      |
         ---              ---


y matrix is: 
         ---              ---
        |       2   3       |
        |                   |
        |       1   1       |
         ---              ---

и у меня есть пример

w = r * w;

outfile << w;

которые должны быть отформатированы просто как

-20    40
-80    60

моя реализация

ostream& operator<< (ostream &out, const Matrix& y){
    out << "\t\t" << " ---\t\t\t\t    ---\n"<< "\t\t|\t\t"<<y.tl<< "\t"<<y.tr<< "\t\t|\n\t\t|\t\t\t\t\t|\n\t\t|\t\t"<<y.bl<< "\t"<<y.br<< "\t\t|\n" << "\t\t" << " ---\t\t\t\t    ---\n\n";
    return out;
}

который работает для стандартного вывода cout << thingToShow, но, очевидно, испортил формат outfile << thingToWrite. есть ли свойство аргумента (stream & out,), которое можно ввести в оператор if? или есть ли другой способ различать cout и outfile?

  • 0
    Возможно перегрузка std::ofstream& operator<<(std::ofstream& ofs, const Matrix& y) .
  • 0
    @Galik: Это дало бы странное поведение. Это будет работать для одного не связанного оператора вывода, такого как out << x; - Но если бы вы обращались к ofstream через ссылку ostream , он бы ostream к другому оператору. Например, out << '\n' << x;
Показать ещё 1 комментарий
Теги:
operators
operator-overloading
overloading
cout

3 ответа

2

Вы можете проверить, если ваш ostream - cout:

if (&out == &std::cout)

И вы можете предпринять соответствующие действия, в зависимости от результата. Но если вы хотите мое незатребованное мнение, я думаю, было бы лучше, если бы пользователь решил, как он печатает, используя какой-то класс форматирования:

std::cout << format(my_matrix, fancy);
outfile << format(my_matrix, not_fancy);

В этом примере format будет функция, которая возвращает объект некоторого класса, который содержит объект Matrix (по ссылке) и параметры форматирования. Этот класс будет перегружен operator<< для загрузки соответствующего потока в поток на основе параметров, которые ему были предоставлены. Кроме того, вы можете создавать собственные специализированные манипуляторы ввода-вывода.

0

Не так легко, как я думал.

Это можно сделать, перегружая std::ifstream. Это означает, что вам придется перегружать его для всех типов, поэтому в дополнение к перегрузке Matrix необходима перегрузка шаблонов всех шаблонов.

struct Matrix
{
    int a, b;
};

// Matrix for std::cout
std::ostream& operator<<(std::ostream& os, const Matrix& t)
{
    os << "[\n\t" << t.a << "\n\t" << t.b << "\n]";
    return os;
}

// overload of general types for files
template<typename Type>
std::ofstream& operator<<(std::ofstream& ofs, const Type& t)
{
    // this cast prevents infinite recursion
    static_cast<std::ostream&>(ofs) << t;
    return ofs;
}

// Matrix overload for files
std::ofstream& operator<<(std::ofstream& ofs, const Matrix& t)
{
    // this cast prevents infinite recursion
    static_cast<std::ostream&>(ofs) << "{" << t.a << ", " << t.b << "}";
    return ofs;
}

int main()
{
    std::ofstream ofs("test.txt");

    Matrix m {3, 7};

    std::cout << 4 << m << 9 << '\n';
    ofs << 4 << m << 9 << '\n';
}

Выход: std :: cout

4[
    3
    7
]9

Выход: из

4{3, 7}9

ПРИМЕЧАНИЕ. Этот подход различает std::ofstream и его родительский класс std::ostream. Это означает, что вы должны передать свой std::ifstream явно введенный для любых функций, если вы хотите, чтобы это поведение было доступно внутри функции.

0

Вам нужно поддерживать некоторое состояние, чтобы решить, будет ли выход в кратком формате или в длинном формате. Лучшее место для хранения этих данных, я думаю, в самой Matrix классов.

Затем укажите функции, которые можно использовать для установки формата. Вы также можете предоставить функцию перегруженного operator<< чтобы вы могли использовать их с ostream.

Вот рабочая версия.

#include <iostream>

struct Matrix
{
   int tl;
   int tr;
   int bl;
   int br;

   static void setLongFormat();

   static void setShortFormat();

   enum OutputFormat
   {
      LONG_FROMAT,
      SHORT_FORMAT
   };

   static OutputFormat outputFormat;
};

Matrix::OutputFormat Matrix::outputFormat = Matrix::SHORT_FORMAT;

void Matrix::setLongFormat()
{
   outputFormat = LONG_FROMAT;
}

void Matrix::setShortFormat()
{
   outputFormat = SHORT_FORMAT;
}

std::ostream& operator<< (std::ostream &out, const Matrix& y)
{
   if ( Matrix::outputFormat == Matrix::LONG_FROMAT )
   {
      out << "\t\t" << " ---\t\t\t\t    ---\n"
         << "\t\t|\t\t"<<y.tl<< "\t"<<y.tr<< "\t\t|\n"
         << "\t\t|\t\t\t\t\t|\n"
         << "\t\t|\t\t"<<y.bl<< "\t"<<y.br<< "\t\t|\n"
         << "\t\t" << " ---\t\t\t\t    ---\n\n";
   }
   else
   {
      out << y.tl<< "\t" << y.tr<< "\n"
         << y.bl<< "\t" << y.br<< "\n";
   }

   return out;
}

std::ostream& operator<<(std::ostream &out, void (*fun)())
{
   fun();
   return out;
}


int main()
{
   Matrix a{30, 50, 25, 40};
   std::cout << Matrix::setLongFormat << a << std::endl;
   std::cout << Matrix::setShortFormat << a << std::endl;
};

Вывод:

         ---                    ---
        |       30  50      |
        |                   |
        |       25  40      |
         ---                    ---


30  50
25  40

PS. Вкладки не выглядят совершенно правильно. Я уверен, что функция может быть изменена, чтобы сохранить вкладки в правильном месте.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню