问题是:
Write the program entab that replaces strings of blanks by the minimum number of tabs and blanks to achieve the same spacing. Use the same tab stops as for detab. When either a tab or a single blank would suffice to reach a tab stop, which should be given preference?
我自己做的,书上的答案有不同的解法。我不理解从输入流中读取选项卡时执行的数学公式。这是代码:
#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 带到下一个制表位。这是正确的吗?
我真正不明白的是这个公式是如何运作的,或者他们是如何想出这个公式的。这是编程中出现的常见公式吗?有用吗?它有名字吗?
编辑:我确实理解模运算符的作用。抱歉,我没有具体说明。
最佳答案
此公式没有具体名称 - 它是将小学数学应用到日常问题的一种相对简单的方法。这是发生了什么:'\t'
字符推进 pos
从 1 到 TABINC
的多个位置, 包括在内。
- 何时
pos
是TABINC
的倍数,你跳完整TABINC
- 何时
pos
是TABINC
的下一个倍数以下的一个,你跳了一个, - 何时
pos
比TABINC
的下一个倍数小二,你跳了两个, - 等等 - 当
pos
是x
, 其中0 < x < TABINC
, 低于TABINC
的下一个倍数,你跳x
现在计算跳跃的问题被简化为计算pos
之间的差值。和下一个 TABINC
的倍数.这可以通过计算 pos
的除法余数来完成。和 TABINC
,并从 TABINC
中减去余数.这是通过 %
完成的运营商。
自 pos
是从一开始的 *,公式做的第一件事是使它从零开始,以便计算余数。接下来,该公式计算余数,这是表示“最后一个 TABINC
止损上方的持仓数”的数学方式。现在你需要做的就是从 TABINC
中减去余数。得到你的结果。
* 赋值 pos=0
关于发现'\n'
似乎与 pos
的断言相矛盾是基于一个的。但是,循环 header 执行 pos++
每次迭代后,循环的下一次迭代会看到 pos=1
在下一次迭代中。
关于c - K&R答题簿练习1.21,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21061127/