使用三元运算符写入流?在 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 << '"' ) 这样的表达式是无效的,因为您不能将 doublechar 流式传输到字符串文字(相当于 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;
}