Matthew Schell
Matthew Schell

Reputation: 679

What is the proper way of asking user to input a few numbers in C?

I am trying to make a C program about a Nuclear Missile launch. Below is my source code so far:

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

int nukeLaunchCode = 618243;
int NLC_input;
char *address;

int main(void) {
    address = malloc(sizeof(char) * 60);
    printf("\033[0;34m[INFO] C.E.R.B.E.R.U.S Activating");
    fflush(stdout);
    for (int i = 0; i < 3; i++){
        printf(".");
        sleep(1);
    }
    fflush(stdout);
    printf("\n");
    printf("\033[0;32m[INFO] C.E.R.B.E.R.U.S Initialized. Enter destination for nuke in address form: ");
    fgets(address, 60, stdin);
    printf("\033[0;32m[INFO] Geo locating address via Advanced UAV");
    fflush(stdout);
    for (int i = 0; i < 6; i++) {
        printf(".");
        fflush(stdout);
        sleep(1);
    }
    printf("\n");
    fflush(stdout);
    printf("\033[0;31m[WARNING] Target Acquired. Enter 6-digit Nuke Confirmation code to proceed: ");
    fgets(&NLC_input, 7, stdin);
    return 0;

}

The problem is the fgets at the end of the code. I get a warning saying:

Incompatible pointer types passing 'int *' to parameter of type 'char *'

I've tried using scanf wiht the "%d" conversion symbol and then I get another warning saying:

'scanf' used to convert a string to an integer value, but function will not 
report conversion errors; consider using 'strtol' instead

Can someone please tell me what I'm doing wrong? Also, I've included the fflush functions because i was trying to do something cool. I wanted to print a certain amount of dots every second after a sentence was printed to animate a loading kind of thing. For some reason, without the fflush functions, commands are executed out of order and the dots don't print. But even with the fflush functions, the first line that's printed doesn't print the 3 dots until the next line is printed. I'm pretty sure this is a misplacement in the fflush functions, but can someone help me with that too please? Thank you!

Upvotes: 0

Views: 144

Answers (1)

David C. Rankin
David C. Rankin

Reputation: 84561

Alright, let's do something cool and get you straightened out. To begin with, the proper prototype for fgets() is:

char *fgets(char *s, int size, FILE *stream);

man 3 fgets

In your code you have declared int NLC_input;, but then attempt to use the address of NLC_input as the first parameter to fgets(). Not allowed. Taking the address of a int result in a pointer to int which is int* and does not match the pointer to char (e.g. char*) that fgets() requires.

Further, you cannot convert the user-input of characters to a numeric form (like int) with fgets(). You must use either strtol() or sscanf() to convert the digits contained in the array to a number. (but Good Job using fgets() for user-input, far better than trying to read directly with scanf())

Let's do a quick rundown of your code with additions:

#include <stdio.h>
#include <unistd.h>

#define MAXC 1024       /* if you need a constant, #define on (or more) */
#define ADRSZ  60

(stdlib.h removed as there is no need to dynamically allocate address)

int main(void) {
    
    char address[ADRSZ], tmp[MAXC];             /* avoid global variables */
    int nukeLaunchCode = 618243, NLC_input;

(note: if you don't plan to change nukeLaunchCode, then #define nukeLaunchCode 618243 would be fine -- but note, macros are generally defined in ALL-CAPS in C. Another alternative would be const int nukeLaunchCode 618243;)

You only need fflush() when you are ready for output, you include it is few additional times where it will make no difference. Instead:

    printf ("\033[0;34m[INFO] C.E.R.B.E.R.U.S Activating");
    for (int i = 0; i < 3; i++) {
        putchar ('.');              /* don't use printf for single-char */
        fflush(stdout);             /* fflush only needed when output required */
        sleep(1);
    }
    printf ("\n\033[0;32m[INFO] C.E.R.B.E.R.U.S Initialized. "
            "Enter destination for nuke in address form: ");

(note: the '\n' has been included at the beginning of the second printf())

Now on to input:

    if (!fgets(address, 60, stdin)) {           /* validate EVERY user input */
        puts ("(user canceled input)");
        return 0;
    }
    printf ("\033[0;32m[INFO] Geo locating address via Advanced UAV");
    for (int i = 0; i < 6; i++) {
        putchar ('.');
        fflush(stdout);
        sleep(1);
    }
    printf ("\n\033[0;31m[WARNING] Target Acquired. "
            "Enter 6-digit Nuke Confirmation code to proceed: ");

(note: a user can cancel input by generating a manual EOF by pressing Ctrl + d, (or Ctrl + z on windows) and that is not and error, so you should handle the EOF case for the user)

Just read the input that you will convert to a value in NLC_input into a temporary array using fgets(), e.g.

    if (!fgets (tmp, sizeof tmp, stdin)) {      /* fill temporary array */
        puts ("(user canceled input)");
        return 0;
    }
    if (sscanf (tmp, "%d", &NLC_input) != 1) {  /* validate EVERY conversion */
        fputs ("error: invalid integer input.\n", stderr);
        return 1;
    }

Now on to validating the launch code:

    if (NLC_input != nukeLaunchCode) {          /* validate launch code */
        fputs ("error: Invalid Code, self-destruct sequence started ", stdout);
        for (int i = 0; i < 6; i++) {
            putchar ('.');
            fflush(stdout);
            sleep(1);
        }
        puts (" B O O M ! ! !");
        return 1;
    }
    
    puts ("Launch Code Valid, continuing ..."); 
}

Example Use/Output

Give it a go:

$ ./bin/launchcode
[INFO] C.E.R.B.E.R.U.S Activating...
[INFO] C.E.R.B.E.R.U.S Initialized. Enter destination for nuke in address form: N34W67.123
[INFO] Geo locating address via Advanced UAV......
[WARNING] Target Acquired. Enter 6-digit Nuke Confirmation code to proceed: 618244
error: Invalid Code, self-destruct sequence started ...... B O O M ! ! !

Look things over and let me know if you have further questions.

Upvotes: 4

Related Questions