我如何(在外部函数中)区分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&lt;&lt; thingToShow输出格式,但显然会弄乱outfile&lt;&lt; thingToWrite格式。 我可以在if语句中放入(stream&amp; out,)参数的属性吗?或者是否有其他方法来区分cout和outfile?
答案 0 :(得分:2)
您可以测试ostream
是否为cout:
if (&out == &std::cout)
您可以采取适当的行动,具体取决于结果。但是如果你想要我未经请求的意见,我认为最好让用户决定如何打印出来,使用某种格式化的类:
std::cout << format(my_matrix, fancy);
outfile << format(my_matrix, not_fancy);
在此示例中,format
将是一个函数,它返回某个类的对象,该对象包含Matrix
对象(通过引用)和格式化选项。此类将重载operator<<
,以根据给定的选项为流生成适当的输出。或者,您可以制作自己的专用I / O操纵器。
答案 1 :(得分: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。这些标签在这里看起来不太合适。我确信可以修改该功能以使标签保持在正确的位置。
答案 2 :(得分: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
输出:ofs
4{3, 7}9
注意:此方法区分std::ofstream
及其父类std::ostream
。这意味着如果您希望在函数中使用此行为,则必须将显式类型std::ifstream
传递给任何函数。