C - Modulo返回错误的结果?

时间:2014-07-03 23:51:29

标签: c modulus

所以我现在正试图通过K& R,我对这里发生的事感到困惑。在我添加空格的for循环行中,模数运算正确计算。它运行适当的次数。但是为spaces_to_add分配完全相同的模数操作会返回错误的结果。 (通常存储i_new_str本身。)

关于为什么会发生这种情况的任何想法?

// replaces tabs with spaces up until next tab stop
void detab(char str[]) {
        char new_str[STR_LEN], c;
        int i, j, i_new_str, spaces_to_add;
        i_new_str = 0;
        while((c = str[i++])) {
                if(c == '\t') {
                        spaces_to_add = i_new_str % SPACES_FOR_TAB;
                        printf("%d\n", spaces_to_add);
                        for(j = 0; j < (i_new_str % SPACES_FOR_TAB); ++j) {
                                printf("Adding space\n");
                                new_str[i_new_str++] = ' ';
                        }           
                } else {    
                        new_str[i_new_str++] = c;
                }           
        }           

        for(i = 0; new_str[i]; ++i) {
                str[i] = new_str[i];
        }           
        str[i] = '\0';

        printf("str changed to length %d\n", i);
}

以下是一些示例输出,其中包含一些未在上面发布的代码:

a   b   c
Input was:
a   b   c
Length of input: 5

spaces_to_add = 1 (1 % 8)
Adding space
Adding space
Adding space
Adding space
Adding space
Adding space
Adding space
spaces_to_add = 1 (9 % 8)
Adding space
Adding space
Adding space
Adding space
Adding space
Adding space
Adding space
str changed to length 17
Detabbed str:
a       b       c

2 个答案:

答案 0 :(得分:1)

循环中的表达式(i_new_str % SPACES_FOR_TAB)在每次迭代时得到计算,而赋值在循环之前只计算一次。

答案 1 :(得分:0)

从问题描述(完整空格到下一个tabstop),请注意您应计算到下一个tabstop 的空格数(不是超过最后一个tabstop 的数量)

那是

SPACES_FOR_TAB - i_new_str % SPACES_FOR_TAB

(而不是您的i_new_str % SPACES_FOR_TAB)。

那就是说,看看你的for循环(在j上):它会计算j直到i_new_str % SPACES_FOR_TAB,完全改变i_new_str。

要么在计算之前计算出限制,要么根本不计算:

while (i_new_str % SPACES_FOR_TAB) {
    printf("Adding space\n");
    new_str[i_new_str++] = ' ';
}

请注意,如果正在处理的标签正好位于tabstop上,则上述解决方案将错过第一个循环。要添加必填空间:

do {
    printf("Adding space\n");
    new_str[i_new_str++] = ' ';
} while (i_new_str % SPACES_FOR_TAB);