如何从 C 中的用户输入中检索三个变量
How can I retrieve three variables from a user input in C
我需要为学校制作一个小型计算器,使用以下模板:"operation(operator1, operator2)"
。例如:"Add(1, 2)"
将 return 3
,"Multiply(2, 5)"
将 return 10
。我知道我可以使用 strtok
来检索操作,但我不确定如何检索运算符。目前我有以下内容:
#include <stdio.h>
int main()
{
char Math_Input[32]; //This is where I will store the input in the following template: operation("operator1, operator2")
float Operator_1, Operator_2;
printf("What calculation do you wish to do?: ");
fgets(Math_Input,20,stdin); //Here I retrieve the entire line and I'll store it in Math_Operation, next step is to retrieve the operation, operator1 and operator2
char * Math_Operation = strtok(Math_Input, "(");
printf("%s\n", Math_Operation);
}
更新:
在给出一些使用 sscanf() 的代码后,我将我的代码修改为以下内容:
#include <stdio.h>
int main()
{
char Math_Input[32]; //This is where I will store the input in the following template: operation("operator1, operator2")
char Math_operation[16];
float Operator_1, Operator_2;
printf("What calculation do you wish to do?: ");
fgets(Math_Input,20,stdin); //Here I retrieve the entire line and I'll store it in Math_Input, next step is to retrieve the operation, operator1 and operator2
if (3 != sscanf(Math_Input, "%15s (%f ,%f )", Math_operation, &Operator_1, &Operator_2)) {
fprintf(stderr, "Incorrect line >%s<\n", Math_Input);
printf("Operation: %s \n", Math_operation);
printf("Operator1: %d \n", Operator_1);
printf("Operator2: %d \n", Operator_2);
}
else {
// Ok process the operation...
printf("Else");
printf("Operation: %s \n", Math_operation);
printf("Operator1: %d \n", Operator_1);
printf("Operator2: %d \n", Operator_2);
}
}
我用了一些 printf 来调试。这在理论上应该可行吗?但是当我这样测试它时:(所以这是我的控制台)它似乎不起作用...
What calculation do you wish to do?: Add(1, 2)
Incorrect line >Add(1, 2)
<
Operation: Add(1,
Operator1: 0
Operator2: 0
Process returned 0 (0x0) execution time : 3.698 s
Press any key to continue.
如果输入的格式应为 operation(value_1, value2)
,那么 sscanf
似乎是一个正确的用例。 scanf
家族被认为是一个穷人的解析器,因为它不支持错误恢复。但是在这里您已经从 fgets
获得了输入行,只需要简单的解析。所以我只会使用:
char Math_Input[32]; //This is where I will store the input in the following template: operation("operator1, operator2")
char Math_operation[16];
float Operator_1, Operator_2;
printf("What calculation do you wish to do?: ");
fgets(Math_Input,20,stdin); //Here I retrieve the entire line and I'll store it in Math_Operation, next step is to retrieve the operation, operator1 and operator2
if (3 != sscanf(Math_Input, "%15[^ (] (%f ,%f )", Math_operation, &Operator_1, &Operator_2)) {
fprintf(stderr, "Incorrect line >%s<\n", Math_input);
}
else {
// Ok process the operation...
}
...
sscanf
的好消息是它会忽略任何无意义的空白字符。
其他改进:确保 fgets
可以得到完整的一行(不超过 19 个字符),否则一直读到行尾,稍后需要循环
正如您在评论中所说:
the user will be typing in "Add(1,2)" or "Multiply(2,5)"
你可以做你正在做的事情,即标记字符串:
#include <stdio.h>
#include <string.h>
int main()
{
int data_field = 3;
char Math_Input[32];
char* Math_Operation = NULL;
// operation("operand1,operand2")
float operand_1, operand_2;
printf("What calculation do you wish to do?: ");
scanf("%31[^\n]%*c", Math_Input);
Math_Operation = strtok(Math_Input, "(");
while(data_field-- != 0)
{
printf("%s\n", Math_Operation);
if (data_field == 2)
{
Math_Operation = strtok(NULL, ",");
sscanf(Math_Operation, "%f", &operand_1);
}
if (data_field == 1)
{
Math_Operation = strtok(NULL, ")");
sscanf(Math_Operation, "%f", &operand_2);
}
}
return 0;
}
输出:
What calculation do you wish to do?: Add(2,1)
Add
2
1
P.S.: 您可以使用 sscanf()
.
存储操作数
在我看来,最好(也是最有效)的方法是编写一个简单的解析器,如下所示:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(void)
{
char input[32], function_name[32];
float function_args[2];
char *iterator, *bufptr, buffer[32];
/* we will use buffer to temporarily store float,
and bufptr to store tokens beginning */
printf("What calculation do you wish to do?: ");
fgets(input, 20, stdin);
/* On this step we have input, probably in format `name(val1, val2)`.
Now we are going to parse this: */
iterator = input; /* iterator will point to first character of an input */
bufptr = iterator; /* bufptr will now point to a beginning of a token */
while (*iterator != '(' && *iterator != '[=10=]')
++iterator;
/* Now iterator points to '(', or string ended because we got
NULL-terminator, so we will check for a terminator: */
if (*iterator == '[=10=]') { /* String ended */
fputs("Syntax error :(", stderr);
exit(1);
}
/* Copying function name to function_name variable.
We will copy amount of characters equal iterator - input,
because we added 1 to iterator, so iterator points to '(' now: */
strncpy(function_name, bufptr, iterator - bufptr);
/* Now, we are doing exacly the same thing, but now for ','.
You can surround this loops with a function: */
++iterator; /* iterator points to '(', so we will just add 1 */
bufptr = iterator;
while (*iterator != ',' && *iterator != '[=10=]') ++iterator;
if (*iterator == '[=10=]') { /* String ended */
fputs("Syntax error :(", stderr);
exit(1);
}
strncpy(buffer, bufptr, iterator - bufptr);
function_args[0] = strtof(buffer, NULL);
/* Now we can continue parsing, iterator now should point to a comma.
Doing same thing as upper, but now for ')' */
++iterator;
bufptr = iterator;
while (*iterator != ')' && *iterator != '[=10=]') ++iterator;
if (*iterator == '[=10=]') { /* String ended */
fputs("Syntax error :(", stderr);
exit(1);
}
strncpy(buffer, bufptr, iterator - bufptr);
function_args[1] = strtof(buffer, NULL);
while (*iterator != ')' && *iterator != '[=10=]') ++iterator;
if (*iterator == '[=10=]') { /* String ended */
fputs("Syntax error :(", stderr);
exit(1);
}
/* Printing */
printf("Function that you called: %s(%f, %f)\n",
function_name, function_args[0], function_args[1]);
/* And on this point you have all expected data, so you can call functions */
if (!strcmp(function_name, "Add")) {
Add(function_args[0], function_args[1]);
} else if (!strcmp(function_name, "Substract")) {
Substract(function_args[0], function_args[1]);
} else {
/* ... */
}
}
我需要为学校制作一个小型计算器,使用以下模板:"operation(operator1, operator2)"
。例如:"Add(1, 2)"
将 return 3
,"Multiply(2, 5)"
将 return 10
。我知道我可以使用 strtok
来检索操作,但我不确定如何检索运算符。目前我有以下内容:
#include <stdio.h>
int main()
{
char Math_Input[32]; //This is where I will store the input in the following template: operation("operator1, operator2")
float Operator_1, Operator_2;
printf("What calculation do you wish to do?: ");
fgets(Math_Input,20,stdin); //Here I retrieve the entire line and I'll store it in Math_Operation, next step is to retrieve the operation, operator1 and operator2
char * Math_Operation = strtok(Math_Input, "(");
printf("%s\n", Math_Operation);
}
更新:
在给出一些使用 sscanf() 的代码后,我将我的代码修改为以下内容:
#include <stdio.h>
int main()
{
char Math_Input[32]; //This is where I will store the input in the following template: operation("operator1, operator2")
char Math_operation[16];
float Operator_1, Operator_2;
printf("What calculation do you wish to do?: ");
fgets(Math_Input,20,stdin); //Here I retrieve the entire line and I'll store it in Math_Input, next step is to retrieve the operation, operator1 and operator2
if (3 != sscanf(Math_Input, "%15s (%f ,%f )", Math_operation, &Operator_1, &Operator_2)) {
fprintf(stderr, "Incorrect line >%s<\n", Math_Input);
printf("Operation: %s \n", Math_operation);
printf("Operator1: %d \n", Operator_1);
printf("Operator2: %d \n", Operator_2);
}
else {
// Ok process the operation...
printf("Else");
printf("Operation: %s \n", Math_operation);
printf("Operator1: %d \n", Operator_1);
printf("Operator2: %d \n", Operator_2);
}
}
我用了一些 printf 来调试。这在理论上应该可行吗?但是当我这样测试它时:(所以这是我的控制台)它似乎不起作用...
What calculation do you wish to do?: Add(1, 2)
Incorrect line >Add(1, 2)
<
Operation: Add(1,
Operator1: 0
Operator2: 0
Process returned 0 (0x0) execution time : 3.698 s
Press any key to continue.
如果输入的格式应为 operation(value_1, value2)
,那么 sscanf
似乎是一个正确的用例。 scanf
家族被认为是一个穷人的解析器,因为它不支持错误恢复。但是在这里您已经从 fgets
获得了输入行,只需要简单的解析。所以我只会使用:
char Math_Input[32]; //This is where I will store the input in the following template: operation("operator1, operator2")
char Math_operation[16];
float Operator_1, Operator_2;
printf("What calculation do you wish to do?: ");
fgets(Math_Input,20,stdin); //Here I retrieve the entire line and I'll store it in Math_Operation, next step is to retrieve the operation, operator1 and operator2
if (3 != sscanf(Math_Input, "%15[^ (] (%f ,%f )", Math_operation, &Operator_1, &Operator_2)) {
fprintf(stderr, "Incorrect line >%s<\n", Math_input);
}
else {
// Ok process the operation...
}
...
sscanf
的好消息是它会忽略任何无意义的空白字符。
其他改进:确保 fgets
可以得到完整的一行(不超过 19 个字符),否则一直读到行尾,稍后需要循环
正如您在评论中所说:
the user will be typing in "Add(1,2)" or "Multiply(2,5)"
你可以做你正在做的事情,即标记字符串:
#include <stdio.h>
#include <string.h>
int main()
{
int data_field = 3;
char Math_Input[32];
char* Math_Operation = NULL;
// operation("operand1,operand2")
float operand_1, operand_2;
printf("What calculation do you wish to do?: ");
scanf("%31[^\n]%*c", Math_Input);
Math_Operation = strtok(Math_Input, "(");
while(data_field-- != 0)
{
printf("%s\n", Math_Operation);
if (data_field == 2)
{
Math_Operation = strtok(NULL, ",");
sscanf(Math_Operation, "%f", &operand_1);
}
if (data_field == 1)
{
Math_Operation = strtok(NULL, ")");
sscanf(Math_Operation, "%f", &operand_2);
}
}
return 0;
}
输出:
What calculation do you wish to do?: Add(2,1)
Add
2
1
P.S.: 您可以使用 sscanf()
.
在我看来,最好(也是最有效)的方法是编写一个简单的解析器,如下所示:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(void)
{
char input[32], function_name[32];
float function_args[2];
char *iterator, *bufptr, buffer[32];
/* we will use buffer to temporarily store float,
and bufptr to store tokens beginning */
printf("What calculation do you wish to do?: ");
fgets(input, 20, stdin);
/* On this step we have input, probably in format `name(val1, val2)`.
Now we are going to parse this: */
iterator = input; /* iterator will point to first character of an input */
bufptr = iterator; /* bufptr will now point to a beginning of a token */
while (*iterator != '(' && *iterator != '[=10=]')
++iterator;
/* Now iterator points to '(', or string ended because we got
NULL-terminator, so we will check for a terminator: */
if (*iterator == '[=10=]') { /* String ended */
fputs("Syntax error :(", stderr);
exit(1);
}
/* Copying function name to function_name variable.
We will copy amount of characters equal iterator - input,
because we added 1 to iterator, so iterator points to '(' now: */
strncpy(function_name, bufptr, iterator - bufptr);
/* Now, we are doing exacly the same thing, but now for ','.
You can surround this loops with a function: */
++iterator; /* iterator points to '(', so we will just add 1 */
bufptr = iterator;
while (*iterator != ',' && *iterator != '[=10=]') ++iterator;
if (*iterator == '[=10=]') { /* String ended */
fputs("Syntax error :(", stderr);
exit(1);
}
strncpy(buffer, bufptr, iterator - bufptr);
function_args[0] = strtof(buffer, NULL);
/* Now we can continue parsing, iterator now should point to a comma.
Doing same thing as upper, but now for ')' */
++iterator;
bufptr = iterator;
while (*iterator != ')' && *iterator != '[=10=]') ++iterator;
if (*iterator == '[=10=]') { /* String ended */
fputs("Syntax error :(", stderr);
exit(1);
}
strncpy(buffer, bufptr, iterator - bufptr);
function_args[1] = strtof(buffer, NULL);
while (*iterator != ')' && *iterator != '[=10=]') ++iterator;
if (*iterator == '[=10=]') { /* String ended */
fputs("Syntax error :(", stderr);
exit(1);
}
/* Printing */
printf("Function that you called: %s(%f, %f)\n",
function_name, function_args[0], function_args[1]);
/* And on this point you have all expected data, so you can call functions */
if (!strcmp(function_name, "Add")) {
Add(function_args[0], function_args[1]);
} else if (!strcmp(function_name, "Substract")) {
Substract(function_args[0], function_args[1]);
} else {
/* ... */
}
}