Там какой-либо путь состоит в том, чтобы определить, сколько символов будет записано sprintf?

Попробуйте:

var holder = new pieceHolder({});

При создании объекта-держателя вы ничего не передаете как кусок, так что это undefined. При попытке получить доступ к holder.piece.tileLocation вы пытаетесь найти tileLocation из undefined. Лучше всего всегда использовать параметры по умолчанию для вас.

12
задан Screndib 5 February 2009 в 07:31
поделиться

6 ответов

Страница справочника для snprintf говорит:

   Return value
       Upon  successful  return,  these  functions return the number of
       characters printed (not including the trailing '\0' used to  end
       output to strings).  The functions snprintf and vsnprintf do not
       write more than size bytes (including the  trailing  '\0').   If
       the output was truncated due to this limit then the return value
       is the number of characters (not including  the  trailing  '\0')
       which  would  have  been  written  to the final string if enough
       space had been available. Thus, a return value of size  or  more
       means  that  the  output  was  truncated.  (See also below under
       NOTES.)  If an output error is encountered, a negative value  is
       returned.

То, что это означает, - то, что можно звонить snprintf с размером 0. Ничто не будет записано, и возвращаемое значение скажет Вам, сколько места необходимо выделить к строке:

int how_much_space = snprintf(NULL, 0, fmt_string, param0, param1, ...);
22
ответ дан 2 December 2019 в 05:04
поделиться

Поскольку другие упомянули, snprintf() возвратит количество символов, требуемых в буфере препятствовать тому, чтобы вывод был усеченным. Можно просто звонить, это с 0 параметрами длины буфера для получения необходимого размера затем использует соответственно размерный буфер.

Для небольшого улучшения эффективности можно назвать его с буфером, это является достаточно большим для нормального случая, и только сделайте второй вызов к snprintf() если вывод является усеченным. Чтобы удостовериться, что буфер (буферы) правильно освобожден в этом случае, я буду часто использовать auto_buffer<> возразите, что обрабатывает динамическую память для меня (и имеет буфер по умолчанию на стеке для предотвращения выделения "кучи" в нормальном случае).

При использовании компилятора Microsoft MS имеет нестандартное _snprintf() это имеет серьезные ограничения не всегда пустой указатель, завершающий буфер и не указывающий, насколько большой буфер должен быть.

Для работы вокруг неподдержки Microsoft я использую почти общественное достояние snprintf() от Holger Weiss.

Конечно, если Ваш неMS C или компилятор C++ отсутствуют snprintf(), код из вышеупомянутой ссылки должен работать точно также.

5
ответ дан 2 December 2019 в 05:04
поделиться

Я использовал бы двухэтапный подход. Обычно большой процент выходных строк будет находиться под определенным порогом, и только некоторые будут больше.

Этап 1, используйте разумный размерный статический буфер, такой как 4K. С тех пор snprintf() может ограничить, сколько символов записано, Вы не получите переполнение буфера. Из чего Вы будете возвращены snprintf() количество символов, которые оно записало бы, был ли Ваш буфер достаточно большим.

Если Ваш вызов к snprintf() возвраты меньше, чем 4K, затем используйте буфер и выход. Как указано, подавляющее большинство вызовов должно просто сделать это.

Некоторые не будут, и именно тогда Вы вводите этап 2. Если вызов к snprintf() не поместится в буфер 4K, Вы по крайней мере теперь знаете, как большой буфер Вам нужно.

Выделите, с malloc(), буфер, достаточно большой для содержания его затем snprintf() это снова к тому новому буферу. Когда Вы сделаны с буферным, освобождаете его.

Мы работали над системой в дни прежде snprintf() и мы достигли того же результата путем соединения дескриптора файла с /dev/null и использование fprintf() с этим./dev/null, как всегда гарантировали, возьмет столько данных, сколько Вы даете его так, мы на самом деле получили бы размер от этого, затем выделили бы буфер при необходимости.

Сохраните натуральными, который не имеют все системы snprintf() (например, я понимаю, что это _snprintf() в Microsoft C), таким образом, Вам, вероятно, придется найти функцию, которая делает то же задание, или возвращаются к fprintf /dev/null решение.

Также будьте осторожны, если данные могут быть изменены между проверкой размера snprintf() и фактическое snprintf() к буферу (т.е. wathch для потоков). Если размеры увеличатся, то Вы получите повреждение переполнения буфера.

Если Вы будете следовать правилу, что данные, когда-то врученные функции, принадлежат той функции исключительно, пока не возвращено, то это не будет проблемой.

2
ответ дан 2 December 2019 в 05:04
поделиться

Смотрите на CodeProject: CString-клон Используя Стандарт C++. Это использует решение, которое Вы предложили с увеличением размера буфера.

// -------------------------------------------------------------------------
    // FUNCTION:  FormatV
    //      void FormatV(PCSTR szFormat, va_list, argList);
    //
// DESCRIPTION: // This function formats the string with sprintf style format-specs. // It makes a general guess at required buffer size and then tries // successively larger buffers until it finds one big enough or a // threshold (MAX_FMT_TRIES) is exceeded. // // PARAMETERS: // szFormat - a PCSTR holding the format of the output // argList - a Microsoft specific va_list for variable argument lists // // RETURN VALUE: // -------------------------------------------------------------------------

void FormatV(const CT* szFormat, va_list argList)
{
#ifdef SS_ANSI

    int nLen    = sslen(szFormat) + STD_BUF_SIZE;
    ssvsprintf(GetBuffer(nLen), nLen-1, szFormat, argList);
    ReleaseBuffer();
#else
    CT* pBuf            = NULL;
    int nChars          = 1;
    int nUsed           = 0;
    size_type nActual   = 0;
    int nTry            = 0;

    do  
    {
        // Grow more than linearly (e.g. 512, 1536, 3072, etc)

        nChars          += ((nTry+1) * FMT_BLOCK_SIZE);
        pBuf            = reinterpret_cast<CT*>(_alloca(sizeof(CT)*nChars));
        nUsed           = ssnprintf(pBuf, nChars-1, szFormat, argList);

        // Ensure proper NULL termination.
        nActual         = nUsed == -1 ? nChars-1 : SSMIN(nUsed, nChars-1);
        pBuf[nActual+1]= '\0';


    } while ( nUsed < 0 && nTry++ < MAX_FMT_TRIES );

    // assign whatever we managed to format

    this->assign(pBuf, nActual);
#endif
}

0
ответ дан 2 December 2019 в 05:04
поделиться

Я искал ту же функциональность, Вы говорите о, но насколько я знаю, что-то как простой, поскольку метод C99 не доступен в C++, потому что C++ в настоящее время не включает опции, добавленные в C99 (такие как snprintf).

Ваш лучший выбор состоит в том, чтобы, вероятно, использовать объект stringstream. Это является более громоздким, чем явно записанный вызов sprintf, но это будет работать.

0
ответ дан 2 December 2019 в 05:04
поделиться

Так как Вы используете C++, нет действительно никакой потребности использовать любую версию sprintf. Самая простая вещь сделать использовать станд.:: ostringstream.

std::ostringstream oss;
oss << a << " " << b << std::endl;

oss.str() возвраты станд.:: строка с содержанием того, что Вы записали в oss. Использовать oss.str().c_str() получить a const char *. Это будет намного легче иметь дело с в конечном счете и устраняет утечки памяти или переполнение буфера. Обычно, если Вы волнуетесь о проблемах памяти как этот в C++, Вы не используете язык для его полного потенциала, и необходимо заново продумать дизайн.

0
ответ дан 2 December 2019 в 05:04
поделиться
Другие вопросы по тегам:

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