LINUX.ORG.RU

Конвертация целого в строку по формату.

 , ,


0

2

В стандарте C++20 это скорее всего можно решить фичами пришедшими из библиотеки fmt. А что изящнее будет выглядеть на C++11?

Суть вопроса следующая. Есть std::string строка. К ней в цикле нужно присоединить целый номер в 4 позиции, пустые заполняются нулями. Например, i = 23, «test0023». Не вывести, а получить переменную std::string.

Первое что гуглится - использование «oimanip» + «stringstream», с использованием временной переменной std::stringstream, в которую пишется значение «0023» с помощью setw и fill, и конвертацией её в std::string. В начале цикла разве что её ещё опустошать нужно, иначе следующим шагом поистыковываться будет «00230024».

Есть ещё способы из стандартной библиотеки для <C++20, но без оперирования нуль-терминированными строками в явном виде?

Перемещено leave из talks

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

кто мешает использовать новый компилятор?

например он может отсутствовать под целевую платформу или есть «привязка» к blob

причин много, конечно обычно на x86_64 с ними не сталкиваются, но в embedded это широко распространнёно

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

И в iostream и sprintf обязана использоваться locale, что ставит крест на высокой производительности.

Компилятор вправе менять конкретную реализацию, пока поведение кода остаётся тем же. Если форматная строка содержит только %04u и известна на этапе компиляции, код можно переписать.

printf уже меняется на puts(), что экономит время на парсинг строки во время исполнения. Нет принципиальных преград в реализации аналогичной оптимизации для sprintf.

i-rinat ★★★★★
()
Ответ на: комментарий от AlexVR

Ну так std::string и std::vector тоже вполне себе нормальные обёртки над СИ-строкой.

Заранее создать вектор строк вида «0001»,«0002», «0003», …, «9998», «9999» и дергать их оттуда по порядковому номеру слишком заманчиво. Не искушай меня!

Шучу. Пока всё-таки оставлю streamstring, так как от замены на sprintf лучше не станет, а внешние либы и хэдеры тащить не хочется.

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

А что насчёт какого-нить std::replace()?

Что-то вроде такого?

std::string fstr = "File_0000";
str_i = std::to_string(i);
fstr.replace(fstr.begin() + fstr.length() - str_i.length(), fstr.end(), str_i);

Что-то мне самому уже страшно.

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

на современных компиляторах норм: https://quick-bench.com/q/9nWh6hEx78PUb09O5Y9vV7mrbJ8

тут похожие результаты: https://www.zverovich.net/2020/06/13/fast-int-to-string-revisited.html

в 2013 говорят to_string был не очень(правда там Apple и clang, может на Linux и gcc и тогда было норм):

https://www.zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html

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

в 2013 говорят to_string был не очень

По табличке почти в 2 раза лучше по скорости чем stringstream. Хотя скорость в данном случае не критична.

Надо проверить как работает с replace.

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

а внешние либы и хэдеры тащить не хочется.

Вот что за детский сад для тех кому за 50. Почему если писать на Go/Rust/Python/Foo/Bar/Baz/…, то использование внешних библиотек нормально. А как плюсы, так всё. Мандраж.

Тебе же сказали. Хочешь как в С++20, то используй fmtlib. Быстро, просто, и не только для вывода числа. gcc 4.7 поддерживается. Вот что ещё надо? stringstream + iomanip - это ужас на крыльях ночи.

AlexVR ★★★★★
()

А если уж совсем зависимости тянуть лень. То:

str[i+3] = '0' + x % 10;
x /= 10;
str[i+2] = '0' + x % 10;
x /= 10;
str[i+1] = '0' + x % 10;
x /= 10;
str[i+0] = '0' + x % 10;
AlexVR ★★★★★
()
Ответ на: комментарий от AlexVR

stringstream + iomanip - это ужас на крыльях ночи

Я выше вариант с str.replace() предложил или созданием вектора строк с готовым результатом ;)

Вот что за детский сад для тех кому за 50. Почему если писать на Go/Rust/Python/Foo/Bar/Baz/…, то использование внешних библиотек нормально. А как плюсы, так всё. Мандраж.

Если их использование можно отложить, то стараюсь их отложить. Там не так много операций со строками и выводом требуется, даже в функцию лень заворачивать из-за «разовости».

Go/Rust/Python/Foo/Bar/Baz/…, то использование внешних библиотек нормально.

Смотря для чего: не тащить же мне, например, ради разового перемножения матрицы 2х2 на число целую библиотеку. С внешними библиотеками есть одна проблема - они иногда меняют API, за чем приходится отдельно следить время от времени.

Я ничего не имею против fmt и считаю её существование несомненным плюсом, очень рад, что она есть.

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

А так не работает

Уже давно работает, но это не с++, так как нельзя подменять ключевые слова макросами.

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

так как нельзя подменять ключевые слова макросами.

Где написано? Почему мой g++ про это не знает?

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

16.5.4.3.2 Macro names [macro.names]

2 A translation unit shall not #define or #undef names lexically identical to keywords, to the identifiers listed in Table 4, or to the attribute-tokens described in 9.12, except that the names likely and unlikely may be defined as function-like macros (15.6).

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

g++ не знает, а clang знает

Как всегда clang не дает погромистам программистам программировать.

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