Единственной фактической ошибкой является то, что вы не проверяете возвращаемое значение malloc
для нуля.
Имя itoa
уже используется для функции, которая является нестандартной, но неэто необычно.Он не выделяет память, скорее он записывает данные в буфер, предоставленный вызывающей стороной:
char *itoa(int value, char * str, int base);
Если вы не хотите полагаться на вашу платформу, я бы посоветовал следовать этой схеме.Функции обработки строк, которые возвращают вновь выделенную память в C, как правило, доставляют больше хлопот, чем они стоят в долгосрочной перспективе, потому что большую часть времени вы заканчиваете тем, что выполняете дальнейшие манипуляции, и поэтому вам нужно освободить много промежуточных результатов.Например, сравните:
void delete_temp_files() {
char filename[20];
strcpy(filename, "tmp_");
char *endptr = filename + strlen(filename);
for (int i = 0; i < 10; ++i) {
itoa(endptr, i, 10); // itoa doesn't allocate memory
unlink(filename);
}
}
с
void delete_temp_files() {
char filename[20];
strcpy(filename, "tmp_");
char *endptr = filename + strlen(filename);
for (int i = 0; i < 10; ++i) {
char *number = itoa(i, 10); // itoa allocates memory
strcpy(endptr, number);
free(number);
unlink(filename);
}
}
Если у вас была причина особенно беспокоиться о производительности (например, если вы реализуете библиотеку в стиле stdlib, включающую itoa
), или если вы реализуете базы, которые sprintf
не поддерживает, вы можете не вызывать sprintf
.Но если вам нужна базовая строка 10, тогда ваш первый инстинкт был верным.В спецификаторе формата %d
нет абсолютно ничего «неправильного».
Вот возможная реализация itoa
, только для базы 10:
char *itobase10(char *buf, int value) {
sprintf(buf, "%d", value);
return buf;
}
Вот та, которая включает snprintf-стиль подхода к длине буфера:
int itobase10n(char *buf, size_t sz, int value) {
return snprintf(buf, sz, "%d", value);
}