2

I have function:

int read_file() {
  ifstream file("plik");
  if(!file.is_open()) {
    throw -1;
  }
  int i = 0;
  string line[MAXSIZE];
  while(getline(plik, line[i])) {
    cout<<line[i]<<endl;
    i++;
  }

  return i; 
}

But i want to return array of strings:

line[]

How can I do this?

4 Answers 4

14

Don't. Arrays are not copyable.

Use a std::vector<std::string> instead.

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

Comments

3

Standard 8.3.5p6:

Functions shall not have a return type of type array or function, although they may have a return type of type pointer or reference to such things.

As @Tomalak hinted, Just Say No to arrays. They're related to all sorts of gotchas that you can usually avoid if you can use a vector instead.

Comments

3

If you really, really wanted to, you could dynamically allocate an array and return a pointer to that array:

std::string* getArray() 
{
  return (new std::string[10]);
}

BUT you then need to cater for freeing up the memory you allocated using delete[] to avoid a memory leak.

Ask yourself:

  • Which bit of your code should be responsible for doing this?
  • Will you remember that that pointer represents a dynamically-allocated array later on, elsewhere in your code?
  • What happens if you pass that pointer around your program and accidentally use it somewhere after another bit of code has called delete[] on it? (Segmentation fault is the answer).
  • If you pass a pointer to an array around, how does the code that uses that pointer know the size of your array? std::vector keeps count of the items for you, so no problem there.

That's why using an std::vector<std::string> is a better idea. Returning a pointer to a dynamically allocated array introduces all sorts of problems that are better avoided than solved.

2 Comments

Another tough question raised by the example and solved by vector: How does the calling function know how many elements are in the array?
@thefourtheye Sure, better than returning a naked pointer to an array, but worse than using a container like vector which gives you an api to manage the data. See aschepler's point above.
2

I'd advise against returning an std::vector<std::string> as well. Instead, I'd pass an iterator, and have the function write the data to wherever the iterator points. This way, the function can equally well write the data to a vector, or a deque, or (if you want) directly to an output stream.

Using that, your function borders on trivial:

// I've changed the definition slightly, to let you pass it a filename instead
// of hard-coding one.
//
template <class outIt>
void read_file(std::string const &filename, outIt output) { 
     std::ifstream in(filename);
     std::string line;

     while (std::getline(in, line))
         *output++ = line;
}

To use this to copy the data to standard output, roughly as in the question, you'd do something like:

read_file("plik", std::ostream_iterator<std::string>(std::cout, "\n"));

1 Comment

+1 - I like your answer better than mine, as it avoids the (comparatively) expensive copy.

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.