Reputation: 9
I want to check if the user entered value is a string or an integer. The input is taken as cin>>obj[i].int_code; in the code.
The problem is that if user enter any string instead of an integer, the program goes in an infinite loop.
#include<iostream>
using namespace std;
class item{
public:
int int_code;
string str_name;
};
item obj[100];
main(){
int c,i=0,int_cd,n=0,pos=0;
do{
cout<<"\n_______YOUR OPTIONS________\n";
cout<<"\t1.Add Item\n\t2.View Item\n\t3.Delete Item\n\t4.List Item\n\t5.Exit\n";
cout<<"Enter your choice: ";
cin>>c;
switch(c){
case 1://Add Item
cout<<"Enter the item_code: ";
cin>>obj[i].int_code;
cout<<"Enter the item_name: ";
cin>>obj[i].str_name;
i++;
n++;
break;
case 2://View item
cout<<"Enter the item_code: ";
cin>>int_cd;
for(i = 0;i < n;i++)
if(int_cd == obj[i].int_code)
cout<<obj[i].int_code<<"\t"<<obj[i].str_name<<"\n";
break;
case 3://Delete Item
cout<<"Enter the item_name: ";
cin>>int_cd;
for(i = 0;i < n; i++)
if(int_cd==obj[i].int_code)
pos=i;
for(i=pos;i<n;i++){
if(obj[i].int_code != NULL)
obj[i]=obj[i+1];
else
obj[i].int_code=NULL;
//obj[i].str_name=;
}
n--;
break;
case 4://list Item
for(i=0;i<n;i++)
cout<<obj[i].int_code<<"\t"<<obj[i].str_name<<"\n";
break;
default:
cout<<"Enter any number between 1 to 5";
break;
}
}while( c != 5 );
}
enter code here
Upvotes: 0
Views: 3465
Reputation: 373
Please note that the "check if entered value is a string or integer" part is an issue in multiple parts of the application. Namely, case 1, 2, and 3 all expect integer inputs (case 3 is addressed further below). The get_int and get_string methods are adapted from How to make cin take only numbers. Initially I only created a get_int method; however, I found that a get_string was also needed otherwise the "Enter your choice" would occur twice, rather than once, after a "Add Item", case 1, was completed.
Additionally, the "Delete Item", case 3, had an error in the wording as the request is for the "item_name"; however, the cin is expecting an integer, and not a string, so I modified the wording there as well as the input method. I commented out the cout statement in the default as it is now redundant if a previous case was not applicable to the entered value. Lastly, the "Delete Item" code still had a bug in it (fixed below) as a request to delete item_code 2 would delete an item_code 1 if that was only contained item due to pos not being reset.
#include <iostream>
#include <limits>
#include <sstream>
#include <string>
using namespace std;
class item
{
public:
int int_code;
string str_name;
};
item obj[100];
string get_string(string message)
{
string line = "";
string rs = "";
cout << message;
getline(cin, line);
stringstream ss(line);
ss >> rs;
return rs;
}
int get_int(string message)
{
int ri = -1;
string line = "";
bool isint = false;
while (!isint)
{
cout << message;
getline(cin, line);
stringstream ss(line);
if (ss >> ri)
{
if (ss.eof())
{ // Success
isint = true;
}
}
}
return ri;
}
int main (int argc, char ** argv)
{
int c,i=0,int_cd,n=0,pos=0;
do
{
cout<<"\n_______YOUR OPTIONS________\n";
cout<<"\t1.Add Item\n\t2.View Item\n\t3.Delete Item\n\t4.List Item\n\t5.Exit\n";
c = get_int("Enter your choice: ");
switch(c){
case 1://Add Item
obj[i].int_code = get_int("Enter the item_code: ");
obj[i].str_name = get_string("Enter the item_name: ");
i++;
n++;
break;
case 2://View item
int_cd = get_int("Enter the item_code: ");
for(i = 0;i < n;i++)
if(int_cd == obj[i].int_code)
cout<<obj[i].int_code<<"\t"<<obj[i].str_name.c_str()<<"\n";
break;
case 3://Delete Item
int_cd = get_int("Enter the item_code: ");
pos = -1;
for(i = 0;i < n; i++)
if(int_cd==obj[i].int_code)
pos=i;
// ensure specified item_code is found before deleting an item
if(pos != -1)
{
for(i=pos;i<n;i++)
{
if(obj[i].int_code != NULL)
obj[i]=obj[i+1];
else
obj[i].int_code=NULL;
//obj[i].str_name=;
}
n--;
}
break;
case 4://list Item
for(i=0;i<n;i++)
cout<<obj[i].int_code<<"\t"<< obj[i].str_name.c_str() <<"\n";
break;
default:
//cout<< "Enter any number between 1 to 5" << endl;
break;
}
} while( c != 5 );
return 0;
}
Upvotes: 0
Reputation: 3731
As an alternative to lexical_cast
you could do something like this:
#include <iostream>
static const int ZERO_ASCII = 48;
static const int MAX_OPTION = 5;
static const int MIN_OPTION = 1;
int main() {
std::string input;
std::cin >> input;
if(input.length() > 1 ){
std::cout << "Not correct length" << input << std::endl;
return -1; // in your case use "continue"
}
char val = *(input.c_str());
int intVal = static_cast<int>(val);
int option = intVal - ZERO_ASCII; // see your printed out ASCII chart :)
if (MIN_OPTION > option || option > MAX_OPTION) {
std::cout << "Not valid value " << option << std::endl;
return -1; // in your case use "continue"
}
std::cout << "selected option " << option << std::endl;
}
This is a valid option because of a couple of things:
Upvotes: 1
Reputation: 2735
change your line
from
cin>>c;
to
c = -1;
cin>>c;
if (c < 1 || c > 5)
{
cout<<"Enter any number between 1 to 5";
continue;
}
Upvotes: 1
Reputation: 443
Exit when Not A Number :
#include<iostream>
using namespace std;
class item{
public:
int int_code;
string str_name;
};
item obj[100];
main(){
int c,i=0,int_cd,n=0,pos=0;
do{
cout<<"\n_______YOUR OPTIONS________\n";
cout<<"\t1.Add Item\n\t2.View Item\n\t3.Delete Item\n\t4.List Item\n\t5.Exit\n";
cout<<"Enter your choice: ";
cin >> c;
if (!cin) break;
switch(c){
case 1://Add Item
cout<<"Enter the item_code: ";
cin>>obj[i].int_code;
cout<<"Enter the item_name: ";
cin>>obj[i].str_name;
i++;
n++;
break;
case 2://View item
cout<<"Enter the item_code: ";
cin>>int_cd;
for(i = 0;i < n;i++)
if(int_cd == obj[i].int_code)
cout<<obj[i].int_code<<"\t"<<obj[i].str_name<<"\n";
break;
case 3://Delete Item
cout<<"Enter the item_name: ";
cin>>int_cd;
for(i = 0;i < n; i++)
if(int_cd==obj[i].int_code)
pos=i;
for(i=pos;i<n;i++){
if(obj[i].int_code != 0)
obj[i]=obj[i+1];
else
obj[i].int_code= 0;
//obj[i].str_name=;
}
n--;
break;
case 4://list Item
for(i=0;i<n;i++)
cout<<obj[i].int_code<<"\t"<<obj[i].str_name<<"\n";
break;
default:
cout<<"Enter any number between 1 to 5";
break;
}
}while( c != 5 );
}
Upvotes: 0
Reputation: 27567
Use boost::lexical_cast
:
string str;
cin >> str;
int val;
try
{
val = lexical_cast<int>(str));
}
catch(const bad_lexical_cast &)
{
// not an int
}
Upvotes: 2