Use lstrip:
question.lstrip("-").isdigit()
Example:
>>>'-6'.lstrip('-')
'6'
>>>'-6'.lstrip('-').isdigit()
True
You can lstrip('+-') if you want to consider +6 a valid digit.
But I wouldn't use isdigit, you can try int(question), it'll throw an exception if the value cannot be represented as int:
try:
int(question)
except ValueError:
# not int
Answer from Maroun on Stack OverflowUse lstrip:
question.lstrip("-").isdigit()
Example:
>>>'-6'.lstrip('-')
'6'
>>>'-6'.lstrip('-').isdigit()
True
You can lstrip('+-') if you want to consider +6 a valid digit.
But I wouldn't use isdigit, you can try int(question), it'll throw an exception if the value cannot be represented as int:
try:
int(question)
except ValueError:
# not int
Use a try/except, if we cannot cast to an int it will set is_dig to False:
try:
int(question)
is_dig = True
except ValueError:
is_dig = False
if is_dig:
......
Or make a function:
def is_digit(n):
try:
int(n)
return True
except ValueError:
return False
if is_digit(question):
....
Looking at your edit cast to int at the start,checking if the input is a digit and then casting is pointless, do it in one step:
while a < 10:
try:
question = int(input("What is {} {} {} ?".format(n1,op,n2)))
except ValueError:
print("Invalid input")
continue # if we are here we ask user for input again
ans = opsop
n1 = random.randint(1,9)
n2 = random.randint(1,9)
op = random.choice(list(ops))
if question == ans:
print ("Well done")
else:
print("Wrong answer")
a += 1
Not sure what Z is doing at all but Z = Z + 0 is the same as not doing anything to Z at all 1 + 0 == 1
Using a function to take the input we can just use range:
def is_digit(n1,op,n2):
while True:
try:
n = int(input("What is {} {} {} ?".format(n1,op,n2)))
return n
except ValueError:
print("Invalid input")
for _ in range(a):
question = is_digit(n1,op,n2) # will only return a value when we get legal input
ans = opsop
n1 = random.randint(1,9)
n2 = random.randint(1,9)
op = random.choice(list(ops))
if question == ans:
print ("Well done")
else:
print("Wrong answer")
isdigit to work with negative numbers - Post.Byes - Bytes
C++ how to isdigit() a negative number?
caesar - Unable to confirm user input is a number using isdigit in c - CS50 Stack Exchange
c++ - Is there an isdigit function (overload) which includes the negative symbol? - Stack Overflow
No there isn't. A digit is one thing that comprises a representation of a number, along with the radix, sign, decimal separator, thousands separator, and perhaps other things such as exponentation.
If - was emitted into isdigit then you could expect some folk to want + to be included too, and perhaps even ( and ) to keep the accountants happy.
So in summary, testing if something is a representation of a number is an entirely different beast to testing if a particular character is a digit.
There is not, but it is trivial to make one
bool my_isdigit(unsigned char ch)
{
return ch == '-' || std::isdigit(ch);
}
If you think about what a digit is this makes sense. According to the standard a digit is defined as [0-9] and as detailed here, there aren't actually any negative literals in C++. It is a positive number that gets the unary operator - applied to it.
Here is the code:
import re s = " -42" s = re.split(r'\s+', s) s = list(filter(None,s)) print(s[0].isdigit())
This prints out False. I don't understand why because if I go to simply print it without the isdigit it gives back 42.
The trick is that the isdigit function does not take an argument of type char. Quoting the standard (N1570 7.4p1:
The header
<ctype.h>declares several functions useful for classifying and mapping characters. In all cases the argument is anint, the value of which shall be representable as anunsigned charor shall equal the value of the macroEOF. If the argument has any other value, the behavior is undefined.
The type char may be either signed or unsigned. If it's signed (as it very commonly is), then it can hold negative values -- and passing a negative value other than EOF (typically -1) to isdigit, or to any of the other functions declared in <ctype.h>, causes undefined behavior.
The solution is to convert the argument to unsigned char before passing it to isdigit:
char c = -46;
if (isdigit((unsigned char)c) {
puts("It's a digit (?)");
}
else {
puts("It's not a digit");
}
And yes, this is exactly as annoying and counterintuitive as you think it is.
The isdigit() function does not check if a number is a number, numbers are always numbers, it checks if the number is the ascii code of a character that corresponds to a numeric value or more precisely to a digit, i.e. a charachter of the following set
0, 1, 2, 3, 4, 5, 6, 7, 8, 9
You can try to use strtol() for that purpose, like this
char *endptr;
char *number = "-46";
strtol(number, &endptr, 10);
if (*endptr == '\0') /* read the manual in the link to understand this please */
printf("yes, it's a number!\n");
else
printf("NO, `%s' is not a number!\n", number);
Note: if you read the manual or the standard specification of each function you use, you will improve your language skills, I very often see misuses of every single function from the standard library mostly because the user didn't read the manual.
Original Question
I just started my first attempt at learning to program. I'm currently working through "Learn C Programming for the Absolute Beginner" and for the life of me I can't understand why this code does not work as expected:
//1. Build a number-guessing game that uses input validation (isdigit() function) to verify that the user has entered
// a digit and not a nondigit (letter). Store a random number between 1 and 10 into a variable each time the program
// is run. Prompt the user to guess a number between 1 and 10 and alert the user if he was correct or not.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
int main()
{
int iRandomNum = 0;
int iGuess = 0;
srand(time(NULL));
iRandomNum = (rand() % 10) + 1;
printf("\nNumber Guessing Game, Chapter 3 Challenge");
printf("\nGuess a number between 1 and 10: ");
scanf("%d", &iGuess);
if (isdigit(iGuess))
{
if ( iGuess > 0 && iGuess < 11)
{
printf("You guessed %d", iGuess);
printf("The correct answer was %d", iRandomNum);
if ( iGuess == iRandomNum)
{
printf("Congratulations! You guessed correctly!");
}
else
{
printf("Sorry! You guessed incorrectly...");
}
}
else
{
printf("Invalid Response: You did not choose a number between 1 and 10");
}
}
else
{
printf("\nInvalid Response: You did not select a number");
}
return 0;
}No matter what my input, whether it is a number 1 - 10, or some other character, the code returns:
"Invalid Response : you did not select a number"
Edit:
All, thanks for your help. I understand now that isdigit only tests whether a single character is a digit.
To fix my code, (if isdigit returns true), I convert the character to a number like so:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
int main()
{
int iRandomNum = 0;
int iGuess = 0;
char cResponse = '\0';
srand(time(NULL));
iRandomNum = (rand() % 10) + 1;
printf("\nNumber Guessing Game, Chapter 3 Challenge");
printf("\nGuess a number between 1 and 10: ");
scanf("%c", &cResponse);
if (isdigit(cResponse) == 0)
{
printf("\nInvalid Response, you did not input a number!");
}
else
{
//if iResponse is a digit, convert it to integer type by subtracting '0'
iGuess = cResponse - '0';
if ((iGuess < 1) || (iGuess > 10))
{
printf("\nInvalid Response: You did not choose a number between 1 and 10");
printf("\nYou guessed %d", iGuess);
printf("\nThe correct answer was %d", iRandomNum);
}
else
{
if ( iGuess == iRandomNum)
{
printf("\nCongratulations! You guessed correctly!");
}
else{
printf("\nSorry! You guessed incorrectly...");
}
}
}
return 0;
}Edit 2:
Welp, looks like I still have some debugging to do, but that's another issue, unrelated to isdigit and more so catching a response that is longer than a single character. Not looking for help on that, just wanted to add this note in case someone tries to rely on this subpar codeblock for learning purposes. Back to it. Thanks again everyone.
Edit 3: (last one I promise)
Once again, I stand corrected. Isdigit does accept integers. As u/CodeTinkerer so kindly pointed out, I missed an explanation of isdigit posted by u/strcspn in an earlier reply on this thread. For the sake of correcting some misinformation in my post (above), here it is:
The function actually takes an
int, but the value of thatintis supposed to represent a character.It's basically to allow passing in EOF, which can't be represented by
unsigned char.
Hopefully, someone can take something useful away from my (mis)adventures in scanf().