-1

I meet error "String subscript out of range" when run these codes

#include <iostream>
#include <string>
#include <fstream>
using namespace std;

int main ()
{
    ifstream in("_start.txt");
    ofstream out("_end.txt");

    string str;
    while (getline(in, str))
    {
        if ((str[0] != '/') && (str[1] != '/'))
            out << str << endl;     
    }

    //getline(in, str);
    //if ((str[0] != '/') && (str[1] != '/'))
        //out << str << endl;
    return 0;
}

File _start.txt is like this

//<3403> 「それじゃまるで…俺おまえのライバルみたいじゃんか…」
<3403> 「It's like...we were actually rivals or something...」
<3403> 「Giống như...chúng ta là đối thủ thật sự hay sao ấy...」

//<3404> 井上
<3404> Inoue

//<3405> 「きっとね」
<3405> 「I'm sure we were.」
<3405> 「Tôi tin là thế.」

My purpose is to check 2 character at start of each line if have "//-character" will be ignored. Then I keep checking 6 characters at start of each line with same format

<[number with at least 4 characters, so number 1 will be written 0001]>

and this line's number is bigger than previous line's number 1. So if this line's number is equal

Add "//-character" at start of previous line

or bigger previous line's number 2, 3 or 4,... (larger than 1) will be fixed.

It is a long way so I started with mini-purpose is to print all lines except lines with "//-character" at beginning and I meet this error. If I do without loop, everything is fine with first line but when I include loop, error appears.

LogicStuff
  • 19,397
  • 6
  • 54
  • 74
  • 1
    What makes you sure that accessing `str[1]` is validly inside the actual bounds? – πάντα ῥεῖ Feb 15 '16 at 22:42
  • If I debug with "Step over" in VS without loop, at "str" value VS show first line, if i do with loops but without "if statement", VS show each line after each loop. I think is fine if I add "if" in loops but error appears. – user3422857 Feb 15 '16 at 22:51

1 Answers1

2
if((str[0] != '/') && (str[1] != '/'))
//                 ^^
//         btw, this should be ||

will invoke undefined behavior on empty lines and lines with single / and no other characters.
Add this check (short-circuit evaluation):

if(str.length() < 2 || (str[0] != '/') || (str[1] != '/'))

Read it as:

If str is shorter than two characters, we already know that it won't contain // at the beginning. Otherwise, do the check (which is only possible for longer strings).

Using De Morgan's laws, it is the same as:

if(!(str.length() >= 2 && str[0] == '/' && str[1] == '/'))

which might be easier to understand. Read it as:

First, check if str has at least two characters. If it does, check if the first two are //. Execute the code below if this condition yields false.

It is also possible to use std::string::substr to achieve shorter code:

if(str.length() < 2 || str.substr(0, 2) != "//")

or

if(!(str.length() >= 2 && str.substr(0, 2) == "//"))
Community
  • 1
  • 1
LogicStuff
  • 19,397
  • 6
  • 54
  • 74
  • Thank you so much. I'm new with C++ so I miss the case empty line. – user3422857 Feb 15 '16 at 22:58
  • 1
    note: since C++11 the length check is not actually necessary; `str[str.size()]` is defined as referring to a read-only null terminator stored somewhere, and the short-circuiting will prevent `str[1]` being tried if `str[0]` were indeed the null terminator – M.M Feb 16 '16 at 00:30