How to close input stream in c++? - c++

So what im trying to do is to allow user to input name, age, education.
If user ended adding data, by entering 's' the program moves to sorting.
If user didnt enter 's' the input loop continues, and user may add more people.
So at line: std::cin>>stop;. I'm opening input stream to check if user entered 's'. If they didn't - this input should be closed, and then new input should start at line: while(std::cin>>name>>age>>education) - to add more people.
My question is how to close this std::cin>>stop; input? If it's not closed, the first character of name will be put into char stop, and name will be lacking the first character.
std::cin.unget() does the trick but its not exactly the purpose it should serve, because if the the type of stop is changed from char to std::string, the whole name will be put into stop variable.
int main()
{
int age;
std::string name, education;
std::vector<Data> zbior;
std::cout << "Enter: name, age, education: ex: Ala 20 primary" << std::endl;
while(std::cin>>name>>age>>education)
{
zbior.push_back(Data(name, age, education));
char stop;
std::cout << "Type s to end input or continue adding data" << std::endl;
std::cin>>stop;
if(stop == 's') break;
else std::cin.unget();
system("cls");
sortManual();
std::string sort;
while (std::cin>>sort) {
if(sort =="ar") { system("cls"); print_young_to_elder(zbior); std::cout << "\n" << std::endl; sortManual();}
if(sort =="am") { system("cls"); print_elder_to_younger(zbior); std::cout << "\n"; sortManual();}
if(sort =="er") { system("cls"); print_Edu_rising(zbior); std::cout << "\n"; sortManual();}
if(sort =="em") { system("cls"); print_Edu_descending(zbior); std::cout << "\n"; sortManual();}
}
}

Please use string not char to read one of the words (like name) and compare it to your "s" and if equal take approprioate action.
I would not reverse input streams or things like that in that simple program as it like adds a layer of complication when it is not needed..

Related

A decision condition is triggered without input

I am currently working on a very simple project and I found a problem in the testing phase when I tried to enter his name for the new employee and the decision condition was suddenly triggered, I am not sure why this happened. Based on my limited coding experience, in general, a statement in an output judgment statement needs to fulfil a judgment condition, but why would a judgment condition be triggered if I didn't do any input? Thank you all for your help.
Here is a part of the code.
void Management::Add_Staff() {
std::cout << "Please enter the number of staffs you want to add: " << std::endl;
int addNum = 0; // saves the amount entered by the user
std::cin >> addNum;
while (addNum <= 0 || addNum >= 50) {
std::cout << "Invaild number. Please try again" << std::endl;
std::cout << "Please enter the number of staffs you want to add: " << std::endl;
std::cin.clear(); // clear error enter
std::cin.ignore(INT_MAX, '\n'); // INT_MAX means an extremely large number,'\n' means empty space
std::cin >> addNum;
}
int new_Size = this->_StaffNumber + addNum; // The number of existing employees plus
// the number of new employees
Person** new_Space = new Person*[new_Size]; // Open up new space
if (this->_StaffArray !=
NULL) // if the data of the original pointer is not null
{
for (int i = 0; i < this->_StaffNumber;
i++) // data of the original pointer is added to the new pointer
{
new_Space[i] = this->_StaffArray[i];
}
}
for (int i = 0; i < addNum; i++) {
int ID; // create an variable nameed id to store the staff number entered
// from users
std::cout << "Please enter pure and positive number as the staff number of " << i + 1 << " staff: " << std::endl;
std::cin >> ID;
while (ID <= 0) {
std::cout << "Invalid staff number, please enter again: " << std::endl;
std::cin.clear();
std::cin.ignore(INT_MAX, '\n');
std::cin >> ID;
}
std::string NAME; // create an variable nameed id to store the staff
// number entered from users
std::cout << "Please enter the name: " << std::endl;
// std::cin >> NAME;
while (std::getline(std::cin, NAME)) {
if (NAME.length() == 0)
{
std::cout << "Your input is not correct. Please re-enter your name" <<
std::endl;
}
// This will check if the NAME contains only characters.
else if (std::all_of(NAME.begin(), NAME.end(), isalpha)) // isalpha: The function returns a non-zero value if the argument is an alphabetic character, or zero otherwise.
{
break;
}
else {
std::cout << "Only characters are allowed:" << std::endl;
}
}
That is my test case.
*********************************************************
********Welcome to the employee management system********
***********0.Exit the management page********************
***********1.Add the employee information****************
***********2.Display the employee information************
***********3.Delete the employee information*************
***********4.Modify the employee information************
***********5.Search the employee information************
***********6.Sort by number*****************************
Please enter the numbers 0 through 6 as your next step
1
Please enter the number of staffs you want to add:
1
Please enter pure and positive number as the staff number of 1 staff:
12
Please enter the name:
Your input is not correct. Please re-enter your name
After I entered the employee number, the judgment condition was triggered before I entered the name, but I didn't enter a space, I didn't even have time to enter something, and the judgment condition was triggered.
When you get input form the user using std::cin the input from the user does not go directly into the program. Instead that input sits in a buffer, which temperately stores that user entered data so you can later tie that data to a variable or perform some other task with that data. However, if that buffer does not get cleared and you use std::getline then std::getline will read the buffer instead of the new user input that you actually wanted. This is why its important to make use of the std::cin.ignore() function, which will clear the buffer of unwanted int and characters. If you want a more en-depth overview of std::cin.ignore() check out this link .
The Fix:
Looking at your code you do make use of cin.ignore() to clear the buffer but only the user enters something other then a number which will drop them into that while loop.
This is what you currently have:
while (ID <= 0) {
std::cout << "Invalid staff number, please enter again: " << std::endl;
std::cin.clear();
std::cin.ignore(INT_MAX, '\n');
std::cin >> ID;
}
std::string NAME; // create an variable named id to store the staff
// number entered from users
std::cout << "Please enter the name: " << std::endl;
To correct this you will need that std::cin.ignore() call out side of the while loop so that it always happens whether there is an error or not. I have a comment that says NEW CODE LINE for where I made the change.
while (ID <= 0) {
std::cout << "Invalid staff number, please enter again: " << std::endl;
std::cin.clear();
std::cin.ignore(INT_MAX, '\n');
std::cin >> ID;
}
std::cin.ignore(INT_MAX, '\n');//NEW CODE LINE
std::string NAME; // create an variable named id to store the staff
//number entered from users
std::cout << "Please enter the name: " << std::endl;

Assigning the "Enter Key" value to a string [C++]

In this rather simple exercise I have to receive an user input, store said input into a string, pass the string to a function by reference and finally modify the string so that every character is "parsed" by the toupper() function.
However, should the user insert 'q' as input, the program stops saying "Bye" OR if he just presses the Enter Key, the program is supposed to say something like "Hey, this string is empty".
Now the real problem here is in the last part since my code won't manage the case where the user inputs only the Enter Key value (to be honest, even if I just text a bunch of spaces followed by the Enter Key, nothing happens)
void uppercase(std::string &);
int main(){
using namespace std;
string ex2;
cout << "Exercise 2" <<endl;
while(ex2!="Bye"){
cout << "Enter a string(q to quit): ";
cin >> ex2;
cout << "Was: " << ex2 << endl << "Now is: ";
uppercase(ex2);
}
return 0;
}
void uppercase(std::string &str){
using namespace std;
if(str[0]=='\n')
cout <<"Empty string dude!" << endl;
else{
if(str.length()==1 && str[0]=='q'){ //press 'q' to exit program
str="Bye";
cout << str;
}
else{ //uppercase
for(int i=0;i<str.length();i++){
str[i]=(toupper(str[i]));
}
cout << str <<endl;
}
}
}
I also tried the compare() function and even to compare the whole string to null (pointless, but still worth a shot) and to the string "";
Sorry for the bad interpretation of your problem, trying
if( (str.length()==1 && str[0]=='q') || str.length() == 0)
{}
May help you out of the problem

Reading a particular word in .txt file

I have a txt file which contains the name and roll number of students. I want to read and display a particular roll number from his file. It shows only the first roll number, but I want to read the roll number of the 2nd person.
That is, if I want to read the roll number of "ss", it shows the roll number of the first person
The program is
#include<iostream.h>
#include<conio.h>
#include<fstream.h>
#include<string.h>
#include<stdio.h>
void student_read()
{
clrscr();
char name[30], n[30], temp[30];
int i, roll_no, code, count=0;
ifstream fin("tt.txt",ios::in|ios::beg);
if(!fin)
{
cout << "cannot open for read ";
return;
}
cout << "Enter the name of student" << "\n";
cin >> n;
while(fin >> name >> roll_no)
{
cout << roll_no << endl;
}
if(string[name] == string[n])
{
cout << "roll no" << "\n" << roll_no;
}
else
cout << "Not found";
}
void main()
{
clrscr();
cout << "Students details is" << "\n";
student_read();
getch();
}
The txt file contains this data:
sourav
123
ss
33
Does you have end of each line in your text file? Does you have sourav 123 ss 33 or sourav 123\nss 33?And this if(n[30]==name[30]) compare only 1 character in string.
You're doing the output of what is in the file already before you even input the name to search for.
Reorder your statements, like this:
cout<<"Enter the name of student"<<"\n";
cin>>n;
while(fin>>name>>roll_no)
{
//...
Also, if you only want to output one name and roll_no, in your loop, you have to check some kind of condition whether to print or not. At the moment, your code should actually print the roll_no of all rows in the file, and possibly sometimes the last one twice.
So the condition you have after the input belongs into the loop.
Additionally, however, you're only comparing the 31st character of the char array (which is actually already out of the bounds of your array variables! Their indices go from 0..29, i.e. even if you allocated a 30 characters array, the ). That means, your condition will be true if the next to last character matches. This place will most likely not be initialized yet, so you compare basically gargabe values and will get unexpected/random results.
If you want to, as the description suggests, want to compare the whole char array, that works differently by the way (not with the == operator, that would only compare pointer addresses), you'd need to use the strcmp function. But even better would be to use std::string instead of char *.
void student_read()
{
clrscr();
std::string name, n, temp;
int i, roll_no, code, count = 0;
std::ifstream fin("tt.txt", ios::in | ios::beg);
if (!fin)
{
std::cout << "cannot open for read ";
return;
}
std::cout << "Enter the name of student" << "\n";
std::cin >> n;
while (fin >> name >> roll_no)
{
std::cout << roll_no << std::endl;
}
if (name == n)
{
std::cout << "roll no" << "\n" << roll_no;
}
else
std::cout << "Not found";
}
int main()
{
clrscr();
std::cout << "Students details is\n";
student_read();
getch();
}

Why is exit(0); giving me a std:string... error?

I'm new to C++. I decided to not watch the next tutorial and put my skills to use, by making a funny Mind Reader application. I'm pleased with myself, however, even though I've ironed out most bugs, I still have one concerning the exit function. I read the C++ documentation for it, and I'm not sure what I did wrong. I did exit(0);. I have a very weird error, which is:
no match for call to '(std::string {aka std::basic_string<char>}) (int)
I have searched online, however I am still unaware of what the problem is. My error is on line 59 (marked in the code):
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
int main()
{
//declaring variables to be used later
string name;
string country;
int age;
//header goes below
cout << "#######################################";
" ############ MIND READER ############"
"#######################################\n\n";
//asks if the user would like to continue and in not, terminates
cout << "Would like you to have your mind read? Enter y for yes and n for no." << endl;
cout << "If you do not choose to proceed, this program will terminate." << endl;
string exitOrNot;
//receives user's input
cin >> exitOrNot;
//deals with input if it is 'y'
if (exitOrNot == "y"){
cout << "Okay, first you will need to sync your mind with this program. You will have to answer the following questions to synchronise.\n\n";
//asks questions
cout << "Firstly, please enter your full name, with correct capitalisation:\n\n";
cin >> name;
cout << "Now please enter the country you are in at the moment:\n\n";
cin >> country;
cout << "This will be the final question; please provide your age:\n\n";
cin >> age;
//asks the user to start the sync
cout << "There is enough information to start synchronisation. Enter p to start the sync...\n\n";
string proceed;
cin >> proceed;
//checks to see if to proceed and does so
if (proceed == "p"){
//provides results of mind read
cout << "Sync complete." << endl;
cout << "Your mind has been synced and read.\n\n";
cout << "However, due to too much interference, only limited data was aquired from your mind." << endl;
cout << "Here is what was read from your mind:\n\n";
//puts variables in sentence
cout << "Your name is " << name << " and you are " << age << " years old. You are based in " << country << "." << endl << "\n\n";
cout << "Thanks for using Mind Reader, have a nice day. Enter e to exit." << endl;
//terminates the program the program
string exit;
cin >> exit;
if (exit == "e"){
exit(0); // <------------- LINE 59
}
}
}
//terminates the program if the input is 'n'
if (exitOrNot == "n"){
exit(0);
}
return 0;
}
Thanks
The local variable exit shadows other identifiers from outer scopes with the same name.
To illustrate with a smaller example:
int main()
{
int i;
{
int i;
i = 0; // assign to the "nearest" i
// the other i cannot be reached from this scope
}
}
Since the only exit visible is an object of type std::string, the compiler sees exit(0) as a call to operator()(int) and throws a hissy fit when it doesn't find one among std::string members.
You can either qualify the name (std::exit(0);) or rename the variable. And since all of your code is in main you can simply say return 0; instead.
Try using return 0; or return EXIT_SUCCESS;. It's the exact same thing. Also, you can only input one word into a cin. Instead, use getline(cin, string name); If it still doesn't work, add a cin.ignore(); before your getline(cin, string name);, like this:
//stuff
string country;
cout << "Now please enter the country you are in at the moment:\n\n";
cin.ignore();
getline(cin, country);
//stuff
return 0;
The problem is arrising because you declared a standard keyword as the name of a local variable.
Now as the local variable is of type sting it is not able to take it as its value.

C++ cin only accept numeric values

I've written this piece of code that allows the user to choose input either the value 1 or 2. This is working perfectly fine aside from one minor issue:
If the user inputs something like "1asdaosd" the input is recognized only as 1.
I've tried using the isdigit function but I still didn't manage to make this work.
bool validInput;
do
{
cout << "Choose the game type: ";
cin >> gametype;
validInput = true;
if (cin.fail())
{
validInput = false;
cin.clear();
cin.ignore(std::numeric_limits<int>::max(), '\n');
}
if (gametype<1 || gametype>2) {
validInput = false;
}
} while (!validInput);
The expected behaviour should be:
Anything other than "1" or "2" shouldn't be considered a validInput and therefore repeating the cycle. What happens is that "1asdasd" or "2aods" is considered a validInput but I want it to fail.
Below is a method based on stuff I read in one of the early chapters of Stroustrup's Programming: Principles and Practice Using C++ and an answer provided by Duoas at cplusplus.com. It defines a function, get_int_between(), that allows you to do something like this:
int my_variable;
get_int_between(my_variable, min, max, prompt, error_msg);
Which would prompt, validate, and store into my_variable.
Just for fun, I've also included a function, get_int(my_variable, prompt, error_msg), that does the same thing but allows an integer of any value.
#include <iostream>
#include <sstream> // stringstream
void get_int(int& d, std::string prompt, std::string fail);
void get_int_between(int& d, int min, int max, std::string prompt, std::string fail);
int main()
{
int my_number = 1; // initialize my_number
get_int(my_number, "Please enter an integer: ", "Sorry, that's not an integer.\n");
//Do something, e.g.
std::cout << "You entered: " << my_number << "\n";
get_int_between(my_number, 1, 2, "Choose the game type (1 or 2): ", "Sorry, that's not an integer.\n");
//Do something, e.g.:
std::cout << "Let's play Game " << my_number << "!\n";
return 0;
}
void get_int(int& d, std::string prompt, std::string fail)
{
while(1) {
std::cout << prompt;
std::string str;
std::cin >> str;
std::istringstream ss(str);
int val1;
ss >> val1;
if(!ss.eof()) {
std::cout << fail;
continue;
} else {
d = val1;
break;
}
}
}
void get_int_between(int& d, int min, int max, std::string prompt, std::string fail)
{
while(1) {
get_int(d, prompt, fail);
if(d > max || d < min) {
std::cout << "Sorry, your choice is out of range.\n";
continue;
}
break;
}
}
If you want to use strings use getline.
#include <iostream> // std::cin, std::cout
int main ()
{
char name[256], title[256];
std::cout << "Please, enter your name: ";
std::cin.getline (name,256);
std::cout << "Please, enter your favourite movie: ";
std::cin.getline (title,256);
std::cout << name << "'s favourite movie is " << title;
return 0;
}
if you make gametype as an int it will only accept 1 or 2 (of course you have to prevent other numbers to be accepted).
It's because gametype is an integer, so it's trying to read as much as would be valid for an integer. 1asdaosd is not a valid integer so it stops at the 1. If you want to read that thing in completely you'll have to make gametype a string for example, but then you won't be able to compare it to integers as you already do.
You can read it as a string if you want, and if you want to handle the case of strings and ints both, then you can use something like stoi to attempt to convert the string to an integer. Then catch the std::invalid_argument exception so you can know if the string can be converted to an integer. If it can't, then you know to keep it as a string.
It reads an int as far the input can be construed as such. Then stops. If you read into a string variable it will get it all.
Read data into a string variable.
Check that data is a valid integer.
Convert string to integer.
Tedious but it's the only way to do it
I'm guessing you want one input value on each line. You need to read this as string and then check if you got more than you asked for. If you need it as an integer you can convert the read string later.
I'm also assuming you only need to read single digit integers. More digits need the string to integer conversion in the loop and some more checks.
string gametype;
do
{
cout << "Choose the game type: ";
// read one word as string, no conversion, so will not fail (may hit eof though)
cin >> gametype;
// ignore rest of line (assuming you want next valid input on next line)
cin.ignore(std::numeric_limits<int>::max(), '\n');
}
while ( gametype.size() != 1 || gametype.at(0) < '1' || gametype.at(0) > '2') );
// char to int conversion (single digit only)
int gametypeint = gametype.at(0) - '0';
// other way to convert string to int
istringstream iss(gametype);
iss >> gametypeint;
// yet another way (C++11)
gametypeint = stio(gametype);