Home > Enterprise >  Accepting multiple user inputs in C
Accepting multiple user inputs in C

Time:10-31

I am writing a program in C that accepts user input in either of these formats:

  1. string, int
  2. string, int, int or float

Some examples of valid inputs:

  1. Susan 5
  2. David 10 24
  3. Sarah 6 7.5

How do I accomplish this in C?

Here is the code I have so far:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>

int main()
{
    char name[10];
    int num1;
    int num2;

    if(scanf("%s %d", name, &num1) != 2 || scanf("%s %d %d", name, &num1, &num2) != 3)
    {
            printf("Failure");
    }
    else
    {
        printf("Pass");
    }
}

This intends to print "Failure" if there is invalid user input and "Pass" if the user input is valid. The issue here is this code forces me to enter both formats in order to print "Pass." So if I input "Susan 5" I would have to input "David 10 24" in order to print "Pass" even though I have an or conditional and not an and conditional, which I don't understand. What I want is once I input "Susan 5" and hit enter, my program should be able to print "Pass."

CodePudding user response:

If I understand your question correctly, there are three possible inputs:

One word followed by an integer followed by

  1. nothing, or
  2. another integer, or
  3. a floating-point number.

Since you have stated in the comments section that it is acceptable in case #2 to store the second integer as a floating-point number, we can consider cases #2 and #3 to be the same case.

In the line

if(scanf("%s %d", name, &num1) != 2 || scanf("%s %d %d", name, &num1, &num2) != 3)

the second scanf function call will probably not work, because the first one has already consumed some of the input. Therefore, you should first read one line of input using fgets and replace the calls to scanf with calls to sscanf:

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

int main()
{
    char name[10];
    int num1;
    double num2;

    char line[100];
    int num_consumed;

    //attempt to read one line of input
    if ( fgets( line, sizeof line, stdin ) == NULL )
    {
        fprintf( stderr, "input error!\n" );
        exit( EXIT_FAILURE );
    }

    //verify that entire line was read in
    if ( strchr( line, '\n' ) == NULL )
    {
        fprintf( stderr, "line too large for input buffer!\n" );
        exit( EXIT_FAILURE );
    }

    //attempt to convert first two parameters
    if ( sscanf( line, "%9s%d%n", name, &num1, &num_consumed ) != 2 )
    {
        printf( "Failure\n" );
        return 0;
    }

    printf( "Pass\n" );

    //attempt to read third parameter as a floating-point number
    if ( sscanf( line num_consumed, "%lf", &num2 ) != 1 )
    {
        printf( "User entered only one number:\n%d\n", num1 );
    }
    else
    {
        printf( "User entered two numbers:\n%d\n%f\n", num1, num2 );
    }
}

This program has the following behavior:

Bad input:

Susan David
Failure

Only one number as input:

Susan 5
Pass
User entered only one number:
5

Two integers as input:

David 10 24
Pass
User entered two numbers:
10
24.000000

One integer and one floating-point number as input:

Sarah 6 7.5
Pass
User entered two numbers:
6
7.500000

One possible problem with the program is that it does not check why the second sscanf failed. For example, it will treat the input

Susan 5 dslfhksdhfkl

the same as if the user has simply entered:

Susan 5

The question does not state whether the input should print Failure in such a case or not. However, meanwhile in the comments section, you have stated that the program should reject input such as the following:

Susan 5 ddggghh
David 10 24 dslfhksdhfkl

Therefore, in the program below, I have added an additional check in both cases to verify that all remaining characters after the matched characters are whitespace characters (there will always at least be a newline character at the end of the line). If not, then the input gets rejected.

In order to determine whether a character is a whitespace character, I use the function isspace.

Here the updated program with these additional checks:

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

//this function will return whether a string consists
//entirely of whitespace characters
bool is_string_whitespace( const char *str )
{
    for ( const char *p = str; *p != '\0'; p   )
    {
        if ( !isspace( (unsigned char)*p ) )
            return false;
    }

    return true;
}

int main()
{
    char name[10];
    int num1;
    double num2;

    char line[100], *p;
    int num_consumed;

    //attempt to read one line of input
    if ( fgets( line, sizeof line, stdin ) == NULL )
    {
        fprintf( stderr, "input error!\n" );
        exit( EXIT_FAILURE );
    }

    //verify that entire line was read in
    if ( strchr( line, '\n' ) == NULL )
    {
        fprintf( stderr, "line too large for input buffer!\n" );
        exit( EXIT_FAILURE );
    }

    //attempt to convert first two parameters
    if ( sscanf( line, "%9s%d%n", name, &num1, &num_consumed ) != 2 )
    {
        printf( "Failure\n" );
        return 0;
    }

    //attempt to read third parameter as a floating-point number
    p = line   num_consumed;
    if ( sscanf( p, "%lf%n", &num2, &num_consumed ) == 1 )
    {
        //verify that all remaining characters are whitespace
        if ( !is_string_whitespace( p num_consumed ) )
        {
            printf( "Failure" );
            return 0;
        }
        printf( "Pass\n" );
        printf( "User entered two numbers:\n%d\n%f\n", num1, num2 );
    }
    else
    {
        //verify that all remaining characters are whitespace
        if ( !is_string_whitespace( p ) )
        {
            printf( "Failure" );
            return 0;
        }

        printf( "Pass\n" );
        printf( "User entered only one number:\n%d\n", num1 );
    }
}

This program now correctly rejects the inputs mentioned above:

Susan 5 dslfhksdhfkl
Failure
David 10 24 dslfhksdhfkl
Failure
  •  Tags:  
  • c
  • Related