0

(Sorry if my sentances are full of mystakes, I'll do my best to write something readable) Hi, I'm working on a function that reads a file and store every line whose first char is ":" and removes every dash contained in the string. Every time this kind of line is found, push_back() is used to store this line in a vector. The problem is that, every time push_back() is used, all the elements in the vector takes the value of the last one. I don't understand why does it happen. Here's the code :

 string listContent;
 size_t dashPos;
 vector<char*>cTagsList;
 while(!SFHlist.eof())
 {
    getline(SFHlist,listContent);
    if(listContent[0]==':')
    {
        listContent.erase(0,1);
        dashPos = listContent.rfind("-",string::npos);
        while(dashPos!=string::npos)
        {
            listContent.pop_back();
            dashPos = listContent.rfind("-",string::npos);
        }
        char* c_listContent = (char*)listContent.c_str();
        cTagsList.push_back(c_listContent);
    }
 }

I first thought it was a problem with the end of the file but aborting the searching process before reaching this point gives the same results.

Faeralis
  • 87
  • 1
  • 6
  • 2
    First of all, [`while (!eof())` is wrong.](http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong) Second, casting the result of `c_str` to `char *` is very bad. Third, that pointer is invalid as soon as you modify the string, which happens right after. Use a vector of `std::string`. Anyway, you're not removing every dash, you're removing everything after and including the first dash. Use `std::remove` and pair it with `erase`. – chris Jul 25 '14 at 12:24
  • 3
    Do *not* store the results of `c_str`! Instead, just make `std::vector cTagsList;` instead and just `cTagsList.push_back(listContent);` – crashmstr Jul 25 '14 at 12:26
  • use char* only when dealing with pure c, you have strings in c++ –  Jul 25 '14 at 12:26
  • besides other comments, don't use char*, use std::string and you don't have to think too much – codekiddy Jul 25 '14 at 12:27
  • Well, thanks for the help. As i need a char array (because of ncurses in fact) i think i'll use a vector of string and then convert it to char, this should do the trick – Faeralis Jul 25 '14 at 12:34
  • you can get every single character using the subscript operator my_string[index], after all a string is an array of chars –  Jul 25 '14 at 12:40

1 Answers1

2

the c_str()-method of std::string states:

The pointer returned may be invalidated by further calls to other member functions that modify the object.

If you're allowed to use a std::vector< std::string > instead of the vector of char*, you're fine since there would be always a copy of the std::string listContent pushed into the vector, ie.

std::string listContent;
 size_t dashPos;
 std::vector<std::string>cTagsList;
 while(!SFHlist.eof())
 {
    getline(SFHlist,listContent);
    if(listContent[0]==':')
    {
        listContent.erase(0,1);
        dashPos = listContent.rfind("-",string::npos);
        while(dashPos!=string::npos)
        {
            listContent.pop_back();
            dashPos = listContent.rfind("-",string::npos);
        }
        cTagsList.push_back(listContent);
    }
 }

(I haven't tested it)

wonko realtime
  • 545
  • 9
  • 26
  • As i replied to the first post, i need a char, but i'll try to get it by converting a std::vector to a char, thanks for the help – Faeralis Jul 25 '14 at 12:41
  • @Faeralis blade already pointed out the [] operator of std::string which provides random access to every character in the string and what you can do alternatively is to use .c_str() as you did before, but on the strings already stored in the vector – wonko realtime Jul 25 '14 at 15:09