c++ isalnum endless loop - c++

Greetings!
Lets cut the excessive intro this time and get straight to the point.
I have a problem in C++ using the isalnum method.
the code:
int playAgainst = 0;
do
{
cout << "Who do you want to play against?(1/2)\n";
cout << "1: Human player\n";
cout << "2: Computer player\n";
cin >> playAgainst
} while(!isalnum(playAgainst) && playAgainst != 0);
As seen in the code, I'm providing the user with a choice. Play against human or play against a computer.
What I want is, as long as the user enters anything else then an integer value(cin >> playAgainst) to repeat the question. However, If i enter a char, or string value, it keeps looping endlessly. I am not 100% sure, but it would be obvious, if the problem is, that the non int value is already saved as the value for playAgainst.. How can I check in this bit of code if the input value is int before saving it?
Or is the only possibility to save as a char/string and then check?
If the latter is the case, a new problem arises. isalnum only accepts int as parameter, atleast from what I know. How will I check if that string or char is an int?
Thank you for taking the time to read. And hopefully Ill be accepting a reply as answer soon ^^
Thanks everyone for the answers.
I have gotten what I wanted, and everything has been solved.
The reason I chose for the accepted answer, is well... because initially, it made my code work the way I want it to. I want to accept multiple answers though..

Make playAgainst a char and compare against '0', not 0. Right now, the user has to enter the ASCII (or whatever your character set is) code for the character '1' or '2'.
isalnum won't work on ints outside the valid range of char, except for EOF. (The fact that it takes an int argument is a leftover from C, which has different integer promotions rules than C++. to accomodate for EOF.)

Remove the isalnum() check. cin >> playAgainst will convert anything except a number to zero, which will be caught by the second check. Note that this is only an option because zero is not a valid input.
isalnum() is useful if you're interpreting the characters yourself, but in this case the stream has already done that for you.

This is how the compiler will implement isalnum:
int isalnum (int ch)
{
return (ch >= 'a' && ch <= 'z') ||
(ch >= 'A' && ch <= 'Z') ||
(ch >= '0' && ch <= '9');
}
So you might as well write that code snippet in your own code, and it will be equivalent with an inlined version of isalnum.

It's because you don't clear the buffer. When the input is invalid, you need to clear it from the buffer, and then you can move on to the next input, else you're trying to extract the same input every time (which fails, because it's the same bad input), and thus enter an infinite loop.

The problem is that you're inputing an int, and not a char. And if the
text in the input isn't an int, then the input fails. In which case,
playAgainst isn't modified, and the failure is memorized in std::cin
until you explicitly clear the error. And inputting from a stream in an
error state is a no-op. What you probably want to do is
Input a single character: if you don't want to skip spaces, using
`std::cin.get( ch )` or `ch = std::cin.get()`. (In the latter
case, `ch` should be an `int`, since it must also handle `EOF`.
On the other hand, you can use `::isalnum` on it directly, which
you can't do if `ch` is a `char`.
Fully check for valid input: not just `::isalnum`, but rather
whether the input is a legal selector in your list. Something
along the lines of:
ch != EOF && std::find( legalChars.begin(), legalChars.end(), (char)ch ) != legalChars.end()
In case of error, clear any remaining input, say with:
std::cin.ignore(INT_MAX, '\n');
In practice, you'll probably want to treat EOF differently from
an erroneous command. (If you don't clear the input after EOF, you
won't be able to read anything else. But presumably, if you got EOF,
it's because the user gave up, and doesn't want to try any more.)
Finally, it's probably preferrable to keep all of the information in
a common location, using a table of:
struct Command
{
char op;
char const* prompt;
void (* func)();
};
You then loop over a table of these to output the prompt, search it to
see if the character was legal, and finally, call the function on the
entry you found. Or define an abstract base class, a concrete class
deriving from it for each command, and use an std::map<char,
AbstractBase*> for the mapping, etc. Very C++, but perhaps a bit
overkill for such a simple case.

Why not use isdigit().

Related

How To Compare Strings In C++?

I am just messing around in C++ with some things I recently learned and I wanted to know how to correctly compare two strings to each other. I looked at a previous thread for help, but I am not sure I am getting the variables right and there was a repeating error. (P.S. This is executed to the command prompt.)
string Users = "Username1";
//Set an empty string.
string UserChoice;
//Print out a line that warns the user to type a user.
std::cout << "Username: ";
std::cin >> UserChoice;
//If the user types out whatever "Users" is, run the code below.
if (strcmp(Users, UserChoice) == 0){
//Do Stuff
}
You want:
if (Users == UserChoice) {
The std::string class (well, really std::basic_string) overloads the == operator (and many others) to do what you want. You should not be using C functions like strcmp in C++ code, and in any case they cannot be directly applied to C++ std::strings.
Comparing strings is the same as comparing int values, char values, etc... . You should use the following method:
string a
string b
if (a == b)
{
// Do something
}
In your case, 'a' and 'b' would be replaced by 'Users', 'UserChoices'. But the basic format of comparing 2 variables of the same type stays the same regardless of the type (I'm not sure whether there are any exceptions to this rule or not).
It is also recommended, just as #latedeveloper mentioned, not to use c-language functions in a c++ program. The 2 languages are NOT interchangeable!
** Helpful tip: Always strive to keep your code as simple as possible. With some exceptions possible, the more complicated you make your code, the more hard you will make it for others to understand your code. To connect it to your case, why use a function strcmp() when you can keep it simple by using the == sign? This is just my 2 bits based on personal experience.
c style:
string a
string b
if(strcmp(a.c_str(),b.c.str()) == 0)

C++ Programming Syntax and function assistance? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Okay so still new to the syntax of the C++ programming language and have come across a few things that are shown in examples but don't quite explain things on a level for someone to fully understand what it is.
For example if you were going to create a variable say : int x = 0; what does the zero part do, sets it to zero or holds a false value? Particullary in the code below.
Also some explanation on : if (!(cin>> input)) input = 0 if (!(cin>> 0)? if its not zero? seems like zero holds some other value.
Also cin.clear() and cin.ignore sure i've heard it clears the next line or erases something but really a thorough explanation of whats going on with this would really help?
Can't really move on to bigger things if this simply parts has holes in it.
Two other things is the endl function and cin.get() what do these do as well?
int main()
{
int input = 0;
do
{
cout<<"Enter a number (-1 = QUIT):";
if (!(cin>> input))
{
cout<<"INVALID" <<endl;
cin.clear();
cin.ignore(10000, '\n');
}
if (input != -1)
{
cout<<input<<" was entered"<<endl;
}
}
while (input != -1);
cout<<"Done"<<endl;
cin.get();
return 0;
}
The code below is the code provided in the question as I write this, except I've added the requisite headers and using directive at the top:
#include <iostream>
using namespace std;
int main()
{
int input = 0;
do
{
cout<<"Enter a number (-1 = QUIT):";
if (!(cin>> input))
{
cout<<"INVALID" <<endl;
cin.clear();
cin.ignore(10000, '\n');
}
if (input != -1)
{
cout<<input<<" was entered"<<endl;
}
}
while (input != -1);
cout<<"Done"<<endl;
cin.get();
return 0;
}
#include <iostream>
is a preprocessor directive. The source code preprocessor is run before the compiler proper, and performs text substitution, text inclusion and text selection. The #include directs it to include all the text from a header called iostream. The angle brackets, as opposed to double-quote characters, says that it shouldn't bother to search in the including file's directory. Well actually it's unspecified what extra search it shouldn't do, but in practice, with current compilers, it's as described.
The iostream header provides declarations of i/o stuff from the standard library, such as std::cout.
using namespace std;
makes the identifiers from the std namespace available directly in the global namespace. Meaning you can write, for example, just cout instead of qualified std::cout or fully qualified ::std::cout.
A using namespace directive is practical for small exploratory and personal tool programs, but can be more troublesome in larger code base.
Anyway, remember to NEVER put such directive in the global namespace in a header, because that's a sure way to create name collisions in code that includes that header. As an example, the standard library defines a name std::distance. Without the qualification, with a using namespace std; directive, the name distance is very likely to collide with a name distance in using code.
int main()
is the minimal declaration of main. The main function was the user-provided startup function in C, and in C++ it serves roughly the same purpose, except that in C++ dynamic initialization of static variables can happen before main is executed.
The declaration above is the C++03 way. In C++11 it can alternatively be declared as
auto main() -> int
which means exactly the same, and which is a bit more verbose, but can be reasonable to indicate a convention of using this syntax in general. I.e. for consistency.
The main function can also have arguments, which then represent the command line arguments provided to the process, but this scheme only works well in UTF-8 based *nix-es. For the main arguments are char-based, and the default char-based text encoding in Windows is such that e.g. filenames with international characters can't be represented. Thus, it's not a generally good idea to use the main arguments for portable code.
int input = 0;
declares a variable called input, of type int, and initializes it to 0.
Any zero value of a fundamental type represents false when it's used as a boolean. Conversely, any non-zero value represents true, and this convention stems from early C, which didn't have a bool type. In modern C++ it's better to use the bool type for booleans, with the values (literally) false and true.
The variable above, however, is not used as a boolean, but represents the last number input by the user.
do
{
// Stuff, called the "loop body".
}
while (input != -1);
This is a do-while loop. The continuation condition stated after the while is checked after each iteration. Which means that the loop body is guaranteed to be executed at least once.
C++ has three other loops: the while loop; the ordinary for-loop, which collects all the loop control stuff in the loop head; and the range-based for, which is especially nice for iterating over the items in a collection.
cout<<"Enter a number (-1 = QUIT):";
if (!(cin>> input))
{
cout<<"INVALID" <<endl;
cin.clear();
cin.ignore(10000, '\n');
}
The first statement above just prompts the user. The cout and cin streams are synchronized, so that when the subsequent input operation is attempted, the output, if not already presented on the screen, is flushed. Instead of such automatic, implicit flushing, you can guarantee a flush by doing it explicitly, like this:
cout<<"Enter a number (-1 = QUIT):" << flush;
The expression cin >> input
attempts to interpret the next "word" of user input as an integer, and store that in the variable input, and
produces a reference to cin as its expression result.
If the input of text fails, or if the conversion from textual specification to int fails, then cin enters a failure state. In this state further input is just ignored. Happily that's easy to check for, because when a stream is used directly as an if or while (including do-while) condition, then it converts implicitly to boolean as if you had written !stream.fail().
Hence, !(cin >> input) does all of the above, and produces the result of !!cin.fail() (twice negated, “not not”), where fail is a member function that check whether the stream is in a failure state.
If the stream is in a failure state, then that state must be cleared, lest further input operations will all be ignored, and that's what
cin.clear();
achieves.
In addition there will be some input text – at the least a newline (end of line marker) – left in the input buffer, and to avoid that text being processed as valid input the next time around the loop, it should better be removed! And that's what the
cin.ignore(10000, '\n');
accomplished. Under the assumption that there's not more than 10000 characters left in the input buffer…
cout<<"INVALID" <<endl;
Outputs the text “INVALID” followed by a newline. Outputting the endl manipulator has the effect of a newline plus a flush. Thus the above is equivalent to and just short for
cout<<"INVALID\n" << flush;
It often happens that newbies are concerned with the lack of efficiency of endl as opposed to just \n. This concern is however misplaced. Iostreams are for convenience and (due to stronger type checking) avoiding the easy bugs of C style i/o; they're generally not what one would choose for efficiency.
After the loop, the
cout<<"Done"<<endl;
cin.get();
stops the program until the user enters some input.
This is because when the program is run from an IDE (as opposed to from the command line), the console window could just otherwise disappear. And especially for non-interactive programs that's undesirable. So the statement above, while not needed for this particular program, is a general convention.
However, it's ungood. It becomes very annoying when the program is run from the command line! Instead, to see all the output of a program, do either
run it from the command line, or
run it in a way that automatically stops at the end (e.g. Ctrl+F5 in Visual Studio), or
place a breakpoint at the last } right curly brace of main, and run it in the debugger.
return 0;
is unnecessary, since this is the default function result for main (main is unique in having a default function result).
The value returned from main will in practice become a process exit code.
In both Windows and *nix the convention is that 0 means success and any other value means failure.
In C++ the only portable values are 0, EXIT_FAILURE and EXIT_SUCCESS, where the latter two come from the stdlib.h header. EXIT_FAILURE and EXIT_SUCCESS depend on the system at hand, but the latter is typically just 0. In Windows you may want to use Windows' own E_FAIL instead of EXIT_FAILURE, because (for unfathomable reasons) Windows C++ compilers typically define EXIT_FAILURE as 1, which is also a specific Windows error code – and in Windows the process exit code is typically literally what that term indicates, namely a standard error code, with 0 as “no error”.

C++: cin.peek(), cin >> char, cin.get(char)

I've got this code with use of cin.peek() method. I noticed strange behaviour, when input to program looks like qwertyu$[Enter] everything works fine, but when it looks like qwerty[Enter]$ it works only when I type double dollar sign qwerty[Enter]$$. On the other hand when I use cin.get(char) everything works also fine.
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
char ch;
int count = 0;
while ( cin.peek() != '$' )
{
cin >> ch; //cin.get(ch);
count++;
}
cout << count << " liter(a/y)\n";
system("pause");
return 0;
}
//Input:
// qwerty$<Enter> It's ok
//////////////////////////
//qwerty<Enter>
//$ Doesn't work
/////////////////////////////
//qwerty<Enter>
//$$ works(?)
It's because your program won't get input from the console until the user presses the ENTER key (and then it won't see anything typed on the next line until ENTER is pressed again, and so on). This is normal behavior, there's nothing you can do about it. If you want more control, create a UI.
Honestly I don't think the currently accepted answer is that good.
Hmm looking at it again I think since, operator<< is a formatted input command, and get() a plain binary, the formatted version could be waiting for more input than one character to do some formatting magic.
I presume it is way more complicated than get() if you look what it can do. I think >> will hang until it is absolutely sure it read a char according to all the flags set, and then will return. Hence it can wait for more input than just one character. For example you can specify skipws.
It clearly would need to peek into more than once character of input to get a char from \t\t\t test.
I think get() is unaffected by such flags and will just extract a character from a string, that is why it is easier for get() to behave in non-blocking fashion.
The reason why consider the currently accepted answer wrong is because it states that the program will not get any input until [enter] or some other flush-like thing. In my opinion this is obviously not the case since get() version works. Why would it, if it did not get the input?
It probably still can block due to buffering, but I think it far less likely, and it is not the case in your example.

using peek() in overloading an input stream

I'm working on overloading >> for a fraction class and there are a few different types of input that need to be handled. Examples: 1/2 (regular fraction), 2+3/4 (mixed number), 2 (whole number). The professor provided a hint below saying that we need to use the peek() function in order to figure out what the second character is after the integer. So what that means is that temp needs to be declared as an int right? My question is that if temp is an int, how do you get the rest of the fraction (when it's not a whole number)?
Based on my experience, I would declare temp as a string instead and not use peek. But the int and peek approach must have some merit since the prof suggested it.
in >> temp;
if (in.peek() == '+'){
doSomething...
} else if (in.peek() == '/'){
doSomethingElse...
} else {
doThirdOption
}
Here, when you use in>>temp , it will get all the numbers till some non numeric character is encountered. At this time, using peek() you can check if the next character is a '+' or a '/'. In either case, you will have to read another number from the input stream and repeat this procedure.
Once the user hits enter, then you have all your numbers, and you can perform the required operations.
Also, if you have to calculate the value of fractions, you might be better off using float or double datatypes instead of int.

How to cover all possible data types when declaring a function parameter?

I'm attempting to construct a function that will perform a sanity check on the user's response to a number of questions, each of which would ideally be a non-zero integer. How can I construct a function that would be able to accept a parameter of any data type, but only have a single parameter? For example:
bool SanityCheck(<type id> number)
where <type id> would cover any data type.
It's not clear exactly what you really want here. Unverified input from a user normally comes in the form of a string. Typically you read in a string, verify that it has the desired form (e.g., for an integer, all digits). If it has the right form, you convert that to the desired type, and use it. If it doesn't, you ask the user to re-enter their data, usually with a prompt like "Please enter an integer between 1 and 10".
A function template is sort of a direct answer to the question you asked, but I have a hard time imagining it being of any help in a situation like you've described. A function template is most often of use in cases where you have to carry out some operations that are syntactically the same across a number of types. For example, it lets you add two numbers, regardless of whether those happen to be of type short, int, long, float, double, long double, etc. That only works because they're really all numbers, and you can reasonably use + to add any of them together.
When you're dealing with some unknown input, that doesn't apply though -- you need to verify enough about the data to be sure the operation is sensible and meaningful before you can do much else with it; it's pretty hard to get a meaningful result from comparing (for example) 7 to a sunset.
C++ is a statically typed language. What type a variable is of will be fixed at compile-time and cannot be changed at run-time. What users enter, however, will only be known at run-time, and cannot be known at compile-time. Therefore your question makes no sense.
When you expect an integer from a user, then the best way would be to try to read an integer, and check whether this succeeds:
int i;
std::cin >> i;
if(!std::cin)
throw "Stupid user blew it!"; // or some real error handling
However, the catch with this is that, once an input operation fails, an input stream enters a bad state and the data that couldn't be read stays in the input buffer. If you want to handle this gracefully, would have to clear the stream's error state flags, and make it ignore whatever is in the input buffer.
So sometimes it might be easier to first read a string
std::string input;
std::cin >> input; // either read up to any whitespace, or
std::getline(std::cin, input); // newline, or
std::getline(std::cin, input, '\t'); // tab, or whatever you want
because this always succeeds, and then try to convert it into whatever data you need. The way to do this is via string streams:
std::istringstream iss(input);
int i;
iss >> i;
Now you can check the string stream's state
if(!iss)
and if the conversion failed, std::cin will still be usable and the erroneous input read from its buffer.
However, there's one more catch: If a user inputs '"42 thousand"', then this won't catch the error. The remaining characters will be in the string streams input buffer and silently ignored. So what you usually need to do for such a conversion is to test whether the string stream's buffer is fully read, that is: reading reached EOF. You can check for this by invoking iss.eof(). However, if you read a whole line, there might be extra whitespace at the end, which you wouldn't want to make the conversion fail, so you need to read extra whitespace before you check for EOF: iss >> std::ws. (std::ws is a stream manipulator that "eats" consecutive whitespaces.)
by now, the conversion would look like this:
std::istringstream iss(input);
int i;
iss >> i >> std::ws; // you can chain input
if(!iss.eof())
throw invalid_input(input);
Of course, this is pretty elaborated for a one-time conversion and I wouldn't exactly swear by the life of my kids that there isn't a nice improvement left that I hadn't thought of yet. So you would at least want to wrap this into a function and put that into your toolbox for reusing it (and improving on it, if you find an error):
bool convert_to_int(const std::string& str, int& result)
{
std::istringstream iss(input);
iss >> result >> std::ws;
return iss.eof();
}
Or, generic for any type:
template< typename T >
bool convert_from_string(const std::string& str, T& result
{
std::istringstream iss(input);
iss >> result >> std::ws;
return iss.eof();
}
Even better would be to use a ready-made off-the-shelf solution for this. Boost has just such a thing with its lexical_cast.
Here's a skeleton algorithm for the whole input routine:
int i;
do {
read string input
convert to int i
while(!conversion succeeded);
With the bits from further above, you should be able to fill in the missing parts.
Use templates:
template <typename T>
bool SanityCheck(T number);
The sanity check may vary for different types. As this is a homework, I won't post any more code just hint you with a Google search term "partial template specialization".
Ok, I think I get what you actually want now.
I imagine your situation is something like this:
Read some user input (maybe using std::cin).
Check to make sure it is an int.
Use the int if it is one.
If this is the case then you do not want a function that can handle different data types, because the user cannot enter different data types, he can only enter characters and you have to choose what datatype you want to store that as.
I think this is what you need:
bool valid = false;
int input = 0;
while (!valid)
{
std::string inputStr;
std::cin >> inputStr;
valid = isInteger(inputStr);
if (!valid)
std::cout << "Please enter an integer." << std::endl;
else
input = atoi(inputStr.c_str());
}
std::cout << "You entered " << input << "!" << std::endl;
You're going to have to write isInteger yourself, but hopefully you get the idea.
Option 1: use boost::variant if you want it to be a single function
Option 2: overload this function for all types that you need
Making your function a template function would achieve this.
template<typename T>
bool SanityCheck(T number);
A lot of online surveys that I'm asked to fill out don't ask me to enter data but only select an option from 1 to 5. 1 = Totally Agree, 5 = Totally Disagree. This seems a more efficient way of collecting user input since you have total control over data type and all I have to do is highlight an option box.