0

I am trying to stop the loop when user gives a blank line, otherwise push name and score to a vector pair. But this code is not working.

Input format:

<name><score>

e.g.:

Akash 45

My code is below:

 int m;
cin>>m;
vector<pair<string,int>>player;
string name;
int score;
while(1)
{      


    cin>>name;
    if(name.empty())
    break;
    cin>>score;
    player.push_back(make_pair(name,score));
}

Also , I have tried the following:

  1. if(name.length()==0)
  2. while(getline(cin,name))
  3. if (name=="")

None of them worked.

Can anyone help me?

Martijn Pieters
  • 889,049
  • 245
  • 3,507
  • 2,997
deba98
  • 13
  • 6

3 Answers3

2

operator>> ignores whitespace, and line breaks are treated as whitespace, so cin>>name will never return a blank string (baring an input failure).

To accomplish what you are attempting, you need to use get::getline() instead to read an entire line at a time. You can then test for blank lines, and can use std::istringstream to parse values from each non-blank line, eg:

vector<pair<string,int>> player;
string line, name;
int score;
while (getline(cin, line) && !line.empty())
{
    istringstream iss(line);
    if (iss >> name >> score)
        player.push_back(make_pair(name, score));
}
Remy Lebeau
  • 454,445
  • 28
  • 366
  • 620
  • Hi, this code is working fine. Thanks for that. But there is one more problem, whenever I am trying to take some another input before this vector pair, the program is not taking input for this pair. Suppose, I want to take input M ( an int) then this pair. 5 ABC 545 CDS 45 like this – deba98 Jun 09 '20 at 07:10
  • @deba98 it is difficult to see the actual formatting of the input in a comment. Please edit your question with more detail and formatting. – Remy Lebeau Jun 09 '20 at 07:15
  • I have edited the question. Kindly check , I have added one more input m, before taking input of name. When I am running your solution, after taking input of m, program gets terminated. But if I disable the line, taking input of m, program is running fine – deba98 Jun 09 '20 at 08:09
  • @deba98 you edited your question to include `m` in the context of your old code, not in the context of the code I have given you. Also, you did not show the format of the updated input. Is the value for `m` input on its own line, or is it on the same line as the 1st pair? It makes a big difference, as in the latter case you have to [watch out for this issue](https://stackoverflow.com/questions/21567291/). – Remy Lebeau Jun 09 '20 at 09:29
1
 `std::cin >>`  

does not return with empty input. When the user wrote just the "Enter" key, the std::cin still wait. I made the test, this is working :

std::getline(std::cin, name);
if(name.empty())
break;

Edit :

#include <iostream>
#include <vector>
#include <string>

int main()
{
    std::vector<std::pair<std::string, int>>player;
    std::string name;
    int score;
    while (1)
    {
        std::getline(std::cin, name);
        if (name.empty())
            break;
        std::cin  >> score;

        player.push_back(make_pair(name, score));

        // clear the std::cin buffer else the next std::getline won't wait next input
        std::cin.seekg(0, std::ios::end);
        std::cin.clear();
    }

    return 0;
}

the

std::cin.seekg(0, std::ios::end);
std::cin.clear();

fix the problem of the second std:getLine

MatthieuL
  • 474
  • 1
  • 1
  • 7
0

There's a small program to demonstrate you how to achieve so:

#include <iostream>
#include <vector>

int main(void) {
    std::string name;
    std::vector<std::string> nameList;

    std::getline(std::cin, name); // statement X
    nameList.push_back(name);

    for (; ;)
        if (name.empty())
            break;
        else {
            std::getline(std::cin, name); // recalling statement X again
            nameList.push_back(name);
        }

    for (int i = 0; i < nameList.size(); i++)
        std::cout << nameList[i] << std::endl;

    return 0;
}

First of all, let the user input something before going inside the loop directly. As soon as the user hits Enter, the loop will be broken when name.empty() conditions becomes true and returns true and break statement is executed.

In the other hand, as long as the user will hit the Enter key and keep writing something line-by-line, the loop will be executed.

Notice that I've used a For loop in this case, you could do the same trick with a While loop as shown:

while (true)
    if (name.empty())
        break;
    else {
        std::getline(std::cin, name); // recalling statement X again
        nameList.push_back(name);
    }
Rohan Bari
  • 6,523
  • 3
  • 9
  • 30
  • Hi, I have tried this method, but the loop stopped before giving the second time input. Here is my code: std::getline(std::cin, name); cin>>score; player.push_back(make_pair(name,score)); for(;;) { if(name.empty()) break; else { std::getline(std::cin, name); cin>>score; player.push_back(make_pair(name,score)); } } – deba98 Jun 09 '20 at 06:47
  • One problem, you're already trying to accept the whole line for just `name` (which accepts whitespaces too), how do you expect accepting `score` in the same line? – Rohan Bari Jun 09 '20 at 06:53