In case of an invalid input, I want extract the invalid input from cin and store it in a variable that fits. How can I do that?
#include<iostream>
using namespace std;
int main(){
int number;
cout << "Enter a number: " << endl;
cin >> number;
if(cin.fail()){
cout << "Error!" << endl;
//HOW CAN I STORE THE INVALID INPUT WHICH IS STORED IN cin INTO A STRING?
}
return 0;
}
When you detect that failbit is set, reset it, and use std::getline to read entire line of invalid input into std::string from std::cin:
#include <iostream>
#include <string>
int main()
{
int number;
while(true)
{
std::cout << "Enter a number (0 to exit): " << std::endl;
std::cin >> number;
if(std::cin.fail())
{
std::string error_data;
std::cin.clear(std::cin.rdstate() & ~std::ios::failbit);
std::getline(std::cin, error_data);
std::cout << "You didn't enter a number - you've entered: " << error_data << std::endl;
}
else
{
std::cout << "Number is: " << number << std::endl;
if(number == 0)
{
break;
}
}
}
return 0;
}
Related
#include <iostream>
#include <string>
#include <vector>
using namespace std;
//void FillNames(vector<string> & vecNames);
//void SortNames(vector<string> & vecNames);
int main() {
string firstName;
int i = 0;
cout << "Information:" << endl;
cout << "EOF character in windows is Control + Z" << endl;
cout << "and EOF character on Mac is Control + D:" << endl;
cout << "-----------------------------------------------" << endl;
while (i < 13) {
cout << "Enter first name only in all caps (example: JOHN)" << endl;
cout << "Enter EOF character to exit name entry: ";
cin >> firstName;
i++;
}
}
Here is a link to what i'm trying to accomplish.
https://drive.google.com/file/d/1AuW9hQPbd1f294dCZN6Q8Ac6lgIy0Ivf/view?usp=sharing
You can use the stream's input state to break the loop when EOF is entered:
while (i < 13) {
cout << "Enter first name only in all caps (example: JOHN)" << endl;
cout << "Enter EOF character to exit name entry: ";
if (cin >> firstName)
i++;
else
break;
}
The code has been updated in order to solve a different section of the whole picture within the coding process. Now I need help within the second case of the switch. The problem now is that the while loop always executes within the second function of the switch. I don't no if the array is verifying the number or the user input.. I could use while (string::npos != studID2[i].find_first_of(studID2[a])) I need some help here it is getting very complex and I am hitting a brick wall.
1)I need to verify each user input using a for loop and two arrays. I tried to increment the of the arrays in order to execute the while statement.
2) If the condition is true the while loop will execute telling the user that he must enter 3 different digits, the reason why I am using an array and a for loop is because the user gets to choose how many names and IDs he would like to input into the archive.
3) The for loop increments a++ in order to check to see if the last input is the same as the newest user input.
It is getting too complex here any help would be appreciated.
Number 4 is the expected error...
4) The second user input will always make the while loop run regardless of what digits you use.
5)The reason for so much code is because I am not completely sure where the problem begins and the problem ends...
6)I am using two arrays here in this problem.
7)There is another error if you change the a from 0 to 1 it will automatically close the program. The reason you would change the a to a 1 is so that a will increment by 1.
//I am trying to verify multiple inputs with a array and a for loop..
// The expected output is that the second ID you input in the second option of the switch case is going to execute the while loop.
//I am trying to execute the while loop properly within the second function of the switch case.
//I need help any form of help can be appreciated.
#include<iostream>
#include<string>
#include<fstream>
#include<sstream>
#include <cstddef>
#include <limits>
#include <cstdlib>
int name2 = 0;
int studentID = 0;
int email2 = 0;
int studentID2[100];
std::string let("abcdefghijklmnopqrstuvwxyz");
int numbers = (1, 3, 0);
std::string str;
std::string name;
std::string studID;
std::string studID2;
std::string email;
std::string emailbackup;
std::string studFinal;
std::stringstream concatenate;
std::stringstream concatenatetwo;
int x;
std::string fileName = "StudentArchive.txt";
void emailEntry();
void readDocument();
int readNumber();
void deleteInformation();
void getStudentinformation();
using std::cout;
using std::cin;
int main()
{
do {
std::cout << "What would you like to do?" << std::endl;
std::cout << "1)Would you like to see the archive?" << std::endl;
std::cout << "2)Would you like to register student information?" << std::endl;
std::cout << "3)Would you like to find a student within the registry?" << std::endl;
std::cout << "4)Delete all student information?" << std::endl;
std::cout << "5)Exit Program?" << std::endl;
std::cin >> x;
switch (x)
{
case 1:
readDocument();
break;
case 2:
emailEntry();
break;
case 3:
deleteInformation();
break;
case 4:
getStudentinformation();
break;
case 5:
cout << "Exiting Program." << std::endl;
system("PAUSE");
break;
}
} while (x != 5);
}
void emailEntry()
{
std::ofstream outfile;
outfile.open(fileName, std::ios_base::app);
int amountofStudent;
std::cout << "How many student Identities would you like to enter?" << std::endl;
std::cin >> amountofStudent;
cin.ignore();
Here is where the user chooses how many students he would like to enter into the registry. I am having difficulty verifying the user input regarding the studentIDs.
if (outfile.is_open()) {
for (int i = 0; i < amountofStudent; i++)
{
std::string studID2[100];
std::stringstream(name) >> name2;
cout << "Please enter your name.." << std::endl;
getline(cin, name);
outfile << name;
std::stringstream(name2) >> name;
while (std::string::npos != name.find_first_of("0123456789"))
{
cout << "You must have letter within user input." << std::endl;
cout << "Please enter your name." << std::endl;
getline(cin, name);
outfile << name;
}
//I need to check to see if the first 3 numbers are correct?
//The student ID must be at least 6 digits, and the first 3 numbers must be 130.
cout << "Please enter Your student I.D." << std::endl;
getline(cin, studID);
outfile << studID;
std::stringstream(studID) >> studentID;
while (/*std::string::npos != studID.find_first_of("130") */ studentID != 130 /*&& studID.length() <= 6*/)
{
std::stringstream(studentID) >> studID;
cout << "You must enter 130 as the first 3 digits" << std::endl;
getline(cin, studID);
std::stringstream(studID) >> studentID;
}
//==============
//std::stringstream(studentID2) >> studID2[i];
cout << "Please enter the second part of the student I.D. " << studentID << "-" << std::endl;
getline(cin, studID2[i]);
outfile << studID;
//outfile << studID2[i];
std::stringstream(studID2[i]) >> studentID2[i];
//cout << i;
This is the for loop, and array I need help with. Below this text is where I am having problems. I don't understand why the while loop won't execute I am trying to verify the first user input with the next user input. For example if the user enters 888 on the first input then tries to enter 888 on the second input they need to re-enter different digits or the input will go on forever. The main struggle is if the user chooses to enter multiple student accounts within this minor registry.
for (int a = 0; a < i; i++)
{
while (studID2[i] == studID2[a])
{
cout << "The numbers cannot be repeated you must re-enter the student ID." << std::endl;
std::stringstream(studentID) >> studID;
cout << "You must enter 130 as the first 3 digits" << std::endl;
getline(cin, studID);
std::stringstream(studID[i]) >> studentID;
//std::stringstream(studID2[i]) >> studentID2;
cout << "Please enter the second part of the student I.D. " << studentID << "-" << std::endl;
getline(cin, studID2[i]);
outfile << studID;
outfile << studID2[i];
//std::stringstream(studID2[i]) >> studentID2;
}
}
This is where the verification of the studentIDs end...
while (/*std::string::npos != studID.find_first_of("130") */ studID2[i].length() < 3 || studID2[i].length() > 3)
{
//stringstream(studentID) >> studID;
cout << "Add 3 more digits." << std::endl;
getline(cin, studID2[i]);
outfile << studID2[i];
}
concatenate << studentID << "-" << studID2 << std::endl;
studFinal = concatenate.str();
/*while (studID.length() != 6)
{
cout << "You must enter 130 as the first 3 digits and you must have 6 digits." << std::endl;
std::cin >> studID;
}*/
cout << "Please enter your email.." << std::endl;
std::stringstream(email) >> email2;
getline(cin, email);
outfile << email;
std::stringstream(email2) >> email;
while (email == emailbackup || email.empty())
{
cout << "Please enter your email..." << std::endl;
std::stringstream(email) >> email2;
getline(cin, email);
outfile << email;
std::stringstream(email2) >> email;
}
concatenatetwo << email << "#atlanticu.edu" << std::endl;
email = concatenatetwo.str();
emailbackup = email;
cout << "Your email is" << email << std::endl;
std::system("pause");
}
}
outfile.close();
}
Here is where the user deletes info..
void deleteInformation()
{
std::ofstream infile(fileName, std::ios::trunc);
if (infile.is_open()) {
cout << "You have now have no books." << std::endl;
system("PAUSE");
system("cls");
infile.close();
}
}
void getStudentinformation()
{
std::ifstream outfile;
outfile.open(fileName);
if(outfile.is_open())
{
int x;
cout << "1)Name" << std::endl;
cout << "2)studentNumber" << std::endl;
cout << "3)Exit" << std::endl;
cin >> x;
switch (x)
{
case 1:
cout << "Please enter the student's name.." << std::endl;
getline(cin, name);
cout << name << std::endl;
outfile >> name;
break;
case 2:
cout << "Please enter the first 3 digits of the student's ID number.. " << std::endl;
getline(cin, studID);
cout << "Please enter the last 3 digits of the student's ID number.. " << std::endl;
getline(cin, studID2);
outfile >> studID;
outfile >> studID2;
break;
case 3:
std::string choice;
cout << "Would you like to return to the main menus?" << std::endl;
cin >> choice;
break;
}
}
}
int readNumber()
{
int number;
cin >> number;
std::string tmp;
while (cin.fail())
{
cin.clear();
std::getline(cin, tmp);
cout << "Only numbers please: ";
cin >> number;
}
getline(cin, tmp);
return number;
}
Here is where the user reads the txt doc.
void readDocument()
{
std::ifstream infile;
infile.open(fileName);
if (infile.is_open()) {
std::string info;
while (getline(infile, info))
{
cout << info << std::endl;
}
infile.close();
}
else {
cout << fileName << " doesn't exists !" << std::endl;
}
std::system("PAUSE");
std::system("cls");
}
//std::ofstream outfile;
//outfile.open(fileName, ios_base::app);
//if(outfile.is_open()) {
// cout << "How many books do you want to add: ";
// int n = readNumber();
// while (n <= 0)
// {
// cout << "Only positive numbers, please: ";
// n = readNumber();
// }
// for (int i = 0; i < n; i++) {
// string title = "Book's Title: ";
// cout << title;
// title += readText();
// string author = "Author: ";
// cout << author;
// author += readText();
// string genre = "Book's Genre: ";
// cout << genre;
// genre += readText();
// cout << endl;
// outfile << title << endl;
// outfile << author << endl;
// outfile << genre << endl << endl;
// }
//}
// outfile.close();
// cout << "Books have been added to the library !" << endl;
// system("PAUSE");
// system("cls");
Think about your function signature.
void email(string emailbackup);
Do you actually want the caller to pass a string to the function email()?
Because you then define emailbackup inside the function again.
You want something like this probably...
...
case 2:
const string backup = "backup#email";
email(backup);
break;
...
void email(string emailbackup)
{
// string emailbackup; // delete this line
...
}
Also, remove using namespace std; and be consistent with your namespace usage. Why add using namespace cout, cin etc if you are calling them with the namespace explicitly i.e. std::cin, std::cout.
Either add using namespace std::cout and use cout rather than std::cout or vice versa. Don't mix it up. Same with std::string and string. Makes it look like you defined your own string...
Just one last thing, for the sake of readability I would suggest breaking this email function into smaller functions. For instance:
void email(string emailbackup)
{
...
int studentID = getStudentID();
string studentEmail = getStudentEmail();
...
}
int getStudentID()
{
int studentID;
cout << "Please enter Your student I.D." << std::endl;
std::cin >> studID;
stringstream(studID) >> studentID;
while (/*std::string::npos != studID.find_first_of("130") */ studentID != 130 /*&& studID.length() <= 6*/)
{
stringstream(studentID) >> studID;
cout << "You must enter 130 as the first 3 digits" << std::endl;
std::cin >> studID;
stringstream(studID) >> studentID;
}
return studentID;
}
I'm trying to display "invalid option" when the user enters a letter instead of a number. I tried using the isalpha() function but I get an infinite loop showing 0 Invalid option!try again:. The 0 from the output is displayed when entering a letter. When I actually type in the number 0 the message is displayed and the loop is exited.
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cctype>
using namespace std;
int main() {
// Vaules do not change
const int minNum = 1;
const int maxNum = 100;
int userInput;
// Changes every second
srand(time(0));
// Random number is stored
const int answer = minNum + (rand() % maxNum);
cout << answer << endl; // For testing purposes
cout << "Guess a number 1-100: ";
cin >> userInput;
cout << endl;
if(userInput == answer) {
cout << "Correct!\n\n";
}
while(userInput != answer) {
if(userInput < 1 || userInput > 100 || isalpha(userInput)) {
cout << userInput << " Invalid option!\ntry again: ";
cin >> userInput;
cout << endl;
}
else if(userInput < answer) {
cout << userInput << " is too low!\ntry again: ";
cin >> userInput;
cout << endl;
}
else if(userInput > answer) {
cout << userInput << " is too high!\ntry again: ";
cin >> userInput;
cout << endl;
}
}
cout << userInput << " is correct!\n\n";
return 0;
}
When you need to deal with user input differently based on some logic, your best option is to:
Read lines of text. Figure out what to do when there is no more input.
Process each line of text using custom logic.
In your case, you could use:
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cctype>
using namespace std;
int main() {
// Vaules do not change
const int minNum = 1;
const int maxNum = 100;
int userInput;
// Changes every second
srand(time(0));
// Random number is stored
const int answer = minNum + (rand() % maxNum);
cout << answer << endl; // For testing purposes
std::string line;
cout << "Guess a number 1-100: ";
while ( getline(std:::cout, line ) )
{
// Deal with empty lines.
if ( line.size() == 0 )
{
continue;
}
// If the first character is a letter ...
if(isalpha(line[0])) {
cout << line << "\n Invalid option!\ntry again: ";
continue;
}
// Extract the number from the line using a stringstream.
// If there is a problem extracting the number ...
std::istringstream str(line);
if ( !(str >> userInput ) )
{
cout << line << "\n Invalid option!\ntry again: ";
continue;
}
cout << endl;
// Check the user input against the random answer.
if(userInput == answer) {
cout << "Correct!\n\n";
}
else if(userInput < 1 || userInput > 100 ) {
cout << userInput << " Invalid option!\ntry again: ";
}
else if(userInput < answer) {
cout << userInput << " is too low!\ntry again: ";
}
else if(userInput > answer) {
cout << userInput << " is too high!\ntry again: ";
}
cout << "Guess a number 1-100: ";
}
cout << userInput << " is correct!\n\n";
return 0;
}
I'm trying to write a program that reads input as int from the command line, and if the user enters an int, program prints "Input is " + the number if users enter an incorrect type input, output "wrong input".
Here is my code:
#include <iostream>
#include <string>
using namespace std;
int main() {
int input;
cout << "Enter an Int:" << endl;
cin >> input;
if (!(cin >> input)) {
cout << "wrong format input" << endl;
return 1;
}
cout << "input is " << input << endl;
return 0;
}
Now with cin >> input; (case-1) program asks for twice input when enter correct integer; it prints "wrong format input" if user enter '2.2' or 'a'.
Without cin >> input; (case-2) program ask for once input when enter correct integer; but it prints "input is 2" when user enter '2.2', instead of printing "wrong" message, program prints "Input is 2".
Which part in my code did I make mistake? How can I fix this?
For case-2:
Here is the sample that allows to enter several integers on the same line, but disallows anything else
#include <iostream>
#include <string>
int main()
{
std::string input;
while(std::cin >> input){
size_t last;
int res;
bool good = true;
try{
res = std::stoi(input,&last);
}
catch(...){
good = false;
}
if(!good || last != input.length()){
std::cout << "Incorrect input: " << input << ", try again.\n";
}
else{
std::cout << "Integer read: " << res << '\n';
}
}
return 0;
}
/***************
Output
$ ./test
2
Integer read: 2
hello
Incorrect input: hello, try again.
2.2
Incorrect input: 2.2, try again.
1111111111111111111111111111111111111111111111111111111111111111111111
Incorrect input: 1111111111111111111111111111111111111111111111111111111111111111111111, try again.
3 4
Integer read: 3
Integer read: 4
^Z
[3]+ Stopped ./test
*/
Another version - using stringstream
while(std::cin >> input){
std::istringstream ss(input);
int res;
ss >> res;
if(!ss){
std::cout << "Incorrect input: " << input << ", try again.\n";
}
else{
char ch = ss.get();//let's check that no more characters left in the string
if(!ss){
std::cout << "Integer read: " << res << '\n';
}
else{
std::cout << "Incorrect input: " << input << ", try again.\n";
}
}
}
if(!(cin >> input)) is the reason for the second input. Just do this:
#include <iostream>
#include <string>
using namespace std;
int main() {
int input;
cout << "Enter an Int:" << endl;
cin >> input;
if (cin.fail()) {
cout << "wrong format input" << endl;
return 1;
}
cout << "input is " << input << endl;
return 0;
}
This is the program:
#include <iostream>
#include <string>
#include <stdlib.h>
using namespace std;
int main(){
string strKingdom = "";
bool conquered_me;//see if was conquered, was going to use this on other program and true = game over.
int gold;
int food;
int citizens;
int soldiers;
cout << endl <<"Name of kingdom: ";
cin >> strKingdom;
cout << endl << "were you conquered (true/false): ";
cin >> conquered_me;
cout << endl << "How many gold do you have?:";
cin>>gold;
cout << endl << "How many food do you have?:";
cin >> food;
cout << endl << "How many citizens do you have?:";
cin >> citizens;
cout << endl << "How many soldiers do you have?:";
cin >> soldiers;
return 0;
}
The problem is that when I compile it the progam only lets me insert the first 2 variables and then it shows the rest of the questions (after compile):
Name of kingdom: steve
were you conquered (true/false): false
How many gold do you have?:
How many food do you have?:
How many citizens do you have?:
How many soldiers do you have?:
Entering string "true" to the bool variable does not work. You should enter 1 or 0. Your "true" cannot be "consumed", so it's left in the buffer. Next, you're trying to read int value, so "true" also does not match. And so on... until the end of the program.
That's how I would do that:
#include <string>
#include <iostream>
#include <errno.h>
#include <stdlib.h>
using namespace std;
void askForString(string aPrompt, string &aValue) {
cout << aPrompt << " ";
cin >> aValue;
}
void askForBool(string aPrompt, bool &aValue) {
string tString;
while (1) {
cout << aPrompt << " ";
cin >> tString;
if (tString == "true") {
aValue = true;
break;
} else if (tString == "false") {
aValue = false;
break;
} else {
cout << "Repeat, please?" << endl;
}
}
}
void askForInt(string aPrompt, int &aValue) {
string tString;
char *endptr;
while (1) {
cout << aPrompt << " ";
cin >> tString;
errno = 0;
aValue = strtol(tString.c_str(), &endptr, 10);
if (errno || tString.c_str() == endptr || (endptr != NULL && *endptr != 0)) {
cout << "Repeat, please?" << endl;
} else {
break;
}
}
}
int main(void) {
string strKingdom;
bool conquered_me;
int gold;
int food;
int citizens;
int soldiers;
askForString("Name of kingdom:", strKingdom);
askForBool("were you conquered (true/false):", conquered_me);
askForInt("How many gold do you have?:", gold);
askForInt("How many food do you have?:", food);
askForInt("How many citizens do you have?:", citizens);
askForInt("How many soldiers do you have?:", soldiers);
cout << "Kingdom: " << strKingdom << endl;
cout << "Conquered: " << (conquered_me ? "true" : "false") << endl;
cout << "Gold: " << gold << endl;
cout << "Food: " << food << endl;
cout << "Citizens: " << citizens << endl;
cout << "Soldiers: " << soldiers << endl;
return 0;
}
Bring them all into strings, and convert as needed.
For some reason (probably compatibility with older code) iostreams default to converting true to 1 and false to 0 during I/O.
That's only the default though--there's a manipulator named boolalpha that will set the stream to use true and false (or localized equivalents) instead.
So, code like:
std::cout << 1 == 0; // produces `0`
std::cout << boolalpha << 1 == 0; // produces `false`
This also works for input, so you can change your code to something like this:
cin >> boolalpha >> conquered_me;
...and it should work as expected (and in: it should accept inputs of false or true, and produce values of false and true from them, and if it doesn't that's bug in the standard library).
None of your read commands check for error. ALL of them should be written as something like:
while (!(std::cin >> strKingdom)) {
std::cerr << 'Bad input' << std::endl;
std::cin.clear(); // clear the error
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // ignore the rest of the line
// output the same prompt again?
}
To make this easier, you might want to write a helper function:
template<typename T> void get_input(const char *prompt, T &result) {
std::cout << prompt << std::endl;
while (!(std::cin >> result)) {
std::cerr << 'Bad input' << std::endl;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << prompt << std::endl; } }
You can then specialize that for bool types to read true/false properly...
This line:
cin >> conquered_me;
Should be like this:
cin >> boolalpha >> conquered_me;
Otherwise the input expects either a "0" or a "1".
By using boolalpha your input can be "true" or "false.
You need to employ std::getline and std::string to read the various values. (You can then use functions like atoi to parse them.) Here is your code sample using the std::getline function.
#include <iostream>
#include <string>
#include <cstdlib>
int main(){
std::string strKingdom = "";
bool conquered_me;//see if was conquered, was going to use this on other program and true = game over.
int gold;
int food;
int citizens;
int soldiers;
std::string tString = ""; // Used to read and subsequently parse the string.
std::cout << std::endl <<"Name of kingdom: ";
std::getline(std::cin,strKingdom);
std::cout << std::endl << "were you conquered (true/false): ";
std::getline(std::cin,tString);
conquered_me = (tString == "true");
std::cout << std::endl << "How many gold do you have?:";
std::getline(std::cin,tString);
gold = std::atoi(tString.c_str());
std::cout << std::endl << "How many food do you have?:";
std::getline(std::cin,tString);
food = std::atoi(tString.c_str());
std::cout << std::endl << "How many citizens do you have?:";
std::getline(std::cin,tString);
citizens = std::atoi(tString.c_str());
std::cout << std::endl << "How many soldiers do you have?:";
std::getline(std::cin,tString);
soldiers = std::atoi(tString.c_str());
return 0;
}