1

I'm starting to use strings in place of character arrays and am encountering an error when I change one of my character arrays defined with a size of 5 to a string. The error I get is "Expression: string subscript out of range" upon trying to run the program.

"newWord" was originally a character array, but upon changing it to a string I'm getting this error. I don't understand what could be causing this, when using the character array the program performs fine.

int main() {
fstream inputFile;
fstream outputFile;
string newWord;
int i, k;
string word;
inputFile.open( "H:\\word.txt" );
outputFile.open( "H:\\newword.txt" );
if( inputFile )
{
    while( getline( inputFile, word ) )
    {
        for( i = 0; i < (word.length()- 3); ++i )
        {
            for( k = 0; k < 4; ++k )
                newWord[k] = word[i+k];
            cout << newWord << endl;
            outputFile << newWord << endl;
        }
    }
}
return 0;
}
user1560249
  • 343
  • 2
  • 5
  • 14
  • Your post is missing two things: `int main()` and a question. Would you please add your specific question to your post, and provide an [SSCCE](http://sscce.org)? – Robᵩ Feb 27 '13 at 01:49
  • 1
    Sorry, I only included the content inside the function. – user1560249 Feb 27 '13 at 01:52
  • 1. note that `std::string` has substring functionality. you can use that to really simplify the innermost logic. – Cheers and hth. - Alf Feb 27 '13 at 02:05
  • 2. also note that `(word.lengt()-3` does *unsigned arithmetic*, which means you will never get a negative result. for now you can just apply a workaround, like `int(word.length())-3`. for later consider defining a general signed integer `size` function. – Cheers and hth. - Alf Feb 27 '13 at 02:07
  • 3. the `if( inputFile )` check is unnecessary, since with the stream in error mode the `getline` will just fail first time. – Cheers and hth. - Alf Feb 27 '13 at 02:07
  • 4. you can just initialize the streams in the declarations, instead of using separate `open` calls. – Cheers and hth. - Alf Feb 27 '13 at 02:08
  • 5. but even better, using `cin` (standard input) and `cout`. then you can more easily test the program. just redirect the streams to get the effect of reading from "word.txt" and writing to "newword.txt" (this is about command interpreter usage). – Cheers and hth. - Alf Feb 27 '13 at 02:09
  • 6. preferentially declare variables as close to first use as possible. e.g. `i` should be declared *in the `for` loop head*. – Cheers and hth. - Alf Feb 27 '13 at 02:10
  • 7. the `return 0;` at the end is technically unnecessary, since it is the default for `main`. however, some people still prefer to have it, perhaps for (subjective) clarity. – Cheers and hth. - Alf Feb 27 '13 at 02:11
  • 8. it is a good idea to use **systematic indentation**. the particular scheme chosen is much less important than applying that scheme systematically. this means: the statements within `main` should be indented. – Cheers and hth. - Alf Feb 27 '13 at 02:13
  • 9. have you checked what happens if the output file already exists and already contains text -- more than the program will output? i haven't and i don't *know* what would happen, but i suspect ungood. to avoid this, use `ofstream` for output and `ifstream` for input, not generic `fstream`. or even better, as noted in point 5, just use the standard i/o streams. – Cheers and hth. - Alf Feb 27 '13 at 02:16
  • 10. finally, **magic numbers** such as `3` and `4` are generally ungood. it's okay in a very small program like this, but it doesn't scale to use them. so it will be beneficial to adopt a habit of using **named constants** for such numbers. in this case there would only be one named constant, with one of the numbers expressed in terms of the other. also keep in mind that one man's constant is another man's variable. perhaps this number should better be a program argument, with a default? – Cheers and hth. - Alf Feb 27 '13 at 02:20

2 Answers2

2
newWord[k]

The size of the newWord string is zero. The behavior of indexing beyond the end of a std::string is not defined.

You may need to resize the string, thus:

newWord.resize(5);
Robᵩ
  • 163,533
  • 20
  • 239
  • 308
1

The error is because newWord[k] = word[i+k]; does not allocate a space for the string in newWord. The string length is 0, and it is undefined behaviour to do this. Use .append instead.

From cplusplus.com:

If pos is not greater than the string length, the function never throws exceptions (no-throw guarantee).Otherwise, it causes undefined behavior.

In the case of newWord[k], pos is k.

This is easy to avoid by using the append function in the string lib.

From cplusplus.com, again:

string& append (const string& str); //Appends a copy of str.

David D
  • 1,571
  • 11
  • 12