As the question says, for some reason my program is not flushing the input or using my variables in ways that I cannot identify at the moment. This is for a homework project that I've gone beyond what I had to do for it, now I just want the program to actually work :P
Details to make the finding easier:
The program executes flawlessly on the first run through. All throws work, only the proper values( n > 0 ) are accepted and turned into binary.
As soon as I enter my terminate input, the program goes into a loop and only asks for the terminate again like so:
When I run this program on Netbeans on my Linux Laptop, the program crashes after I input the terminate value. On Visual C++ on Windows it goes into the loop like just described.
In the code I have tried to clear every stream and initialze every variable new as the program restarts, but to no avail. I just can't see my mistake.
I believe the error to lie in either the main function:
int main( void )
{
vector<int> store;
int terminate = 1;
do
{
int num = 0;
string input = "";
if( cin.fail() )
{
cin.clear();
cin.ignore( numeric_limits<streamsize>::max(), '\n' );
}
cout << "Please enter a natural number." << endl;
readLine( input, num );
cout << "\nThank you. Number is being processed..." << endl;
workNum( num, store );
line;
cout << "Go again? 0 to terminate." << endl;
cin >> terminate // No checking yet, just want it to work!
cin.clear();
}while( terminate );
cin.get();
return 0;
}
or in the function that reads the number:
void readLine( string &input, int &num )
{
int buf = 1;
stringstream ss;
vec_sz size;
if( ss.fail() )
{
ss.clear();
ss.ignore( numeric_limits<streamsize>::max(), '\n' );
}
if( getline( cin, input ) )
{
size = input.size();
for( int loop = 0; loop < size; ++loop )
if( isalpha( input[loop] ) )
throw domain_error( "Invalid Input." );
ss << input;
ss >> buf;
if( buf <= 0 )
throw domain_error( "Invalid Input." );
num = buf;
ss.clear();
}
}
When you call cin >> terminate, it will read the value of terminate, but leave the newline following it in the input stream. Late when you call getline(cin, input), it will read up to the newline, which means it will get an empty string.
You can discard all characters up to the newline by adding this after cin >> terminate:
cin.ignore(99, '\n');
Or avoid mixing operator >> and getline.
Don't mix those >> and getline operators as interjay mentioned.
Also, if you want to clear your code, I assume it can be rewritten the folllowing way:
int main() {
while (true) {
std::cout << "Please enter a natural number" << std::endl;
int num;
std::cin >> num;
// Exception handling here can be done easily
// like this
// if (!(std::cin >> num) || num < 0)
// throw std::domain_error("TROLOLOLO");
std::cout << "Thank you. Number is being processed..." << std::endl;
//workNum(num, store) here
std::cout << "Go again? 0 to terminate." << std::endl;
int terminate;
std::cin >> terminate;
if (terminate == 0) break;
}
}
Related
Currently learning C++, newbie.
I have an issue when ending the input with the '|' character, my program skips to the end/ends and does not allow for further input. I believe it is because std::cin is in an error state due to inputting a char when expecting an int, so i have tried to use std::cin.clear() and std::cin.ignore() to clear the issue and allow the remainder of the programme to run but I still cannot seem to crack it, any advice appreciated.
int main()
{
std::vector<int> numbers{};
int input{};
char endWith{ '|' };
std::cout << "please enter some integers and press " << endWith << " to stop!\n";
while (std::cin >> input)
{
if (std::cin >> input)
{
numbers.push_back(input);
}
else
{
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max());
}
}
And then pass the vector to a function to iterate through x amount of times and add each element to a total, but the program always skips past the user input:
std::cout << "Enter the amount of integers you want to sum!\n";
int x{};
int total{};
std::cin >> x;
for (int i{ 0 }; i < x; ++i)
{
total += print[i];
}
std::cout << "The total of the first " << x << " numbers is " << total;
Please help!
When the use enters a "|" (or anything that is not an int), the loop ends and the error handling that is inside the loop does not execute. Just move the error code to outside the loop. Also, you read from stdin twice which will skip every other int.
while (std::cin >> input) {
numbers.push_back(input);
}
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
Note: If you want to specifically check for "|" can change to something like this:
while (true) {
if (std::cin >> input) {
numbers.push_back(input);
}
else {
// Clear error state
std::cin.clear();
char c;
// Read single char
std::cin >> c;
if (c == '|') break;
// else what to do if it is not an int or "|"??
}
}
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
"Write a program that consists of a while-loop that (each time around the loop) reads in two ints and then prints them.
Exit the program when a terminating '|' is entered."
my attempt
#include <iostream>
#include <cstdlib>
using namespace std;
int main(){
int firstnumber;
int secondnumber;
int stopnumber;
while(stopnumber!='|'){
cout <<"Please enter an integer, followed by another integer: \n";
cin >> firstnumber >> secondnumber;
cout <<"\n" << firstnumber <<" "<< secondnumber<< " \n";
}
return 0;
}
the program takes 2 number and prints them, but when i enter '|' , it goes in infinite loop. How to stop the program when i enter '|'
Thanks
This is how your loop should look like:
Read a character (std::cin::get).
If successful and your character is the stop symbol, break the loop.
If your character is not a digit (::isdigit), continue looping.
If your character is a digit, put it back(std::cin::putback).
Read two integers.
If successful, display them, if not, clear the stream (std::cin::clear).
You will have to patiently try to understand what get, putback & isdigit are doing.
[EDIT]
Run it
#include <iostream>
#include <cctype>
int main()
{
char c;
while ( std::cin.get( c ) && c != '|' )
{
if ( !std::isdigit( c ) )
continue;
std::cin.putback( c );
int i, j;
if ( std::cin >> i >> j )
std::cout << i << ' ' << j << std::endl;
else
std::cin.clear();
}
return 0;
}
Your loop is testing stopnumber which is never set. If you set stopnumber to either firstnumber or secondnumber then perhaps you can get your logic to work but there is a step missing as it is.
Ok, I think I have found my answer
I tried putting my cin in the while loop as such
int firstnumber;
int secondnumber;
while (cin >> firstnumber >> secondnumber)
And it worked! Thanks everyone for your help
This depends on whether you need to exit directly after you receive the '|' character or whether you mind running through the rest of the loop first before exiting it......
Personally I'd want to exit straight after receiving the '|' so would follow the basic idea of....
int a,b;
while(){
read your values a,b in
if (a='|' || b='|'){exit()};
print your values
}
std::stoi(std::string) - returns int from std::string
#include <iostream>
#include <string>
bool isNumber(std::string &str) {
for (auto i : str) {
if (i < '0' || i > '9') return false;
return true;
}
int main () {
int a, b;
std::string s;
while (true) {
std::cin >> s;
if (s == "|" || !isNumber(s)) break;
a = std::stoi(s);
std::cin >> s;
if (s == "|" || !isNumber(s)) break;
b = std::stoi(s);
std::cout << a << " " << b << std::endl;
}
return 0;
}
This question already has answers here:
Infinite loop with cin when typing string while a number is expected
(4 answers)
Closed 6 years ago.
I have the following code which simply takes a string and find each character's index in the alphabet.
void encrypt()
{
string alpha = "abcdefghijklmnopqrstuvwxyz";
string word;
vector<char> temp;
char a, b;
cout << "Enter string to encrypt: \n";
cin >> word;
for (int i=0; i<word.length(); i++)
{
bool t = false;
a = word[i];
for (int j=0; j<alpha.length(); j++)
{
b = alpha[j];
if (a == b)
{
cout << a << "'s index = " << j+1 << endl;
t = true;
}
}
if (t == false)
{
cout << "space here\n";
}
}
}
when i input a word/string with no space the code works fine but when i input a string with a space the program goes into an infinite loop.
edit main() added due to request:
main()
{
int a;
bool b = false;
while (b == false)
{
cout << "1. Encrypt a string\n";
cout << "2. Decrypt a string\n";
cout << "3. Exit\n";
cout << endl;
cin >> a;
cout << endl;
if (a == 1)
{
encrypt();
}
else if (a == 2)
{
decrypt();
}
else if (a == 3)
{
b = true;
}
}
return 0;
}
cin >> word;
will read only the first word and leave the second word in the input stream. After that, the call
cin >> a;
will result in an error unless the second word starts with a number. Once the program enters a state of error, nothing is read and the program stays in a loop.
To diagnose problems like these, always check the state of the stream after a read operation.
if ( cin >> word )
{
// Use word
}
else
{
// Deal with error.
}
if ( cin >> a )
{
// Use a
}
else
{
// Deal with error.
}
To address your real problem, don't use operator>> to read space separated string. Use getline (and use a variable name different from word).
std::string str;
if ( getline(std::cin, str) )
{
// Use str
}
else
{
// Deal with error.
}
However, in order to use getline successfully, you have to make sure that after a is read, you ignore the rest of the line. Otherwise, the rest of the line will be read by getline.
if ( cin >> a )
{
// Ignore rest of the line
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// Use a
}
else
{
// Deal with error.
}
Replace cin >> word; with getline(cin, word);. It will accept a line as input. Which will resolves your input containing spaces.
As far as infinite loop concern, clear the error bits on the stream cin.clear();
You can check whether cin is accepting the space separated string completely, by doing a cout instantly after the cin. If cin is not accepting the space separated string, then try using getline
Issue resolved:
Use the following:
cout << "Enter string to encrypt: ";
scanf(" %[^\n]s",word);
for (int i=0; word[i]!='\0'; i++)
{
use
include <cstdio>
Hope this solves the problem!! I will get back to you with the solution using string..
I'm having a problem with what should be incredibly simple code. I want to take in an integer between 1 and 3 with error checking. It works fine for checking for numbers that are too large or too small, but when a alpha/number combination is entered, it gets stuck in an infinite loop. Suggestions?
#include <iostream>
using namespace std;
int main(int argc, char *argv[]){
int input;
cout << "\nPlease enter a number from 1 to 3:" << endl;
cout << "-> ";
cin >> input;
while(input< 1 || input> 3){
cout << "\n---------------------------------------" << endl;
cout << "\n[!] The number you entered was invalid." << endl;
cout << "\nPlease re-enter a number from 1 to 3" << endl;
cout << "-> ";
cin >> input;
}
cout << "You chose " << input << endl;
}
The problem is that:
cin >> input;
Will cause the bad bit to be set when you try and read a non numeric value. After that happens any attempt to use the operator>> is silently ignored.
So the way to correct for this is to test if the stream is in a good state and if not then reset the state flags and try and read again. But note that the bad input (that caused the problem) is still on the input so you need to make sure you throw it away as well.
if (cin >> input)
{
// It worked (input is now in a good state)
}
else
{
// input is in a bad state.
// So first clear the state.
cin.clear();
// Now you must get rid of the bad input.
// Personally I would just ignore the rest of the line
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// now that you have reset the stream you can go back and try and read again.
}
To prevent it getting stuck (which is caused by the bad bit being set) read into a string then use a string stream to parse user input. I also prefer this method (for user interactive input) as it allows for easier combination of different styles of reading (ie combining operator>> and std::getline() as you can use these on the stringstream).
#include <iostream>
#include <sstream>
#include <string>
// using namespace std;
// Try to stop using this.
// For anything other than a toy program it becomes a problem.
int main(int argc, char *argv[])
{
int input;
std::string line;
while(std::getline(std::cin, line)) // read a line at a time for parsing.
{
std::stringstream linestream(line);
if (!(linestream >> input))
{
// input was not a number
// Error message and try again
continue;
}
if ((input < 1) || (input > 3))
{
// Error out of range
// Message and try again
continue;
}
char errorTest;
if (linestream >> errorTest)
{
// There was extra stuff on the same line.
// ie sobody typed 2x<enter>
// Error Message;
continue;
}
// it worked perfectly.
// The value is now in input.
// So break out of the loop.
break;
}
}
#include <iostream>
#include <string>
using namespace std;
int validatedInput(int min = 1, int max = 3)
{
while(true)
{
cout << "Enter a number: ";
string s;
getline(cin,s);
char *endp = 0;
int ret = strtol(s.c_str(),&endp,10);
if(endp!=s.c_str() && !*endp && ret >= min && ret <= max)
return ret;
cout << "Invalid input. Allowed range: " << min << "-" << max <<endl;
}
}
int main(int argc, char *argv[])
{
int val = validatedInput();
cout << "You entered " << val <<endl;
return 0;
}
Most of these answers include unnecessary complexity.
Input validation is a perfect time to use a do-while
do{
cout << "\nPlease enter a number from 1 to 3:" << endl;
cout << "-> ";
if(!cin){
cout << "Invalid input"
cin.clear()
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
}while(!(cin >> input))
Use numeric_limits<streamsize>::max() to completely clear the
buffer after a failed cin.
Use cin.clear() to reset the fail flag on cin so !cin wont
always evaluate false.
cin.fail() is fine. However some would consider !cin more natural.
from my previous post https://stackoverflow.com/a/43421325/5890809
You declared input as int but when you write an alphanumeric character to input it will try to implicitly convert it into integer. But you error checking does not account for this.
Ur problem can be easily solved by changing your while loop. instead of checking this how about you check
while(input!=1 || input!=2 || input!=3)
cout << "How many questions are there going to be on this exam?" << endl;
cout << ">>";
getline(cin, totalquestions);
This small piece of code comes from a function in a class that I have created and I need totalquestions to be an int so that it can run through a for loop and keep asking the total amount of questions that I have asked.
question q;
for(int i = 0; i < totalquestions; i++)
{
q.inputdata();
questions.push_back(q);
}
Where does this piece of code comes to play? Does anyone have any idea to make this work?
Use
cin >> totalquestions;
Check the errors too
if (!(cin >> totalquestions))
{
// handle error
}
getline reads an entire line as a string. You'll still have
to convert it into an int:
std::string line;
if ( !std::getline( std::cin, line ) ) {
// Error reading number of questions...
}
std::istringstream tmp( line );
tmp >> totalquestions >> std::ws;
if ( !tmp ) {
// Error: input not an int...
} else if ( tmp.get() != EOF ) {
// Error: unexpected garbage at end of line...
}
Note that just inputting std::cin directly into
totalquestions does not work; it will leave the trailing
'\n' character in the buffer, which will desynchronize all of
the following input. It's possible to avoid this by adding a
call to std::cin.ignore, but this would still miss the error
due to trailing garbage. If you're doing line oriented input,
stick with getline, and use std::istringstream for any
necessary conversions.
Do this:
int totalquestions;
cout << "How many questions are there going to be on this exam?" << endl;
cout << ">>";
cin >> totalquestions;
Getline is meant for grabbing chars. It can be done with getline(), but cin is much easier.
One of the better ways of getting an int from user :-
#include<iostream>
#include<sstream>
int main(){
std::stringstream ss;
ss.clear();
ss.str("");
std::string input = "";
int n;
while (true){
if (!getline(cin, input))
return -1;
ss.str(input);
if (ss >> n)
break;
std::cout << "Invalid number, please try again" << std::endl;
ss.clear();
ss.str("");
input.clear();
}
Why is it better than using cin >> n ?
Actual article explaining why
As for your question, use the above code to get the int value and then use it in the loop.
Don't use getline:
int totalquestions;
cin >> totalquestions;