【问题标题】:C - Recursion instead of loopsC - 递归而不是循环
【发布时间】:2021-03-20 05:22:57
【问题描述】:

我做了一个评估表达式的程序,例如

Enter text: 97+74/51-98-11+68-34-2-22+73/40+81/15+100

输出:

105.36

如果提供任何错误数据,用户会收到回复Incorrect input

我想知道是否可以将所有 for 循环替换为递归,但我不知道如何实现。有人可以帮忙吗?

任何帮助将不胜感激。

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

int my_atoi(const char* tab, int from, int to)
{
    int score = 0;
    int minus = 0;
    for (int i = from; i <= to; i++)
    {
        if (*(tab + i) == 10)
            break;

        if (*(tab + i) == 32)
            break;

        if (*(tab + i) == '-' && from == i)
        {
            minus = 1;
            continue;
        }
        if (*(tab + i) == '+' && i == from)
        {
            continue;
        }
        if (*(tab + i) > '9' || *(tab + i) < '0')
            break;
        else if (*(tab + i) >= '0' && *(tab + i) <= '9')
        {
            score *= 10;
            score += (*(tab + i) - '0');

        }
    }
    if (minus == 1)
        score *= -1;
    return score;
}
int validate_expression(const char* expr)
{
    if (!expr)return -1;
    int lng = strlen(expr) - 1;
    if (*(expr) > '9' || *(expr) < '0' ||  * (expr + lng) > '9' || *(expr + lng) < '0')return 0;

    int flaga = 0; // flag
    for (int i = 1; i < lng; i++) {
        if (*(expr + i) <= '9' && *(expr + i) >= '0')
        {
            flaga = 0;
        }
        else if (*(expr + i) == '/' || *(expr + i) == '*' || *(expr + i) == '-' || *(expr + i) == '+')
        {
            if (flaga == 1)
                return 0;
            flaga = 1;
        }
        else
            return 0;
    }
    return 1;
}
int calculate(const char* expr, float* result)
{
    if (!expr || !result || !validate_expression(expr)) return 0;
    if (strpbrk(expr, "i") != NULL) return 0;

    int index = 0;
    float score = 0;
    char sign_memory = 'A';
    int flaga = 0;
    unsigned int i = 1;

    for (; i <= strlen(expr); i++) {
        if (*(expr + i) == '-' || *(expr + i) == '+' || *(expr + i) == '/' || *(expr + i) == '*' || *(expr + i) == '\0') {
            score += (int)my_atoi(expr, index, i - 1);
            index = i;
            break;
        }
    }
    for (; i <= strlen(expr); i++) {
        if (*(expr + i) == '-' || *(expr + i) == '+' || *(expr + i) == '/' || *(expr + i) == '*' || i == strlen(expr)) {
            flaga = 1;
            if (sign_memory == '+')
                score += (int)my_atoi(expr, index, i - 1);
            else if (sign_memory == '-')
                score -= (int)my_atoi(expr, index, i - 1);
            else if (sign_memory == '/')
            {
                if (my_atoi(expr, index, i - 1) == 0)return 0;
                score /= (int)my_atoi(expr, index, i - 1);
            }
            else if (sign_memory == '*')
                score *= (int)my_atoi(expr, index, i - 1);
            sign_memory = *(expr + i);
        }
        else if (*(expr + i) <= '9' && *(expr + i) >= '0' && flaga == 1) {
            flaga = 0;
            index = i;
        }
    }
    *result = score;
    return 1;
}
int main()
{
    char tab[201];
    float result, * pointer = &result;

    printf("Enter text: ");
    fgets(tab, sizeof(tab), stdin);

    *(tab + strlen(tab) - 1) = '\0';
    if (!validate_expression(tab))
    {
        printf("Incorrect input");
        return 1;
    }
    else
    {
        if (calculate(tab, pointer))
            printf("%.2f", *pointer);
        else {
            printf("Incorrect input");
            return 1;
        }
    }
    return 0;
}

【问题讨论】:

  • if (tab[i] == '\n') 替换if (*(tab + i) == 10) 会更清楚。使用下标是明智的;使用*(ptr + idx) 不是;换行使用'\n',空格使用' '比使用10和32更明智。还要考虑&lt;ctype.h&gt;isdigit()等的优点。
  • 你可能可以使用递归;我不相信这会使代码受益。你支持括号吗?你应该吗?
  • 我需要使用指针,我现在需要使用递归,我已经尝试过实现它,但对我来说很难。从一开始就应该知道使用它..
  • for (; i &lt;= strlen(expr); i++) {
  • 指针符号将归结为教师对“使用指针”的定义——使用ptr[idx] 是使用指针(其中一个术语必须是订阅才能使用的指针),但是它使用指针比使用*(ptr + idx) 更具可读性。至于递归,您需要决定递归的内容。例如,如果您支持括号,则可能有代码在遇到左括号(左括号,又名()时对表达式进行递归,并在遇到平衡的右括号(又名))时停止递归。如果遇到另一个(,请递归。

标签: c loops recursion


【解决方案1】:

我会创建一个函数,它执行以下操作:

  • 检查是否只有一个或多个运算符(“+”、“-”、“*”、“/”)
  • 如果只有一个,请执行计算。
  • 如果有两个,按照Jonathan 的建议执行尾递归,类似于:
calculate("97+74/51-98-11+68-34-2-22+73/40+81/15+100")
 = calculate("97+74/51-98-11+68-34-2-22+73/40+81/15") + 100
 = (calculate("97+74/51-98-11+68-34-2-22+73/40+81") / 15) + 100
 = ((calculate("97+74/51-98-11+68-34-2-22+73/40") + 81) / 15) + 100
 = (((calculate("97+74/51-98-11+68-34-2-22+73") / 40) + 81) / 15) + 100
 = ((((calculate("97+74/51-98-11+68-34-2-22") + 73) / 40) + 81) / 15) + 100
 = (((((calculate("97+74/51-98-11+68-34-2") - 22) + 73) / 40) + 81) / 15) + 100
 = ((((((calculate("97+74/51-98-11+68-34") - 2) - 22) + 73) / 40) + 81) / 15) + 100
 = (((((((calculate("97+74/51-98-11+68") - 34) - 2) - 22) + 73) / 40) + 81) / 15) + 100
 = ((((((((calculate("97+74/51-98-11") + 68) - 34) - 2) - 22) + 73) / 40) + 81) / 15) + 100
 = (((((((((calculate("97+74/51-98") - 11) + 68) - 34) - 2) - 22) + 73) / 40) + 81) / 15) + 100
 = ((((((((((calculate("97+74/51") - 98) - 11) + 68) - 34) - 2) - 22) + 73) / 40) + 81) / 15) + 100
 = (((((((((((calculate("97+74") / 51) - 98) - 11) + 68) - 34) - 2) - 22) + 73) / 40) + 81) / 15) + 100
 = ((((((((((((97 + 74) / 51) - 98) - 11) + 68) - 34) - 2) - 22) + 73) / 40) + 81) / 15) + 100

【讨论】:

  • 如果表达式未知怎么办?
  • @Simonsoft177:未知表达式是什么意思?
  • U 向我展示了函数 calculate("97+......") 但如果我得到另一个表达式怎么办,例如 2+2 或 4/2
猜你喜欢
  • 2010-09-17
  • 2018-11-25
  • 1970-01-01
  • 1970-01-01
  • 2011-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多