0

I just started using the stringstream for the first time and I love the concept, but I am having a hard time finding where exactly I am having an out of range in memory with my stringstream function.

What my function does is it takes in a string, for example, "N02550 G3 X16.7379 Y51.7040 R0.0115" This is machine code for a CNC machine at my job. I pass the string to a stringstream in order to find the strings that have a X, Z, Y next to them, these are coordinates. It then gets rid of the character at the beggining in order to save the float number to my struct "Coordinate"(there are 3 doubles, x, y, z).

When I run a text file that has this machine code with 33 lines, my program works. When I run it with machine code of 718 lines, it gets to 718, then crashes with out of range memory. Then another weird part is when I run machine code with 118,000 lines, it goes up to around 22,000 lines then crashes. So I'm having trouble figuring out why it is able to do that and whats causing the problem.

Here is the function:

   void getC(string& line, Coordinates& c)//coordinates holds 3 doubles, x, y, z
{
    //variables
    string holder;
    stringstream ss(line);

    while(ss)
    {
        ss >> holder;
        if(holder.at(0) == 'X')
        {
            holder.erase(0,1);//get rid the the character at the beggining
            stringstream sss(holder);
            sss >> c.x;
            sss.clear();
        }
        if(holder.at(0) == 'Y')
        {
            holder.erase(0,1);
            stringstream sss(holder);
            sss >> c.y;
            sss.clear();
        }
        if(holder.at(0) == 'Z')
        {
            holder.erase(0,1);
            stringstream sss(holder);
            sss >> c.z;
            sss.clear();
        }
        if(ss.eof()) // to get out of the ss stream
            break;

    }
    ss.clear();
}

If you want to see the whole application(the application is well documented) then ask or if you need the txt files containing the machine code. Thank you!

Derek Welton
  • 95
  • 1
  • 6
  • By "crashes" do you mean "throws an exception" ? The most obvious scenario would be if `at(0)` fails because the string is empty – M.M Jun 02 '15 at 06:04

1 Answers1

2

Try changing:

while(ss)
{
    ss >> holder;
    ...
    if(ss.eof()) // to get out of the ss stream
        break;
}

To simply this:

while(ss >> holder)
{
    ...
}

And you can get rid of those calls to clear in each branch (X/Y/Z) as it doesn't really do anything given that sss is a temporary and you're not doing anything more with it (no point setting flags on something you're going to discard right after). I suspect your out of range issue is coming from trying to access holder.at(0) after ss >> holder fails.

You generally want to check for input failure right after reading a token, and a convenient way to both attempt to input and check for failure at once is to simply check if ss >> token evaluates to true. So we can write code like:

if (ss >> token)
{
    ...
}
else
{
    // handle failure if necessary
}

I generally find it's a lot easier to avoid getting in trouble writing code that way than manually checking error flags.

As a simplified version:

void getC(string& line, Coordinates& c)
{
    stringstream ss(line);   
    for (string holder; ss >> holder; )
    {
        const char ch = holder.at(0);
        stringstream sss(holder.substr(1));
        if (ch == 'X')
            sss >> c.x;
        else if (ch == 'Y')
            sss >> c.y;
        else if (ch == 'Z')
            sss >> c.z;
    }
}
  • I found out what was causing the problem, it was due to white lines. Thank you for explaining why and for the advice instead of just posting the answer. Its hard to learn with just code. Thanks for the advice of always puting an else statement to help find problems easier! – Derek Welton Jun 03 '15 at 00:46