go back to first instruction when there is an error - c++

I am creating a simple console application that obtain user input which is an integer.
I want the condition so that it should only be an integer and it should be not more than 3 and not less than 0.
The code i came up so far is:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main()
{
int uinval;
while (true) {
string tempoval;
cout << "Please enter a value between 0-3:\n>";
cin >> tempoval;
stringstream ss(tempoval);
if (ss >> uinval)
{
break;
cout << "Entered an invalid value";
}
while (true)
{
if (uinval < 0 || uinval > 3)
break;
cout << "Value must be between 0-3";
}
cout << "You have entered:" << uinval;
return 0;
}
This works when I input a non-integer value like a,b,c,d. But it does not work when i input -1 or 4 as value.
I am not sure, maybe I confused myself with the while loops.

This is incorrect:
while(true){
if(uinval < 0 || uinval > 3)
break;
cout <<"Value must be between 0-3";
}
You check the condition on uinval repeatedly, without giving user a chance to enter a new value.
To fix the problem, remove the second loop, and replace
if(ss >> uinval) {
break;
}
inside the first loop with
if(ss >> uinval && uinval >= 0 && uinval < 4) {
break;
}

You have your if statement holding the opposite of what you want it to.
Right now if the value is under 0 or over 3, it'll break and continue. You want it to continue if it's over 0 and under 3.
if(uinval > 0 && uinval < 3)

Related

How can I throw a error if the user enters more than one integer

So this is my code:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
long int iterFunc(int);
long int recurFunc(int);
int main() {
int n;
while(true){
try{
cout << "Enter: ";
if (!(cin >> n))
throw("Type Error");
if (n < 0)
throw n;
else
if (n == 0)
break;
cout << "Iterative: " << iterFunc(n) << endl;
cout << "Recursive: " << recurFunc(n) << endl;
}
catch(int n){
cout << "Error. Enter positive number." << endl;
}
catch(...){
cin.clear();
cin.ignore(100, '\n');
cout << "Error. Please enter a number" << endl;
}
}
cout << "Goodbye!";
return 0;
}
long int iterFunc(int n){
vector<long int> yVec = {1, 1, 1, 3, 5};
if (n <= 5)
return yVec[n - 1];
else
for(int i = 5;i < n; i++){
long int result = yVec[i - 1] + 3 * yVec[i- 5];
yVec.push_back(result);
}
return yVec.back();
}
long int recurFunc(int n){
switch (n) {
case 1:
case 2:
case 3:
return 1;
break;
case 4:
return 3;
break;
case 5:
return 5;
break;
default:
return recurFunc(n - 1) + 3 * recurFunc(n - 5);
break;
}
}`
The program shoud accept only one integer and return the y of the function using both iterative and recursive implemetations. Ex.: 30, 59, 433. How can I throw an error message if the user enters more then one integer, separated by space? Ex.: '3 45 32'.
I tried using if (cin.getline == ' ') throw("Error name") but the program still executes and return the y of the function for number in the input
Something like this works:
int main()
{
std::string str;
std::cout << "? : ";
std::getline(std::cin, str);
std::string::size_type pos(0);
int i = std::stoi(str, &pos);
if (pos != str.length())
return 1;
}
I found a part of my old code that might come in handy.
int val;
do
{
cin>>val;
if(!cin){ //you can add more conditions here
cin.clear();
cin.sync();
/* additional error handling */
}
else{
break; //input is correct - leaving loop
}
}while(true); //or here
Basically what !cin does is - it checks what type of value you actually want to write to, because it's needed anyway to figure out if data type is written to the correct type of our val. This means, that "30" or "433" etc. are integers (correct), "s" or "string" etc. are strings (or char*, correct me if I am wrong) (incorrect).
This also means, that "3 45 32" should be interpreted as string, which should result in another loop run.
Note: I didn't really test this code, so it might be completely wrong.
Edit: Okay now after some tests I realised this code needs some retweaking.
Firstly, "3 45 32" is not interpreted as string (now understandable). Instead, first number (before whitespace) is saved as an integer and all other numbers are stored in the buffer (next cin will be filled with it), which we can avoid using cin.clear() and cin.sync() once again.
The question is - is it okay for you to accept the first integer and ignore everything after the first whitespace? If not, you will have to save the input as string and extract whatever data you want from it.
I am leaving the original answer as is for simplicity of finding references in this edit.

C++ do while loop not working

I'm trying to make this code work:
#include <iostream>
using namespace std;
int main()
{
int i;
do
{
cout << ("please enter a number between 1 and 10");
cin >> i;
} while(i > 10 && i < 1)
cout << "the square of the number you have entered is " << i*i;
}
Basically, the idea is that a user enters a number between 1 and 10. While the number is not between 1 and 10, it keeps asking the user to enter a number between the values. Then, when the number is between the values, it is squared and returned to the user.
I can't see why this isn't working
Any help is appreciated
You have:
while (i > 10 && i < 1)
You want:
while (i > 10 || i < 1)
while (i > 10 && i < 1)
Your condition is logically faulty; if reinterpreted, it says:
while i is greater than 10 AND i is less than 1
Judging from your code, the || operator should be used:
} while (i > 10 || i < 1);
As others mentioned, your condition is faulty.
a number can't obviously be under 1 AND above 10 at the same time, so the while loop exits immediately after the do statement.
#include <iostream>
using namespace std;
int main()
{
int i;
do
{
cout << ("please enter a number between 1 and 10");
cin >> i;
} while (i < 1 || i > 10)
cout << "the square of the number you have entered is " << i*i;
}
You should use an Or ||, that condition with && will never be true.
The loop condition is wrong and will never loop, as i cannot be less than 1 && greater than 10 at the same time. You should use the logical OR (||) operator instead. In addition, there must be a semicolon placed after the do-while statement. And you probably want and end of line placed after the prompt. Also, you don't want to start the bad habit of polluting the global namespace, even with the awesomeness of std. So:
#include <iostream>
int main()
{
int i;
do {
std::cout << "please enter a number between 1 and 10\n";
std::cin >> i;
} while (i > 10 || i < 1);
std::cout << "the square of the number you have entered is " << i*i << std::endl;
}

How can I check if the user has entered valid value?

I'm writing a project and I have to check if the user has entered a valid value for specific things. For example, first case is to check whether he inputted an integer, which is no longer than 6 length and >0. I am working with struct, so my code is this:
#include <iostream>
using namespace std;
int dolzina_int(int vlez);
int main()
{
struct pole{
int sifra; // sifra na artiklot
string opis; // opis na artiklot
float cena; // edinecna cena
int vlez_kol; // vlezna kolicina
int izlez_kol; // izlezna kolicina
float dan_stapka; // danocna stapka
float iznos; // iznos
int datum; // datum na vlez i izlez (GGMMDD)
}artikli[100]; // maksimalen broj na artikli e 100
for (int i = 0; i < 5; i++){
cin >> artikli[i].sifra;
while(!(cin >> artikli[i].sifra) ||
(artikli[i].sifra < 0 || (dolzina_int(artikli[i].sifra) > 6)))
{
cout << "Error" << endl;
cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
return 0;
}
// funkcija za dolzina na integer
int dolzina_int(int vlez){
int dolzina = 1;
while(vlez > 0){
dolzina++;
vlez /= 10;
}
return dolzina;
}
So, my code seems to work, the first part, it does check if it's >6 or <0, but the second else if, it doesn't work properly to check if it's an integer or not. So my question is the following, how can i make sure that it's an integer value that the user enters and how can I make sure the length of integer is not >6 or the value is <0 and meanwhile, if it is, to make him re-enter it, and also check the newly entered value, as my code doesn't do that currently.
for (int i = 0; i < 5; i++){
artikli[i].sifra = 1;
do{
cout << "Enter a code: ";
while(!(cin >> artikli[i].sifra)){
cin.clear();
cin.ignore();
cout << "Invalid entry. Enter a new value: ";
}
}while(artikli[i].sifra > 0 && dolzina_int(artikli[i].sifra) > 6);
}
You should note that the extraction will only succeed if the contents read from the file can be used as a correct value of the type of the object (in this case the integer sifra). If it doesn't work, ios_base::failbit will be set in the stream state.
So what needs to be done is that when an incorrect value is given, we discard the wrong text, clear the stream state, and re-try the extaction. For example:
#include <iostream>
#include <string>
#include <limits>
int main()
{
for (int i = 0; i < 5; ++i)
{
while (!(std::cin >> artikli[i].sifra) ||
((artikli[i].sifra < 0) || (artikli[i].sifra > 6)))
{
std::cout << "Entered an incorrect value, try again.\n";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
// ...
}
}
First you should check this out:
http://www.cplusplus.com/reference/cctype/
Second, I think your over complicating it...
1) Read in int
2) check value of int
3) repeat
So I would do this
for (i = 0 to i < 5 add one to i)
while (entered value is not digit)
get digit until value is valid
Something like this:
for(i = 0; i < 5; i++) {
cout << "Enter the code" << endl;
cin >> artikli[i].sifra;
while(!is_digit) {
cout << "Invalid, please repeat" << endl;
cin >> artikli[i].sifra;
}
}
Assuming you want to restrict your input to integers and have them in a specific [min, max] range, you would do it like this:
int input = -1;
do
{
std::cout << "Enter a value in the range [min, max]: ";
while (!(std::cin >> input)) // while the input is invalid
{
std::cin.clear(); // clear the fail bit
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // ignore the invalid entry
std::cout << "Invalid Entry! Please Enter a valid value: ";
}
} while (min > input || max < input);
Where min and max are whatever values you are looking to keep the value between.

Infinite while loop happens when asking user for 2 numbers

I'm trying to implement a simple game where user is asked for 2 valid integer coordinates between 0 and 10. (int row, int column)
An exemple of what I would realize is:
Insert coordinates: 4C
*Error, number of row and column must be integer
Insert coordinates: 44 2
*Error, number of row or column are too high
Insert coordinates: 4 3
The coordinates you entered are (4,3)
I realized all of these with a do-while cycle.
int r,c;
do{
cout<<"Insert coordinates: ";
cin>>r>>c;
if (cin.fail())
{
cout << "ERROR: Number of row and column must be integer." << endl << endl;
}
if ((r<0 || r>10) || (c<0 || c>10)
{
cout << "*Error, number of row or column are too high [0-10]" << endl << endl;
}
cout<<endl;
}
while (((r<0 || r>10)||(c<0 || c>10)) || cin.fail());
This code doesn't work properly. If I enter 2 numbers between 0 and 10, it works. If I enter a number bigger then 10, it also works. But if I entered a character the program goes into an infinite loop, and does not work properly.
How to implement this to handle errors with character input? Is there a way to recognize, and remain inside the while cycle, if user inputs a character?
If you enter a letter instead of a number, then that letter is not extracted from the input buffer, so your code will continue to fail forever.
If the input fails (why not use e.g. if (!(cin >> r >> c))?) then you can skip the line by doing calling the ignore function:
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
You also want to clear the failbit as it's not cleared automatically, this is done with the clear function.
You can also bypass this problem by getting the whole line, and using std::istringstream for the parsing:
do
{
std::string line;
if (!std::getline(std::cin, line))
... // Could not read from input
std::istringstream iss(line);
int r, c;
if (!(iss >> r >> c))
... // Failed to parse as numbers
...
} while (...);
You could simply check if characters were entered, for example:
if (x >= 0x41 && x <= 0x7A)
cout<<"error, you entered a letter";
(((r<0 || r>10)||(c<0 || c>10)) || cin.fail());
change to
(((r>0) && (r<10))||((c>0) && (c<10))) //It will work, no need to check cin.fail();
If cin fails then it might produce errors in buffer so better to quit the program..
The program goes into an infinite loop because you never clear the fail state. You can simplify your entire loop:
#include <iostream>
using namespace std;
int main()
{
int r = -1;
int c = -1;
bool valid = false;
do
{
cout<<"Insert coordinates: ";
if (cin >> r >> c)
{
if (r >= 0 && r <= 10 && c >= 0 && c <= 10)
{
valid = true;
}
}
else
{
cin.clear();
cin.ignore();
}
if (!valid)
{
cout << "ERROR: Number of row and column must be an integer between 0 and 10." << endl;
}
} while (!valid);
cout << "You entered (" << r << ", " << c << ")" << endl;
return 0;
}

Receiving integers, but also want to test for char

Say I am looking to receive a series of numeric values and read them into an int, but I also want to test if the user hit key 'x'.
I am sure I am missing something obvious, and have tried a few things but seem to be stuck.
This is what I have so far...
cout << endl << "Enter key (or 'x' to exit): ";
cin >> key;
if (key == 'x') { cout << "exiting";}
// continue on...
You need to read into a string and then convert that to an integer. In outline:
#include <string>
#include <sstream>
#include <iostream>
using namespace std;
int main() {
string s;
cout << endl << "Enter key (or 'x' to exit): ";
getline( cin, s );
if ( s == "x" ) {
// do exit stuff
}
else {
istringstream is( s );
int n;
if ( ! is >> n ) {
// report not an integer
}
else {
// do something with n
}
}
}
It depends on how key is declared.
If key is an int, you can only test for numbers, of course.
How about the following outline of an algorithm:
int n = 0
bool xentered = false
while (not xentered and there is one more character before EOF)
if that character is 'x' then xentered = true
else if it is a digit
n = 10*n + numeric value of the digit
else
error
I leave the task to translate that to the programming language of your choice. :)