问题描述
这里的业余爱好者。来这里之前我已经尽力了,我的解决方案“有点奏效”,但并非总是如此,而且我发现调试这个“简单”的问题特别困难。
“编写一个程序 entab,用最少数量的制表符和空格替换空格字符串以获得相同的间距。使用相同的制表位,比如每 n 列。n 应该是变量还是符号参数?”
为了帮助更容易理解我的代码,这里有一个简短的解释,希望有人能理解我想要做什么。
- 位置由制表符和任何其他非空格字符设置/增加,空格不会增加它。我需要 pos 和 space_count 才能在第 3 步进行检查。
- 检查输入是空格还是其他东西,如果是空格,则增加空格计数,如果不是,则执行步骤 2-3-4:
- 如果输入不是空格,首先我检查是否有足够的空格将它们转换为制表符,因此如果我输入以 17 个空格开头并且制表符为 8 个空格,则打印两个制表符,将 space_count 减为 1,并将位置设置为第 16 列处的第二个制表位。
- 在此之后,我检查剩余空格和当前位置的总和是否达到或超过下一个制表位,如果是,则打印一个制表符,将 space_count 减少到超过当前制表位的数量。
- 毕竟我使用 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;
}
解决方法
其实我发现了问题,第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;
}