Подтвердить что ты не робот

Лучший способ безопасно распечатать строку?

Кто-нибудь знает хороший безопасный способ перенаправления вывода функции printf в строку? Очевидные пути приводят к переполнению буфера.

Что-то вроде:

string s;
output.beginRedirect( s );  // redirect output to s

... output.print( "%s%d", foo, bar );

output.endRedirect();

Я думаю, что проблема такая же, как просить, "сколько персонажей будет печатать продукцию?" Идеи?

4b9b3361

Ответ 1

fooobar.com/questions/296588/... имеет аналогичное обсуждение. Также в этом вопросе я представляю свое любимое решение - функцию "format", которая принимает идентичные аргументы printf и возвращает std::string.

Ответ 2

Вы можете использовать:

std::snprintf, если вы работаете с char *

std::stringstream, если вы хотите использовать строки (не такие же, как printf, но позволяете вам легко манипулировать строкой, используя обычные функции потока).

boost::format, если вы хотите использовать функцию, аналогичную printf, которая будет работать с потоками. (в соответствии с комментариями)

Ответ 3

Функция snprintf() печатает в строке, но только до тех пор, пока она не указана.

Возможно, вы ищете...

Ответ 4

Поскольку вы отметили это как С++ (а не только C), я укажу, что типичный способ сделать это на С++ - это использовать stringstream, а не семейства printf. Не нужно беспокоиться о переполнении буфера потоками строк.

Библиотека Boost Format также доступна, если вам нравится строки формата в формате printf, но нужно что-то более безопасное.

Ответ 5

Старая школа:

snprintf()

позволяет установить лимит на записанное число и вернуть фактический размер записи и

asprintf()

выделяет (с malloc()) достаточный буфер, который затем становится вашей проблемой до free(). `asprintf - это функция GNU libc, переопределенная в BSD libc.

Ответ 6

snprintf() возвращает количество байтов, необходимых для записи всей строки. Итак, в качестве крошечного примера:

#include <strings.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv) 
{
    char* buf = 0;
    size_t bufsize = 0;
    size_t sz;

    const char* format="%s and %s.";
    const char* str_1 ="string 1";
    const char* str_2 ="string 2";

    sz = snprintf(buf, bufsize, format, str_1, str_2);
    printf("The buffer needs to be %d bytes.\n", sz);

    buf=malloc(sz+1);
    if(!buf) {
        printf("Can't allocate buffer!\n");
        return 1;
    }
    bufsize = sz+1;
    buf[bufsize-1] = '\0';
    sz = snprintf(buf, bufsize, format, str_1, str_2);
    printf("Filled buffer with %d bytes.\n", sz);
    printf("The buffer contains:\n'%s'\n", buf);
    return 0;
}

выход:

The buffer needs to be 22 bytes.
Filled buffer with 22 bytes.
The buffer contains:
'string 1 and string 2.'

Ответ 7

Библиотека fmt предоставляет функцию fmt::sprintf, которая выполняет форматирование, совместимое с printf (включая позиционные аргументы в соответствии с спецификация POSIX) и возвращает результат как std::string:

std::string s = fmt::sprintf( "%s%d", foo, bar );

Отказ от ответственности. Я являюсь автором этой библиотеки.

Ответ 8

С C99 у вас есть snprintf-функция, которая принимает размер буфера в качестве параметра. В C-библиотеке GNU есть asprintf, который выделяет вам буфер. Для С++, возможно, вам лучше использовать iostream.

Wikipedia содержит больше информации.

Ответ 9

Я считаю, что форматирование printf очень полезно и проще в использовании, чем потоки. С другой стороны, мне очень нравится std::string. Решение заключается в использовании sprintf, но не может обрабатывать произвольный размер буфера.

Я обнаружил, что мне нужно обрабатывать общий случай (скажем, буфер, ограниченный 256 символами) без использования накладные расходы и, тем не менее, безопасно обрабатывать большой буфер. Для этого у меня есть буфер из 256 символов, выделенных в моем классе как член, и я использую snprinf, передавая этот буфер и его размер. Если snprintf преуспевает, я могу сразу перенастроить форматированную строку. Если он терпит неудачу, я выделяю буфер и снова вызываю snprinf. Буфер освобождается в деструкторе класса.

Ответ 10

Microsoft представляет для этого функции safe.

Вы можете использовать printf_s()

Ответ 11

В Windows:

StringCchPrintf
StringCbPrintf

из strsafe.h/lib.