2015-12-16 4 views
2

Программа позволяет ввести в математике вопрос, такие как:Как создать гибкие выражения заполнителя (% d% s% d) в c?

Bob has 1 apple and Mike 2. What is the 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); 
} 
+4

'fflush (stdin);' invokes * undefined behavior *. Не используйте его. – MikeCAT

+0

Не уверен, что 'sscanf' - это путь сюда. –

+2

@MikeCAT im в настоящее время в школе. Учитель сказал мне использовать его. Не стесняйтесь показать мне альтернативу: ( – Asperger

ответ

0

Что-то вроде "%*[^0-9]%d%*[^0-9]%d" может работать, но это довольно ненадежное использование sscanf().

Спецификатор формата в основном означает «пропустить, пока вы не увидите цифру, не преобразуйте одно десятичное число, а затем пропустите до следующей цифры и, наконец, преобразуйте другое десятичное число». Это, конечно, предполагает, что вход не начинается с первого числа и т. Д.

Вы должны проверить возвращаемое значение sscanf(), прежде чем полагаться на переменные, имеющие значения.

+0

Я могу использовать регулярные выражения в c? Я никогда не знал – Asperger

+0

Я имею в виду, я думал, что регулярное выражение не работает в c – Asperger

+2

@Asperger Код, который я показал, не является регулярным выражением, он является стандартным спецификатором формата для 'sscanf()', используя '% []' и '% d' спецификаторы преобразования. – unwind

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

Обратите внимание, что вам нужно будет добавить гораздо больше контроля ошибок для приличной надежности, но приведенный выше код должен помочь проиллюстрировать, как Teh проблема может быть решена.

Затем вы можете использовать что-то вроде Reverse Polish Notation, чтобы расширить функциональность вашего синтаксического анализа.

+0

похоже на ошибку в этой строке token = strtok (NULL, s); – Asperger

+0

@Asperger Yup, просто заметил это. Спасибо. –

+0

Что вы думаете о том, чтобы развязать решение «стиль регулярного выражения»? Каков недостаток обоих? – Asperger

Смежные вопросы