使用有限的工具、没有数组和库函数评估简单的数学表达式

Dav*_*lic 4 c getchar

这是我大学去年第一次“编程入门”考试中的一个问题:

使用该getchar()函数读取由数字、+ 和 - 符号组成的输入序列。输出应该是那些算术运算的结果。

例如,如果输入是10+13-12+25-5+100,则输出应该是131

现在,鉴于我在参加大学之前有一点 C 经验,使用指针、数组等似乎很容易解决这个问题。

但这里有一个问题:在考试中,你只能使用学生目前学到的东西。鉴于此考试仅在学年开始后一个月,您的选择相当有限。

您只能使用变量、基本输入/输出内容、运算符(逻辑和按位)、条件语句和循环、函数

这意味着不:数组、字符串、指针、递归、结构或任何其他使这变得容易的东西。

我他妈的怎么做?今天是我第二次花了 3 个小时试图解决这个问题。我已经成功解决了它,但只有在“作弊”并使用数组、字符串函数 ( strtol) 和指针之后。知道如何通过规则解决它对我来说很重要,因为我将在即将到来的考试中遇到类似的问题。

编辑:到目前为止,我的尝试都是将 while 循环与getchar()for 输入结合使用,之后我就卡住了。如果不使用更多“工具”,我对我应该做什么没有丝毫的想法。

Mar*_*lli 5

解决方案非常简单,但对于初学者来说可能并不明显。我不会提供一个完整的程序,而是仅用几个变量来概述实现它所需的步骤。

首先,重要的是要注意两件事:

  1. 您的输入只能包含其中之一-+或任何数字 ( 0123456789)。
  2. getchar()函数将一次读取输入的一个字符,并EOF在输入结束或发生错误时返回。

现在,进入解决方案:

  1. 首先循环读取一个字符。只有在输入结束或发生错误时才会停止:

    int c;
    
    while ((c = getchar()) != EOF) {
        // logic here
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 从设置为 的累加器开始0,并在每次遇到数字时向其“添加”数字。

    // outside the loop
    int acc = 0;
    
    // inside the loop
    if (/* c is a digit */)
            acc = acc * 10 + (c = '0');
    
    Run Code Online (Sandbox Code Playgroud)

    提示:这个/* c is a digit */条件可能并不简单,你可以把它放在else检查-和的 中+

  3. 每次遇到-or +,记住操作,每次遇到操作符,先执行上一个操作,重置累加器。

    // outside the loop
    int op = 0;
    int result = 0;
    
    // inside the loop
    if (c == '+' || c == '-') {
        if (op) {
            // there already is a previous operation to complete, do it
            if (op == '+')
                result += acc;
            else
                result -= acc;
        } else {
            // first operation encountered, don't do anything yet
            result = acc;
        }
    
        acc = 0; // reset
        op = c; // remember the current operation for the future
    }
    
    Run Code Online (Sandbox Code Playgroud)
  4. 当您到达输入的末尾(即退出循环)时,执行最后一个操作(与第if3 点中的逻辑相同)。

  5. 输出结果:

    你通常会写这样的东西:

    printf("%d\n", result);
    
    Run Code Online (Sandbox Code Playgroud)

    但是,如果您不能使用字符串文字 ( "%d\n") 或printf()函数,则必须使用putchar(). 这基本上与我们之前将数字扫描到累加器中所做的相反。

    1. 如果需要,首先打印符号,并将值设为正值:

      if (result < 0) {
          putchar('-');
          result = -result;
      }
      
      Run Code Online (Sandbox Code Playgroud)
    2. 找出小于您的数字的 10 的最大幂:

      int div = 1;
      
      while (result / div / 10)
          div *= 10;        
      
      Run Code Online (Sandbox Code Playgroud)
    3. 使用幂以除法和除以 10 的模数提取和打印每个数字:

      while (div) {
          putchar('0' + ((result / div) % 10));
          div /= 10;
      }
      
      Run Code Online (Sandbox Code Playgroud)

      注意:'0' +开头的用于将数字(从 0 到 10)转换为相关的 ASCII 字符。

    4. 以换行符结束:

      putchar('\n');
      
      Run Code Online (Sandbox Code Playgroud)