Problem with a format function

So, I've written a function to format input I give it. It's intended to keep words from splitting at the end of a line, and remove spaces from the beginning of lines. It works for most any input I give it, but here's one line of input that causes a runtime error, and I'm not sure why. Here's what I have:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>
#include <string>
using namespace std;
string f(string);

int main()
{
    cout << f("\"X7, initiate hover mode and get in the speeder. We're leaving.\" The droid's torso emits a humming throb as he activates his custom repulsor unit. The droid begins to float above the repair bay floor. X7 retracts his legs into his barrel shaped torso-manifold, coming to rest in the passenger seat of your landspeeder.");
    system("pause");
    return 0;
}

string f(string text)
{
       cout << "\n\n";
       for(int x = 1; x <= (text.size() / 80); x++)
       {
               if(!(text.at(80*x-1) == ' '))
               {
                                  if(!(text.at(80*x) == ' '))
                                  {
                                                       int count = 1;
                                                       while(!(text.at(80*x-count) == ' '))
                                                       {
                                                                                   count = count + 1;
                                                       }
                                                       for(int y = 1; y < count; y++)
                                                       text.insert(80*x-count, " ");
                                  }
                                  else text.erase(text.begin() + (80*x));
               }
       }
       return text;
}


Like I said, it works for just about everything else I can give it, but for some reason this doesn't work. Any suggestions?
Your spacing is insane, dude! Notice how I've broken the ultra long string into multiple lines.

Your error is caused by your use of string::erase(). Once you've erased the character, you must decrement your x counter. Note that there is a version of erase() that takes an index (as opposed to an iterator).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>
#include <string>
using namespace std;

string f (string);

int main()
{
    string str (
        "\"X7, initiate hover mode and get in the speeder. We're leaving.\" "
        "The droid's torso emits a humming throb as he activates his custom "
        "repulsor unit. The droid begins to float above the repair bay floor. "
        "X7 retracts his legs into his barrel shaped torso-manifold, coming "
        "to rest in the passenger seat of your landspeeder.");

    cout << f (str) << '\n';

    system ("pause");
}

string f (string text)
{
    const int LineLen = 80;

    for (int x = 1; x <= text.size() / LineLen; x++)
    {
        int offset = 0;
        while (text.at (LineLen * x - offset) != ' ')
            ++offset;
        if (offset == 0) {
            text.erase (LineLen * x, 1);
            --x;
        }
        else
            for (int y = 1; y < offset; y++)
                text.insert (LineLen * x - offset, " ");
    }
    return text;
}

Thank you for the reply, but I don't understand why decrementing X helps. Can anyone explain this?

Also, while it fixes the runtime error, it causes the program to have another error:

If a word on a new line had a space in front of it, the space is removed.

The program reads through the line again thinking that the word on the new line, and the word above it on the previous line are one word (since the space between them has been removed).

So, the program shoves the whole new 'word' onto the new line, causing an error.

If anyone can help by explaining why decrementing X helps, I might be able to figure this out myself, or any ideas on how to keep the program from causing the new error. (I've tried several things, but it always causes a runtime error again) =(
You're right. Decrementing x doesn't make any sense now that I think about it. I had apparently forgotten it was counting lines not chars.

I think instead of inserting and removing spaces you should just replace the last space on a line with a newline.
Hmmm, here's the thing. The last spaces on a line are fine where they are, it's the FIRST spaces on a line that are what I'm trying to remove, and if I replace them with a newline, it just causes an entirely blank line...

Also, is there any chance you could tell me why the initial runtime error was being caused in the first place? I'd still like to know to try and avoid any problems in the future = /
Ok I think I've figured something out, and pardon if I'm not using the correct terms, I'm fairly new to C++ but eager to learn. I believe the function gets to a point where it is attempting to check a part of the string that doesn't exist. I think that's called stepping overbounds or something? Would this cause a runtime error?
Instead of erasing the character and then inserting another one, why not just overwrite that character with a newline.
What I did last time was keeping track of where had the last space appeared and replacing it with a newline if I later found that I needed to break the line.
I'm not erasing a character then adding a new one, I'm just removing the space altogether, and when it is displayed, the line happens to end at the end of the word. The next word is then displayed on the next line, without the space.
Hmmm, here's the thing. The last spaces on a line are fine where they are, it's the FIRST spaces on a line that are what I'm trying to remove, and if I replace them with a newline, it just causes an entirely blank line...

Also, is there any chance you could tell me why the initial runtime error was being caused in the first place? I'd still like to know to try and avoid any problems in the future = /
I think I have a working solution =)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
string f(string text)
{
       for(int x = 1; x <= (text.size() / 80); x++)
       {if(text.size() - 1 < 80 * x)
                       break;
           if(!(text.at(80*x-1) == ' '))
               {if(!(text.at(80*x) == ' '))
                                  {int count = 1;
                                  while(!(text.at(80*x-count) == ' '))
                                  {count = count + 1;
                                  }
                                  for(int y = 1; y < count; y++)
                                  text.insert(80*x-count, " ");
                                  }
                                  else text.erase(text.begin() + (80*x));
               }
       }
       return text;
}


All I did was add the
1
2
if(text.size() - 1 < 80 * x)
                       break;

so it wouldn't attempt to read past the strings bounds. If anyone has a better solution or any advice it'd be appreciated. Thanks for all the help I received =)

Please use a consistent indentation and also use some vertical whitespace.

If you have an off-by one error, why not fix the error instead of adding code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
string f(string text)
{
   for (unsigned x = 1; x < (text.size() / 80); x++)
   {
        if (text.at(80*x-1) != ' ')
        {
             if (text.at(80*x) != ' ')
             {
                 int count = 1;
                 while (text.at(80*x-count) != ' ')
                 {
                     count = count + 1;
                 }
                 for (int y = 1; y < count; y++)
                     text.insert (80*x-count, " ");
             }
             else text.erase (text.begin() + (80*x));
         }
    }
    return text;
}


BTW, your code doesn't work on a large number of inputs...
I was thinking of something like the code below when I said you might want to replace some spaces with newlines instead of inserting and erasing spaces. For simplicity, this impl. assumes there is at least one space every LineLen chars and that there are only single spaces (not more than 1 in a row). These limits could easily be removed if one were so inclined.

1
2
3
4
5
6
7
8
9
string f( string text ){
    const int LineLen = 50;
    for( size_t p = LineLen; p < text.size(); p += LineLen ){
        size_t space = text.find_last_of( " ", p );
        text[space] = '\n';
        p = space + 1; // set p to beginning of next line
    }
    return text;
}

Topic archived. No new replies allowed.