0

I've done lots of programming and arduino and would like to learn in C, since this is also an requirement for my current study. At this moment, I am trying to make a program which checks if the "age" variable contains a character. This will give the user an error message which loops until the input is a number. This is what I have at the moment:

#include <stdio.h>
#include <ctype.h>

#define MAXIMUM 10
#define BASE 10


char name[MAXIMUM]; // Input[Range to prevent overflow]
int age = 0; // Input
int nage; // nage = age + 1;
int error1 = 0;

void errorProgram() 
{
    if (isdigit(age))
    {
        error1 = 0;
        printf("Error = 0\n");
    }
    else {
        error1 = 1;
        printf("Error = 1\n");
    }
}

void main(void)
{
    system("cls");
    printf("What is your name: ");
    scanf("%15[^\n]", name);
    system("cls");
    printf("What is your age: ");
    scanf("%d", &age);
    errorProgram();
    while (error1 != 0) {
    printf("Age contains character, please enter again: ");
    scanf("%d", &age);
    }
    nage = age + 1;
    system("cls");
    printf("Hello %s, you'll be %d next year.", name, nage);
    return(0);
}

This is what happens when I run the program when we just ignore the what's your name part

Scenario 1(number)

Output

What is your age:

Input

5

Output

Error = 1
Age contains character, please enter again:

After I hit enter, it uses the while loop to ask it again until I have it right which is a wished behavior. However, it seems to detect age as a character?

Scenario 2(Character)

Output

What is your age:

Input

d

Output

    Age contains character, please enter again: d
Age contains character, please enter again: Age contains character, please enter again: Age contains character, please enter again: Age contains character, please enter again: Age contains character, please enter again: Age contains character, please enter again: Age contains character, please enter again: Age contains character, please enter again: Age contains character,

I'd like to know why if I enter a character, it spams the console with the lines. Both 5 and d throws an error1 = 1, but the while function doesn't seem to behave the same way it does things different when it comes to the character.

Can someone explain this behavior?

Btw, I am using a template from my study which uses the "Void main". Hence it's a bit different.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 1
    With [ASCII encoding](http://en.cppreference.com/w/c/language/ascii) the expression `isidit(age)` will be true only if `age` is between `48` and `57` (inclusive). – Some programmer dude Sep 20 '18 at 17:08
  • 1
    Nothing changes `error1` inside the loop. So once you're in there you'll never get out. – Kevin Sep 20 '18 at 17:09
  • I know @Kevin , like @Someprogrammerdude said. If it's outside the `48-57` then error1 is still the same. That means `0` - `47` and `a` - `z` will put you in the loop. My question is why it either send the error once, or spams when I fill a character or a number, even though both will set `error1 = 1`. Different behavior while error1 = 1 in both cases. – Capt. Frost Sep 20 '18 at 17:17
  • To understand this behavior, step through the program with a debugger and look at the value stored in `age` after the `scanf` call. Your are specifying a decimal numeric format so entering `5` should give you the value 5 and `d` is not a number so should give the value 0. Neither of which is in the range that `isdigit()` expects for an ASCII numeral. – Chris Ryding Sep 20 '18 at 17:45
  • What do you think checking if an `int` is a digit does? – David Schwartz Sep 20 '18 at 17:50
  • @DavidSchwartz I want to "filter" characters out. By using string, this whole ordeal with isdigit works, but as you know, it has to string > DEC which messes up with the addup. The problem is because the format of the scanf isn't met, it stays in the buffer and simply skip the command. It has to flush out. "What do you think checking if an int is a digit does?". If it's an digit it's no problem. If not, then it skips the `scanf("%d", &age);`. Maybe I don't understand you that well. – Capt. Frost Sep 20 '18 at 19:03
  • @ChrisRyding I've done it already. It equals to zero. However, entering 0 or d will give me a different behavior even it has the same value. – Capt. Frost Sep 20 '18 at 20:22
  • 1
    Better read that possible duplicate link, and never forget to check what `scanf` ***returns***. – Some programmer dude Sep 20 '18 at 20:32
  • when compiling, always enable the warnings, then fix those warnings. 1) there are only two valid signatures for `main()`. They both have a return type of `int`, not `void` 2) the posted code is missing the statement: `#include ` for the function: `system()` 3) the statement: `return(0);` is not correct for a function returning `void` (of course, fixing the signature for `main()` will correct this problem. 4) regarding: `system( "cls" );` is not portable, suggest using the ANSI excape sequences – user3629249 Sep 21 '18 at 05:38
  • it is (almost) always a bad idea to make the data `file global` rather than local to a function and passed as parameters to any sub functio – user3629249 Sep 21 '18 at 05:39
  • the call to `scanf()` for the age is allowing any integer to be entered (even negative values) by the user. Suggest using the type `size_t` rather than `int`. Also a `int` is (depending on the underlying architecture and certain compiler options) typically 4 bytes long and the function: `isdigit()` is expecting its' parameter to be a single character Not an array of characters – user3629249 Sep 21 '18 at 05:43
  • OT: when call any of the `scanf()` family of functions: 1) always check the returned value (not the parameter values) to assure the operation was successful. (note the input format specifier: `%d` will not input any characters, only digits,) – user3629249 Sep 21 '18 at 05:46
  • the array `char name[ MAXIMUM ];`, due to `#define MAXIMUM 10` only has room for a 9 character name + the NUL termination character, However, `scanf("%15[^\n]", name);` is allowing 14 characters + a NUL termination character. This (can) result in undefined behavior and even a seg fault event. – user3629249 Sep 21 '18 at 05:49
  • all the code used to input the `age` would be much better written as a `do...while` loop rather than a long messy sequence of instructions. And since the user might have entered something other than digits, the call(s) to `scanf()` will NEVER input a valid value, unless the code clears the `stdin` stream, with something like: `int ch; while( ( ch = getchar() ) != EOF && ch != '\n' );` – user3629249 Sep 21 '18 at 05:51
  • the variable `nage` can be eliminated by replacing: `printf("Hello %s, you'll be %d next year.", name, nage);` with `printf("Hello %s, you'll be %d next year.", name, age+1);` Also, `stdout` is buffered, To get it be actually displayed on the terminal, any of certain events must happen, like the buffer filled or a input statement executed of (in this case) end the format string with '\n' as in: `printf("Hello %s, you'll be %d next year.\n", name, age+1);` – user3629249 Sep 21 '18 at 05:58
  • when calling `scanf()` with the input format specifier: `%d`, no non-digit characters will ever by placed in the variable `age`. Therefore, the function: `errorProgram()` will NEVER be needed and therefore can be eliminated – user3629249 Sep 21 '18 at 06:08

1 Answers1

0

the following proposed code:

  1. cleanly compiles
  2. properly checks for errors
  3. caveat: does not empty stdin and retry getting age
  4. eliminates unneeded #defines and variables and useless code
  5. properly uses scanf() to input the name string
  6. immediately outputs the final printf() rather than waiting for the program to end (wherein the OS will output the final data from the printf()
  7. does not use non-portable statements like: system( "cls" );

and now, the proposed code:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#define MAXIMUM 100



char name[MAXIMUM]; // Input[Range to prevent overflow]
int age = 0; // Input


int main(void)
{
    //system("cls");
    printf("\nWhat is your name: ");
    if( scanf("%99[^\n]", name) != 1 )
    {
        fprintf( stderr, "scanf for name failed\n" );
        exit( EXIT_FAILURE );
    }

    //system("cls");
    printf("\nWhat is your age: ");
    if( scanf("%d", &age) != 1 )
    {
        fprintf( stderr, "scanf for age failed\n" );
        exit( EXIT_FAILURE );
    }

    //system("cls");
    printf("\nHello %s, you'll be %d next year.\n", name, age+1);
    return(0);
}
user3629249
  • 16,402
  • 1
  • 16
  • 17
  • Thanks for pointing those stuff out. However, my question is not on how to fix it but why it behaves like that. I've read the duplicate and it explained that the buffer isn't cleared when the input is not the same as the pointed format. This skips the scanf so the loop will just print and skip the scanf request. – Capt. Frost Sep 21 '18 at 11:52
  • `scanf()` never gets 'skipped' however, if the input format specifier does not match the data from the `stdin` stream, no characters will be input. Strongly suggest checking the returned value from `scanf()` as that will indicate if the input(s) were successful or not. – user3629249 Sep 21 '18 at 15:32