You are basically running into an old problem, when working with input functions.
You need to learn about the difference between formatted and unformatted input.
The extraction and inserter operators >>
and <<
are formatted input functions. They read or write a sequence of characters and format them. Example:
int i = 42;
std::cout << i;
This is an example of formatted IO. Although 42 has the binary representation of 101010 you will see the character sequence "42" on the screen.
Same is valid vice versa. If you want to read a number from the user, you typically use something like
int i;
std::cin >> i;
And, although you enter the characters '4' and '2' and ENTER ('\n') in the terminal, you will get the value 42 in your variable "i". The ENTER ('\n') is still in the input stream and has not yet been consumed. This is an additional problem that I will explain in a minute.
If you want to read a string, like "Peter Parker", and use
std::string name{};
std::cin >> name;
You will only get "Peter", because the formatted input functions (per default) stop converting after they hit a white space. So, after "Peter" has been read. The whitespace will not be consumed and will be still in the input stream.
For this reason you will use std::getline
to read a string. This will not stop at a whitespace, but at a delimiter, per default at '\n'. So it will read a complete line.
From reading above, you may now see the problem. If there is a transition from formatted to unformatted input there is often the problem that there is still a whitespace (often the ENTER '\n', in your case the space) in the input stream. And you need to eliminate this whitespace.
You tried it with std::ignore
, but there is a better possibility: std::ws
. You may read here about it. This will often be the better approach. You may use it after the transition from formatted to unformatted input the eat away the non wanted white spaces. You can also use it in general if you want to eat up leading white spaces using unformatted input. (Beware: the formatted input functions like >>
will skip the white spaces (per default)).
ignore
is a unformatted input function and will actively wait for characters. It is an input function. It will not return until it read something. So, be careful. It will often be just used in error cases.
With the above knowledge, we could rewrite your code like the below:
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
class banca
{
private:
std::string name;
std::string email;
std::string course_aluno;
int semestre;
int id;
public:
friend std::istream& operator >>(std::istream& in, banca& p);
friend std::ostream& operator <<(std::ostream& out, const banca& p);
};
std::istream& operator>>(std::istream& in, banca& p)
{
std::cout << "\n\n--------ALUNO--------\n";
std::cout << "Name:\n";
std::getline(in >> std::ws, p.name);
std::cout << "Email:\n";
std::getline(in, p.email);
std::cout << "Course:\n";
std::getline(in, p.course_aluno);
std::cout << "Semestre:\n";
in >> p.semestre;
std::cout << "ID:\n";
in >> p.id;
return in;
}
std::ostream& operator <<(std::ostream& out, const banca& p) {
return out << "\nName:\t\t " << p.name << "\nEMail:\t\t " << p.email << "\nCourse:\t\t "
<< p.course_aluno << "\nSemestre:\t " << p.semestre << "\nID:\t\t " << p.id << '\n';
}
int main() {
banca b1,b2;
std::cin >> b1;
std::cout << b1;
std::cin >> b2;
std::cout << b2;
}
But beware. Input functions may fail. Check the return code of each input function. And if you have an error, then use ignore
.
Example. If you expect a number and enter a string, then the formatted input function will fail, and all invalid characters will still be in the stream. Enter "abc" for the semester and you will see it.
Solution. Check result of IO function:
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <limits>
class banca
{
private:
std::string name{};
std::string email{};
std::string course_aluno{};
int semestre{};
int id{};
public:
friend std::istream& operator >>(std::istream& in, banca& p);
friend std::ostream& operator <<(std::ostream& out, const banca& p);
};
std::istream& operator>>(std::istream& in, banca& p)
{
std::cout << "\n\n--------ALUNO--------\n";
std::cout << "Name:\n";
std::getline(in >> std::ws, p.name);
std::cout << "Email:\n";
std::getline(in, p.email);
std::cout << "Course:\n";
std::getline(in, p.course_aluno);
std::cout << "Semestre:\n";
in >> p.semestre;
std::cout << "ID:\n";
in >> p.id;
return in;
}
std::ostream& operator <<(std::ostream& out, const banca& p) {
return out << "\nName:\t\t " << p.name << "\nEMail:\t\t " << p.email << "\nCourse:\t\t "
<< p.course_aluno << "\nSemestre:\t " << p.semestre << "\nID:\t\t " << p.id << '\n';
}
int main() {
banca b1,b2;
if (std::cin >> b1)
std::cout << b1;
else {
std::cerr << "\nError: Problem with input\n\n";
std::cin.clear(); // unset failbit
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // skip bad input
}
if (std::cin >> b2)
std::cout << b2;
else {
std::cerr << "\nError: Problem with input\n\n";
std::cin.clear(); // unset failbit
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // skip bad input
}
}