2

Input

void sum(int a, int b) {
        a + b;
}

void quit() {
        exit(0);
}

int main() {
    
    char str[10];
    int x, y; 

    printf("Call a function");
    scanf("%s %d %d", str, &x, &y); //<-this is the part I cannot resolve

    //tried to call a function but failed
    if (strcmp(str, "quit") == 0)
          quit();
    else if (strcmp(str, "sum") == 0) 
          sum(x, y);
}

Summary:

sum(int a, int b) and quit() function requires different scanf. If I want to call a function regardless of the arguments how should I fix it? I want the program to identify what function to be called according to user input.

plus: the code only works for sum() function because the scanf() only accepts ["%s %d %d", str, &x, &y] input. However, I want program to scan sum() and quit() both.

2
  • Can you not just give them the options to choose from and get the option? Then using switch case you can call the required function. Commented Apr 9, 2022 at 3:08
  • 4
    I strongly suggest doing an input a line at a time (getline is in all reasonable C libraries already; if not, it's a couple line wrapper for fgets), then possibly using sscanf or strtok_r or something to parse within the line. Commented Apr 9, 2022 at 3:18

3 Answers 3

2

When dealing with line-based user input, it makes sense to always read one line at a time. This is not what the function scanf does. For example, if you use the "%s %d %d" format string, then scanf will continue reading input until it is able to match both numbers, or until it encounters a character that makes the match impossible (such as an alphabetical character). It will continue reading input past the end of the line if the user enters "quit" without entering two numbers on the same line, which is probably not what you want.

For reading exactly one line of input, I recommend that you use the function fgets. You can then, if you want, use sscanf on that single line of input. That way, you won't have the problem of your program attempting to read more than one line of input. The function sscanf will simply report that it was only able to match the first specifier, if the user does not enter any numbers afterwards.

With the functions scanf and sscanf, you can check the return value of the function to determine how many specifiers in the format string were matched.

It is unsafe to use the result of scanf or sscanf without first checking the return value of that function, in order to determine how many arguments were matched. Otherwise, you may be using a non-existant result. See this guide for further information:

A beginners' guide away from scanf()

Also, when using the %s format specifier in scanf or sscanf (but not printf), it is generally a good idea to limit the number of characters written. Otherwise, a buffer overflow will occur if the user enters more than 9 characters (10 characters including the terminating null character), because the array str only has room for 10 characters. A buffer overflow should always be prevented, because it can cause bugs that are very hard to find.

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

void sum( const int a, const int b )
{
    printf( "The sum of %d and %d is %d.\n", a, b, a + b );
}

void quit()
{
    printf( "Quitting.\n" );
    exit( EXIT_SUCCESS );
}

int main( void )
{
    char line[100];
    char str[10];
    int x, y;
    int num_matched;

    printf( "Call a function: " );
    if ( fgets( line, sizeof line, stdin ) == NULL )
    {
        fprintf( stderr, "Input error!\n" );
        exit( EXIT_FAILURE );
    }

    num_matched = sscanf( line, "%9s %d %d", str, &x, &y );

    if      ( num_matched >= 1 && strcmp( str, "quit" ) == 0 )
        quit();
    else if ( num_matched >= 3 && strcmp( str, "sum"  ) == 0 ) 
        sum( x, y );
    else
        printf( "Bad input!\n" );
}

This program has the following behavior:

Call a function: sum 5
Bad input!
Call a function: sum 5 7
The sum of 5 and 7 is 12.
Call a function: quit
Quitting.
Sign up to request clarification or add additional context in comments.

2 Comments

May also note that since a and b are not changed in sum(), you can use const int a, const int b as parameters and allow the compiler a bit more freedom in optimizing (not that there is a whole lot to optimize in this sum()), but just as a general note. Also 100 chars (unless programming for a microcontroller) is a bit short as an input buffer, with a minimum of 512K stack size on windows 1M/4M on Linux, using 1K for the input buffer isn't a bad choice. Good answer.
@DavidC.Rankin: Yes, you are correct that it is better to use const in the function parameters. Thanks for pointing it out. I have edited my answer accordingly. Regarding the size of the input buffer, I agree that it is generally better to use a larger input buffer. However, in this case, in my opinion, there is little point in having a larger buffer, because I do not have the impression that OP will ever need it for this program. Also, when entering a "sum" command, the representable range of an int will be exceeded long before the input buffer size will become a problem.
2

You can scan the integer inputs separately, after you've established that you need them (in its if block):

int main() {
    
    char str[10];
    int x, y; 

    printf("Call a function");
    scanf("%s", str); // you only need to know the function name for now

    if (strcmp(str, "quit") == 0)
    {
          quit();
    }
    else if (strcmp(str, "sum") == 0)
    {
          scanf("%d %d", &x, &y);
          sum(x, y);
    }
}

demo

3 Comments

You should use %9s instead of %s since you only have enough storage in str[10] to store 9 characters and a NUL terminator.
@Wyck, Thanks for the feedback. There's a lot to cover with correctly handling i/o, but I think that goes beyond what the OP was really asking about.
One thing I don't like about this solution is that if the user enters for example "sum 5" on one line, then this program will not immediately reject the input, but scanf will instead attempt to read input past the end of the line, waiting for another line of input from the user. That is why my solution uses fgets and sscanf instead, so that only a single line of input is read. However, this means that my solution requires more code. Since OP did not ask for input validation in the question, your answer probably is the simplest solution to the question. Therefore, I have upvoted it.
-1

Im a little confused with the question statement. Take a look at the modifications and tell me if it's fixed your problem or made it clearer. If you want to read what void sum() computes then you need to change it to a different return value like int sum()

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

void sum(int a, int b) {
        a + b;
        printf("sum was called"); //this just confirms that sum was used since no return value
}

void quit() {
        exit(0);
}

int main() {

    char str[10];
    int x, y;

    printf("Call a function");
    scanf("%s %d %d", str, &x, &y);

    if (strcmp(str, "quit") == 0)
          quit();
    else if (strcmp(str, "sum") == 0)
          sum(x, y);
          quit();
    return 0;
}

1 Comment

They want to accept an input like sum 5 6 or quit. This answer doesn't fix the issue.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.