如何为 istream/istringstream 使用“固定”浮点域?

Posted

技术标签:

【中文标题】如何为 istream/istringstream 使用“固定”浮点域?【英文标题】:How to use 'fixed' floatfield for istream/istringstream? 【发布时间】:2015-06-21 19:01:12 【问题描述】:

C++ 有一个称为“固定”的 I/O 操纵器,用于以固定(非科学)形式输入/输出浮点数。它适用于输出,但我不明白如何让输入正常工作。

考虑这个例子:

#include <sstream>
#include <iostream>
using namespace std;

int main() 
    double value;
    istringstream("1.4e1") >> fixed >> value;
    cout << value << endl;

在我看来,它应该像这样工作。输入流有一些字符串。当我们在其上应用fixed 操纵器并尝试读取双精度/浮点数时,它应该停在不是数字或点的第一个字符上(不接受第二/第三/更多次点)。所以,正确的输出应该是1.4(当我们遇到'e'时我们会停止处理输入)。

相反,此代码输出14。为什么?它是如何工作的,fixed 用于输入流的目的是什么?如何从输入流中读取双精度并在 'e' 处停止(将其保留在输入流中)?

【问题讨论】:

std::fixed 对输入流没有任何用途。算术格式化操纵器都不适用于输入流。 @0x499602D2 好的,谢谢。解决方案呢?是否有任何简单的方法(无需编写解析器)来读取双精度,将e 留在输入流中? 显然没有简单的方法。我正在查看提取器的代码,似乎没有办法阻止解析器使用eE。您必须将其读入字符串并自己解析。 @0x499602D2,你能发表你的评论作为答案吗? 【参考方案1】:

你应该使用 std::scientific 我试过这样:

#include <sstream>
#include <iostream>
using namespace std;

int main() 
    double value;
    cin >> std::fixed>> std::scientific >> value;
    cout << std::scientific<<value << endl;

输入:1.4e1 输出:1.400000e+01

【讨论】:

不完全是。我需要读取一个值作为1.4,将e 留在输入流中。有可能吗?【参考方案2】:

这个问题有点误导。 1.4e1 = 1.4 * 10¹ = 1.4 * 10 = 14

[...] 它应该停在不是数字或点的第一个字符(点 不接受第二次/第三次/更多次)。

为什么会这样? 1.4e1 中的e1 是数字的部分:没有它,含义就不同了。如果你想正确解析它,你必须阅读它。

所以,正确的输出应该是 1.4(当我们停止处理输入时 遇到'e')。

如果您正在读取整数类型,当遇到非数字字符 ([0-9]) 或触发其他条件(如上溢或下溢)时“停止”解析,这将适用。

【讨论】:

如果我对您的问题的假设是正确的,我们可能会尝试讨论解决方案。 不,我只想阅读1.4 部分并停止。假设我们没有最终的1,而e 只是表示某个单位的后缀。所以,输入是1.4e,或1.4euro。我不需要在数字后读取任何字符到我的号码中,它将转到另一个变量。但我还需要读取双精度数,而不是整数。看起来没有简单的方法可以做到这一点。 我明白了,@JIghtuse。但是eeuro 是不同的!如果你有1.4 euro,它会起作用。由于指数必须在尾数旁边,因此可以在它们之间留一个简单的空格。 @Steephen 它与 UDL 无关。 是的,我知道一个空格会改变一切。之后我对阅读 double 和 char 感兴趣,因此在这种情况下,euro 中的 e 是相同的(即,我对第一个之后的字符不感兴趣)。【参考方案3】:

我需要读取1.4 的值,将e 留在输入流中。有可能吗?

对此没有标准的操纵器,我相信有一种方法可以定义自定义的操纵器,但这太复杂了。我还没有找到关于如何在 SO 上执行此操作的答案,我只找到了 a question about output stream modifier。

让我们至少找到某种解决方案。那将是自己解析它:

#include <iostream>
#include <sstream>
#include <string>
#include <cctype>

int main()

    std::istringstream iss("1.4e1");
    double value;

    
        std::string s;

        while(iss.peek() != 'e' && !std::isspace(iss.peek()))
            s.push_back(iss.get());

        std::istringstream(s) >> value;
    

    std::cout << value << std::endl;

【讨论】:

以上是关于如何为 istream/istringstream 使用“固定”浮点域?的主要内容,如果未能解决你的问题,请参考以下文章

如何为@Valid 指定验证组?

如何为下拉菜单制作 CSS 边框?

如何为 CAShapeLayer 路径和填充颜色设置动画

iPhone - 如何为图像着色?

如何为 RecyclerView 设置 onItemClickListener? [复制]

WCF - 如何为 NTLM 身份验证配置 netTcpBinding?