【问题标题】:Why do I receive an unexpected result when result is calculated in switch statement? [closed]为什么在 switch 语句中计算结果时会收到意外结果? [关闭]
【发布时间】:2021-05-10 22:15:59
【问题描述】:

首先,我想做一个简单的计算器程序。
我输入公式为2-3*4。此外,该代码是按照运算符之间的优先顺序排列的。 如果我提到意外的结果,根据等式在result=(usertxt[i] * usertxt[i + 2]); printf("%d\n", result); usertext[i]=3, usertext[4],那么我在这段代码中从result 得到2652。当我期望 12 来自 result 时,我该如何纠正这个问题?提前致谢。

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

unsigned int i;

int main() {
    char a[100] = { 0, }, usertxt[100] = { 0, };
    a[99] = 0;
    int result = 0;
    int myoperator = 0;
    int num;
    printf("Please, enter your calculation\n");
    gets_s(a,sizeof(a));
    printf("You entered: %s\n", a);
    num = strlen(a);
    printf("Number of characters: %d\n", num);

    for (int i = 0; i < num; i++) {
        usertxt[i + 1] = a[i];
        printf("%c", usertxt[i + 1]);
    }

    for (int i = 0; i < num; i++) {
        if (usertxt[i + 1] == '*' || usertxt[i + 1] == '/') {
            myoperator = usertxt[i + 1];
        }
        {
            switch (myoperator) {
              case '*':
                printf("Multiplication operation\n");
                printf("%c%c", usertxt[i], usertxt[i + 2]);
                result = 0;
                result = (usertxt[i] * usertxt[i + 2]);
                printf("%d\n", result);
                break;
              case '/':
                printf("Division operation\n");
                result = usertxt[i] / usertxt[i + 2];
                printf("Result=%d\n", result);
                break;
            }
        }
    }
    int i = 0;
    for (int i = 0; i < num; i++) {
        if (usertxt[i + 1] == '+' || usertxt[i + 1] == '-') {
            myoperator = usertxt[i + 1];
        }
        {
            switch (myoperator) {
              case '+':
                printf("Addition operation\n");
                result = usertxt[i] + usertxt[i + 2];
                printf("Result=%d\n", result);
                break;
              case '-':
                printf("Subtraction operation\n");
                result = usertxt[i] - usertxt[i + 2];
                printf("Result=%d\n", result);
                break;
              default:
                printf("Please, try again.\n");
                break;
            }
        }
    }
    return 0;
}

【问题讨论】:

  • 这可以编译吗? gets_s(a) 缺少 sizeInCharacters 参数。另外请不要使用不可移植和不可读的硬编码,例如 case 42:case '*':
  • '我该如何解决这个问题?' ........您是否考虑过调试您的应用程序?
  • 当然。马丁詹姆斯
  • 风向标,我可以编译它,但我说的结果是意外的。代码变得更加不稳定。可以再看一遍吗?
  • if (usertxt[i + 1] &gt; 41) {

标签: c algorithm


【解决方案1】:

请注意,字符 '3' 在 ascii 中是 51,'4' 是 52,并且 51 * 54 == 2652。您将 ascii 值相乘,而不是数字 3 和 4。您会看到将调试打印语句更改为使用 %d 而不是 %c

【讨论】:

  • 您能否提供更明显的信息,关于“%d 而不是 %c”应该更改哪些行?
  • printf("%c%c", usertxt[i], usertxt[i + 2]); 是您为了调试目的而放入的特定的。总的来说,如果你想看看你正在使用的操作符应该用%c打印,数字值用%d
【解决方案2】:

你的实现有问题:

  • 您应该首先将字符串转换为一个值数组和一个单独的运算符数组。字符串中的数字是字符:它们的数值是通过从 char 值中减去 '0' 的代码获得的。
  • 然后您将在多个通道中处理运算符,每个优先级一个,假设从左到右关联。您这样做,但是当您处理一个运算符时,您应该将所有值和运算符移到它的右边,以从数组中删除第二个参数。
  • 最终值位于 int 数组的索引 0 处。

这是修改后的版本:

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

int main() {
    char expr[100];
    int values[50];
    char operators[50];
    char *p;
    int i, j, n, result;

    printf("Please, enter your calculation\n");
    if (!fgets(expr, sizeof expr, stdin)) {
        printf("Missing input\n");
        return 1;
    }
    // analyse the expression
    for (p = expr, n = 0;;) {
        if (*p >= '0' && *p <= '9') {
            //values[n] = strtol(p, 0, &p);
            values[n] = *p - '0';
            p++;
        } else {
            printf("Missing operand\n");
            return 1;
        }
        if (*p == '\n') {
            // strip the trailing newline
            *p = '\0';
        }
        if (*p == '\0') {
            // end of the expression
            // there are n operators and n+1 operands
            break;
        }
        if (!strchr("+-*/", *p)) {
            printf("Invalid operator: %c\n", *p);
            return 1;
        }
        operators[n] = *p;
        p++;
        n++;
    }
    printf("You entered: %s\n", expr);
    /* handle multiplicative operators */
    for (i = 0; i < n;) {
        switch (operators[i]) {
          case '*':
            printf("Multiplication operation\n");
            result = values[i] * values[i + 1];
            break;
          case '/':
            printf("Division operation\n");
            result = values[i] / values[i + 1];
            break;
          case '%':
            printf("Modulo operation\n");
            result = values[i] % values[i + 1];
            break;
          default:
            i++;
            continue;  // skip other operators
        }
        printf("%d %c %d = %d\n", values[i], operators[i], values[i + 1], result);
        values[i] = result;
        // shift remaining operators and operands
        for (j = i + 1; j < n; j++) {
            operators[j - 1] = operators[j];
            values[j] = values[j + 1];
        }
        n--;
    }
    /* handle additive operators */
    for (i = 0; i < n;) {
        switch (operators[i]) {
          case '+':
            printf("Addition operation\n");
            result = values[i] + values[i + 1];
            break;
          case '-':
            printf("Subtraction operation\n");
            result = values[i] - values[i + 1];
            break;
          default:
            i++;
            continue;  // skip other operators
        }
        printf("%d %c %d = %d\n", values[i], operators[i], values[i + 1], result);
        values[i] = result;
        // shift remaining operators and operands
        for (j = i + 1; j < n; j++) {
            operators[j - 1] = operators[j];
            values[j] = values[j + 1];
        }
        n--;
    }
    printf("Result: %d\n", values[0]);
    return 0;
}

示例会话:

请输入您的计算 1+2*4-6/5 您输入:1+2*4-6/5 乘法运算 2 * 4 = 8 分工操作 6 / 5 = 1 加法运算 1 + 8 = 9 减法运算 9 - 1 = 8 结果:8

尝试按照以下思路扩展代码:

  • 如注释所示,使用strtol() 泛化为任意整数。
  • 跳过分析循环中的空格以接受1 + 2*6 - 10
  • 处理位运算符&amp;|^
  • strtod() 实现double 算术

这种迭代方法对于简单的表达式是可以的,但是更精细的解析(递归下降、树转换、有限状态机)建议支持:

  • 一元运算符:-1-2*3-2*-3...
  • 括号
  • 变量
  • 函数调用
  • 作业

【讨论】: