C++下标越界问题

3
我正在运行一个C++程序,它应该将字符串转换为十六进制。它编译了,但在运行时出错,显示:

Debug Assertion Failed!(哦,不!)

Visual Studio2010\include\xstring

Line 1440

Expression: string subscript out of range

而且我别无选择,只能终止程序... 它似乎已经把字符串转换成了十六进制,但我不确定发生了什么。我的代码很简单:

#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
int main()
{
    string hello = "Hello World";
    int i = 0;
    while(hello.length())
    {
        cout << setfill('0') << setw(2) << hex << (unsigned int)hello[i];
        i++;
    }

    return 0;
}

这个程序的作用是将每个字母逐个转换为十六进制。
5个回答

6

您没有从字符串中删除任何内容,因此 length() 总是返回相同的数字,这个数字会转换为 true

请改用 for 循环:

for(int i = 0; i < hello.length(); ++i)
{
    cout << setfill('0') << setw(2) << hex << (unsigned int)hello[i];
}

甚至更好的方法是使用迭代器。
for(std::string::iterator it = hello.begin(); it != hello.end(); ++it)
{
    cout << setfill('0') << setw(2) << hex << *it;
}

4
您的while条件不正确:
while(hello.length())

循环永远不会终止,i 变得很大(大于字符串长度减一),当你在该索引处访问字符串时,会出现运行时断言错误。
更改为:

修改它为:

while(i < hello.length())

或者更好的方法是使用迭代器。

哇,为什么它会编译并给出如此奇怪的错误信息呢?(顺便说一句,谢谢) - Howdy_McGee
@Howdy_McGee 因为编译器不应该寻找运行时错误。请注意,如果您在 while 表达式中有一个常量或局部变量 - 您将会收到一个警告。但是函数调用会让编译器假设数据可能会改变。 - littleadv

2
while(i < hello.length())
    {
        cout << setfill('0') << setw(2) << hex << (unsigned int)hello[i];
        i++;
    }

您原本的循环永远不会结束。对于计数索引,我认为 for 循环语法更加合适。


@Jesse 谢谢 :) 有时候我感觉自己就像在比赛谁射击更快... - littleadv

0
你在 while 循环中缺少条件。
 while(i < hello.length())
    {
        cout << setfill('0') << setw(2) << hex << (unsigned int)hello[i];
        ++i;
    }

0

我更喜欢在for循环中使用迭代器。

for (std::string::const_iterator it = hello.begin(); it != hello.end(); ++it) {
    // String processing
}

或者,在C++11中:

for (char const c : hello) {
    // String processing
}

一般来说,在 C++ 中,我更喜欢使用迭代器来访问事物。这是更符合惯用法的方式,并且适用于所有类型的 STL 容器。例如,如果您将来想要使用 std::dequestd::list,那么迭代器仍然可以使用。
另外,我建议避免使用 C 风格的转换。也就是说,不要使用 (unsigned int)。相反,使用 static_cast<unsigned> (*it)。这样只会给您提供您实际需要的转换能力,从而传达您的意图。C 风格的转换范围更广,但在这里,您只想在整数类型之间进行转换。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接