我尝试按如下方式执行字符串到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
}
但结果并不是我所期待的。老实说,我是一个Java,我正在等待抛出一些异常。但事实并非如此。是否可以在没有遗留atoi
功能的情况下以安全的方式执行此类投射。
请注意,我C++0x
因此无法使用std::stoi
。
答案 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,因此是流式数字转换。结果是scanf
,istream >>
,atoi
和strol
都停留在第一个不属于有效数字的字符处。
然后,您的目标是确定输入是否已完全消耗,或者是否存在尾随“垃圾”字符。最简单的方法是使用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
}