-4

I need to read a file in c++ and save every line(in a vector) as i will be processing them later.

I also need to save a vector of char* that will point to the first position of each string*.

The problem is that I don't know how to assign the string* to char*.

FYI, i can not use const char*, it has to be char*.

Code:

void ClassA::readFile() {

    std::ifstream file("test.txt");

    std::string* str = new string();
    while (std::getline(file, *str))
    {

        _aVector.push_back(*str);


        char *c = &str[0]; <-- This works if string is not declared as string*
        char *c = ....     <--What is the equivalent for string*

        str = new string();

        someFunction(c); <-- This function saves the *c in a vector.

    }
}
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
Marchu
  • 51
  • 1
  • 6
  • Why do you need to store `char*`'s? What is the purpose of that? – NathanOliver Jul 02 '18 at 19:39
  • 1
    It's a constraint that i have. – Marchu Jul 02 '18 at 19:39
  • 4
    `&(*str)[0]` would do the trick -- although given this is C++98, it is not guaranteed that the entire string is contiguous (see https://stackoverflow.com/questions/1986966/does-s0-point-to-contiguous-characters-in-a-stdstring) – Acorn Jul 02 '18 at 19:41
  • Why are you `new`ing a `std::string`? – Cory Kramer Jul 02 '18 at 19:41
  • 3
    The chances that you need to allocate a `string` with `new` are quite small. –  Jul 02 '18 at 19:43
  • 1
    I'm guessing you can't use `string::c_str()` because it is `const` ? If you don't need to modify the string, that would be an option and more clear. – JPhi1618 Jul 02 '18 at 19:52
  • What is this? Some weird homework assignment? What do you *really* want to achieve. Even if you'd need to convert `std::string` to `char*`, why can't it be `const`? – JHBonarius Jul 02 '18 at 19:54
  • @Marchu: You are welcome :-) – Acorn Jul 02 '18 at 20:02
  • C++ 17 provide access to the char* pointer via the data method, although I strongly recommend checking boundaries before modifying the contents. –  Jul 02 '18 at 21:52
  • @Marchu for your information the current solution you provide would leak memory, as you replace the str pointer with a new string without freeing the previous one. As shown by Stephan Lechner you don't need a pointer to a string, you can use string on it's own. Internally the string manages the pointer for you, and ensures there are no memory leaks. –  Jul 03 '18 at 06:25

1 Answers1

1

Though the std::string protocol gives you access to the underlying memory, e.g. by calling member c_str(), these pointers are all const. If you cast it to a non-const pointer, you risk undefined behaviour if a function beyond your control then modifies the content through such a pointer.

Since C++17, the data-method gives you access to a non-const pointer to the underlying data.

Anyway, note that a string-object will - again beyond your control - replace the underlying memory if necessary, and your pointers might become invalid then. So I'd say that it's generally not a good idea to store pointers to the contents of string objects.

The only way to get a char*-pointer to the contents of an std::string I see is to copy the contents of the string, e.g. by using strdup. Thereby you avoid undefined behaviour from unintended modifying access, and you decouple the char* from the memory managed by the string object.

See the following code illustrating this:

int main() {

    std::vector<std::string> aVector;
    std::ifstream file("test.txt");
    std::string str;
    while (std::getline(file, str))
    {
        aVector.push_back(str);

        char *c = strdup(str.c_str());

        someFunction(c); // <-- This function saves the *c in a vector.

    }
}
Stephan Lechner
  • 34,891
  • 4
  • 35
  • 58
  • 1
    Thanks Stephan! I didn't knew of strdup method. That simplifies it. – Marchu Jul 02 '18 at 20:03
  • 1
    @Stephan Lechner Actually since C++ 17 you can access the underlying pointer, via the data method, so this information is out of date. –  Jul 02 '18 at 21:55
  • @Curg Thanks for the comment; adapted the answer accordingly. But "The pointer obtained from data() may be invalidated...", such that copying before saving a pointer to `data` is still the best choice. – Stephan Lechner Jul 02 '18 at 22:24
  • @Stephan Lechner The pointer may only be invalidated if you pass that string into another function as a non-const reference, or you call a modifying function on the object, so data is perfectly safe to use with that in mind. In fact taking it further, it would need to work, otherwise why would the C++ standards body add it into C++ 17? –  Jul 03 '18 at 06:15