Show a specific number of string at a time

Dec 28, 2016 at 8:12pm
Say that you have 15 strings but you only want to output 5 at a time and after each 5 you let the user press a key to show five more. How would you do that? Here is an output example.


Hello
My 
World
I
am
Show five more?(y/n)
Last edited on Dec 28, 2016 at 8:12pm
Dec 28, 2016 at 9:05pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <sstream>
#include <vector>
using namespace std;

int main()
{
   char ans;
   string value;
   string line = "It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness,";
   vector<string> words;
   stringstream ss( line );
   while ( ss >> value ) words.push_back( value );


   for ( int i = 1; i <= words.size(); i++ )
   {
      cout << words[i-1] << endl;                // watch out for array index
      if ( i%5 == 0 && i != words.size() )       // every 5, give the opportunity to break out of the loop
      {
         cout << "Show 5 more? (y/n)";
         cin >> ans;
         if ( ans != 'y' ) break;                // may want to consider alternative responses
      }
   }
}
Dec 29, 2016 at 4:10am
@lastchance pretty much nailed it. Don't see why you haven't marked this answer as complete, unless there's something else you're confused with.

-VX
Dec 29, 2016 at 11:01am
Say that I have vector of structs, with friends would something like this work then?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void coutlist((vector<Person> friends)
{
   char ans;
   string value;
   stringstream ss( friends );
   while ( ss >> value ) friends.push_back( value );

   for(auto& e : friends)
    {
        cout << right << setw(20) << e.firstname;
        cout << setw(20) << e.lastname << endl;

      if ( i%5 == 0 && i != friends.size() )       // every 5, give the opportunity to break out of the loop
      {
         cout << "Show 5 more? (y/n)";
         cin >> ans;
         if ( ans != 'y' ) break;                // may want to consider alternative responses
      }
   }
}
Dec 29, 2016 at 11:36am
Hello Markusfurst

If you already have content in your friend structure you certainly don't need to put any more in with stringstream (which I doubt you can do anyway). I only used stringstream as a quick way of creating some strings for an example.

Your for () loop won't work with auto & e because it doesn't know what i is. If you insist on using auto rather than a counter then you will have to increment i deliberately within the loop (having set it to 0 before looping). You will also have to test for your last element, unless you want a redundant prompt at the end.
Dec 29, 2016 at 12:54pm
@lastchance So I can remove this?
1
2
3
string value;
stringstream ss( friends );
while ( ss >> value ) friends.push_back( value );


This feels better, am I on the right track?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
char ans;
int counter=0;
    
for(auto& e : friends)
{
    counter++;
}

for( int i = 0; i <= counter; i++ )
    {
        cout << right << setw(20) << e.firstname;
        cout << setw(20) << e.lastname << endl;

      if ( i%5 == 0 && i != counter )       // every 5, give the opportunity to break out of the loop
      {
         cout << "Show 5 more? (y/n)";
         cin >> ans;
         if ( ans != 'y' ) break;                // may want to consider alternative responses
      }
   }
    
Last edited on Dec 29, 2016 at 12:55pm
Dec 29, 2016 at 3:45pm
void coutlist((vector<Person> friends)
This will create an entirely new copy of the vector. It would be better to pass the existing vector by const reference:
void coutlist((cont vector<Person> &friends)

The problem you seem to be having is that you want to use a range-based for loop, but in lastchance's solution, you have to know if you're at the end of the input. The way to get around this is to ask if they want to see 5 more when you know that you already have one to display and to ask before displaying it, not after.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
#include <sstream>
#include <vector>
using namespace std;

int
main()
{
    char ans;
    string value;
    string line = "It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness,";

    vector<string> words;
    stringstream ss( line );
    while ( ss >> value ) words.push_back( value );


    int i=5;
    for (string & word : words) {
        if (i-- == 0) {
            i = 4;
            cout << "Show 5 more? (y/n)";
            cin >> ans;
            if (ans != 'y') {
                break;
            }
        }
        cout << word << '\n';
    }
}

Note that inside the loop I had to reset the counter to 4, not 5.

Also note that I'm just using a counter rather than %, which is slower. Most of the time this won't matter.
Dec 30, 2016 at 5:19pm
Dosen't work with your method either.
Dec 30, 2016 at 5:31pm
@markusfurst: could you post your code, please. Complete, compilable version.
Dec 30, 2016 at 5:33pm
It works with your code @lastchance, I just looked at it the wrong way, sorry for that!
Dec 31, 2016 at 4:07pm
Well, I'm glad that you got it to work, @markusfurst.

It would be worth having a go to make it work with @dhayden's method as well, because that does two important things:
- it deals with the end of the more modern range-based for() loop;
- it uses a subset counter (actually, count-down); in itself, I don't think the % operation would take much time compared with writing to screen; however, a subset counter would be especially useful if, in the future, you decided to ask for "how many more to show", rather than the simple "y/n".
Jan 1, 2017 at 1:37am
Thanks lastchance.

Markusfurst, what was wrong with my version? I tested it and thought that it was working correctly.
Topic archived. No new replies allowed.