Вход
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().
Я настоятельно рекомендую вводить построчно (getline
уже есть во всех разумных библиотеках C; если нет, это парная оболочка для fgets
), затем, возможно, использовать sscanf
или strtok_r
или что-то еще для разбора внутри строки.
Я немного смущен формулировкой вопроса. Взгляните на модификации и скажите, исправили ли они вашу проблему или сделали ее более ясной. Если вы хотите прочитать, что вычисляет 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
. Этот ответ не решает проблему.
При работе с построчным пользовательским вводом имеет смысл всегда читать по одной строке за раз. Это не то, что делает функция 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 КБ для входного буфера — неплохой выбор. Хороший ответ.
@DavidC.Rankin: Да, вы правы, лучше использовать const
в параметрах функции. Спасибо, что указали на это. Я отредактировал свой ответ соответственно. Что касается размера входного буфера, я согласен, что обычно лучше использовать больший входной буфер. Однако в этом случае, на мой взгляд, нет большого смысла иметь больший буфер, потому что у меня нет впечатления, что OP когда-либо понадобится для этой программы. Кроме того, при вводе команды «сумма» представляемый диапазон int
будет превышен задолго до того, как размер входного буфера станет проблемой.
Вы можете сканировать целочисленные входы отдельно после того, как установили, что они вам нужны (в блоке 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, спасибо за отзыв. Для правильной обработки ввода-вывода нужно многое охватить, но я думаю, что это выходит за рамки того, о чем на самом деле спрашивал ОП.
Одна вещь, которая мне не нравится в этом решении, заключается в том, что если пользователь вводит, например, «сумма 5» в одной строке, эта программа не сразу отклонит ввод, а вместо этого попытается прочитать ввод после конца строки. , ожидая очередной строки ввода от пользователя. Вот почему в моем решении вместо этого используются scanf
и fgets
, так что читается только одна строка ввода. Однако это означает, что для моего решения требуется больше кода. Поскольку OP не запрашивал проверку ввода в вопросе, ваш ответ, вероятно, является самым простым решением вопроса. Поэтому я проголосовал за это.
Разве вы не можете просто дать им варианты выбора и получить выбор? Затем, используя case case, вы можете вызвать нужную функцию.