string .erase getting rid of vector element

I'm trying to use code from stack overflow to get rid of dashes from multiple strings that I input, but it's getting rid of the element entirely.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;

int main(){
  int inputs;
    cin>> inputs;
    vector <string> travel;
    for (int i=0;i< inputs;i++){
        string a;
        cin>>a;
        travel.push_back(a);
        //get rid of the dashes
     travel[i].erase(std::remove(travel[i].begin(), travel[i].end(), '-'), travel[i].end());
     //travel[i] is inaccessible for some reason...
    }
}


if it's relevant, I'm accessing my information using travel[i].substr(0,3) [where the string is guaranteed to be longer than 3 elements, I just want to see the first 3 characters], where it says it's out of range and gives an absurdly big number for where I'm accessing for __pos.
Last edited on
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 <algorithm>
#include <vector>
#include <string>
using namespace std;

int main() {

    int num_inputs;
    cin >> num_inputs;

    vector<string> travel;
    string str ;
    // add to the vector num_inputs strings
    for( int cnt = 0 ; cnt < num_inputs && cin >> str ; ) { // give up if input fails

        // get rid of the dashes in the input string
        str.erase( std::remove( str.begin(), str.end(), '-' ), str.end() ) ;

        // append to vector if the string has at least three characters
        if( str.size() > 2 ) {

            travel.push_back(str) ;
            ++cnt ;
        }
    }

    // print out the first three characters of each string in the vector
    for( const std::string& str : travel ) {

        // assert( str.size() > 2 ) ; // sanity check
        cout << str.substr(0,3) << '\n' ;
    }
}
using travel[i].substr(0,3) [where the string is guaranteed to be longer than 3 elements

Here it says it is irrelevant:
https://en.cppreference.com/w/cpp/string/basic_string/substr
cppreference wrote:
If the requested substring extends past the end of the string, or if count == npos, the returned substring is [pos, size()).

I think you should post your original code to spot the error.

In this example based on the code you posted, std::string::substr() seems to work even where I don’t check the string length and it should be lower than 3:
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
40
41
42
#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>


int main()
{
    std::istringstream iss { "ab-cdef gh-ijkl mn-opqr st-uvwx y-z a" };
    
    // std::cout << "How many words? ";
    int howmany { 6 };
    // std::cin >> howmany;

    std::cout << "Words are: " << iss.str() << "\n\n";

    std::vector <std::string> travel;
    for (int i {}; i < howmany; ++i) {
        // std::cout << "Next word is? ";
        std::string s;
        // std::cin >> s;
        iss >> s;
        travel.push_back(s);
        
        // get rid of the hyphens
        travel.at(i).erase( std::remove( travel.at(i).begin(),
                                         travel.at(i).end(),
                                         '-'),
                            travel.at(i).end() );

        std::cout << "First 3 characters of travel.at(" << i << ") are "
                  << ( travel.at(i).size() > 2 ? travel.at(i).substr(0, 3)
                                               : travel.at(i) )
                  << '\n';
    }

    std::cout << "\nAgain:\n";
    for(const auto& e : travel) {
        std::cout << e.substr(0, 3) << '\n';
    }
}


Output:
Words are: ab-cdef gh-ijkl mn-opqr st-uvwx y-z a

First 3 characters of travel.at(0) are abc
First 3 characters of travel.at(1) are ghi
First 3 characters of travel.at(2) are mno
First 3 characters of travel.at(3) are stu
First 3 characters of travel.at(4) are yz
First 3 characters of travel.at(5) are a

Again:
abc
ghi
mno
stu
yz
a

alright, here's the full code. The error with positioning is still within accessing travel[i] which somehow doesn't exist, and when I debug, printing out travel[0] gets no elements (using break with line after erase). The cout does not output anything (not even after next/continue)... most likely because travel[0] is inaccessible

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;

int main(){
    int inputs;
    cin>> inputs;
    vector <string> names;
    vector <string> status;
    vector <string> travel;
    for (int i=0;i< inputs;i++){
        //name, status, itinenary
        string a, b, c;
        cin>>a>>b>>c;
        names.push_back(a);
        status.push_back(b);
        travel.push_back(c);
        //get rid of the dashes
     travel[i].erase(std::remove(travel[i].begin(), travel[i].end(), '-'), travel[i].end());
     cout<<"name was "<<names[i]<< " status "<<status[i]<< " and itinerary "<<travel[i]<<endl; //testing only
    }

    int count = 0;
    vector <string> sickguys;
    while (true){
         int sickcount =0;
           //traverse through the peoples
           for (int i=0;i<inputs;i++){
               // cout<<"status "<< i<< " is "<<status[i]<<endl; //testing only
           if (status[i].compare("sick") == 0|| status[i].compare("recovering") ==0){
               sickcount++;
               if (status[i].compare("sick")==0){ status[i] = "recovering";}
               else if (status[i].compare("recovering") ==0){ status[i]= "healthy";}
              //cout<<"immediately, sick/recover became "<<status[i]<<endl; //testing only
               int icount;
               if ((count+1)*3 >= travel[i].length()){
                   icount = (count+2)*3%(travel[i].length()); //obtain which day in the guy's itenerary
               }
               else{
                   icount = (count+1)*3;
               }
               // can change healthy back to sick!
               for (int j=0; j< inputs;j++){
                   int jcount;
                   if ((count+1)*3 >= travel[j].length()){
                    jcount = (count+2)*3%(travel[j].length());
                   }
                   else{
                    jcount = (count+1)*3;
                   }
                  cout<<"count = "<<count<< " icount = "<< icount<<" and jcount = "<<jcount<<endl; //testing only
                //cout<<"icount to -3: "<<travel[i].substr(icount-3, 3)<< " jcount to +3: "<<travel[j].substr(jcount-3, 3)<<endl; //testing only
               if (travel[i].substr(icount-3, 3).compare(travel[j].substr(jcount-3, 3)) == 0 && status[j].compare("healthy") == 0){
                       status[j]="sick";
                   }

               } //end j loop
                sickguys.clear();
                sickguys.push_back(names[i]); //on any day with sick people, re-add them

             } //end IF
           } //end FOR
           if (sickcount==0|| count ==99){
               cout<<"Got to the end!"<<endl; //testing only
               for (int k=0;k<sickcount;k++){ //output the sick people's names
                   cout<<sickguys[k]<<" ";
               }
               cout<<sickcount<<" ";
               break; //output result since everyone is good or 100 day pass
           }
           count++;
           //cout<<"Got to count = "<<count<< " with sickcount "<<sickcount<<endl; //testing only
    } //end WHILE
    cout<<endl;
    return 0;
}


input:
8
Pat sick XPU-JBK-TNU-BEN-HEM-ZJY-IMY-WFA-PPT
Xan sick KSB-TRV-XPU-JBK-TNU-BEN-HEM-IMY-WFA-NND
Mel sick KSB-TRV-XPU-TNU-BEN-HEM-ZJY-IMY-WFA-PPT-NND
Nick healthy KSB-TRV-JBK-HEM-IMY-WFA
Alf recovering KSB-TRV-XPU-JBK-TNU-BEN-IMY-WFA-NND
Tim healthy TRV-XPU-TNU-HEM-ZJY-PPT-NND
Irv recovering KSB-TRV-XPU-JBK-BEN-HEM-ZJY-IMY-PPT
Andy recovering XPU-JBK-TNU-BEN-HEM-ZJY-IMY-PPT-NND

perhaps it's the "input three strings" in the original program requirement that are messing me up? hmmm....
Last edited on
I hard-coded your input (as a stringstream) and your code ran to produce the following output:
name was Pat status sick and itinerary XPUJBKTNUBENHEMZJYIMYWFAPPT
name was Xan status sick and itinerary KSBTRVXPUJBKTNUBENHEMIMYWFANND
name was Mel status sick and itinerary KSBTRVXPUTNUBENHEMZJYIMYWFAPPTNND
name was Nick status healthy and itinerary KSBTRVJBKHEMIMYWFA
name was Alf status recovering and itinerary KSBTRVXPUJBKTNUBENIMYWFANND
name was Tim status healthy and itinerary TRVXPUTNUHEMZJYPPTNND
name was Irv status recovering and itinerary KSBTRVXPUJBKBENHEMZJYIMYPPT
name was Andy status recovering and itinerary XPUJBKTNUBENHEMZJYIMYPPTNND
count = 0 icount = 3 and jcount = 3
count = 0 icount = 3 and jcount = 3
count = 0 icount = 3 and jcount = 3
count = 0 icount = 3 and jcount = 3
.... Many not-very-interesting lines removed ....
count = 9 icount = 6 and jcount = 6
count = 9 icount = 6 and jcount = 3
count = 9 icount = 6 and jcount = 30
count = 9 icount = 6 and jcount = 15
count = 9 icount = 6 and jcount = 6
count = 9 icount = 6 and jcount = 12
count = 9 icount = 6 and jcount = 6
count = 9 icount = 6 and jcount = 6
count = 10 icount = 9 and jcount = 9
count = 10 icount = 9 and jcount = 6
count = 10 icount = 9 and jcount = 3
count = 10 icount = 9 and jcount = 0

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
terminate called after throwing an instance of 'std::out_of_range'
  what():  basic_string::substr: __pos (which is 18446744073709551613) > this->size() (which is 18)


I imagine that, since jcount =0, your code is not going to like
substr(jcount-3, 3)

Probably your output was buffered on your system and the code had crashed before it got round to writing this out.

Whatever your methodology is for taking things in threes, to me it is indecipherable.
Why don't you just split strings at the '-' and put the three-letter codes into containers?
Last edited on
it has to emulate a circular array, but I'll try split
Last edited on
Topic archived. No new replies allowed.