Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C K&;R答案册练习1.21_C - Fatal编程技术网

C K&;R答案册练习1.21

C K&;R答案册练习1.21,c,C,问题是: 编写程序entab,用最少的制表符和空格数替换空格串,以达到相同的间距。使用与detab相同的制表位。当一个制表符或一个空格足以到达制表位时,应优先选择哪一个 我自己做了这个练习,这本书的答案有一个不同的解决方案。我不理解从输入流读取选项卡时执行的数学公式。代码如下: #include <stdio.h> #define TABINC 8 main() { int c, nb, nt, pos; nb = 0; nt = 0; for (pos = 1; (c =get

问题是:

编写程序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;
    }
}
通过在VisualStudio中的调试,我可以看到当输入流中出现一个制表符时,这个构造将pos带到下一个制表符停止点。这是正确的吗

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


编辑:我确实理解模运算符的作用。很抱歉,我没有指定它。

它没有名字或类似的东西。
详细信息:

首先,必须增加多少pos取决于pos%TABINC,
例如,TABINC是8,因此如果pos是8的倍数,则添加8,
如果位置%8是1(如9,17…),则添加7,
如果位置%8为2(10,18…),则添加6,依此类推。

完整列表:
位置%8->要添加的编号
0->8
1->7
2->6
3->5
4->4
5->3
6->2
7->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-((位置-1)%TABINC))-1

=TABINC-((位置%TABINC)-1)-1

=TABINC+1-(位置%TABINC)-1

=TABINC-(位置%TABINC)


这与我上面的简短公式相同,只是毫无原因地更加复杂。

这个公式没有特定的名称-它是一种相对简单的方法,可以将小学数学应用于日常问题。下面是发生的情况:
'\t'
字符将
pos
向前推进多个位置,范围从1到
TABINC

  • pos
    TABINC
    的倍数时,跳转整个
    TABINC
  • pos
    TABINC
    的下一个倍数低一倍时,您跳一次
  • pos
    TABINC
    的下一个倍数低两倍时,您跳两倍
  • 以此类推-当
    pos
    x
    时,其中
    0
    ,在
    TABINC
    的下一个倍数下方,您跳转
    x
现在,计算跳转的问题简化为计算
pos
TABINC
的下一个倍数之间的差值。这可以通过计算
pos
TABINC
的除法余数,然后从
TABINC
中减去余数来实现。这是通过
%
运算符完成的

由于
pos
是以一为基础的*,因此公式所做的第一件事就是将其设置为以零为基础,以便计算余数。接下来,公式计算余数,这是一种数学方法,表示“最后一个
TABINC
stop上方的位置数”。现在,您只需从
TABINC
中减去余数即可得到结果

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

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