Apologies, i'm still new to C. Learned Java first Im trying to complete my first assignment and I'm not quite sure about how to achieve the result of making it say "input could not be interpreted as an integer value". My code does interpret the string "abc" as an integer value, namely 0. How would I get it to function differently. Or rather, how would I get the scanner to function differently? Many Thanks.
#Test if input is character or integer?
1 messages · Page 1 of 1 (latest)
When your question is answered use !solved to mark the question as resolved.
Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question run !howto ask.
@silver grotto
Screenshots!
Your message appears to contain screenshots but no code. Please send code and error messages in text instead of screenshots if applicable!
#include <stdio.h>
int main() {
int grade;
printf("Please enter a numeric grade: ");
scanf("%d", &grade);
printf("Your input =%i\n",grade);
if (grade <= 100 && grade >= 90) {
printf("Your grade is an A.\n");
} else if (grade < 90 && grade >= 80) {
printf("Your grade is a B.\n");
} else if (grade < 80 && grade >= 70) {
printf("your grade is a C.\n");
} else if (grade < 70 && grade >= 60) {
printf("Your grade is a D.\n");
} else if (grade < 60 && grade > 0) {
printf("Your grade is an F.\n");
} else if (grade < 0 || grade > 100) {
printf("Error: Invalid Value.\n");
} else {
printf("Error: Your input could not be interperted as an integer value.\n");
}
return 0;
}
We havn't gone over any of those in class yet. I guess I just wont worry about it for now
Alright, I'll write you an example anyways and will also link you this article cause scanf is really cursed and dangerous: https://sekrit.de/webdocs/c/beginners-guide-away-from-scanf.html
thx ^^
Okay, I've come up with two versions.
Version 1:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
int main() {
char buf[1024];
fgets(buf, sizeof buf, stdin); // I'll omit the error check for when a user enters more than 1023 characters
size_t last_index = strcspn(buf, "\n");
buf[last_index] = '\0';
char *endptr;
errno = 0;
int grade = /* implicit cast to int */ strtol(buf, &endptr, 10);
if (errno || endptr != buf + last_index) {
printf("Error: Your input could not be interperted as an integer value.\n");
return -1;
}
printf("grade = %d\n", grade);
}
```This abuses the fact that `strtol` itself tells you if there has been an error during the conversion and also the last character that couldn't be converted anymore is stored.
The issue you may find with this is that it doesn't like trailing spaces (leading spaces are okay). If you want to accept trailing spaces you'd need to trim them before actually parsing the string.
Another issue is that if you enter an empty line, then it'll actually think you just entered `0` (but maybe that is what you'd want as intended behaviour anyways).
Version 2 (a bit simpler and without abusing strtol as much):
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int only_digits(char *str) {
for (char *cur = str; *cur; cur++) {
// printf("isdigit(%1$c) = %2$d, isspace(%1$c) = %3$d\n", *cur, !!isdigit(*cur), !!isspace(*cur));
if (!(isdigit(*cur) || isspace(*cur))) // isspace checks for space, newline, etc.
return 0;
}
return 1;
}
int main() {
char buf[1024];
fgets(buf, sizeof buf, stdin); // I'll omit the error check for when a user enters more than 1023 characters
if (!only_digits(buf)) {
printf("Error: Your input could not be interperted as an integer value.\n");
return -1;
}
int grade = /* implicit cast to int */ strtol(buf, NULL, 10);
printf("grade = %d\n", grade);
}
```This version uses a separate custom function `only_digits` which returns `1` if the string consists entirely of digits and/or whitespace. The issue with this version is that it doesn't check whether there's even any digits in the string, so one should likely add a check if there is also at least 1 digit, e.g. by adjusting the `only_digits` function like so:
```c
int only_digits(char *str) {
int at_least_one_digit = 0;
for (char *cur = str; *cur; cur++) {
if (!(isdigit(*cur) || isspace(*cur))) // isspace checks for space, newline, etc.
return 0;
if (isdigit(*cur))
at_least_one_digit = 1;
}
return at_least_one_digit;
}
This version also doesn't care about whether there is whitespace between digits as opposed to the other version which would fail in that case.
So e.g. for version 2 the input 12 34 would be valid and convert it to 12, while the same input for version 1 would cause the error message
@silver grotto
jeez man i still got a lot to learn about c
@silver grotto The giant if-else/if-else/if-... construct of yours is entirely correct however (besides the fact that the error: couldn't convert case is now already handled further up).
Nonetheless I think this monstrosity can be shortened and made more readable:
char grade_letter;
if (grade > 100 || grade < 0) {
printf("invalid value\n");
return -1;
} else if (grade >= 90)
grade_letter = 'A';
else if (grade >= 80)
grade_letter = 'B';
else if (grade >= 70)
grade_letter = 'C';
else if (grade >= 60)
grade_letter = 'D';
else
grade_letter = 'F';
// This will only run if the grade_letter has been set
printf("Your grade is %c.\n", grade_letter);
If you don't want to immediately return you can also do:
char grade_letter = 0;
if (grade > 100 || grade < 0)
printf("invalid value\n");
else if (grade >= 90)
grade_letter = 'A';
else if ...
// This will only run if the grade_letter has been set
if (grade_letter)
printf("Your grade is %c.\n", grade_letter);
I wanted to solve this by using a switch case but i didnt know how to make each case a range. I couldn't do case(grade <= 100 && grade >= 90
Also yeah Im used to Java being verbose i like having the curly brackets lol
You wouldn't need the curly brackets in Java either
switch-case doesn't have that per C standard.
However gcc has an extension which allows for ranges in switch-cases:
char grade_letter = 0;
switch (grade) {
case 0 ... 59: grade_letter = 'F'; break;
case 60 ... 69: grade_letter = 'D'; break;
case 70 ... 79: grade_letter = 'C'; break;
case 80 ... 89: grade_letter = 'B'; break;
case 90 ... 100: grade_letter = 'A'; break;
default: printf("invalid value\n");
}
if (grade_letter)
printf("Your grade is %c.\n", grade_letter);
@silver grotto You could also check the return code for scanf().
If you enter "abc" when the scanf() expects an integer, then it will return 0, meaning no parameters were successfully scanned.
In your case you want it to be 1.
if (scanf("%d", &grade) == 1) {
// user entered a number
}
// else ???
This question is being automatically marked as stale.
If your question has been answered, run !solved.
If your question is not answered feel free to bump the post or re-ask.
Take a look at !howto ask for tips on improving your question.