首页 > 解决方案 > 常青K&R ex。1-21 安塔布

问题描述

这里的爱好者。在来这里之前我尽了最大努力,我的解决方案“有点工作”,但并非总是如此,而且我发现调试这个“简单”问题特别困难。

“编写一个程序entab,用最少数量的制表符和空格替换空格字符串以实现相同的间距。使用相同的制表位,例如每n列。n应该是变量还是符号参数?”

为了帮助更容易理解我的代码,这里有一个简短的解释,所以希望有人能理解我想要做什么。

  1. 位置由制表符和任何其他非空格字符设置/增加,空格不会增加它。我将需要 pos 和 space_count 在第 3 步进行检查。
  2. 检查输入是空间还是其他东西,如果是空间,那么我增加 space_count,如果不是,则执行步骤 2-3-4:
  3. 如果输入不是空格,首先我检查是否有足够的空格将它们转换为制表符,所以如果我输入以 17 个空格开头并且制表符是 8 个空格,则打印两个制表符,将 space_count 减为 1,然后设置定位到第 16 列的第二个制表位。
  4. 在此之后,我检查剩余空格和当前位置的总和是否达到或超过下一个制表位,如果是,则打印一个制表符,将 space_count 递减到它超过当前制表位的数量。
  5. 在所有这些之后,我使用 if - else if - else 分支来处理如果选项卡、换行符或任何其他非空格字符是输入时会发生什么。由于这些与空间不同,可以立即打印,所以我打印它们。(所以继续上面的例子,我有 2 个制表符,pos=16,space_counter = 1,下一个制表位停止在 24。如果我按字母 A,打印空格(在这种情况下为 1),打印 A,将位置设置为 18。现在,如果我要放置超过 5 个空格,则第 3 步分支将执行为 18 + 6 = 24,因此我们到达下一个制表位)。

对于我测试的大多数输入,我猜它是有效的,但如果输入包含:“5 个空格,A,44 个空格,2 个制表符,3 个空格,A”(不是字面意思,所以它以 开头 A)。如果我将 TAB_INC 设置为 8,并且我在记事本中检查它,它没有相同的间距(缺少 1 个制表符),所以结果不好。如果我将 TAB_INC 设置为 4,并在 sublime 文本中检查它,如果我在那里复制源+结果一切都很好......所以除了无法调试它之外,我什至无法使用不同的文本编辑器获得相同的结果。

我的问题是,为什么或者什么时候这个逻辑/代码会中断?

代码是

#include <stdio.h>
#define TAB_INC 4

static int get_tab_stop(int pos) {
    return ((pos / TAB_INC) + 1) * TAB_INC;
}

static void init(void) {
    int c, pos, space_count;
    c = pos = space_count = 0;

    while (EOF != (c = getchar())) {
        if (' ' == c)
            ++space_count;
        else {
            while (TAB_INC <= space_count) {
                space_count -= TAB_INC;
                pos = get_tab_stop(pos);
                putchar('\t');
            }
            if (pos + space_count >= get_tab_stop(pos)) {
                space_count -= get_tab_stop(pos) - pos;
                pos = get_tab_stop(pos);
                putchar('\t');
            }
            if ('\t' == c) {
                space_count = 0;
                pos = get_tab_stop(pos);
            }
            else if ('\n' == c)
                pos = space_count = 0;
            else {
                pos = pos + space_count + 1;
                while (space_count) {
                    putchar(' ');
                    --space_count;
                }
            }
            putchar(c);
        }
    }
}

int main() {
    init();
    return 0;
}

标签: ckernighan-and-ritchie

解决方案


实际上我发现了问题,第 2 步完全没有必要,它自己造成了问题,第 3 步需要返工。无论如何,我把我的代码留在这里,它可能对将来解决这个问题的人有用。

#include <stdio.h>
#define TAB_INC 8

static int get_tab_stop(int pos) {
    return ((pos / TAB_INC) + 1) * TAB_INC;
}

static void init(void) {
    int c, pos, eval_ts, space_count;
    c = pos = eval_ts = space_count = 0;

    while (EOF != (c = getchar())) {
        if (' ' == c)
            ++space_count;
        else {
            while (pos + space_count >= (eval_ts = get_tab_stop(pos))) {
                space_count -= eval_ts - pos;
                pos = eval_ts;
                putchar('\t');
            }
            if ('\t' == c) {
                space_count = 0;
                pos = get_tab_stop(pos);
            }
            else if ('\n' == c)
                pos = space_count = 0;
            else {
                pos = pos + space_count + 1;
                while (space_count) {
                    putchar(' ');
                    --space_count;
                }
            }
            putchar(c);
        }
    }
}

int main() {
    init();
    return 0;
}

推荐阅读