繁体   English   中英

使用 string::size_type vs int 遍历字符串

[英]Iterating over a string with string::size_type vs int

这是我在 TDM-GCC 上使用 C++14 标准(32 位/Windows 10)的代码:

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可以容纳的长。

现在,当我用string::size_type替换int时,会发生一些奇怪的事情; 以下代码可以编译,但是当我执行它时,它什么也不做。 而是 windows 弹出“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最大可能值 然后,当您索引x[i]时,您会调用未定义的行为。

我建议这样写循环:

for(int i = static_cast<int>(x.size()) - 1; i >= 0; i--)
  // ...

注意在减 1之前static_cast (否则你会遇到空字符串的问题)。

除非你有非常大的字符串,否则长度应该在int可以处理的范围内。 如果确实需要string::size_type索引,也可以执行此循环:

auto i = x.size();
while (i-- > 0)
  // ...

请注意,这对unsigned类型是健壮的。 0的比较发生i递减之前(因此是后递减运算符)。 所以你很好地得到了索引size-1, size-2, ..., 1,0 i0时,比较将失败,然后i变为大正数这一事实并不重要。

当您编写使用无符号索引和 go 向后的循环时,您必须稍微更改您的习惯用法:

for (std::string::size_type i = x.size(); i > 0; --i)
    num.push_back(x[i-1] - '0');

这样你就不必处理从 0 中减去 1 的可能性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM