Razi Kallayi
Razi Kallayi

Reputation: 9

Can i check if entered value is string or integer in c++

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

Answers (5)

localhost
localhost

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

Dennis
Dennis

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:

  1. Your user is giving you a random string value. So your program should read a random string value and then validate it.
  2. You can apply any kind of checking on it you like. Here I have checked that it is one character long and that the value is the ASCII representation of a digit, and that the digit is in a range.
  3. For simple validation it is less costly to do if statements than exceptions as users often give you garbage input.

Upvotes: 1

Anil8753
Anil8753

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

Guillaume Kiz
Guillaume Kiz

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

Paul Evans
Paul Evans

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

Related Questions