c - 解析数学表达式字符串

标签 c string

所以这是我的问题,我必须创建一个程序来实现 shunting yard algorithm在 C 中。 为此,我首先需要将给定的数学表达式解析为它的组成部分。所以我认为对给定字符串进行简单的 for 循环就可以解决问题。

char *math_exp = "2 + 4";
for (int i = 0; (unsigned) i < strlen(math_expr); i++) {
    printf("%c", math_expr[i]);
}

> 2 + 4

但是当字符串包含的数字位数多于 1 时,这很快就会遇到问题。

for (int i = 0; (unsigned) i < strlen(math_expr); i++) {
    // skip if char is a space
    if ((int) math_expr[i] == 32) {
        continue;
    }
    printf("%c ", math_expr[i]);
}
> 2 2 + 4

22 现在被视为两个单独的数字。因此,我尝试通过使用分隔符 SPACE 拆分字符串来遍历字符串中的所有标记。

char math_expr[] = "22 + 4";
char *token = strtok(math_expr, " ");

while (token != NULL) {
    printf("%s ", token);
    token = strtok(NULL, " ");
}
> 22 + 4

这似乎可行,但很快就遇到了当表达式中有括号时该怎么做的问题。例如:

char math_expr[] = "(22 + 2)";
char *token = strtok(math_expr, " ");

while (token != NULL) {
    printf("%s\n", token);
    token = strtok(NULL, " ");
}
> (22
> +
> 2)

现在我卡住了,有没有办法绕过这个问题?我需要能够提取每个运算符和数字(包括所有可能的数字),此外我还需要能够区分括号和它们所附加的数字。我希望有一些简单的方法可以做到这一点。感谢任何帮助。

最佳答案

Tokenization是句法分析的第一步。因此,将它封装到一个抽象层中可能是个好主意,一个一次产生一个标记的函数。此函数还丢弃空格并将连续的数字组合成数字。很难将这些步骤委托(delegate)给 strtok()。最后,该函数可能会将单个字符重新包装成更结构化的信息。

#include <ctype.h>
#include <stdio.h>

#define T_NUMBER 0
#define T_OPERATOR 1
#define T_BRACKET 2

typedef struct {
  int type;
  int value;
} token;

/* Reads the next token from stdin. Returns 1 on success, 0 on EOL. */
int next_token(token *t) {
  char c;

  /* discard spaces silently */
  do {
    c = getchar();
  } while (c == ' ');

  if (isdigit(c)) {
    t->type = T_NUMBER;
    t->value = 0;
    do {
      t->value = t->value * 10 + (c - '0');
      c = getchar();
    } while (isdigit(c));
    ungetc(c, stdin); /* save the non-digit for next time */

  } else if (c == '+' || c == '-' || c == '*' || c == '/') {
    t->type = T_OPERATOR;
    t->value = c;

  } else if (c == '(' || c == ')') {
    t->type = T_BRACKET;
    t->value = c;

  } else if (c == '\n') {
    ungetc(c, stdin); /* make sure we always return 0 from now on */
    return 0;

  } else {
    /* handle illegal character */

  }

  return 1;
}

int main() {

  token t;

  while (next_token(&t)) {
    switch (t.type) {
      case T_NUMBER:   printf("number   %d\n", t.value); break;
      case T_OPERATOR: printf("operator %c\n", t.value); break;
      case T_BRACKET:  printf("bracket  %c\n", t.value); break;
    }
  }

  return 0;
}

样本运行:

(22+   37 * ( 1534-9)) + 18
bracket  (
number   22
operator +
number   37
operator *
bracket  (
number   1534
operator -
number   9
bracket  )
bracket  )
operator +
number   18

关于c - 解析数学表达式字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54544125/

相关文章:

c# - 修改 C# 中的 "G"字符串格式化程序以在数字包含至少两个零 d.p 时使用指数

c - 如何用C语言实现 ' continuous call'语法糖?

c - 字符到整数转换的巧妙之处

c - 同时修改数组的所有元素

java - 在 Java 中使用长字符串(heredocs)——可读的方法?

python-3.x - 在Python中将特定的中文标点符号替换为相应的英文标点符号

c++ - 我的程序在不同的机器上给出不同的输出..!

C++ Windows 移除最大化框

在 C 程序中创建数据危险

javascript - 创建字符频率列表