I am teaching myself C++. I am writing a lotto program to read in dates and numbers and update a file. This code snippet:

int numberset[6];

			cout<<endl<<"now, enter the 6 numbers. Hit return between each number:";

			for(int i=0;i!=6;i++){
				cin>>numberset[i];
				while(numberset[i]<1 || numberset[i]>53){
					cout<<"the number is not a valid, lotto number! please re-enter: ";
					cin>>numberset[i];
				}

works completely as expected when the user inputs an integer, any integer. If a float is entered, the loop becomes infinite. I attempted to correct by adding this line:
cin.clear(); right before the second attempt to cin>numberset ;

Which did not help at all. I guess something is wrong with the istream, but i dont know what it is, or how to fix it. I do appreciate any help.

Well, I defined numberset[] as an INT becuase there are no floating point lotto numbers. I know that it is highly unlikely for a user to enter a number like 4.5 when asked to enter a lotto number, but I am trying to develop a style wherein my programs will work under all circumstances. If I define numberset[] as float, and someone enters 4.5 as a lotto number, how would my program then recognize it as invalid?

If it has to be an integer then use isdigit to check that each character of the input is a digit.

a simp,e way to do this is

char ch[2];
ch[1] = '\0';
int x = 0;
const int MULTI = 10;

	std::cout<<"enter a number->";
	while ((ch[0] = std::cin.get()) != '\n')
	{
		if (isdigit(ch[0]))
		{
			x = (x * MULTI) + strtol(ch, NULL, 10);
		}
	}
	std::cout<<"x->"<<x<<"\n";

this is only a suggestion, but may use it if you like it

If I define numberset[] as float, and someone enters 4.5 as a lotto number, how would my program then recognize it as invalid?

You can simply truncate the fractional portion of the number.

#include <cmath>
#include <cstdlib>
using std::abs;
using std::floor;

int numberset[6];
cout << endl << "now, enter the 6 numbers. Hit return between each number:";

for(int i=0;i!=6;i++)
  {
    for(;;)
      {
	double temp;
	cin >> temp;
	if( temp >= 1 && temp <= 53 )
	  {
	    numberset[i] = abs( floor( temp ) ); 
	    break;
	  }
        cin.ignore();
	cout<<"the number is not a valid, lotto number! please re-enter: ";
      }
  }

Upon further thought there is a problem here. Assume the user enters an alpha string "1 25 55 AA 45 22", your program will stall b/c the alpha chars are retained in the cin buffer. You need to discard the cin buffer with cin.ignore()

Well, I would not want to truncate, because if the user enters say, 4.5 I have no way of knowing if 4 is what they really want. All I want to do is report to them that their input is erroneus, and please re-enter it.

I am not really looking for a work around at this point(at least I don't think I am). I am trying to understand why the loop becomes infinite when a float is read in to any numberset.

Is it due to the state of Cin?

If it has to be an integer then use isdigit to check that each character of the input is a digit.

a simp,e way to do this is

char ch[2];
ch[1] = '\0';
int x = 0;
const int MULTI = 10;

	std::cout<<"enter a number->";
	while ((ch[0] = std::cin.get()) != '\n')
	{
		if (isdigit(ch[0]))
		{
			x = (x * MULTI) + strtol(ch, NULL, 10);
		}
                else
               {
                      std::cout<<ch[0]<<" error message\n";
                     //or you could throw and exception
               }
	}
	std::cout<<"x->"<<x<<"\n";

this is only a suggestion, but may use it if you like it

This does report the problem value all you had to do was put an else in the if statement. Plus this will
report any values that are not digits i.e not integers. Why the language allows this type of behavior (enter floats values for ints then looping forever)to keep it light wieght. i.e. if you wanted the functionality you should have to developed it into the application. That's my understanding

Please ignore all those bozos above.

The reason your loop becomes infinite is the '.' is not valid for an integer, therefore
1) cin reads the number up to the '.' and stops. The '.' is left in the input buffer
2) the next cin tries to read the '.' and can't so it returns an error which you never check, and leaves the '.' in the buffer
3) the next cin tries to read the '.' and can't so it returns an error which you never check, and leaves the '.' in the buffer
4) the next cin tries to read the '.' and can't so it returns an error which you never check, and leaves the '.' in the buffer
etc.

This would also happen if you entered 23T65.

The easies way to handle this is to stop using cin and use getline() to read the entire line as a string. Then you can pull off (convert to number) the integer part and actually throw out the rest of the line.

The easies way to handle this is to stop using cin and use getline() to read the entire line as a string. Then you can pull off (convert to number) the integer part and actually throw out the rest of the line.

If you read the prevous post you see that what I posted using

while ((ch[0] std::cin.get) != '\n')
                {
                          if (isdigit(ch[0]))
                                      ....etc
                }

I'm still working on this. I think i agree the problem is with the state of CIN. In all honesty, I have not yet worked through the code suggestions above, because, as I said, I need to understand just what is going wrong before I try to implement a new solution. Going to do some a bit more research on iostreams.

If you read the prevous post you see that what I posted using

while ((ch[0] std::cin.get) != '\n')
                {
                          if (isdigit(ch[0]))
                                      ....etc
                }

True, but the code in it's entirety is too complicated and hard to follow by creating essanitally a 1-character string and the use of strtol() instead of a simple subtraction.

IOW, it's not a good example. Sorry, it's confusing.

This article has been dead for over six months. Start a new discussion instead.