Как я могу (во внешней функции) различать 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?
Вы можете проверить, если ваш ostream
- cout:
if (&out == &std::cout)
И вы можете предпринять соответствующие действия, в зависимости от результата. Но если вы хотите мое незатребованное мнение, я думаю, было бы лучше, если бы пользователь решил, как он печатает, используя какой-то класс форматирования:
std::cout << format(my_matrix, fancy);
outfile << format(my_matrix, not_fancy);
В этом примере format
будет функция, которая возвращает объект некоторого класса, который содержит объект Matrix
(по ссылке) и параметры форматирования. Этот класс будет перегружен operator<<
для загрузки соответствующего потока в поток на основе параметров, которые ему были предоставлены. Кроме того, вы можете создавать собственные специализированные манипуляторы ввода-вывода.
Не так легко, как я думал.
Это можно сделать, перегружая 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
явно введенный для любых функций, если вы хотите, чтобы это поведение было доступно внутри функции.
Вам нужно поддерживать некоторое состояние, чтобы решить, будет ли выход в кратком формате или в длинном формате. Лучшее место для хранения этих данных, я думаю, в самой 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. Вкладки не выглядят совершенно правильно. Я уверен, что функция может быть изменена, чтобы сохранить вкладки в правильном месте.
std::ofstream& operator<<(std::ofstream& ofs, const Matrix& y)
.out << x;
- Но если бы вы обращались кofstream
через ссылкуostream
, он быostream
к другому оператору. Например,out << '\n' << x;