Поиск способа вызова функций с разными аргументами в C

Вход

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);
}

Резюме:

Функция sum(int a, int b) и quit() требует разных scanf. Если я хочу вызвать функцию независимо от аргументов, как мне это исправить? Я хочу, чтобы программа определяла, какую функцию следует вызывать в соответствии с пользовательским вводом.

плюс: код работает только для функции sum(), потому что scanf() принимает только ввод ["%s %d %d", str, &x, &y]. Однако я хочу, чтобы программа сканировала как sum(), так и quit().

Разве вы не можете просто дать им варианты выбора и получить выбор? Затем, используя case case, вы можете вызвать нужную функцию.

Nezuko 09.04.2022 05:08

Я настоятельно рекомендую вводить построчно (getline уже есть во всех разумных библиотеках C; если нет, это парная оболочка для fgets), затем, возможно, использовать sscanf или strtok_r или что-то еще для разбора внутри строки.

o11c 09.04.2022 05:18
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
Четыре эффективных способа центрирования блочных элементов в CSS
Четыре эффективных способа центрирования блочных элементов в CSS
У каждого из нас бывали случаи, когда нам нужно отцентрировать блочный элемент, но мы не знаем, как это сделать. Даже если мы реализуем какой-то...
2
2
91
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Я немного смущен формулировкой вопроса. Взгляните на модификации и скажите, исправили ли они вашу проблему или сделали ее более ясной. Если вы хотите прочитать, что вычисляет void sum(), вам нужно изменить его на другое возвращаемое значение, например 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;
}

Они хотят принять ввод, например sum 5 6 или quit. Этот ответ не решает проблему.

rootkea 09.04.2022 09:14
Ответ принят как подходящий

При работе с построчным пользовательским вводом имеет смысл всегда читать по одной строке за раз. Это не то, что делает функция scanf. Например, если вы используете строку формата "%s %d %d", то scanf будет продолжать считывать ввод до тех пор, пока не сможет сопоставить оба числа или пока не встретит символ, который делает сопоставление невозможным (например, буквенный символ). Он продолжит чтение ввода после конца строки, если пользователь вводит "quit", не вводя два числа в одной строке, что, вероятно, не то, что вам нужно.

Для чтения ровно одной строки ввода рекомендую использовать функцию fgets. Затем вы можете, если хотите, использовать sscanf в этой единственной строке ввода. Таким образом, у вас не будет проблем с попыткой вашей программы прочитать более одной строки ввода. Функция sscanf просто сообщит, что она смогла сопоставить только первый спецификатор, если после этого пользователь не вводит никаких чисел.

С помощью функций scanf и sscanf вы можете проверить возвращаемое значение функции, чтобы определить, сколько спецификаторов в строке формата совпало.

Небезопасно использовать результат scanf или sscanf без предварительной проверки возвращаемого значения этой функции, чтобы определить, сколько аргументов совпало. В противном случае вы можете использовать несуществующий результат. Смотрите это руководство для получения дополнительной информации:

Руководство для начинающих по использованию scanf()

Кроме того, при использовании спецификатора формата %s в scanf или sscanf (но не printf) рекомендуется ограничить количество записываемых символов. В противном случае произойдет переполнение буфера, если пользователь введет более 9 символов (10 символов, включая завершающий нулевой символ), потому что в массиве str есть место только для 10 символов. Всегда следует предотвращать переполнение буфера, потому что это может привести к ошибкам, которые очень трудно найти.

#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" );
}

Эта программа имеет следующее поведение:

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.

Также обратите внимание, что, поскольку a и b не изменяются в sum(), вы можете использовать const int a, const int b в качестве параметров и предоставить компилятору немного больше свободы в оптимизации (не то, чтобы в этом sum() нужно было оптимизировать многое), но в целом примечание. Кроме того, символы 100 (если не программировать для микроконтроллера) немного короче входного буфера, с минимальным размером стека 512 КБ в Windows 1M / 4M в Linux, использование 1 КБ для входного буфера — неплохой выбор. Хороший ответ.

David C. Rankin 09.04.2022 06:16

@DavidC.Rankin: Да, вы правы, лучше использовать const в параметрах функции. Спасибо, что указали на это. Я отредактировал свой ответ соответственно. Что касается размера входного буфера, я согласен, что обычно лучше использовать больший входной буфер. Однако в этом случае, на мой взгляд, нет большого смысла иметь больший буфер, потому что у меня нет впечатления, что OP когда-либо понадобится для этой программы. Кроме того, при вводе команды «сумма» представляемый диапазон int будет превышен задолго до того, как размер входного буфера станет проблемой.

Andreas Wenzel 09.04.2022 06:40

Вы можете сканировать целочисленные входы отдельно после того, как установили, что они вам нужны (в блоке if):

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);
    }
}

демо

Вы должны использовать %9s вместо %s, так как у вас достаточно памяти в str[10] только для хранения 9 символов и терминатора NUL.

Wyck 09.04.2022 06:14

@Wyck, спасибо за отзыв. Для правильной обработки ввода-вывода нужно многое охватить, но я думаю, что это выходит за рамки того, о чем на самом деле спрашивал ОП.

Elliott 09.04.2022 06:16

Одна вещь, которая мне не нравится в этом решении, заключается в том, что если пользователь вводит, например, «сумма 5» в одной строке, эта программа не сразу отклонит ввод, а вместо этого попытается прочитать ввод после конца строки. , ожидая очередной строки ввода от пользователя. Вот почему в моем решении вместо этого используются scanf и fgets, так что читается только одна строка ввода. Однако это означает, что для моего решения требуется больше кода. Поскольку OP не запрашивал проверку ввода в вопросе, ваш ответ, вероятно, является самым простым решением вопроса. Поэтому я проголосовал за это.

Andreas Wenzel 09.04.2022 07:09

Другие вопросы по теме