以下是问题:
编写程序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带到下一个制表位。这是对的吗?
我真正不明白的是这个公式是如何运作的,或者他们是如何想出来的。这是编程中常见的公式吗?它有用吗?它有名字吗?
编辑:我确实理解模运算符的作用。对不起,我没有说明。
答案 0 :(得分:1)
这个公式没有特定的名称 - 这是将数学从小学应用到日常问题的相对简单的方法。以下是正在发生的事情:'\t'
字符使pos
的位置从1到TABINC
不等。
pos
是TABINC
的倍数时,您会全速跳过TABINC
pos
低于TABINC
的下一个倍数时,您会跳过一个,pos
低于TABINC
的下一个倍数,则跳过2,pos
为x
,0 < x < TABINC
时,在TABINC
的下一个倍数下方,您跳转x
现在计算跳跃的问题减少到计算pos
和TABINC
的下一个倍数之间的差异。这可以通过计算pos
和TABINC
的除法余数,并从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)
这与我上面的简短公式相同,只是更加复杂无用。