4

我在 K&R 做一个练习:

编写一个程序 detab,用适当数量的空格替换输入中的制表符,以留出下一个制表位。

这就是我到目前为止所拥有的(没有对文件进行错误检查):

#include <stdio.h>
#define tab 2
#define MAX_LENGTH 1000
int main(int argc, char **argv)
{
    FILE *fp = fopen(argv[1], "r+");    
    int c, n;
    char buffer[MAX_LENGTH + 1];
    for (n = 0; n < MAX_LENGTH && (c = fgetc(fp)) != EOF; ++n) {
        if (c == '\t') {
            for (int x = 0; x < tab; ++x)
                buffer[n++] = ' ';
            --n;
        }
        else
            buffer[n] = c;
    }
    //buffer[n] = '\0';
    //rewind(fp);
    //fputs(buffer, fp);
    printf("%s\n", buffer);
    fclose(fp);
    return 0;
}

它似乎有效,但我想知道为什么\0最后不需要。我只是幸运吗?

4

4 回答 4

5

是的,你很幸运。为避免此问题,您可以使用fwrite,它不需要空终止符(因为您确切指定了要写入的字节数):

fwrite(buffer, 1, n, stdout);
于 2012-01-05T03:12:42.570 回答
4

您可以告诉printf(...)给定字符串要打印的(最大)字符数。

printf("%.*s\n", n, buffer);

请参阅printf(3),“精度”部分:

可选精度,形式为句点 ('.'),后跟可选的十进制数字字符串。而不是十进制数字字符串,可以写“*” [...] 来指定精度在下一个参数 [...] 中给出,它必须是 int 类型。[...] 这给出了 [...] 为 s [...] 转换从字符串中打印的最大字符数。

现场演示:http printf ("%.*s\n", 5, "Hello, world!"): //ideone.com/KHKLl

于 2012-01-05T03:46:06.027 回答
2

您可以使用以下方法初始化缓冲区:

memset(buffer, '\0', MAX_LENGTH + 1);

而且您不必担心空终止。

于 2012-01-05T03:15:48.420 回答
1

正如其他答案所指出的那样,您很幸运该数组在正确的位置包含空值。

您可以在使用以下速记创建它时对其进行初始化:

char buffer[MAX_LENGTH + 1] = { 0 }; // all elements will be zero

请注意,这是因为编译器将用零初始化未指定的条目 - 所以如果你说

char buffer[MAX_LENGTH + 1] = { 'a' };

那么数组将是{'a',0,0,0....}

于 2012-01-05T03:30:07.663 回答