Попробуйте:
var holder = new pieceHolder({});
При создании объекта-держателя вы ничего не передаете как кусок, так что это undefined
. При попытке получить доступ к holder.piece.tileLocation
вы пытаетесь найти tileLocation из undefined
. Лучше всего всегда использовать параметры по умолчанию для вас.
Страница справочника для 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, ...);
Поскольку другие упомянули, snprintf()
возвратит количество символов, требуемых в буфере препятствовать тому, чтобы вывод был усеченным. Можно просто звонить, это с 0 параметрами длины буфера для получения необходимого размера затем использует соответственно размерный буфер.
Для небольшого улучшения эффективности можно назвать его с буфером, это является достаточно большим для нормального случая, и только сделайте второй вызов к snprintf()
если вывод является усеченным. Чтобы удостовериться, что буфер (буферы) правильно освобожден в этом случае, я буду часто использовать auto_buffer<>
возразите, что обрабатывает динамическую память для меня (и имеет буфер по умолчанию на стеке для предотвращения выделения "кучи" в нормальном случае).
При использовании компилятора Microsoft MS имеет нестандартное _snprintf()
это имеет серьезные ограничения не всегда пустой указатель, завершающий буфер и не указывающий, насколько большой буфер должен быть.
Для работы вокруг неподдержки Microsoft я использую почти общественное достояние snprintf()
от Holger Weiss.
Конечно, если Ваш неMS C или компилятор C++ отсутствуют snprintf()
, код из вышеупомянутой ссылки должен работать точно также.
Я использовал бы двухэтапный подход. Обычно большой процент выходных строк будет находиться под определенным порогом, и только некоторые будут больше.
Этап 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 для потоков). Если размеры увеличатся, то Вы получите повреждение переполнения буфера.
Если Вы будете следовать правилу, что данные, когда-то врученные функции, принадлежат той функции исключительно, пока не возвращено, то это не будет проблемой.
Смотрите на 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 }
Я искал ту же функциональность, Вы говорите о, но насколько я знаю, что-то как простой, поскольку метод C99 не доступен в C++, потому что C++ в настоящее время не включает опции, добавленные в C99 (такие как snprintf).
Ваш лучший выбор состоит в том, чтобы, вероятно, использовать объект stringstream. Это является более громоздким, чем явно записанный вызов sprintf, но это будет работать.
Так как Вы используете C++, нет действительно никакой потребности использовать любую версию sprintf. Самая простая вещь сделать использовать станд.:: ostringstream.
std::ostringstream oss;
oss << a << " " << b << std::endl;
oss.str()
возвраты станд.:: строка с содержанием того, что Вы записали в oss. Использовать oss.str().c_str()
получить a const char *
. Это будет намного легче иметь дело с в конечном счете и устраняет утечки памяти или переполнение буфера. Обычно, если Вы волнуетесь о проблемах памяти как этот в C++, Вы не используете язык для его полного потенциала, и необходимо заново продумать дизайн.