I'm trying to get a function that stores integers in char. I need to use char rather than int because I need to use the question mark (?) to terminate my loop. However, I can't seem to make my code work. Here's my work:
int main() {
signed char num;
scanf("%c", &num);
if (num!='?') {
printf("%c\n", num);
}
return 0;
}
When I input a negative number (say, -9), I get the output:
-
I tried using the integer print symbol (%d) rather than %c when I was printing the values, as I saw on this question: https://www.quora.com/Can-I-assign-a-negative-number-to-a-char-variable-Why-or-why-not but makes everything I input junky. ie when I input 2, it returns 50.
I was told that signed char should do the thing here, but I'm not sure that's the case now.
Thanks.
If you want to scan an integer and at the same time scan a character like ? you can do:
Try to scan an integer
If scan for integer fails, try to scan a char
Like
int num;
char c;
if (scanf("%d", &num) == 1)
{
// Okay you got an integer.
c = num; // BUT... watch out for over/underflow !!!
}
else if (scanf("%c", &c) == 1)
{
// Okay you got a char
if (c == '?')
{
// You got your ?
}
else
{
// Some other char
// Some kind of error handling... perhaps
c = 0;
}
}
else
{
// Input error that can't be recovered
exit(1);
}
See online example https://ideone.com/kTPE0M
You use the wrong format:
it has to be (but you will have to enter 63 instead of ?):
signed char num;
scanf("%hhd", &num);
or
char str[6];
char num;
fgets(str,5,stdin);
if (str[0]!='?') {
if(sscanf(str, "%hhd", &num) == 1)
printf("%c\n", num);
else {/* handle scanf error*/}
When you have to do anything at all complicated, scanf is almost never the right tool for the job.
And, although it might not be obvious at first, the task "read a thing that's either an integer, or a question mark that indicates the end of the input" is definitely, in this sense, something that's too complicated for scanf. There's no good format specifier for that kind of "thing".
The easiest thing is to read a line of text (using fgets, not scanf), then start trying to figure out what's in it — question mark, integer, or something else. (What if the user types "x"?)
#include <stdio.h>
int main()
{
char line[512];
int num; /* note int not char */
if(fgets(line, sizeof(line), stdin) == NULL)
printf("end of file or error\n");
else if(line[0] == '?')
printf("end of input\n");
else if(sscanf(line, "%d", &num) == 1)
printf("numeric input: %d\n", num);
else printf("unexpected input!\n");
}
Note that this program still isn't perfect: If the user, types, say, "123x", this program will say it saw numeric input, and won't notice or complain about the extra x. Also, it only looks at the first character of the line to see if it's a ?, so it will also accept things line ?? or ?Cat in the hat. (There are ways to fix both of those things, but they get rather elaborate, and are probably more trouble than they're worth for a simple exercise.)
See also What can I use for input conversion instead of scanf?
Related
I have to finnish a college project, and a part of my code is acting strangely.
The goal of that part is to get an user input of an integer and store it in a variable so that i can use it later, however if the user inputs a character I have to ask for the number again.
I used the scanf function to get the user input and put it inside a while loop to continuously ask for the input in case it's invalid.
The problem is that when a user inputs a character, the code freaks out and starts running the while loop without stopping in the scanf to get the user input.
It makes sense that the loop condition is always true but the strange part is that it doesn't stop to read new inputs.
I deconstructed my code in order to replicate the problem to make it easier to debug.
I know that there are some useless variables but in my original code they are useful, I just kept them there to make it look similar to the original.
I can only use scanf to get user input, despite knowing them, in this project I am only allowed to use scanf. I can't use scanf's format to get characters, only numerical types are allowed in this project.
C11 is the version of the standart we are using in classes.
I'm sory if the solution for this is a dumb thing, I'm not good at C and I'm having some difficultlies this semester...
Thanks in advance.
while (!verification) {
printf(">>>"); //write values in here
check = scanf("\n%d", &var); //input a number and store the number of valid inputs
if (check) verification = 1; //if the input is a number then the while condition should turn to false with this statement
printf("var = %d, check = %d, verification = %d\n", var, check, verification); //printing all variables
}
If the user does not input an integer there are characters left in the input stream after the call to scanf. Therefor you need to read to end of line before making the next attempt to read an integer. Otherwise scanf will try to read the same non-integer characters again and again. Here is an example:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int ch, i, n;
n = scanf("%d", &i);
while (n == 0) {
fprintf(stderr, "wrong input, integer expected\n");
do {
ch = getchar();
} while ((ch != EOF) && (ch != '\n'));
n = scanf("%d", &i);
}
if (n == 1) {
printf("%d\n", i);
} else { /*n == EOF*/
fprintf(stderr, "reading input failed\n");
exit(EXIT_FAILURE);
}
return 0;
}
Don't use scanf() to read input from the user.
It's really only meant for reading data that's known to be in a particular format, and input from a user... often isn't.
While you do correctly check the return value of scanf("%d"), and could fix the case where the input isn't a number, you'll still have problems if the input is either an empty line, or a number followed by something else (123 foobar).
In the case of an empty line scanf() will continue waiting for non-whitespace characters. This is probably confusing, since users will expect hitting enter to do something.
In the case there's trailing stuff after the number, that stuff stays in the input buffer, and the next time you read something, it gets read. This is again probably confusing, since users seldom expect their input to one question to also act as input to another.
Instead, read a full line with fgets() or getline(), then run sscanf() or strtol() on that. This is much more intuitive, and avoids the disconnect caused by scanf() consuming input lines only partially (or consuming more than one line). See also e.g. scanf() leaves the new line char in the buffer
Here, using getline() (POSIX, even if not in standard C. Use fgets() instead if getline() is not available):
#include <stdio.h>
int main(void)
{
char *line = NULL;
size_t len = 0;
int result;
printf("Please enter a number: ");
while (1) {
if (getline(&line, &len, stdin) == -1) {
/* eof or error, do whatever is sensible in your case */
return 1;
}
if (sscanf(line, "%d", &result) != 1) {
printf("That didn't seem like number, please try again: ");
continue;
}
break;
}
printf("You entered the number %d\n", result);
}
The problem is you must discard offending input when the conversion fails.
Here is a simple solution using only scanf() as instructed:
#include <stdio.h>
int main() {
int n;
for (;;) {
printf("Enter an number: ");
switch (scanf("%d", &n)) {
case 1:
/* successful conversion */
printf("The number is %d\n", n);
return 0;
case 0:
/* conversion failure: discard the rest of the line */
scanf("*[^\n]"); // discard characters before the newline if any
scanf("*1[\n]"); // optional: discard the newline if present
printf("Invalid input. Try again\n");
continue;
case EOF:
/* input failure */
printf("Premature end of file\n");
return 1;
}
}
}
I'm trying to scanf an integer to see if it's legal in my program. However, if I input a number followed by a char it still treats it as legal number (my guess is that it only refers to the integer while saving the char in the buffer). Assume I can only use scanf and not something else (since that's what we've leraned). Also, if I input only a char it automatically casts it to an integer. This is what I have tried so far, with the help of what I saw here -
int number_of_numbers;
char number='\n';
printf("Enter size of input:");
if (scanf("%d%c",&number_of_numbers, &number)>=1 && number!='\n')
{
printf("Invalid size");
return 0;
}
How can I identify when I scanf only an integer or an integer followed by a char or just a char?
Thanks!
If you enter "only a character" it does not "automatically cast it to an integer". It does not accept any input at all, as shown by scanf returning 0, but that situation escapes your test.
But the answer to your question is: with difficulty when using scanf.
Here is a way to do it getting the input with fgets. It will tolerate any amount of whitespace before or after the number, but not any letters.
The reason for the space before %c is to instruct it to filter any leading whitespace. This is automatic anyway for %d, but not for %c. Then if there are no readable characters, nothing will be read into extra. If there is at least one character (apart from whitespace) then the sscanf conversion count will be incorrect.
#include <stdio.h>
#include <stdbool.h>
int main(void)
{
int number_of_numbers = 0;
while(number_of_numbers >= 0) {
bool success = false;
char str[100];
if(fgets(str, sizeof str, stdin) != NULL) {
char extra;
if(sscanf(str, "%d %c", &number_of_numbers, &extra) == 1) {
success = true;
}
}
if(success) {
printf("Success: %d\n\n", number_of_numbers);
} else {
printf("Invalid size\n\n");
}
}
return 0;
}
Program session:
123
Success: 123
123a
Invalid size
123 a
Invalid size
123 9
Invalid size
a
Invalid size
-1
Success: -1
The reasons for using fgets are
it doesn't "stall" if there is invalid input: it has already been read.
if there is a mistake, the string can easily be dumped and another one requested.
I'm trying to do a program with a simple game for a user to guess the number. My code is below:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX 30
#define TRYING 5
void guessnumber(int, int, int *);
int main(void) {
int mytry = 1;
guessnumber(MAX, TRYING, &mytry);
if (mytry <= TRYING)
printf("Congratulations! You got it right in %d tries\n", mytry);
else
printf("Unfortunately you could not guess the number in the number of tries predefined\n");
printf("End\n");
return EXIT_SUCCESS;
}
void guessnumber(int _n, int _m, int *_mytry) {
srandom(time(NULL));
int generated = 0, mynum = 0, test = 0;
generated = rand() % (_n + 1);
printf("Welcome to \"Guess the number\" \n");
printf("A number between 0 and %d was generated\n", _n);
printf("Guess the number:\n");
while (*_mytry <= TRYING) {
test = scanf(" %d", &mynum);
if (test != 1 || mynum < 0 || mynum > MAX)
printf("ERROR: please enter a valid number \n");
else
if (mynum > generated)
printf("Wrong! The number your trying to guess is smaller\n");
else
if (mynum < generated)
printf("Wrong ! The number your trying to guess is bigger\n");
else
break;
*_mytry = *_mytry + 1;
}
}
Okay, now the program is working pretty ok except for one thing: the scanf test.
It works if I try to enter a number out of my range (negative or above my upper limit) but it fails if I for example try to enter a letter. What it does is that it prints the message of error _m times and then it prints "Unfortunately you could not guess the number in the number of tries predefined" and "End".
What am I doing wrong and how can I fix this?
In case, a character is entered, you're trying to detect it correctly
if(test!=1 ......
but you took no action to correct it.
To elaborate, once a character is inputted, it causes a matching failure. So the input is not consumed and the loop falls back to the genesis position, only the loop counter is increased. Now, the previous input being unconsumed, is fed again to the scanf() causing failure once again.
This way, the loop continues, until the loop condition is false. Also, for every hit to scanf(), as unconsumed data is already present in the input buffer, no new prompt is given.
Solution: You need to clean the input buffer of existing contents when you face a failure. You can do something like
while ((c = getchar()) != '\n' && c != EOF);
to clean the buffer off existing contents.
When you enter a letter, scanf() leaves the letter in the input stream since it does not match the %d conversion specifier. The simplest thing to do is use getchar() to remove the unwanted character:
if (test != 1) {
getchar();
}
A better solution would be to use fgets() to get a line of input, and sscanf() to parse the input:
char buffer[100];
while (*_mytry<=TRYING)
{
if (fgets(buffer, sizeof buffer, stdin) == NULL) {
fprintf(stderr, "Error in fgets()");
exit(EXIT_FAILURE);
}
test=sscanf(buffer, "%d", &mynum);
if(test!=1 || mynum<0 || mynum>MAX)
printf ("ERROR: please enter a valid number \n");
else if(mynum>generated)
printf("Wrong! The number your trying to guess is smaller\n");
else if(mynum<generated)
printf("Wrong ! The number your trying to guess is bigger\n");
else
break;
*_mytry=*_mytry+1;
}
In the above code, note that the leading space has been removed from the format string. A leading space in a format string causes scanf() to skip leading whitespaces, including newlines. This is useful when the first conversion specifier is %c, for example, because any previous input may have left a newline behind. But, the %d conversion specifier (and most other conversion specifiers) already skips leading whitespace, so it is not needed here.
Additionally, your code has srandom() instead of srand(); and the call to srand() should be made only once, and probably should be at the beginning of main(). And, identifiers with leading underscores are reserved in C, so you should change the names _m, _n, and _mytry.
I'm doing intro to C and I need to write a program that prompts the user to enter in characters, an equal sign, and an integer. I need to use getchar() until the '=' then scanf() for the integer. The program should then output only the integer back to the user.
Right now it prints out unnecessary code re the location for every character input, then at the end outputs the correct integer. This is the code I have:
#include <stdio.h>
#define EQUAL '='
int main(void)
{
char ch;
int integer = 0;
printf("Enter some text, an equal sign and an integer:\n");
while ((ch = getchar())!= '\n') //while not end of line
{
if (ch == EQUAL){
scanf("%d", &integer);
}
printf("The integer you entered is: %d\n", integer);
}
return 0;
}
I can't find an example and need clarification on how to fix the issue.
You got bit by a gotcha in C. The problem is this:
if( ch == EQUAL )
scanf("%d", &integer);
printf("The integer you entered is %d\n", integer);
if with no braces will only include the single statement following it. That code is really this:
if( ch == EQUAL ) {
scanf("%d", &integer);
}
printf("The integer you entered is %d\n", integer);
To avoid this gotcha, I would recommend two things:
Always indent your code properly.
Never use if, else, or while without braces.
gcc supports a warning about this, -Wmisleading-indentation.
For more gotchas like this read "C Traps And Pitaflls" by Andrew Koenig.
anyone knows an efficient way to check out the format of an scanf'ed data?
e.g. if I try to read an integer and I type a character, how would you do to tell the program that is not correct?
You can check if scanf() succeeds, it returns the number of successful conversions it performed.
You should always check this, before relying on the result since if it failed the variable(s) might contain undefined data leading to undefined results if referenced.
You can use if to check, and re-try with a different conversion specifier on failure:
if(scanf("%d", &x) == 1)
printf("got integer %d\n", x);
else if(scanf("%c", &y) == 1)
printf("got character '%c'\n", y);
else /* more attempts */
Of course it can become troublesome if there are "sub-matches", so the order can matter. It's also way better to split the input processing into two steps for the above:
Read a full line of input using fgets()
Use sscanf() to parse the line
That way you avoid problems due to the input being streamed in:
char line[128];
if(fgets(line, sizeof line, stdin) != NULL)
{
int x;
char y;
if(sscanf(line, "%d", &x) == 1)
printf("got integer %d\n", x);
else if(sscanf(line, "%c", &y) == 1)
printf("got character '%c'\n", y);
}
Note that if you wanted to scan for both an integer and a float, it can still become troublesome since a typical float (such as "3.1416") begins with what is a legal integer. For those cases you can use the strtoXXX() family of functions, which let you check the remainder after doing the conversion.
As you have mentioned in the question that you are playing with numbers and chars only there is a very simple solution as follows
//while reading a char
scanf("%c",&temp);
if(!((temp >= 65 && temp <= 90) || (temp >= 97 && temp <= 122)))
printf("Only characters are allowed!\n");
hope this helps!
scanf("%s", &c);
if(!atoi(c)) puts("You have entered a character");
if(atoi(c) != 0) puts("You have entered an integer");
Scanner sc = new Scanner (System.in);
try {
// assume that the input from the user is not an integer,
// in that case the program cannot convert the input (which is a String) into
// an integer. Because of this situation it'll jump to the 'catch' part of the
// program and execute the code.
int input = Integer.valueOf(sc.nextInt);
// if the input is an integer lines below the above code will be executed.
// Ex. "int x = ( input + 10 ) "
}
catch (Exception ex) {
System.out.println("Invalid input, please retry!");
// if you want to get more information about
// the error use the 'ex' object as follows.
System.out.println(ex);
}