0

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.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
charlotte
  • 65
  • 5
  • 3
    You can't do it like this. You need to first read the input as string (`fgets`) and then parse it . You can make it relatively simple, depending on what kinds of bad inputs you want to handle – Eugene Sh. Oct 04 '21 at 18:25
  • Do you know the ASCII code of "2"? Might be enlightening. – Yunnosch Oct 04 '21 at 18:26
  • 2
    You cannot use `%c` to convert user input such as “-9” to a `signed char`. `%c` reads one character and puts the code for that character in the passed variable. Scan for a decimal numeral using `%d` with an `int`. Check the return value of `scanf`. If it is not 1, indicating 1 conversion and assignment was successfully completed, then scan using `%c` with `char`. If that produces a question mark (character literal `'?'`) in the `char`, then accept it as the user indicating termination. Otherwise, report an error to the user that they entered neither a decimal numeral nor a question mark. – Eric Postpischil Oct 04 '21 at 18:26
  • Are you aware of the meaning of the return value of `scanf()`? It is mentioned in the docs https://en.cppreference.com/w/c/io/fscanf Reading up on it will allow you to try scanning for an integer (into an appropriate integer variable) and if it fails check for a character (scanned into a character variable) being equal to "?". – Yunnosch Oct 04 '21 at 18:27
  • Please [edit] your question and add more information: What kind of input do you want to process? Do I understand right that you expect the user to enter either a number or a question mark? What is the allowed range for the numbers? – Bodo Oct 04 '21 at 18:32
  • 3
    It's interesting that you say you must use `char` rather than `int` because you want to store a `?`. Perhaps you are unaware that `'?'` is of type `int`. – William Pursell Oct 04 '21 at 18:35
  • 1
    aaa, What should happen if input is non-numeric and not `"?"`, like `"qwerty\n"`? – chux - Reinstate Monica Oct 04 '21 at 18:47
  • `-9` is two chars. – stark Oct 04 '21 at 20:18

3 Answers3

2

If you want to scan an integer and at the same time scan a character like ? you can do:

  1. Try to scan an integer
  2. 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

Support Ukraine
  • 42,271
  • 4
  • 38
  • 63
  • @chux-ReinstateMonica: The `scanf("%c", &c)` is used only after `scanf("%d, …)` has been tried, and that will have consumed leading white space. – Eric Postpischil Oct 04 '21 at 19:07
0

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*/}
0___________
  • 60,014
  • 4
  • 34
  • 74
0

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?

Steve Summit
  • 45,437
  • 7
  • 70
  • 103