字符串缓冲区在最后一次循环迭代中被跳过

问题描述 投票:0回答:1

我有一个程序应该打印一个简单的直方图。

下面的代码不是一个最小的可重现示例,因为完整代码超过 100 行,这只是理解所必需的部分。如果有人需要完整的代码来回答我的问题,我会更新它。

#define LINE_CHAR '#'

void printHistogram(FILE * const file, size_t const fields_size, char const * const * const names, unsigned const * const data) {
    // for all the names we are using the same buffer to avoid unnecessary heap allocations
    size_t const name_buffer_size = max_string_length(fields_size, names) + 1;
    char name_buffer[name_buffer_size];
    name_buffer[name_buffer_size - 1] = '\0';

    // same for the lines representing data
    size_t line_buffer_size = max_unsigned(fields_size, data) + 1;
    char line_buffer[line_buffer_size];
    memset(line_buffer, LINE_CHAR, line_buffer_size);

    for (size_t i = 0; i < fields_size; i++) {
        size_t current_name_length = strlen(names[i]);
        // fill the rest of the space with spaces
        memset(name_buffer + current_name_length, ' ', name_buffer_size - 1 - current_name_length);
        // copy name to buffer without null terminator
        memcpy(name_buffer, names[i], current_name_length);
        
        // prevent printing out the whole buffer, instead only print the required part
        line_buffer[data[i] + 1] = '\0';
        fprintf(file, "%s|%s\n", name_buffer, line_buffer);
        // remove this early terminator
        line_buffer[data[i] + 1] = LINE_CHAR;
    }
}

int main() {
    char const * const names[] = {"a", "b", "abc"};
    unsigned const data[] = {5, 10, 15};
    printHistogram(stdout, 3, names, data);
}

预期:

a  |######
b  |###########
abc|################

得到:

a  |######
b  |###########
|################

在最后一次迭代中,代码只是跳过名称缓冲区,这是为什么?

c console buffer
1个回答
0
投票

这些行:

        line_buffer[data[i] + 1] = '\0';
...
        line_buffer[data[i] + 1] = LINE_CHAR;
如果

line_buffer

 是最大值,则
写入超出
data[i]
数组的限制。另请注意,输出显示
#
太多(我认为这也是预期输出中的拼写错误)。

应删除

+1

        line_buffer[data[i]] = '\0';
...
        line_buffer[data[i]] = LINE_CHAR;

但是,应该提到的是,通过在

fprintf()
:

中使用格式说明符可以显着简化代码
    for (size_t i = 0; i < fields_size; i++) {
        fprintf(file, "%-*s|%.*s\n", max_name_size, names[i], data[i], line_buffer);
    }
© www.soinside.com 2019 - 2024. All rights reserved.