0

I have an array of pointers to string classes and I need to copy a line from a file into each pointer but I'm not sure how to do that.

void Document::loadFile(string iFileExt){
  ioFile = new fstream(iFileExt.c_str(), ios::in);
  int i = 0;
  string row;
  string *content;

  if (ioFile->fail()){
    cerr << "File failed to open for read" << endl;
    exit(69);
  }

  while(ioFile->good()){ // this loop is just to know how may rows are in the file
    getline (*ioFile, row); 
    i++;
  }

  content = new string[i]; // I allocate memory dynamically so that the numbers of   
  ioFile->seekg(0);        // pointer is the same as the number of rows   
  i = 0;

  while(ioFile->good()){
    getline (*ioFile, *content[i]);  //this is the tricky part
    i++;
  }
  ioFile->close();
}

thanks in advance for any help or hint that you can provide to me! :-)

3 Answers 3

1

Why yours doesn't work:

getline (*ioFile, *content[i]);  //this is the tricky part
                 ^^^
// You have an extra dereference above

It should just be:

getline (*ioFile, content[i]);

How you should do it:

std::ifstream f(filename);
std::vector<std::string> lines;
for(std::string temp; std::getline(f, temp); lines.push_back(std::move(temp)));

Note: there is no cleanup required here. The ifstream closes itself. The vector deletes what it allocates. This is much smaller more efficient code to get the lines of a file as strings.

Sign up to request clarification or add additional context in comments.

2 Comments

it might be easier to manage the fstream as a pointer than a reference since references must be initialized (you cant leave it for later). You can't copy them either so simply using no indirection might not be an option.
@Dave: I remove the "*", the program compiles, runs but it doesn't copy anything :-(
1

Use a deque<string> instead. You'll avoid a whole lot of pain, including the need to read the file twice:

void Document::loadFile(string iFileExt){
    if (ifstream fin(iFileExt)) {
        string row;
        deque<string> content;

        while(getline(fin, row))
            content.push_back(row);

        // Do something with content.
    } else {
        cerr << "File failed to open for read" << endl;
        exit(69);
    }
}

Note: In C++11 — due to move semantics — it might be better to use vector<string> and push_back(move(row)), though I/O will probably swamp the difference.

EDIT: If you really need pointers to strings, the above approach works equally well with minor changes:

        deque<string *> content;

        while(getline(fin, row))
            content.push_back(new string(row));

This is a bad, bad idea, however. At the very least, you should use smart pointers. In C++11, this is easy:

        vector<shared_ptr<string>> content;

        while(getline(fin, row))
            content.push_back(make_shared<string>(move(row)));

4 Comments

thanks for your answer, but I must use an array of pointers to string classes because other part of my program depend on it :-(
@juanp_1982: Do you not have control over that other part? In any event, I've amended my answer.
@juanp_1982: I've also removed the redundant call to c_str().
@Macelo I don't have control over the other parts, I must use an array. Thanks for mention "smart pointers", I'll give it a look right away
-1
void Document::loadFile(string iFileExt)
{
  ioFile = new fstream(iFileExt.c_str(), ios::in); // does this ever get deleted?
  // string *content; // arrays have their place, and this is not it
  std::vector<string> content;

  if (ioFile->fail()){
    cerr << "File failed to open for read" << endl;
    exit(69); // don't ever just unconditionally exit from random places
              // it makes for unmaintainable spaghetti code
  }

  for (int i = 0; ioFile->good(); ++i) // loop manages i for us
  {
    content.push_back((string()));
    getline (*ioFile, content[i]);
  }

  ioFile->close();
}

The following might be useful when replacing the existing code, which uses an array of pointers, to something that takes a vector.

The function probably has a signature something like this:

void ProcessLinesInFile(int numLines, std::string *lines[]); // maybe this
void ProcessLinesInFile(int numLines, std::string **lines);  // or maybe this

Both ways are essentially equivalent. ProcessLinesInFile probably has a body something like this:

for (int i = 0; i < numLines; ++i)
{
    *lines[i] = Process(*lines[i]); // read and maybe write the line
}

The first step would be to make it work with an array of strings, rather than an array of string pointers:

void ProcessLinesInFile(int numLines, std::string lines[])
{
    // should behave exactly the same way as before
    for (int i = 0; i < numLines; ++i)
    {
        lines[i] = Process(lines[i]); // read and maybe write the line
    }
}

From there, using a vector is easy:

void ProcessLinesInFile(std::vector<std::string> &lines)
{
    // should behave exactly the same way as before
    for (int i = 0; i < lines.size(); ++i)
    {
        lines[i] = Process(lines[i]); // read and maybe write the line
    }
}

If you're sure that you never need to actually change the array throughout this process, you can (and it is prudent to) pass the vector reference as a constant:

void ProcessLinesInFile(std::vector<std::string> const &lines);

4 Comments

thanks for your answer, yes, ioFile gets deleted int the destructor, I must use an array of pointers to string classes because other part of my program depend on it, thanks for the suggestion on the "Exit" I changed it to throw an exception instead. and the size of content might change on the fly
Ok, now that I know you HAVE to use a char *[], I'll edit this later. There's no chance of changing the existing stuff to take something more sensible? why does it have to be pointers, must the contents be mutable? You could accomplish this with the vector by passing it by reference.
I wish, right now I'm coding this class twice at the same time, one with vectors following your answer(BTW works just fine!!! thanks for that) and the other one as I stated at the beginning, I received the header file from somebody else and I'm trying to change it to vectors but so far I can't
Are you able to post the header you're working with? If you can, post it in another question and link to it here and I'll take a look. In the meantime, I'll add something that I think may be useful.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.