K& R答案书练习1.21

时间:2014-01-11 10:24:09

标签: c

以下是问题:

  

编写程序entab,用最少数量的制表符和空格替换空白字符串以实现相同的间距。使用与detab相同的制表位。如果一个标签或一个空白就足以达到一个制表位,应优先考虑?

我自己做了这个练习,这本书的答案有不同的解决方案。我不理解从输入流中读取选项卡时执行的数学公式。这是代码:

#include <stdio.h>
#define TABINC 8

main()
{
int c, nb, nt, pos;

nb = 0;
nt = 0;
for (pos = 1; (c =getchar()) != EOF; ++pos)
    if (c == ' '){
        if (pos % TABINC != 0)
            ++nb;
        else {
            nb = 0;
            ++nt;
        }
    }
    else {
        for ( ; nt > 0; --nt)
            putchar('\t');
        if (c == '\t')
            nb = 0;
        else
            for ( ; nb > 0; --nb)
                putchar(' ');
        putchar(c);
        if ( c == '\n')
            pos = 0;
        else if (c == '\t')
            pos = pos + (TABINC - (pos - 1) % TABINC) - 1;
    }
}

我不理解的部分如下:

else if (c == '\t')
    pos = pos + (TABINC - (pos - 1) % TABINC) - 1;

我可以通过visual studio中的调试看到,当输入流中出现选项卡时,此构造将pos带到下一个制表位。这是对的吗?

我真正不明白的是这个公式是如何运作的,或者他们是如何想出来的。这是编程中常见的公式吗?它有用吗?它有名字吗?

编辑:我确实理解模运算符的作用。对不起,我没有说明。

2 个答案:

答案 0 :(得分:1)

这个公式没有特定的名称 - 这是将数学从小学应用到日常问题的相对简单的方法。以下是正在发生的事情:'\t'字符使pos的位置从1到TABINC不等。

  • posTABINC的倍数时,您会全速跳过TABINC
  • pos低于TABINC的下一个倍数时,您会跳过一个,
  • 如果pos低于TABINC的下一个倍数,则跳过2,
  • 等等 - 当posx0 < x < TABINC时,在TABINC的下一个倍数下方,您跳转x

现在计算跳跃的问题减少到计算posTABINC的下一个倍数之间的差异。这可以通过计算posTABINC的除法余数,并从TABINC中减去该余数来完成。这是通过%运算符完成的。

由于pos是基于1的 * ,因此公式所做的第一件事是将其从零开始,以便计算余数。接下来,该公式计算余数,这是表示“最后TABINC停止之上的位置数”的数学方式。现在您只需从TABINC中减去剩余部分即可获得结果。

* 关于发现pos=0的作业'\n'似乎与pos基于一个的断言相矛盾。但是,循环标头在每次迭代后执行pos++,因此循环的下一次迭代在下一次迭代时会看到pos=1

答案 1 :(得分:0)

它没有名字或类似的东西。
详细说明:

首先,必须增加多少pos取决于pos%TABINC,
即。 TABINC是8,所以如果pos是8的倍数,则加8,
如果pos%8为1(如9,17 ......)则添加7,
如果pos%8为2(10,18 ...)则加6等等
完整清单:
pos%8 - &gt;要添加的数字
0 - &gt; 8
1 - &gt; 7
2 - &gt; 6
3 - &gt; 5
4 - &gt; 4
5 - &gt; 3
6 - &gt; 2
7 - &gt; 1

那将是8 - pos%8或更普遍TABINC - pos%TABINC

重要提示:C中的负数模数在数学上是不正确的 在C中,a,b >= 0(-a)%b == -(a%b)

代码中添加的内容是(TABINC - (pos - 1) % TABINC) - 1
通过一些基本的数学和上面的事实,这是
(TABINC - (pos - 1) % TABINC) - 1
= TABINC - ((pos - 1) % TABINC)) - 1
= TABINC - ((pos % TABINC) - 1) - 1
= TABINC + 1 - (pos % TABINC) - 1
= TABINC - (pos % TABINC)
这与我上面的简短公式相同,只是更加复杂无用。