Ending an input stream with a specified character, such as '|'? - c++

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');

Related

How to only accept numbers in the input for cin? [duplicate]

Here is the code
double enter_number()
{
double number;
while(1)
{
cin>>number;
if(cin.fail())
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Invalid input " << endl;
}
else
break;
cout<<"Try again"<<endl;
}
return number;
}
My problem is that when I enter something like 1x, then 1 is taken as input without noticing the character that is left out for another run.
Is there any way how to make it work with any real number e.g. 1.8?
When cin encounters an input it can't properly read in to the variable specified (such as inputing a character into an integer variable), it goes into an error state and leaves the input in it's buffer.
You have to do several things to properly handle this scenario.
You have to test for this error state.
You have to clear the error state.
You have to either alternatively handle the input data that generated the error state, or flush it out and reprompt the user.
The following code provides one of numerous methods of doing these three things.
#include<iostream>
#include<limits>
using namespace std;
int main()
{
cout << "Enter an int: ";
int x = 0;
while(!(cin >> x)){
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Invalid input. Try again: ";
}
cout << "You enterd: " << x << endl;
}
You could just pass in some large value to cin.ignore like 1000 and it's likely to behave exactly the same for all practical purposes.
You can also test cin after the input attempt and handle it that way, something like
if(!cin){//clean up the error} .
Check out the istream reference for other member functions to handle stream state: http://cplusplus.com/reference/iostream/istream/
I would use std::getline and std::string to read the whole line and then only break out of the loop when you can convert the entire line to a double.
#include <string>
#include <sstream>
int main()
{
std::string line;
double d;
while (std::getline(std::cin, line))
{
std::stringstream ss(line);
if (ss >> d)
{
if (ss.eof())
{ // Success
break;
}
}
std::cout << "Error!" << std::endl;
}
std::cout << "Finally: " << d << std::endl;
}

How do I treat an input invalid as a whole (input like combination of numbers+letters where only numeric data is expected) [duplicate]

Here is the code
double enter_number()
{
double number;
while(1)
{
cin>>number;
if(cin.fail())
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Invalid input " << endl;
}
else
break;
cout<<"Try again"<<endl;
}
return number;
}
My problem is that when I enter something like 1x, then 1 is taken as input without noticing the character that is left out for another run.
Is there any way how to make it work with any real number e.g. 1.8?
When cin encounters an input it can't properly read in to the variable specified (such as inputing a character into an integer variable), it goes into an error state and leaves the input in it's buffer.
You have to do several things to properly handle this scenario.
You have to test for this error state.
You have to clear the error state.
You have to either alternatively handle the input data that generated the error state, or flush it out and reprompt the user.
The following code provides one of numerous methods of doing these three things.
#include<iostream>
#include<limits>
using namespace std;
int main()
{
cout << "Enter an int: ";
int x = 0;
while(!(cin >> x)){
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Invalid input. Try again: ";
}
cout << "You enterd: " << x << endl;
}
You could just pass in some large value to cin.ignore like 1000 and it's likely to behave exactly the same for all practical purposes.
You can also test cin after the input attempt and handle it that way, something like
if(!cin){//clean up the error} .
Check out the istream reference for other member functions to handle stream state: http://cplusplus.com/reference/iostream/istream/
I would use std::getline and std::string to read the whole line and then only break out of the loop when you can convert the entire line to a double.
#include <string>
#include <sstream>
int main()
{
std::string line;
double d;
while (std::getline(std::cin, line))
{
std::stringstream ss(line);
if (ss >> d)
{
if (ss.eof())
{ // Success
break;
}
}
std::cout << "Error!" << std::endl;
}
std::cout << "Finally: " << d << std::endl;
}

Why is a space in the string making my code loop infinitely? [duplicate]

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..

How to ignore non-integer user input with cin.ignore [duplicate]

Here is the code
double enter_number()
{
double number;
while(1)
{
cin>>number;
if(cin.fail())
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Invalid input " << endl;
}
else
break;
cout<<"Try again"<<endl;
}
return number;
}
My problem is that when I enter something like 1x, then 1 is taken as input without noticing the character that is left out for another run.
Is there any way how to make it work with any real number e.g. 1.8?
When cin encounters an input it can't properly read in to the variable specified (such as inputing a character into an integer variable), it goes into an error state and leaves the input in it's buffer.
You have to do several things to properly handle this scenario.
You have to test for this error state.
You have to clear the error state.
You have to either alternatively handle the input data that generated the error state, or flush it out and reprompt the user.
The following code provides one of numerous methods of doing these three things.
#include<iostream>
#include<limits>
using namespace std;
int main()
{
cout << "Enter an int: ";
int x = 0;
while(!(cin >> x)){
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Invalid input. Try again: ";
}
cout << "You enterd: " << x << endl;
}
You could just pass in some large value to cin.ignore like 1000 and it's likely to behave exactly the same for all practical purposes.
You can also test cin after the input attempt and handle it that way, something like
if(!cin){//clean up the error} .
Check out the istream reference for other member functions to handle stream state: http://cplusplus.com/reference/iostream/istream/
I would use std::getline and std::string to read the whole line and then only break out of the loop when you can convert the entire line to a double.
#include <string>
#include <sstream>
int main()
{
std::string line;
double d;
while (std::getline(std::cin, line))
{
std::stringstream ss(line);
if (ss >> d)
{
if (ss.eof())
{ // Success
break;
}
}
std::cout << "Error!" << std::endl;
}
std::cout << "Finally: " << d << std::endl;
}

How to make cin take only numbers

Here is the code
double enter_number()
{
double number;
while(1)
{
cin>>number;
if(cin.fail())
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Invalid input " << endl;
}
else
break;
cout<<"Try again"<<endl;
}
return number;
}
My problem is that when I enter something like 1x, then 1 is taken as input without noticing the character that is left out for another run.
Is there any way how to make it work with any real number e.g. 1.8?
When cin encounters an input it can't properly read in to the variable specified (such as inputing a character into an integer variable), it goes into an error state and leaves the input in it's buffer.
You have to do several things to properly handle this scenario.
You have to test for this error state.
You have to clear the error state.
You have to either alternatively handle the input data that generated the error state, or flush it out and reprompt the user.
The following code provides one of numerous methods of doing these three things.
#include<iostream>
#include<limits>
using namespace std;
int main()
{
cout << "Enter an int: ";
int x = 0;
while(!(cin >> x)){
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Invalid input. Try again: ";
}
cout << "You enterd: " << x << endl;
}
You could just pass in some large value to cin.ignore like 1000 and it's likely to behave exactly the same for all practical purposes.
You can also test cin after the input attempt and handle it that way, something like
if(!cin){//clean up the error} .
Check out the istream reference for other member functions to handle stream state: http://cplusplus.com/reference/iostream/istream/
I would use std::getline and std::string to read the whole line and then only break out of the loop when you can convert the entire line to a double.
#include <string>
#include <sstream>
int main()
{
std::string line;
double d;
while (std::getline(std::cin, line))
{
std::stringstream ss(line);
if (ss >> d)
{
if (ss.eof())
{ // Success
break;
}
}
std::cout << "Error!" << std::endl;
}
std::cout << "Finally: " << d << std::endl;
}