std::cin skipped after for loop [duplicate] - c++

I'm working through a text book for self study. I can do the while loop no problem, but I have no idea how to do the terminating character.
Here is what I have now:
#include "../../std_lib_facilities.h" // Supplied by book author
int main()
{
int ii = 0;
int yy = 0;
bool test = true;
cout << "Enter two ints" << endl;
while (test)
{
cin>>ii, cin>>yy;
// this if statement doesn't work
if (ii == '|' || yy == '|')
{
test = false;
}
// this if statement catches all bad input, even the terminating '|'
if (cin.fail())
{
cout << "bad input";
cin.clear();
cin.ignore();
continue;
}
else
cout << ii << yy << endl;
}
return 0;
}

Streams can be a little confusing if you're unfamiliar with them. It's a large topic that's just going to require more research. Here's an example that should work, to hopefully get you started.
int main(int argc, char* argv[])
{
bool test = true;
while ( test ) {
std::cout << "Enter two integers> ";
int x, y;
// if this fails, stream is bad.
// #note this will fail for any input which cannot be interpreted
// as an integer value.
if (std::cin >> x >> y) {
std::cout << x << " " << y << std::endl;
}
else {
// clear stream error state so we can read from it again.
std::cin.clear();
// check for terminating character; else unknown.
if (std::cin.get() == '|')
std::cout << "Terminator found, exiting." << std::endl;
else
std::cerr << "Error: bad input, exiting." << std::endl;
// in either case the loop terminates.
test = false;
}
}
return 0;
}
Hope this helps. Good luck.

Use the cin.peek() function as follows, before you input the two numbers:
c=(cin >> ws).peek();
if(c=='|')
{
cout<<"exiting";return 1;
}
Note: (cin>>ws) is to get rid of leading whitespaces. Also, c is of type char.
The complete code now looks like this:
int main()
{
int ii = 0;
int yy = 0;
bool test = true;
cout << "Enter two ints" << endl;
while (test)
{
char c;
c=(cin >> ws).peek();
if(c=='|')
{
cout<<"exiting";return 1;
}
cin>>ii, cin>>yy;
if (cin.fail())
{
cout << "bad input";
cin.clear();
cin.ignore();
continue;
}
else
cout << ii << yy << endl;
}
return 0;
}

Related

How to Accept [ENTER] key as an invalid input and send out error message

This is a program that grade user inputs for the questions of Driver's License Exam.
I'm having trouble of validating the user input.
I'd like to accept the [ENTER] key as an invalid input and proceed to my validation rather than just go to an empty line and cannot process to the next question. Purpose is to send out error message and that no input is given and [ENTER] key is not valid input and only accept one more chance to enter valid input which are a/A, b/B, c/C, or d/D. So that is why I'm using if statement here instead of loop.
I tried if (testTakerAnswers[ans] == (or =) '\n') {} but still doesn't solve the problem of newline.
I include curses.h in here hope to use getch() statement from the other post but somehow I can't manage to work in my code with an array instead of regular input.
I'm looking for other methods as well rather than getch()
So should I adjust my bool function, or directly validate input in main() function.
#include <iostream>
#include <iomanip>
#include <string>
#include <cctype>
#include <curses.h>
using namespace std;
const unsigned SIZE = 20; // Number of qns in the test
char testTakerAnswers[SIZE]; //Array to hold test taker's answers
bool validateInput(char);
class TestGrader
{
private:
char answers[SIZE]; // Holds the correct answers // Answer is array
int getNumWrong (char[]);
void missedQuestions (char[]);
public:
void setKey(string); // Initialize object with standard keys
void grade(char[]); // Grades the answers from tester
};
void TestGrader::setKey(string key){
if (key.length()!=SIZE){
cout << "Error in key data.\n";
return;
}
for (unsigned pos = 0; pos < SIZE ; pos ++)
answers [pos] = key [pos];
}
void TestGrader::grade(char test[])
{
int numWrong = getNumWrong(test);
if (numWrong <= 5)
cout << "Congratulations. You passed the exam.\n";
else
cout << "You did not pass the exam. \n";
cout << "You got " << (SIZE-numWrong) << " questions correct. \n";
if (numWrong > 0){
cout << "You missed the following " << numWrong << " questions: \n";
missedQuestions(test);
}
}
int TestGrader::getNumWrong(char test[])
{
int counter = 0;
for (int i = 0; i < SIZE; i++){
if (answers[i] != toupper(testTakerAnswers[i])){
counter++;
}
}
return counter;
}
void TestGrader::missedQuestions(char test[])
{
// cout << testTakerAnswers[i]; This is to print taker's answers
int counter = 0;
for (int i = 0; i < SIZE; i++){
if (answers[i] != toupper(testTakerAnswers[i])){
cout << "\n" << i + 1 << ". Correct answers: " << answers[i];
counter++;
}
}
}
bool validateInput(char ans){ // Only A, B, C, D valid input
if (toupper(ans)!='A' && toupper(ans)!= 'B' && toupper(ans)!='C' && toupper(ans)!= 'D'){
cout << "\n********************WARNING*******************\n";
cout << "Invalid input! Enter only a/A, b/B, c/C, or d/D\n";
return false;
}
if (testTakerAnswers[ans] == '\n'){
return false;
}
return true;
}
int main()
{
const int NUM_QUESTIONS = 20;
string name; //Test taker's name
char doAnother; //Control variable for main processing loop
TestGrader DMVexam; //Create a TestGrader object
DMVexam.setKey("BDAACABACDBCDADCCBDA");
do {
cout << "Applicant Name: ";
getline(cin,name);
cout << "Enter answer for " << name << ".\n";
cout << "Use only letters a/A, b/B, c/C, and d/D. \n\n";
for (int i = 0; i < NUM_QUESTIONS; i++){
// Input and validate it
do{
cout << "Q" << i+1 << ": ";
cin >> testTakerAnswers[i];
if (!validateInput(testTakerAnswers[i])){
cout << "You get one more chance to correct.\nOtherwise, it count as wrong answer.";
cout << "\n*********************************************";
cout << "\nRe-enter: ";
cin >> testTakerAnswers[i];
cout << '\n';
break;
}
}while(!validateInput(testTakerAnswers[i]));
}
//Call class function to grade the exam
cout << "Results for " << name << '\n';
DMVexam.grade(testTakerAnswers);
cout << "\nGrade another exam (Y/N)? ";
cin >> doAnother;
while (doAnother != 'Y' && doAnother != 'N' && doAnother != 'y' && doAnother != 'n'){
cout << doAnother << " is not a valid option. Try Again y/Y or n/N" << endl;
cin >> doAnother;}
cout << endl;
cin.ignore();
}while(doAnother != 'N' && doAnother != 'n');
return 0;
}
Your issue is cin >> testTakerAnswers[i]; cin is whitespace delimited, that means that any whitespace (including '\n') will be discarded. So testTakerAnswers[i] can never be '\n'.
I'm not sure exactly what you want to do, but possibly try
getline(cin,input_string);
then
input_string == "A" | input_string == "B" | ...
So if only the enter key is pressed, input_string will become "".

How to write a while loop that takes two ints and terminates with '|' in c++?

I'm working through a text book for self study. I can do the while loop no problem, but I have no idea how to do the terminating character.
Here is what I have now:
#include "../../std_lib_facilities.h" // Supplied by book author
int main()
{
int ii = 0;
int yy = 0;
bool test = true;
cout << "Enter two ints" << endl;
while (test)
{
cin>>ii, cin>>yy;
// this if statement doesn't work
if (ii == '|' || yy == '|')
{
test = false;
}
// this if statement catches all bad input, even the terminating '|'
if (cin.fail())
{
cout << "bad input";
cin.clear();
cin.ignore();
continue;
}
else
cout << ii << yy << endl;
}
return 0;
}
Streams can be a little confusing if you're unfamiliar with them. It's a large topic that's just going to require more research. Here's an example that should work, to hopefully get you started.
int main(int argc, char* argv[])
{
bool test = true;
while ( test ) {
std::cout << "Enter two integers> ";
int x, y;
// if this fails, stream is bad.
// #note this will fail for any input which cannot be interpreted
// as an integer value.
if (std::cin >> x >> y) {
std::cout << x << " " << y << std::endl;
}
else {
// clear stream error state so we can read from it again.
std::cin.clear();
// check for terminating character; else unknown.
if (std::cin.get() == '|')
std::cout << "Terminator found, exiting." << std::endl;
else
std::cerr << "Error: bad input, exiting." << std::endl;
// in either case the loop terminates.
test = false;
}
}
return 0;
}
Hope this helps. Good luck.
Use the cin.peek() function as follows, before you input the two numbers:
c=(cin >> ws).peek();
if(c=='|')
{
cout<<"exiting";return 1;
}
Note: (cin>>ws) is to get rid of leading whitespaces. Also, c is of type char.
The complete code now looks like this:
int main()
{
int ii = 0;
int yy = 0;
bool test = true;
cout << "Enter two ints" << endl;
while (test)
{
char c;
c=(cin >> ws).peek();
if(c=='|')
{
cout<<"exiting";return 1;
}
cin>>ii, cin>>yy;
if (cin.fail())
{
cout << "bad input";
cin.clear();
cin.ignore();
continue;
}
else
cout << ii << yy << endl;
}
return 0;
}

How do I loop a variable?

I have made a "program" that just says welcome! Type two numbers you want to be added to each other:
there you type the two numbers and then you get the answer out...
When that is done it says: Press any key to continue . . .
When you press a key the program shuts down, but I want it to restart when you pres any key...
How do I do that? I use Microsoft visual studio express 2013 for windows desktop...
langue is C++
This is my code:
#include <iostream>
#include <limits>
#include <cstdio>
using namespace std;
int Add(int x, int y)
{
cout << "Calculating the sum of " << x << " + " << y << "\n";
return (x + y);
}
int main()
{
cout << " Welcome!\n";
int a, b, c;
cout << "Type two numbers you want to be added to each other: ";
cin >> a;
cin >> b;
c = Add(a, b);
cout << "The answere is: " << c;
cout << "\nShutting down....\n\n";
system("pause");
return 0;
}
To loop, you can use while.
For example:
while (false) {
std::cout << "You will never see this output" << std::endl;
}
bool loop = true;
while (loop) {
std::cout << "Type 'quit' to quit this loop." << std::endl;
std::string input;
// This will grab a *single word* from the input. If you want a line, look
// at std::getline
std::cin >> input;
if (input == "quit") {
loop = false;
}
}
while (true) {
std::cout << "This will be repeated forever" << std::endl;
}
There are also two other forms, do while:
std::string input;
do {
std::cout << "Type 'quit' to quit." << std::endl;
std::cin >> input;
} while (input != "quit");
... and for (which is generally used for loop over a defined list of things):
for (size_t i = 0; i < 10; ++i) {
std::cout << i << " out of 10" << std::endl;
}
Technically you can use any of these loop types for any kind of looping, but I suspect the type you want is either one of the two standard infinite loops (whichever one you prefer):
while (true) {
// stuff to repeat forever
}
for (;;) {
// stuff to repeat forever
}
... or a do while loop similar to the do { ... } while (input != "quit"); loop above.
int main()
{
cout << " Welcome!\n";
int a, b, c;
while (true)
{
cout << "Type two numbers you want to be added to each other: ";
cin >> a;
cin >> b;
c = Add(a, b);
cout << "The answere is: " << c;
cout << "\nPress a key to go again....\n\n";
system("pause");
};
return 0;
}
You can do something like this:
int main()
{
cout << " Welcome!\n";
int a, b, c;
while(true) {
cout << "Type two numbers you want to be added to each other: ";
cin >> a;
cin >> b;
c = Add(a, b);
cout << "The answere is: " << c;
cout << "\nPress any key to continue\n";
system("pause");
}
return 0;
}
Use a do while loop mentioning your condition
before exiting the program so that you can determine when to continue and when to exit
I am not sure I understand your question, but I think this is what you are looking for. Have a boolean that determines if the program will loop or not.
int main() {
// stillRun is true while we want to keep looping the program
boolean stillRun = true;
while(stillRun) {
runProgram() ; // this function has all the other code in your old main() function
cin >> stillRun ;
}
}

Cannot input more than one string in palindrome program

#include <iostream>
#include <ctype.h>
using namespace std;
void isPalindrome();
int main()
{
char response;
isPalindrome();
cout << "Input another string(y/n)?" << endl;
cin >> response;
response = toupper(response);
if (response == 'Y')
isPalindrome();
return 0;
}
void isPalindrome()
{
char str[80], str2[80];
int strlength;
int j = 0;
int front, back;
bool flag = 1;
cout << "Input a string:" << endl;
cin.getline(str, 80);
strlength = strlen(str);
for (int i = 0; i < strlength; i++)
{
if (islower(str[i]))
str[i] = toupper(str[i]);
}
for (int i = 0; i < strlength; i++)
{
if (isalpha(str[i]))
{
str2[j] = str[i];
j++;
}
}
str2[j] = '\0';
front = 0;
back = strlength - 1;
for (int i = 0; i < j / 2; i++)
{
if (str2[front] != str2[back])
{
flag = 0;
break;
}
}
if (!(flag))
cout << "It is not a palindrome" << endl;
else
cout << "It's a palindrome" << endl;
cout << "str: " << str << " str2: " << str2 << " strlength: " << strlength << " j: " << j << endl;
cout << "front: " << front << " back: " << back << " flag: " << flag << endl;
}
I was just wondering if anybody could help explain to me why my code isn't working.
I can run it once just fine and I get the right answer, but when the prompt asks if I want to input another string and I type 'y', the prompt just skips over the input and terminates on it's own.
I tried cin.ginore('\n', 80), but that just gave me a bunch of blank lines. I added the bit of code at the end to check the values and they all go to 0 and drop the strings.
Maybe a link to a proper explanation of how the system handles memory?
edit:
I keep getting the same problem when running the input sequence a second time. The output looks like this:
Input a string:
Radar
It's a palindrome
Input another string(y/n)?
y
_ <- this being my cursor after pressing enter 3 times
I'll just re-build the program from scratch and try to do it without a function. I'd still appreciate a link to a page that explains how to process user input using modern c++.
The problem is with:
cin >> response;
This reads the user input y/n into the variable response but a newline is left in the input buffer which is picked by the getline function the isPalindrome function.
To fix this you need to remove the newline from the input buffer after you read the user response. You do it by using:
cin >> response;
std::cin.ignore(INT_MAX);
With the above fix you can retry the palindrome check just once. To make multiple retries possible you'll need a loop. I would recommend a do-while loop in your main as:
char response;
do {
isPalindrome();
cout << "Input another string(y/n)?" << endl;
cin >> response;
std::cin.ignore(INT_MAX);
response = toupper(response);
} while(response == 'Y');
You need a loop. There's no code that instructs the program to go back to the top.
char response = 'Y';
while (response == 'Y') {
isPalendrome();
cout << "Input another string(y/n)?" << endl;
cin >> response;
}
This isn't your entire program, just key elements that you need for a while loop. You should get an understanding of how while works and make this work for your program.
In contemporary C++ one would typically use standard library components for string processing:
#include <iostream>
#include <string>
int main()
{
std::string line1, line2, response;
do
{
std::cout << "First string: ";
if (!std::getline(std::cin, line1)) { /* error */ }
std::cout << "Second string: ";
if (!std::getline(std::cin, line2)) { /* error */ }
// check line1 and line2 for palindromy
std::cout << "Again (y/n)? ";
std::getline(std::cin, response);
} while (std::cin && (response == "y" || response == "Y"));
}

Do While loop breaks after incorrect input?

I am trying to have a loop continue to prompt the user for an option. When I get a string of characters instead of an int, the program loops indefinitely. I have tried setting the variable result to NULL, clearing the input stream, and have enclosed in try{}catch blocks (not in this example). Can anyone explain to me why this is?
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int menu(string question, vector<string> options)
{
int result;
cout << question << endl;
for(int i = 0; i < options.size(); i++)
{
cout << '[' << i << ']' << options[i] << endl;
}
bool ans = false;
do
{
cin >> result;
cin.ignore(1000, 10);
if (result < options.size() )
{
ans = true;
}
else
{
cout << "You must enter a valid option." << endl;
result = NULL;
ans = false;
}
}
while(!ans);
return result;
}
int main()
{
string menuQuestion = "Welcome to my game. What would you like to do?";
vector<string> mainMenu;
mainMenu.push_back("Play Game");
mainMenu.push_back("Load Game");
mainMenu.push_back("About");
mainMenu.push_back("Exit");
int result = menu(menuQuestion, mainMenu);
cout << "You entered: " << result << endl;
return 0;
}
It looks like there is a random element here, since result is not initialized.
In any case, test cin directly
if ( cin && result < options.size() )
and reset it upon invalid input so it will again perform I/O operations
result = 0; // inappropriate to initialize an integer with NULL
cin.clear(); // reset cin to work again
cin.ignore(1000, '\n'); // use \n instead of ASCII code