1

I was wondering how I can get scanf to skip reading a character if I press enter... My code is the following:

#include <stdio.h>

int main(void)

{
    int a, status;
    char b;
    printf("Please enter a positive number immediately"
           "followed by at  most one lower-case letter:\n\n");
    status = scanf("%i%c", &a, &b);
    if (status == 1 && getchar() == '\n') {
        printf("\nThank you!\n");
    }
    return 0;
}

When I enter just a number and nothing else, I need to press enter again to trigger the %c, &b in scanf. How do I avoid that and get the program to accept just 1 number to jump to the printf?
I tried:

if (status == 1 && getchar() == '\n')

but that won't work.

Nik
  • 1,780
  • 1
  • 14
  • 23
Matthew_H
  • 11
  • 3
  • 3
    I suggest using `fgets` to read a whole line, and then use `sscanf` to convert the number, if any, at the beginning of the line. – user3386109 Nov 08 '17 at 20:38
  • If `scanf("%i%c"...)` is successful it will return `2`, not `1`. `fgets` would make more sense here. – Barmak Shemirani Nov 08 '17 at 20:42
  • Well I only just started programming, so I'm not familiar with fgets. How would I use it in this context? Could you post me the line? – Matthew_H Nov 08 '17 at 20:42
  • If you added a line: `printf("%d [%c] = %d\n", a, b, status);` after the `scanf()`, doing a debug print of what was given, and if you typed `31` as the number, then you'd see `31 [` on one line, and `] = 2` on the next, because the `%c` would read the newline as the character, and because the `scanf()` as a whole would return 2 because it successfully converted two values. If you used `"%i%[a-z]"` as the format string, then you'd get 1 returned in `status` and 31 in `a` and garbage in `b`. – Jonathan Leffler Nov 09 '17 at 01:32

1 Answers1

0

As noted in the comments, your best course of action is to use fgets to just read in a string, then parse and validate it. This Thread will provide you with enough resources for you to educate yourself about the use of fgets.

Here is one approach you can take. Please note that this code does not attempt to validate every possible input a user can provide, but rather give you a reasonable direction you can take to solve your problem if the input is assumed correct. I will leave the task of validation to you. The code below should provide enough tools to accomplish the rest of your task. Look at using a for loop to step through the buffer and ensure the input is correct. Use isalpha() and isdigit() to test each character. You can also implement your own functions to test each character as is done
in this answer.

#include <stdio.h>
#include <stdlib.h> //for atoi() 
#include <string.h> //for strlen() 
#include <ctype.h> //for isalpha()
#define MAX_INPUTLENGTH 500
int main(void)
{
    //Always a good idea to initialize variables to avoid Undefined Behaviour!
    char buffer[MAX_INPUTLENGTH] = { '\0' };
    int a = 0, status = 1, length = 0;
    char b = '\0';

    printf("Please enter a positive number immediately"
        "followed by at  most one lower-case letter:\n\n");

    //this gets you a string you can work with
    fgets(buffer, sizeof(buffer), stdin);
    length = strlen(buffer);
    buffer[length - 1] = '\0';//remove the trailing '\n'
    length--;

    //now see if last character is a letter
    if (isalpha(buffer[length - 1])) {
        b = buffer[length - 1];//then assign and..
        buffer[length - 1] = '\0';//trim the letter
    }

    //this function converts the remaining string to an int
    a = atoi(buffer);

    //Use the debugger and observe how these functions work in order
    //to validate the input. for now, status is always 1!
    if (status == 1) {
        printf("\nThank you!\n");
    }
    return 0;
}

As noted in the comments below by @Jonathan, to portably get the count of an array, one should use sizeof(buffer) / sizeof(buffer[0]). Since you are using a char[], sizeof(buffer[0]) evaluates to 1, thus can be omitted when calling fgets.

Nik
  • 1,780
  • 1
  • 14
  • 23
  • 1
    Note that `_countof()` is a MS-specific feature. It isn't entirely appropriate here; using `sizeof()` is both portable and correct. The value returned by `_countof()` is the same as the value from `sizeof()` in this case because `sizeof(buffer[0]) == 1`. – Jonathan Leffler Nov 09 '17 at 01:34
  • 1
    Also note that your logic won't be upset by the user typing `31 ants`; it will happily treat the `s` as the 'one lower-case letter' (because the buffer is only 10 characters long, if you entered `31 elephants`, you'd leave the `t` and the `s` and the newline unread; if you typed `2000000000a`, you'd leave the `a` unread). You also need both `` (for `strlen()`) and `` (for `atoi()`). – Jonathan Leffler Nov 09 '17 at 01:43
  • @JonathanLeffler, thank you for your comments. I made edits to my answer accordingly. This feedback is very much appreciated, as I am still relatively new to SO and still learning how to give the best answers. People like you will help me get there quicker! – Nik Nov 09 '17 at 02:14