Howdy_McGee
Howdy_McGee

Reputation: 10673

C++ Out of Subscript Range

I'm running a C++ Program that is supposed to convert string to hexadecimals. It compiles but errors out of me at runtime saying:

Debug Assertion Failed! (Oh no!)

Visual Studio2010\include\xstring

Line 1440

Expression: string subscript out of range

And I have no choice to abort... It seems like it converts it though up to the point of error so I'm not sure what's going on. My code is simple:

#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;
}

What this program should do is convert each letter to hexadecimal - char by char.

Upvotes: 3

Views: 4490

Answers (5)

Pubby
Pubby

Reputation: 53067

You're not removing anything from the string and so length() will always return the same number which converts to true.

Use a for loop instead:

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

Or even better, use iterators.

for(std::string::iterator it = hello.begin(); it != hello.end(); ++it)
{
    cout << setfill('0') << setw(2) << hex << *it;
}

Upvotes: 6

David Stone
David Stone

Reputation: 28893

I would prefer iterators here in a for loop.

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

Or, in C++11:

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

In general, I prefer to use iterators to access things whenever possible in C++. It's the more idiomatic way to do it, and it works for all types of STL containers. For instance, if you want to some day use a std::deque or std::list, then iterators will still work.

On another style note, I would avoid C-style casting. That is where you did (unsigned int). Instead, use static_cast<unsigned> (*it). This conveys your intent by only giving you casting abilities that you are actually after. A C-style cast is much more broad, but all you want here is to convert between sizes of integer types.

Upvotes: 0

Nadeem Yasin
Nadeem Yasin

Reputation: 4534

You are missing the condition in while loop.

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

Upvotes: 0

codaddict
codaddict

Reputation: 455312

Your while condition is incorrect:

while(hello.length())

The loop never terminates and i becomes large (more than string length minus one) and when you access the string at that index you get runtime assertion.

Change it to:

while(i < hello.length())

Or better use iterators.

Upvotes: 4

littleadv
littleadv

Reputation: 20282

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

Your original loop never ends. For counting indexes, I find the for loop syntax better suited.

Upvotes: 2

Related Questions