LINUX.ORG.RU

C++ - как правильно записать число в строку

 ,


1

3

Такой внезапно не совсем понятный вопрос - как в крестах/сишке можно записать данные из переменной типа int в string? Поиск дает какие-то жуткие костыли, неужели нет нормального способа сделать это средствами языка?

★☆

Ответ на: комментарий от Deleted

Это я находил.

error: ‘to_string’ is not a member of ‘std’

error: ‘itoa’ was not declared in this scope

И приехали. gcc version 5.4.0
Для itoa stdlib.h подключаю, нашёл, что для крестов надо подключать cstdlib - ни фига.

WereFox ★☆
() автор топика

Вангую, что в тред заглянет царь, после чего начнётся очередной срач на 10-20 страниц.

Deleted
()
Ответ на: комментарий от Deleted

Так, уже ближе к телу. Осталось только понять, какого *** IDE его не использует. Спасибо, буду смотреть.

WereFox ★☆
() автор топика
Ответ на: комментарий от WereFox

Так, уже ближе к телу. Осталось только понять, какого *** IDE его не использует. Спасибо, буду смотреть.

А должно?

UVV ★★★★★
()
Ответ на: комментарий от eao197

Еще из модных и молодежных: fmtlib

Зачем столько кода на цепепе, если есть printf() :-)

anonymous
()
Ответ на: комментарий от a1batross

Плюсую s{n}printf.

itoa это что-то замшелое и покрытое мохом. Непереносимое и отсутствующее в стандартных библиотеках. Кажется этот костыль был предложен в K&R.

EXL ★★★★★
()
Ответ на: комментарий от a1batross

itoa? Оно только под MSVC есть.

Это, конечно, не так. У itoa другая проблема - код возврата. Так что остается snprintf или std::to_string.

tailgunner ★★★★★
()
Ответ на: комментарий от nikolnik

Шел 2016 год, в плюсах нет одного нормального способа сконвертировать число в строку.

Зато там есть reinterpret_cast :-)

anonymous
()
Ответ на: комментарий от eao197

Я вам больше скажу, в плюсах даже нет нормального понятия «строка».

Лучше скажи, что там есть нормального :-)

anonymous
()
Ответ на: комментарий от eao197

Основная проблема не в том, что в плюсах чего-то нет, а, наоборот, в том, что там этого добра слишком много. В любом проекте, которому больше пары лет и который использует внешние библиотеки, легко наберётся с десяток разного рода велосипедов на тему тех же строк, включая стандартные std::string, std::wstring, std::basic_string<whatever>.

Gvidon ★★★★
()
Ответ на: комментарий от anonymous

А сколько тебе надо лет, чтоб начать их использовать?

Столько, сколько понадобится заказчикам, которые до сих пор живут на всяких древних дебианах и бздях.

Gvidon ★★★★
()
Ответ на: комментарий от tailgunner

Я не разбирался что с ним не так. Знаю точно есть в студии и её библиотеке. В остальных даже намеков нет.

Просто всегда использую snprintf. :)

a1batross ★★★★★
()

как в крестах/сишке можно записать данные из переменной типа int в string?

snprinf(«%d»)
pacify ★★★★★
()
Ответ на: комментарий от Gvidon

или std::to_string

Который из 11 плюсов

Знаю. Но я набыдлил свой. Дело нехитрое.

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

4.2

А ты попробуй это собрать десятой студией. Приходится под ифдефами заменять на _snprintf, да ещё и не забывать, что поведение не совсем идентичное.

Gvidon ★★★★
()
Ответ на: комментарий от Gvidon

О том и речь. Что в каких-нибудь Java, Python или Ruby есть общепринятое понятие «строка», а в C++, в зависимости от условий, доступных библиотек и уровня соответствия компилятора стандарту строкой может быть как char[], так и std::string, так и std::wstring или даже какой-нибудь std::vector<char> с оберткой вроде string_view или чем-то подобным.

Отсюда и вопрос о конвертации числа в строку может иметь целую кучу ответов.

eao197 ★★★★★
()
Ответ на: комментарий от Gvidon

Столько, сколько понадобится заказчикам, которые до сих пор живут на всяких древних дебианах и бздях.

Да ну ладно. У нас есть клиент еще аж Debian Lenny - прекрасно пользуется нашим софтом на С++11.

anonymous
()
Ответ на: комментарий от Gvidon

А ты попробуй это собрать десятой студией

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

anonymous
()
Ответ на: комментарий от Gvidon

которые до сих пор живут на всяких древних дебианах

В oldstable Debian'а, который wheezy, GCC 4.7, который уже поддерживает C++11, хоть и не полностью.

i-rinat ★★★★★
()

Для интов все очень просто:


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

char *itoa(int i){
	int N = 2, M = i; // N=2 - minimal value (1 digit + EOL)
	if(i < 0){ M = -i; ++N;} // signum
	while(M /= 10) ++N;
	char *str = malloc(N);
	printf("allocated %d bytes\n", N);
	snprintf(str, N, "%d", i);
	return str;
}

int main(int argc, char **argv){
	if(argc != 2) return -1;
	long L = strtol(argv[1], NULL, 10);
	if(L > INT_MAX || L < INT_MIN) return -2;
	char *str = itoa((int)L);
	printf("get string: %s\n", str);
	free(str);
	return 0;
}
Для флоатов уже похуже, т.к. без фиксированной длины строки придется выделить буфер побольше, а потом вернуть strdup.

Эту же itoa тоже можно через strdup переписать:

#include <string.h>

char *itoa(int i){
	char buf[32];
	snprintf(buf, 32, "%d", i);
	char *str = strdup(buf);
	printf("allocated %d bytes\n", strlen(str)+1);
	return str;
}

anonymous
()
Ответ на: комментарий от eao197

в плюсах даже нет нормального понятия «строка»

Ну это если только в какой-нибудь суровой ембедщине. На всех остальных платформах есть ICU, в котором помимо очень крутых юникодных строк (fussball.toUpper() работает корректно, в отличие от), есть еще и регулярки для них, API календаря и еще куча разных плюшек.

anonymous
()
Ответ на: комментарий от WereFox

Для itoa stdlib.h подключаю

ЧТООО?

Это с каких таких пор в stdlib.h есть itoa? Его всегда надо было самостоятельно рисовать. Потому как нифига нет в стандартных библиотеках этой хрени. Да даже atoi в манах пользоваться не советуют!

anonymous
()

Если кто-то хочет поговорить о строках в Rust, создайте другую тему.

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

На всех остальных платформах есть ICU

А еще есть Qt. А еще есть обертки вокруг iconv.

И все вместе это приводит к тому, что понятие «строка» в C++ нуждается в дополнительном определении в зависимости от условий.

eao197 ★★★★★
()
Ответ на: комментарий от Gvidon

Да, release() мог бы вернуть мне копию на малых строках, или же указатель на массив - при больших строках :-)

Ps. Там комменты потёрли, не нравятся почему-то :-)

anonymous
()
Ответ на: комментарий от anonymous

А можно просто вспомнить, что snprintf вернёт тебе нужную длину, если ему не хватает, и не надо ничего руками считать. Ну и проверить результат snprintf на ошибку всегда не лишнее.

Gvidon ★★★★
()
Последнее исправление: Gvidon (всего исправлений: 1)
Ответ на: комментарий от a1batross

O RLY?

Хм, даже не знаю, откуда у меня это в голове взялось. Действительно, не из стандарта.

Deleted
()
Последнее исправление: romeo250501 (всего исправлений: 1)
Ответ на: комментарий от anonymous

Да, release() мог бы вернуть мне копию на малых строках, или же указатель на массив - при больших строках :-)

std::string - сам себе массив байт, если уж надо, например, нарезать сишных строк из содержимого. Так что задача больше надуманная, чем реальная.

anonymous
()
Ответ на: комментарий от anonymous

std::string - сам себе массив байт, если уж надо, например, нарезать сишных строк из содержимого. Так что задача больше надуманная, чем реальная.

До тех лишь пор, пока ты сидишь в пределах Си++ :-)

anonymous
()
Ответ на: комментарий от Gvidon

Ну, в этом случае придется итеративно увеличивать размер буфера, либо брать буфер заведомо большего размера, а потом strdup'ить его.

В общем, как-то через задницу все.

anonymous
()
Ответ на: комментарий от anonymous

Ну, в этом случае придется итеративно увеличивать размер буфера

Зачем? Вызови snprintf два раза, после первого он тебе скажет, сколько ему надо, ты выделишь ровно столько (точнее, +1 для нуля ещё), и нет никаких проблем. Это вряд ли будет сильно медленнее ручного подсчёта, но абсолютно точно надёжнее.

Gvidon ★★★★
()
Последнее исправление: Gvidon (всего исправлений: 1)
Ответ на: комментарий от Gvidon

И правда:

If the output was truncated due to this limit then the return value is the number of characters (excluding the terminating null byte) which would have been written to the final string if enough space had been available

А я маны не привык вдумчиво читать. Думал, snprintf возвращает то же, что и printf

anonymous
()
Ответ на: комментарий от Gvidon

Вот:

char *itoa(int i){
	int L = 2;
	char *str = malloc(L);
	int rest = snprintf(str, L, "%d", i);
	if(rest){
		L = rest+1;
		str = realloc(str, L);
		snprintf(str, L, "%d", i);
	}
	printf("allocated %d bytes\n", L);
	return str;
}

anonymous
()
Ответ на: комментарий от Gvidon

Это вряд ли будет сильно медленнее ручного подсчёта

Для чисел по сути ничего считать и не надо - это очевидно. А для сложного форматирования snprintf придется два раза пробежаться по всем исходным данным и форматированию. А это сишные строки пробежать, и кол-во цифр посчитать и пр.

но абсолютно точно надёжнее

Надежнее вообще не иметь дело с длиной буфера, проверками и указателями.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.