2010-05-12 2 views
1

Я преобразование двойного в строку полукокса:Как предотвратить переполнение буфера, преобразуя double в char?

char txt[10]; 
double num; 

num = 45.344322345 

sprintf(txt, "%.1f", num); 

и с помощью «.1f», чтобы усечь знаки после запятой, к цифре балльных.
i.e. - txt содержит 45.3

Обычно я использую точность в sprintf, чтобы гарантировать, что буфер символов не переполнен. Как я могу сделать это здесь, и усечение десятичной дроби без использования snprintf?

(т.е. если Num = +345694876345,3 по какой-то причине)

Благодаря

EDIT Если Num является> буферирования результата больше не имеет значения, просто не хочу, чтобы врезаться. Не уверен, что в этом случае будет иметь наибольший смысл.

EDIT2 Я должен был сделать это более понятным, чем в теге, что это программа на языке C. У меня возникли проблемы с использованием snprintf в программе на C. I don't want to add any 3rd party libraries.

+0

Что бы вы хотели, чтобы результат был, если он не смог правильно напечатать результат? –

ответ

5

Использовать snprintf(), который расскажет вам, сколько байтов было не напечатано. В общем случае размер массива должен быть достаточно большим, чтобы обрабатывать длинное строковое представление целевого целочисленного типа. Если заранее не известно, используйте malloc() (или asprintf(), что является нестандартным, но присутствует на многих платформах).

Редактировать

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

1

Почему вы хотите это сделать без snprintf? Вы должны использовать snprintf, независимо от того, содержит ли ваша строка формата двойную, другую строку или что-то еще. Насколько я вижу, нет причин не.

2

Если вы абсолютно должны сделать это самостоятельно, считать цифры в числе, прежде чем пытаться преобразовать:

int whole = num; 
int wholeDigits = 0; 
do { 
    ++wholeDigits; 
} 
while (whole /= 10); 

double fraction = num - (int) num; 
int decimallDigits = 0; 
while (fraction > 0) { 
    ++decimalDigits; 
    fraction *= 10; 
    fraction = fraction - (int) fraction; 
} 

int totalLength = decimalDigits ? wholeDigits + decimalDigits + 1 : wholeDigits; 

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

3

Почему бы не просто сделать свой буфер достаточно большим, чтобы удержать максимально возможное строковое представление двойника?

Предполагает использование 64-битного двоичного кода с использованием стандарта IEEE для арифметики с плавающей запятой, которая использует 52 бита для мантиссы: 2^52 = 4 503 599 627 370 500. Поэтому нам нужно 16 символов для хранения всех цифр до и после десятичной точки. 19 с учетом десятичной точки, знака и нулевого терминатора.

Я бы использовал размер буфера не менее 20 символов и двигался дальше.

Если вам нужно напечатать двойной, используя научную нотацию, вам нужно будет добавить достаточно места для экспоненты. Предполагая, что 11-значный знак подписан, это еще 4 символа для экспоненты плюс знак для экспонента и буква «E». В этом случае я просто поеду с 30 символами.

+0

Я бы просто сделал это 40 и двигался дальше. Если это не массив, то 40 байтов намного дешевле вашего времени. Но мне тоже нравится snprintf. – progrmr

Смежные вопросы