如何在c中创建灵活的占位符表达式(%d%s%d)?

时间:2015-12-16 13:25:17

标签: c

该程序可让您输入数学问题,例如:

Bob has 1 apple and Mike 2. What is the sum?

程序然后理解单词“sum”并将两个数字加在一起。至少这是我想要实现的目标。它不起作用,因为我得到非常大的数字。我怀疑表达式%d%s%d不够灵活,只有在问题为:

时才有效
1 sum 2

订单似乎很重要。那么如何使其灵活,以便订单无关紧要?

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

int main() {
   char question[100];
   char buffer[100];
   int result;
   int n1, n2;
   int operation;

   printf ("Your mathematical question: ");

   fgets(question, sizeof(question), stdin);
   fflush(stdin);

   if(strstr(question, "sum") || strstr(question, "add")){
        operation = 0;
   }

   sscanf(question, "%d %s %d", &n1, buffer, &n2);

   printf ("%d %d \n", n1, n2);

    switch(operation) {
        case 0: result = n1 + n2;
        break;
    }

   printf ("%d", result);
   return(0);
}

2 个答案:

答案 0 :(得分:2)

尝试使用strtok将输入字符串拆分为运算符和操作数列表。问题是,当表达数学短语时,诸如英语之类的自然语言没有正式的操作符和操作数顺序,而你的程序需要这样。

将输入拆分为运算符和操作数允许您按所需顺序匹配它们。

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

typedef enum
{
    NO_OP,
    ADDITION,
    /* Add new operators here. */
}   operator_t;

/* One operator plus two operands. */
#define NUMBER_OF_ITEMS 3

int main()
{
    char question[100];
    char buffer[100];
    char *token;

    int result = 0;
    /* Extend this to allow more complex sentences with multiple operations. */
    int operands[2];
    int* nextOperand = &operands[0];
    int itemCount = 0;
    /* Turn this into an array to extend the parser. */
    operator_t operator = NO_OP;

    printf ("Your mathematical question: \r\n");

    fgets(question, sizeof(question), stdin);

    /* Tokens are seperated by SPACES in this example. */
    const char delims[] = " ";

    /* Get the first token. */
    token = strtok(question, delims);

    /* Walk through all tokens in the question string. */
    while((token != NULL)&&(NUMBER_OF_ITEMS > itemCount)) 
    {
        /* use strcmp to avoid matches on words like 'summertime'. */
        if((0 == strcmp(token, "sum")) || (0 == strcmp(token, "add")))
        {
            operator = ADDITION;
            itemCount++;
        }
        else
        {
            /* Check that one integer can be parsed from the token. */
            if(1 == sscanf(token, "%d", nextOperand))
            {
                nextOperand++;
                itemCount++;
            }
        }

        /* Find the next token. */
        token = strtok(NULL, delims);
    }

    /* Perform the operation, if possible. */
    if((NUMBER_OF_ITEMS == itemCount) && (NO_OP != operator))
    {
        switch(operator)
        {
            case ADDITION:
                result = operands[0] + operands[1];
                printf("The answer to your question (%d + %d) is %d.\r\n",
                    operands[0], operands[1], result);
                break;
            default:
                printf("Oops, please ask my programmer to do some debugging.");
                break;
        }

    }
    else
    {
        printf ("I did not understand your question.\r\n");    
    }
}

请注意,您需要添加更多错误检查以获得良好的健壮性,但上面的代码应该有助于说明如何解决问题。

然后,您可以使用类似Reverse Polish Notation的内容来扩展解析器的功能。

答案 1 :(得分:0)

"%*[^0-9]%d%*[^0-9]%d"之类的内容可能会有效,但这可能会使用sscanf()

格式说明符基本上是指“跳过,直到看到一个数字,转换一个十进制数,然后跳到下一个数字,最后转换另一个十进制数”。这当然假设输入不是以第一个数字开头,依此类推。

在依赖具有值的变量之前,您应该检查sscanf()的返回值。