c++ - 使用 string::size_type vs int 遍历字符串
问题描述
这是我在使用 C++14 标准(32 位/Windows 10)的 TDM-GCC 上使用的代码:
class var
{
private:
vector<int> num;
public:
var(string x)
{
for(int i = x.size()-1; i >= 0; i--) // Notice use of INT
num.push_back(x[i]-'0');
}
};
int main()
{
var num1("232");
return 0;
}
工作得很好,但最佳实践(和几个 SO 答案)说我应该使用string::size_type
而不是int
因为字符串可能比int
可以容纳的更长。
现在,当我替换int
为 时string::size_type
,会发生一些奇怪的事情;以下代码可以编译,但是当我执行它时,它什么也不做。而是弹出窗口,显示“thisProgram.exe 已停止工作...”对话框,终端突然关闭。(带有任意大的返回码)
class var
{
private:
vector<int> num;
public:
var(string x)
{
// Everything is same except the following line has string::size_type instead of int
for(string::size_type i = x.size()-1; i >= 0; i--)
num.push_back(x[i]-'0');
}
};
int main()
{
var num1("232");
return 0;
}
那么,使用有什么问题string::size_type
呢?这个编译器是特定的吗?我真的很困惑,因为没有错误消息。
解决方案
string::size_type
是无符号类型,这意味着它永远不会是负数。这意味着这种情况:
i >= 0
永远不会是假的。事实上,当i
低于时0
,它会回绕,并成为 的最大可能string::size_type
值。然后,当您 index 时x[i]
,您会调用未定义的行为。
我建议这样写循环:
for(int i = static_cast<int>(x.size()) - 1; i >= 0; i--)
// ...
注意static_cast
在减 1 之前(否则你会遇到空字符串的问题)。
除非您有非常大的字符串,否则长度应该在int
可以处理的范围内。如果确实需要string::size_type
索引,也可以执行此循环:
auto i = x.size();
while (i-- > 0)
// ...
unsigned
请注意,这对类型是健壮的。比较0
发生在减量之前i
(因此是减量后运算符)。所以你很好地得到了索引size-1, size-2, ..., 1,0
。当i
is0
时,比较将失败,然后i
变成一个大正数的事实并不重要。
推荐阅读
- powershell - 从 powershell 发送邮件
- typescript - 如何基于 env 禁用 NestJS Logger?
- java - IJ031070:事务无法继续:STATUS_MARKED_ROLLBACK
- java - 错误:-source 8 中不支持模块 - Intellij Idea
- asp.net-core - Blazor 清理标记字符串
- google-apps-script - 根据单元格中的值发送带有或不带有内联图像的电子邮件
- model - 运行 gensim 的 LDA 模型时出现运行时错误,我该如何解决?
- ruby-on-rails - Windows 10 pro 中的 Docker 文件权限
- python - 如果我想按一个标准升序排序并按另一个标准降序排序,我该如何使用排序功能?
- c# - JsonConvert Items 按特定字段