C: форматирование строк для hexdump (char * to other char *)

Эта страница на официальном сайте mongodb адресует точно этот вопрос:

http://docs.mongodb.org/ecosystem/tutorial/model-data- for-ruby-on-rails /

Когда мы показываем наш список историй, нам нужно будет показать имя пользователя, разместившего историю. Если бы мы использовали реляционную базу данных, мы могли бы выполнить соединение с пользователями и магазинами и получить все наши объекты в одном запросе. Но MongoDB не поддерживает объединения, и поэтому время от времени требуется бит денормализации. Здесь это означает кеширование атрибута «имя пользователя».

Реляционные пуристы уже чувствуют себя неловко, как будто мы нарушаем какой-то универсальный закон. Но давайте иметь в виду, что коллекции MongoDB не эквивалентны реляционным таблицам; каждая из которых служит уникальной проектной цели. Нормализованная таблица обеспечивает атомный изолированный кусок данных. Однако документ более тесно представляет собой объект в целом. В случае сайта социальных новостей можно утверждать, что имя пользователя является неотъемлемой частью истории, опубликованной.

blockquote>

0
задан rfg 17 January 2019 в 17:27
поделиться

1 ответ

Вы не можете использовать strlen() для неинициализированных данных:

char* buffer = malloc(1000000);
memset(buffer,0,strlen(buffer));

Нет способа для strlen() узнать размер выделенной памяти, так как он полагается на завершающий нулевой символ (0, '\0'), который может или не может быть где-то в памяти, на которую указывает буфер. Либо укажите размер памяти, выделенной в memset():

memset(buffer, 0, 1000000);

, либо используйте calloc(), который инициализирует выделенную память нулями:

char buffer = calloc(1000000, sizeof(char));  // or calloc(1000000, 1) since sizeof(char) is 1 by definition.

. Могут быть другие проблемы. в вашем коде. Например, вы вызываете DumpHex2() дважды в main(), но никогда не освобождаете память, которую выделяет функция. Память, выделенная для symbol, также просочилась.

Было бы легче ответить, если бы вы обновили свой вопрос, включив в него точный формат текста, который вы хотите DumpHex2() создать.

Вы должны использовать isprint(), чтобы определить, печатается ли символ или нет.

Короче и ИМХО легче читать и понимать:

#include <ctype.h>   // isprint()
#include <stddef.h>  // size_t
#include <stdlib.h>  // malloc(), free()
#include <string.h>  // strcat()
#include <stdio.h>   // sprintf()

enum {
    DUMP_BYTES_PER_LINE = 16,
    DUMP_BYTES_GROUP = 8,
    DUMP_CHARS_PER_LINE = DUMP_BYTES_PER_LINE * 4 + DUMP_BYTES_PER_LINE / DUMP_BYTES_GROUP + 4
};

char* DumpHex(const void* data, size_t size)
{
    size_t const num_lines = size / DUMP_BYTES_PER_LINE + ((size % DUMP_BYTES_PER_LINE) > 0);
    size_t const result_length = num_lines * DUMP_CHARS_PER_LINE;

    char *result = malloc((result_length + 1) * sizeof(*result));
    if (!result)
        return NULL;

    memset(result, ' ', result_length);
    result[result_length] = '\0';

    char *dump_pos = result;
    char *plain_pos = result + DUMP_BYTES_PER_LINE * 3 + DUMP_BYTES_PER_LINE / DUMP_BYTES_GROUP + 3;
    char unsigned const *src = data;

    for (size_t i = 0; i < size; ++i, dump_pos += 3, ++plain_pos) {

        sprintf(dump_pos, "%02x ", (int)src[i]);
        dump_pos[3] = ' ';
        *plain_pos = isprint(src[i]) ? src[i] : '.';

        if ((i + 1) % DUMP_BYTES_PER_LINE == 0 || i + 1 == size) {
            *++plain_pos = '\n';

            size_t const bytes_per_line_left = (i + 1) % DUMP_BYTES_PER_LINE;
            plain_pos[bytes_per_line_left ? -(long long)bytes_per_line_left - 3 : -DUMP_BYTES_PER_LINE - 3] = '|';

            dump_pos = plain_pos + 1 - 3;
            plain_pos = dump_pos + DUMP_BYTES_PER_LINE * 3 + DUMP_BYTES_PER_LINE / DUMP_BYTES_GROUP + 5;
        }
        else if ((i + 1) % DUMP_BYTES_GROUP == 0) {
            ++dump_pos;
        }
    }

    return result;
}
0
ответ дан Swordfish 17 January 2019 в 17:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: