Trying to limit input to int type

Pages: 12
Aug 19, 2013 at 6:00am
[updated with new question @ post 13] Hello everyone

I'm sure you've all seen this before, but I can't find the solution to my problem.

I don't want any values accepted if they're not within 1 and 100. My problem is that if I enter ffadafdfghf55asdfasdf (or w/e), 55 is entered into the int and the loop becomes true.

I searched the nets which led me here, and to where I've found part of the solution below, however, I get the above stated problem

How do I make it so ONLY a number from 1 to 100 is accepted, and not something like dfg66, or the like?

The book I'm learning from doesn't cover this, and I know there has to be a solution! I'd like to not be able to break my own code!

Thank you for any help and/or insight as to whats happening

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 #include <iostream>

using namespace std;

int main()
{

	cout << "Enter a number between 1 and 100 and I will guess it: ";
	unsigned short playerNumber;
	
	cin >> playerNumber;
	while(!(cin >> playerNumber) || playerNumber < 1 || playerNumber > 100)
	{
		cin.clear();
		cin.ignore(numeric_limits<streamsize>::max(), '\n');
		cout << "Invalid input.  Try again: ";
	}
	
	return 0;
}
Last edited on Aug 19, 2013 at 10:34am
Aug 19, 2013 at 6:16am
One way is to read the input as a string and then parse it character-wise. I'm not sure whether stringstream will work as desired by you but that is another option you can research.
Aug 19, 2013 at 6:19am
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <functional>
#include <sstream>
#include <string>
#include <iostream>

using namespace std;

template <typename T>
T get(const std::string& prompt, std::function<bool(const T&)> validate)
{
    T result;

    bool notDone = true;

    while (notDone)
    {
        std::cout << prompt ;

        std::string line;
        std::getline(std::cin, line);

        std::istringstream is(line);

        char dummy;
        if (!(is >> result) || (is >> std::ws && is.get(dummy)) || !validate(result))
            std::cout << "Invalid input. Try again!\n";
        else
            notDone = false ;
    }

    return result;
}



int main()
{
    typedef unsigned short num_type;

    num_type playerNumber = get<num_type>("Enter a number between 1 and 100 and I will guess it: ", 
                                            [](const num_type& val) { return val > 0 && val < 101; });

    std::cout << playerNumber << '\n';
}
Enter a number between 1 and 100 and I will guess it: 0
Invalid input. Try again!
Enter a number between 1 and 100 and I will guess it: 101
Invalid input. Try again!
Enter a number between 1 and 100 and I will guess it: f
Invalid input. Try again!
Enter a number between 1 and 100 and I will guess it: 99f
Invalid input. Try again!
Enter a number between 1 and 100 and I will guess it: 99 f
Invalid input. Try again!
Enter a number between 1 and 100 and I will guess it: f 99
Invalid input. Try again!
Enter a number between 1 and 100 and I will guess it: f9f9
Invalid input. Try again!
Enter a number between 1 and 100 and I will guess it: q
Invalid input. Try again!
Enter a number between 1 and 100 and I will guess it: 50
50
Last edited on Aug 19, 2013 at 6:20am
Aug 19, 2013 at 6:30am
your output looks very perfect. thank you cire, I will try to learn from your code
Aug 19, 2013 at 6:31am
@cire
Wow! can you please explain the following part?

 
(is >> std::ws && is.get(dummy))


I guess you are checking whether 'is' has a character in it. But why the whitespaces? Does the input 'return' stay inside the istringstream?
Aug 19, 2013 at 6:39am
closed account (28poGNh0)
also @cire is function a part of std?
Aug 19, 2013 at 6:48am
Abhishekm71 wrote:
Wow! can you please explain the following part?

(is >> std::ws && is.get(dummy))


I wanted the operation to succeed if someone entered whitespace after a legitimate number (input: "50 \n" for example.)

is >> std::ws simply removes any leading whitespace from the stream. Then if is.get(dummy) is successful (meaning there was more input to be extracted from the string other than whitespace) the expression evaluates to true.

So, the following would cause that condition to evaluate to true:
"50 f\n"

"50\t5\n"

While the these would be fine:
"50 \n"

"50\t\n"

"50\n"


Techo01 wrote:
also @cire is function a part of std?

As of C++11, yes.
http://en.cppreference.com/w/cpp/utility/functional/function
Last edited on Aug 19, 2013 at 6:52am
Aug 19, 2013 at 6:55am
closed account (28poGNh0)
why my code blocks does not recongnize it? Do I need to update it?

also for c++11 ,is this some other standarazation of c++?
Aug 19, 2013 at 7:30am
How does the expression evaluate to true for an input of 99f as you showed? It does not have any leading whitespaces so is>> std:ws should evaluate to false and the second conditioned wouldn't be checked... what am I missing?
Aug 19, 2013 at 7:30am
Techno01 wrote:
why my code blocks does not recongnize it? Do I need to update it?


http://s17.postimg.org/l9nhiir3j/Code_Blocks_Compiler_Settings.png
Aug 19, 2013 at 7:37am
closed account (28poGNh0)
Thanks chief
Aug 19, 2013 at 7:42am
abhishekm71 wrote:
How does the expression evaluate to true for an input of 99f as you showed? It does not have any leading whitespaces so is>> std:ws should evaluate to false and the second conditioned wouldn't be checked... what am I missing?


Like most extraction functions, an operation that doesn't put the stream into a failure state will be considered a success. Whether there is or isn't whitespace in the buffer, the operation will never put the input stream into a failure state so that portion of the expression will always evaluate to true. We could've used the comma operator there instead of && and we wouldn't have changed the semantics.

http://en.cppreference.com/w/cpp/io/manip/ws
Aug 19, 2013 at 7:45am
Ok... thanx cire!
Aug 19, 2013 at 10:26am

**********

I have another bit of code that doesn't seem to be working the way I imagine it should

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cout << "Enter a number between 1 and 100 and I will guess it: ";
	cin >> playerNum;

	do
	{
		
		cout << "Is your number higher or lower than " << cpuNum << "? ";
		cin >> input;

		if(input == "higher")
		{
			max = 100;
			min = cpuNum;
			cpuNum = rand() % (min + 1) + (max - min);
		}

assume that someone enters '100' and the computers first choice is '50'

if the person continues to input 'higher', then shouldn't this bit of code keep the cpuNum moving upwards towards 100? it often drops down into the 20's...

as you can probably tell I'm new to this, lol, but the above code seems like it should continuously be an increasingly larger random number.

I know % gives you the remainder from division, normally, but is it overloaded in the rand()? When I see rand() % a + b, I read it as 'give me a random number between a and b'... is this correct?
Last edited on Aug 19, 2013 at 10:42am
Aug 19, 2013 at 10:52am
closed account (28poGNh0)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# include <iostream>
# include <cstring>
# include <cstdio>
# include <cstdlib>
using namespace std;

int main ()
{
    char input[20];

    int max=100,min=1,cpuNum = 0,playerNum = 0;

    cout << "Enter a number between 1 and 100 and I will guess it: ";
	cin >> playerNum;

    cin.get();

    cpuNum = rand()%100;

	while(playerNum>0&&playerNum<=100)
	{
		cout << "You number is : " << playerNum << endl;
		cout << "The cpu number is : " << cpuNum << endl;

		gets(input);

        if(!strcmp(input,"higher")&&max!=min)
        {
            max = playerNum;
            min = cpuNum;

			cpuNum = rand() % (max - min) + (min + 1);
			cout << cpuNum << endl;
        }else cout << "Input higher or lower" << endl;

	}cout << "End of program" << endl;

    return 0;
}


hope that helps
Aug 19, 2013 at 11:23am
so, is

cpuNum = rand() % (max - min) + (min + 1);

whats increasing the random number? did I just have mine reversed?

cpuNum = rand() % (min + 1) + (max - min);
Last edited on Aug 19, 2013 at 11:24am
Aug 19, 2013 at 11:25am
closed account (28poGNh0)
Yes that one is reversed
also max should equal playerNumber because you always seek this number right?
Last edited on Aug 19, 2013 at 11:27am
Aug 19, 2013 at 11:30am
Yes that one is reversed
haha, well, i know that... i guess my question was more of a "is that all that was wrong" type of question.

so is this % overloaded for rand()? i guess I don't see whats happening if its not

what im trying to do is make the computer guess the users number, so, from 1 to 100. if the user says 'higher', the computer will guess a random number between its lowest guess and its highest guess

same thing should happen if the user enters 'lower', the computer will guess random numbers between numbers that it has already guessed

I think im trying to make these "end of chapter" tests harder than the author meant for them to be

thanks for the help
Last edited on Aug 19, 2013 at 11:34am
Aug 19, 2013 at 11:37am
also max should equal playerNumber because you always seek this number right?


initially max should be 100

after the user enters 'lower', however, max should change to whatever the last random number was... thats the way ive been looking at it, still not sure
Last edited on Aug 19, 2013 at 11:39am
Aug 19, 2013 at 1:58pm
Here is a nice conversion function I wrote. It's primitive compared to cire's, but it is good for doing stuff like comparisons, etc... I suppose. I use it a lot.

1
2
3
4
5
6
7
8
9
template<class type1, class type2>
type2 conv(const type1& t1)
{
    type2 t2;
    stringstream ss;
    ss<< t1;
    ss>> t2;
    return t2;
}


This erases a lot of bariers for me.

so, mabey a short example:

(psuedo code)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void correct_ans()
{
    cout<< "Correct!"<< endl;
}

void wrong_ans()
{
    cout<< "Wrong..."<< endl;
}

int main()
{
    getline(cin, line);

    // for those who don't know this line: ((bool) ? (condition: bool is true) : (condition: else))
    ((conv<string, int>(line) == 5) ? correct_ans() : wrong_ans());
    
    //so if you entered 5, it will say "correct", otherwise it will say you got it wrong.
    // just a nice little example.
    return 0;
}


It has worked in all of my code so far. If there is somthing you find wrong with it, feel free to tell me and I will fix it.
Pages: 12