提问人:GiaMat45 提问时间:11/3/2022 最后编辑:Remy LebeauGiaMat45 更新时间:11/4/2022 访问量:75
stringstream 运算符>>无法在调试中分配数字
stringstream operator>> fails to assign a number in debug
问:
我有一个简单的函数,给定一个字符串,如果它是一个数字,则返回“true”并覆盖引用输入。str
num
template <typename T>
bool toNumber(string str, T& num)
{
bool bRet = false;
if(str.length() > 0U)
{
if (str == "0")
{
num = static_cast<T>(0);
bRet = true;
}
else
{
std::stringstream ss;
ss << str;
ss >> num; // if str is not a number op>> it will assign 0 to num
if (num == static_cast<T>(0))
{
bRet = false;
}
else
{
bRet = true;
}
}
}
else
{
bRet = false;
}
return bRet;
}
所以我希望:
int x, y;
toNumber("90", x); // return true and x is 90
toNumber("New York", y); // return false and let y unasigned.
在我的机器上,debug 和 release 配置都工作正常,但在服务器上,只有使用调试配置,在像“ss >> num”这样的调用中无法识别这是一个字符串。toNumber("New York", y)
str
我检查了项目配置,但它们对于两台机器都是相同的(服务器是我本地 vs-2015 项目的 svn-checkout)。
我真的不知道如何解决这个问题。谁能帮我解决这个问题?
答:
0赞
n. m. could be an AI
11/3/2022
#1
if (num == static_cast<T>(0))
坏主意。要知道是否失败,请检查流的状态。operator>>
if (ss >> num) { ...
一旦你有了这个检查,(完全不正确的)部分
if (str == "0")
{
num = static_cast<T>(0);
bRet = true;
}
变得多余,并且
if(str.length() > 0U)
也变得多余,然后整个事情简化为一两行。
评论
0赞
GiaMat45
11/4/2022
谢谢你的提示。受此启发,我将 if 语句从 改为 to,它有效!if (num == static_cast<T>(0))
if (ss.fail())
1赞
Remy Lebeau
11/4/2022
@GiaMat45 你真的应该用而不是if (ss >> num)
ss >> num; if (ss.fail())
0赞
GiaMat45
11/4/2022
@RemyLebeau是的,我同意你的看法,我将直接使用 if。谢谢!>>
1赞
Marek R
11/4/2022
#2
你的代码太复杂了,你可以把它简化为:
template <typename T>
bool toNumber(std::string str, T& num)
{
return !!(std::istringstream { std::move(str) } >> num);
}
https://godbolt.org/z/Pq5xGdof5
好的,我错过了您希望在失败时避免零分配(默认情况的作用):
template <typename T>
bool toNumber(std::string str, T& num)
{
T tmp;
std::istringstream stream{ std::move(str) };
if (stream >> tmp) {
num = tmp;
}
return !!stream;
}
https://godbolt.org/z/nErqn3YYG
评论
0赞
Remy Lebeau
11/4/2022
OP 的问题中没有任何内容表明在返回时应保持未分配状态。这样做只会引入一个不必要的逻辑分支。举个例子,OP 的原始代码如果不为空或流失败,则执行零分配。num
false
num
str
"0"
0赞
Marek R
11/4/2022
在代码注释中表示: 和 .不是很直接,但仍然如此。当你想到为什么他的代码如此复杂时,这一定是一个根本原因(例如:必须是那个)。// return false and let y unasigned.
// if str is not a number op>> it will assign 0 to num
if (str == "0")
0赞
Remy Lebeau
11/4/2022
OP 代码的编写方式具有误导性,实际上更像是 since is true。 仅当为空时才未分配,但如果失败,则将分配。行为不是很一致。评论真的应该更像return false and let y unasigned
return false and y may or may not be left unasigned
if str is not a number op>> it will assign 0 to num
y
str
0
stringstream
return false and ignore y
5赞
Remy Lebeau
11/4/2022
#3
检查输出的数字的值是错误的方法。您应该检查 的失败状态,例如:operator>>
stringstream
template <typename T>
bool toNumber(string str, T& num)
{
bool bRet = false;
if (str.length() > 0U)
{
if (str == "0")
{
num = static_cast<T>(0);
bRet = true;
}
else
{
std::stringstream ss;
ss << str;
if (ss >> num) // <--
{
bRet = true;
}
else
{
bRet = false;
}
}
}
else
{
bRet = false;
}
return bRet;
}
operator>>
返回对输入流的引用,并且该流在布尔上下文中可隐式转换为,如语句,其中表示流处于良好状态,表示流处于失败状态。bool
if
true
false
在这种情况下,您可以通过摆脱冗余分配来进一步大大简化函数,并且冗余输入检查已经为您处理,例如:bRet
stringstream
template <typename T>
bool toNumber(const string &str, T& num)
{
std::istringstream ss(str);
return static_cast<bool>(ss >> num);
// or:
// return !!(ss >> num);
}
评论
0赞
GiaMat45
11/4/2022
感谢您的提示,但没有返回布尔值,然后编译器抛出此错误return (ss >> num)
'return': cannot convert from 'std::basic_istream<char,std::char_traits<char>>' to 'bool'
0赞
GiaMat45
11/4/2022
好的,现在演员阵容很好用!我将采用这个非常紧凑的版本。太棒了!
评论