如何检测c ++ 0x中的转换是否失败

时间:2015-06-16 16:52:41

标签: c++ type-conversion

我尝试按如下方式执行字符串到int转换:

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

int main(int argc, char ** argv)
{
    int i;
    char *str = "12a3";
    std::stringstream ss;
    ss << str;
    ss >> i;
    std::cout << i << std::endl; //prints 12
}

DEMO

但结果并不是我所期待的。老实说,我是一个Java,我正在等待抛出一些异常。但事实并非如此。是否可以在没有遗留atoi功能的情况下以安全的方式执行此类投射。

请注意,我C++0x因此无法使用std::stoi

5 个答案:

答案 0 :(得分:4)

这是正确的行为。 <{1}}到>>的操作成功,这是正确的。

你必须问一个不同的问题。您真正想要执行的测试是:“在我成功读取int之后,是否有更多字符在流中剩余并且尚未处理?”

考虑int。当你这样做

cin

它尽可能多地从标准输入读取到int x, y; std::cin >> x; std::cin >> y; ,在第一个非数字处停止。然后,如果在第一个数字后面只有一些空格,那么它将尝试在空格后读取一个数字并将该数字存储在x中。

所有输入流(无论y还是实例cin)都应包含许多字符串/数字/等等。每个stringstream只能尽可能多地读取(成功)。

答案 1 :(得分:0)

我所知道的最简单的方法。

int main(int argc, char ** argv)
{
    std::string num;
    long i;
    char *str = "12a3";
    char * endp;
    std::stringstream ss;
    ss << str;
    ss >> num;
    i = strtol(num.c_str(), // string to convert as a C style string, 
               &endp, //pointer to be updated with character that ended the conversion
               10); //base of number conversion
    if (*endp != '\0')
    {
        //didn't read whole string. conversion failed
    }
    std::cout << i << std::endl; //prints 12
}

答案 2 :(得分:0)

您需要测试不成功的流读取和不完整的流读取:

ss >> i;
if (!ss || !ss.eof()) {
  throw std::invalid_argument("Could not convert to int");
}

答案 3 :(得分:0)

在评论中我们得出结论,您的目标是确定字符串是否仅包含数字的有效表示。

C,并且通过扩展,C ++始终专注于流I / O,因此是流式数字转换。结果是scanfistream >>atoistrol都停留在第一个不属于有效数字的字符处。

然后,您的目标是确定输入是否已完全消耗,或者是否存在尾随“垃圾”字符。最简单的方法是使用strtol,它将返回指向第一个未消耗字符的指针。

char * endptr;
long i = strtol (str, &endptr, 10); 
bool valid = *endptr == '\0';

如果您的输入如下所示,这仍然会失败:“123”,因为扫描将停在'3'后面的空格字符处。

如果您的要求是尾随空格是可接受的,那么您的代码将需要检查在调用后从* endptr开始的字符串,确定它是否是可接受的后缀,或者它可以在执行测试之前修剪输入字符串

答案 4 :(得分:-1)

当运营商>>找到无法使用的结果时,它会在流上设置failbit,并且流本身将评估为false

if(!(ss >> i)) {  // or ss >> i; if(!ss) or if(ss.fail())
    // the conversion failed, do whatever you need to here.
    ss.clear(); // reset the fail flag so you can read from the stream again

    // you can use ss.ignore() to skip bad input if you want to move on to other parts
}