Преобразование int64_t в строку в C - PullRequest
0 голосов
/ 02 августа 2020

Я работаю с языком программирования C и использую базу данных Postgres для вставки записей. Один из столбцов таблицы в базе данных имеет тип timestamp. Данные, которые я получаю в программе C, имеют тип int64_t, и мне нужно передать это значение в качестве параметра в операторе INSERT, как показано ниже. Для этого я попытался преобразовать значение int64_t в строку, используя sprintf().

 char str[21];
 sprintf(str, "%" PRId64 "\n", someTimeReceived inTheProgram);  
 const char * const paramValues[1] = { str };

 PGresult *res =     res = PQexecParams(
            conn,
            "INSERT INTO dummy VALUES(1,to_timestamp($1)::timestamp)",

            1,            /* one parameter */
            NULL,
            paramValues,
            NULL,        /* parameter lengths are not required for strings */
            NULL,        /* all parameters are in text format */
            0            /* result shall be in text format */
        );

Но при использовании sprintf() какое-то значение мусора вставляется в конец строки . Например, если полученное значение int64_t равно 132408394771256230, то sprintf() преобразует его в 132408394771256230\n\0\003. Из-за дополнительных значений мусора, добавленных в конец строки, программе не удается вставить данное значение, а затем завершается.

Пожалуйста, помогите мне исправить эту проблему.

1 Ответ

1 голос
/ 02 августа 2020

если полученное значение int64_t равно 132408394771256230, то sprintf() преобразует его в 132408394771256230\n\0\003

нет, sprintf записывает только 132408394771256230\n\0 в str и пусть остальная часть массива не изменится, символ кода 3 присутствовал до вызова sprintf (массив не инициализирован), но, конечно, это может быть что угодно.

Из-за дополнительных значений мусора, добавленных в конец строки, программа не может вставить данное значение и затем завершает работу.

снова нет, PQexecParams управляет параметрами как массив строк (одна строка в вашем случае) в соответствии с соглашением, строка заканчивается нулевым символом, PQexecParams не читает / не заботится о том, что находится после нулевого символа, и делает знать даже о «конверте» вашей строки (массив из 21 символа в вашем случае).

Вероятно, ваша проблема возникает из-за нежелательной новой строки в вашей строке, в результате чего команда будет строкой

INSERT INTO dummy VALUES(1,to_timestamp(132408394771256230\n)::timestamp)

просто удалите \n в формате вашего sprintf.

Предположим, что необходимо иметь новую строку, ваш массив должен иметь размер 22, а не 21, чтобы управлять отрицательным значением без записи неопределенного поведения из массива.

... какое-то значение мусора

вы наверняка видите нулевой символ и байт после, потому что вы используете отладчик, и этот отладчик знает, что str имеет размер 21 и когда вы запрашиваете значение str , отладчик рассматривает str как массив символов, а не строку. Если вы попросите отладчик показать (char*) str, он будет рассматривать str как строку и не будет отображать нулевой символ или следующий за ним символ.

[править]

Функция запрашивает дату и время в виде строки гггг-мм-дд чч: мм: сс вместо вашего большого числа an ua_datetime

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

nt ua_datetime_snprintf (char * dst, size_t size, const ua_datetime * dt)   

результатом будет строка YYYY-MM-DDThh: mm: ss.nnnZ , поэтому после простой замены последней точки нулевым символом и 'T' пробелом (предположим, что 'T' действительно создается, попробуйте и адаптироваться)

Другой способ - использовать:

time_t ua_datetime_to_time_t(const ua_datetime * dt)    

, а затем сделать вашу строку со стандартной функцией из time_t

В любом случае вы должны понимать, что теряете большую точность, ua_datetime находится в 100 наносекундах, а * временная метка postgress - только в секундах

...