使用三元运算符写入流?在 C++ 中
Writing to stream using ternary operator ? in C++
我有几个double
类型的点。我只想在它们不是 0
时将它们写入流中。还有我要说是哪一个,像这样:
x1=" value "
y1=" value "
等等..
有什么办法可以这样吗:
<< ( (x1 != 0) ? ( "x1=\"" << x1 << '"' ) : ' ') )
<< ( (y1 != 0) ? ( "y1=\"" << y1 << '"' ) : ' ') )
或者我必须做几个 if
else
陈述?
代码将无法正常工作,如图所示。 ?:
运算符的两个操作数必须评估为相同的数据类型。在您的示例中:
左操作数甚至不是有效代码。像 ( "x1=\"" << x1 << '"' )
这样的表达式是无效的,因为您不能将 double
或 char
流式传输到字符串文字(相当于 const char[]
)。但如果它是有效代码,它将计算为 std::ostream&
,这是 <<
运算符的标准输出类型。
右操作数是char
.
由于它们不匹配类型,您不能使用 ?:
。您将不得不使用 if
语句来分解代码:
if (x1 != 0)
mystream << "x1=\"" << x1 << '"';
else
mystream << ' ';
if (y1 != 0)
mystream << "y1=\"" << y1 << '"';
else
mystream << ' ';
您不能将 <<
运算符用作未附加到左侧可流式对象的表达式的一部分,例如 std::ostream
.
如果您有一组 double
个变量,我可能会建议您考虑对它们进行循环。这是 "several if-else
statements" 的改进。将它们放在数组或其他可以迭代的对象中:即:
// Example using 10 elements
#define N 10
double nums[N];
// ... code
for (int i = 0; i < N; ++i) {
if (nums[i] != 0) {
cout << "nums[" << i << "]=\"" << nums[i] << "\"";
}
}
为了帮助澄清这是为什么,请考虑将每个 <<
分解为一个函数调用(本质上是幕后发生的事情):
(((std::cout << "string1") << 10) << std::endl);
std::cout << "string1"
解析为
ostream& operator<<(ostream& stream, const char* str) {
// Ouptut the string
return stream;
}
这允许能够使用连续的 <<
运算符的 "chaining" 效果,因为每个运算符调用解析为相同的 ostream
.
您可以调用采用 lambda 的流操纵器:
#include <functional>
#include <iostream>
struct Manipulator {
using function_type = std::function<void (std::ostream&)>;
function_type function;
Manipulator(function_type function) : function(function) {}
};
inline std::ostream& operator << (std::ostream& stream, const Manipulator& manipulator) {
manipulator.function(stream);
return stream;
}
int main() {
int a = 0;
int b = 1;
std::cout
<< Manipulator([a](std::ostream& stream) { if(a) stream << "a=\"" << a << '"'; })
<< Manipulator([b](std::ostream& stream) { if(b) stream << "b=\"" << b << '"'; })
<< '\n';
}
注意:C++14 广义 lambda 捕获允许将 std::ostream&
替换为 auto&
。
这里是@Dieter Lücking 方法的简化版本
你可以像这样使用 lambda:
#include <iostream>
int main()
{
int a = 0;
int b = 1;
[](std::ostream& stream, int x)->std::ostream& { if(x) stream << "b=\"" << x << '"'; return stream;}(std::cout, a);
[](std::ostream& stream, int x)->std::ostream& { if(x) stream << "b=\"" << x << '"'; return stream;}(std::cout, b) << std::endl;
}
我有几个double
类型的点。我只想在它们不是 0
时将它们写入流中。还有我要说是哪一个,像这样:
x1=" value "
y1=" value "
等等..
有什么办法可以这样吗:
<< ( (x1 != 0) ? ( "x1=\"" << x1 << '"' ) : ' ') )
<< ( (y1 != 0) ? ( "y1=\"" << y1 << '"' ) : ' ') )
或者我必须做几个 if
else
陈述?
代码将无法正常工作,如图所示。 ?:
运算符的两个操作数必须评估为相同的数据类型。在您的示例中:
左操作数甚至不是有效代码。像
( "x1=\"" << x1 << '"' )
这样的表达式是无效的,因为您不能将double
或char
流式传输到字符串文字(相当于const char[]
)。但如果它是有效代码,它将计算为std::ostream&
,这是<<
运算符的标准输出类型。右操作数是
char
.
由于它们不匹配类型,您不能使用 ?:
。您将不得不使用 if
语句来分解代码:
if (x1 != 0)
mystream << "x1=\"" << x1 << '"';
else
mystream << ' ';
if (y1 != 0)
mystream << "y1=\"" << y1 << '"';
else
mystream << ' ';
您不能将 <<
运算符用作未附加到左侧可流式对象的表达式的一部分,例如 std::ostream
.
如果您有一组 double
个变量,我可能会建议您考虑对它们进行循环。这是 "several if-else
statements" 的改进。将它们放在数组或其他可以迭代的对象中:即:
// Example using 10 elements
#define N 10
double nums[N];
// ... code
for (int i = 0; i < N; ++i) {
if (nums[i] != 0) {
cout << "nums[" << i << "]=\"" << nums[i] << "\"";
}
}
为了帮助澄清这是为什么,请考虑将每个 <<
分解为一个函数调用(本质上是幕后发生的事情):
(((std::cout << "string1") << 10) << std::endl);
std::cout << "string1"
解析为
ostream& operator<<(ostream& stream, const char* str) {
// Ouptut the string
return stream;
}
这允许能够使用连续的 <<
运算符的 "chaining" 效果,因为每个运算符调用解析为相同的 ostream
.
您可以调用采用 lambda 的流操纵器:
#include <functional>
#include <iostream>
struct Manipulator {
using function_type = std::function<void (std::ostream&)>;
function_type function;
Manipulator(function_type function) : function(function) {}
};
inline std::ostream& operator << (std::ostream& stream, const Manipulator& manipulator) {
manipulator.function(stream);
return stream;
}
int main() {
int a = 0;
int b = 1;
std::cout
<< Manipulator([a](std::ostream& stream) { if(a) stream << "a=\"" << a << '"'; })
<< Manipulator([b](std::ostream& stream) { if(b) stream << "b=\"" << b << '"'; })
<< '\n';
}
注意:C++14 广义 lambda 捕获允许将 std::ostream&
替换为 auto&
。
这里是@Dieter Lücking 方法的简化版本
你可以像这样使用 lambda:
#include <iostream>
int main()
{
int a = 0;
int b = 1;
[](std::ostream& stream, int x)->std::ostream& { if(x) stream << "b=\"" << x << '"'; return stream;}(std::cout, a);
[](std::ostream& stream, int x)->std::ostream& { if(x) stream << "b=\"" << x << '"'; return stream;}(std::cout, b) << std::endl;
}