0
#include <iostream>
#include <string>
using namespace std;
int main(){
    int a1,a2,a3,a4;

cin>>a1>>a2>>a3>>a4;
string a;
getline(cin,a);
return 0;}

I have this code. I cant input the value of "a". Help me please

2 Answers2

2

You can use std::ws to discard leading whitespace from the input stream.

#include <iostream>
#include <string>

int main()
{
  int a1, a2, a3, a4;
  std::cin >> a1 >> a2 >> a3 >> a4;

  std::string a;
  std::getline(std::cin >> std::ws, a);

  return 0;
}

cin actually stores the integer and a '\n' in the input buffer.

Therefore when the flow reaches the getline statement, it gets just a '\n'.


Anyway reading in numbers directly is problematic: when cin is presented with input it cannot process, it goes into a fail state.

The input it cannot process is left on the input stream and ignored until the "fail" state is cleared (std::cin.clear()).

So you should check and see if the input stream is invalid (!std::cin):

std::cin >> a1;
if (!std::cin)
{    
  std::cin.clear();
  std::cin.ignore(std::numeric_limits<streamsize>::max(),'\n');

  // Get the input again / handle the error
}
manlio
  • 18,345
  • 14
  • 76
  • 126
1

Good documentation like cppreference.com explains the problem very clearly:

When used immediately after whitespace-delimited input, e.g. after int n; std::cin >> n;, getline consumes the endline character left on the input stream by operator>>, and returns immediately.

I'd like to propose an alternative solution than to ignore the leftover character, though. You should generally consider a programming style in which all input is line-based, with std::getline. Individual lines can then be tokenised if needed, using tools such as std::istringstream or std::stoi. This allows you to implement error handling for wrong input in a much easier way than via std::cin's state flags.

For example, in the following example program, when you try to enter less or more than 4 integers in the first line, or if one of the integers cannot be parsed as an integer number, then you will get an exact error message. The important point is that instead of using std::cin to get directly to the integer values, a complete std::string line is received first, and that one is then split and analysed.

#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <stdexcept>
#include <exception>

// using just one of the many possible ways in C++ to tokenise a string:
std::vector<std::string> tokenise(std::string const& line)
{
    std::vector<std::string> tokens;
    std::istringstream is(line);
    std::string token;
    while (std::getline(is, token, ' '))
    {
        tokens.push_back(token);
    }

    return tokens;
}

std::vector<int> parse_four_integers(std::string const& line)
{
    auto const tokens = tokenise(line);

    if (tokens.size() != 4)
    {
        throw std::runtime_error("illegal token count: " + std::to_string(tokens.size()));
    }

    std::vector<int> result;
    for (auto&& token : tokens)
    {
        try
        {
            result.push_back(std::stoi(token));
        }
        catch (std::exception const&)
        {
            throw std::runtime_error("token " + token + " is not a valid integer");
        }
    }
    return result;
}

int main()
{
    try
    {
        std::string line;

        std::getline(std::cin, line);
        auto const four_integers = parse_four_integers(line);

        std::getline(std::cin, line);

        for (auto&& integer : four_integers)
        {
            std::cout << integer << "\n";
        }
        std::cout << line << "\n";
    }
    catch (std::exception const& exc)
    {
        std::cerr << exc.what() << "\n";
    }
}
Community
  • 1
  • 1
Christian Hackl
  • 27,051
  • 3
  • 32
  • 62