2

Say I create a vector whose size is not yet denoted and whose elements are strings. I want to input strings into this vector using a for loop and cin. Then, when the user has finished inputting the strings, I want the for loop to terminate.

I know two ways of doing this. The input stream can be terminated using Ctrl + Z on Windows or Ctrl + D on Unix. I can also use an if statement with a break, so that on the input of a certain string such as "end", the loop terminates.

My implementation would be the latter of the two:

vector<string> words;

for(string temp; cin >> temp;)
{
    if(temp == "end")
    {break;}

    else
    {words.push_back(temp);}
}

So, for the input foo bar the loop won't terminate, but for the input foo bar end the loop terminates (and for foo end bar the loop would terminate such that the vector contains only the string "foo").

Is the above implementation the best way of doing it? Would it be more efficient to just use Ctrl + Z or Ctrl + D as that avoids having to go through an if statement in each iteration?

This would be different if we instead had a vector whose elements were of type int, as the user could enter anything that isn't an integer in order to terminate the loop. But in the case of strings, anything the user enters can be considered a string.

I am working through chapter 4 of the book by Bjarn Stroustrup, "Programming - Principles and Practice using C++".

Joel
  • 35
  • 4
  • 1
    Please measure first, then optimize. There is a much bigger overhead than that small `if` branch: the user. – Rakete1111 Dec 17 '17 at 17:40
  • `Ctrl-D` & `"end"` are two different things so there is no "better". There is only what you want your users to have to do. Different situations will demand different solutions. – Galik Dec 17 '17 at 17:42
  • 1
    The if is irrelevant. Ctrl Z/D closes the input. You can’t read anything after that. –  Dec 17 '17 at 17:43
  • What if they want to write about the end times? – Kenny Ostrom Dec 17 '17 at 17:46
  • Break is considered really bad for why not create a `bool done = false` then in the `for` statement have `cin >> temp && !done`. In the if statement `if(temp == "end") done = !done;` – Jake Freeman Dec 17 '17 at 17:47
  • 1
    @JakeFreeman `break` is just fine, and that `done` thing is much less readable. The way you wrote it is also wrong because it will read an extra line. – interjay Dec 17 '17 at 17:49
  • @interjay `break;` is banned from the Computer Science AP so people will not use it because it is bad for. – Jake Freeman Dec 17 '17 at 17:50
  • Note that the question in the title is inside-out. The loop does not run over a vector of strings; it runs over a sequence of words coming from the console. It **creates** a vector of strings. – Pete Becker Dec 17 '17 at 17:55
  • 3
    @JakeFreeman: Regardless of somebody's silly, arbitrary rule, there's nothing inherently wrong with `break`. It is generally better for the loop condition to directly reflect the termination condition for the loop, but the way you've suggested doesn't do that either. In this case, it's pretty easy for the loop condition to reflect the exit condition though--as shown in my answer. – Jerry Coffin Dec 17 '17 at 17:56
  • 1
    @JakeFreeman, The [official subset doc](https://secure-media.collegeboard.org/digitalServices/pdf/ap/ap-computer-science-a-java-subset.pdf) says that they omit insignificant features that can be expressed by other means to ease test preparation. `break` is even listed as potentially relevant/useful. Keep in mind an AP test environment for some particular high school students is not representative of professional programming work, and not using `break` in that environment is a terrible reason to disallow it everywhere and for everyone. – chris Dec 17 '17 at 18:01

1 Answers1

7

I'd prefer to loop header to reflect the expected exit condition(s), so if you want to read until the user enters end, I'd prefer to have that test in the condition of the loop:

for (std::string temp; std::cin >> temp && temp != "end"; )
    words.push_back(temp);

As far as "efficiency" goes, in a case like this it's almost certainly irrelevant. Concentrate on making the code simple and readable. Optimize only when measuring shows you need to.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • ... I'm kicking myself that I missed the obvious conditional part of the for loop. Also, I noticed you used std::string and std::cin. I usually do this by not doing "using namespace std" but omitted it in the question for the sake of brevity. Is it better practice to avoid "using namespace std;"? – Joel Dec 17 '17 at 18:06
  • @Joel, https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice – chris Dec 17 '17 at 18:24