Преобразовать число в строку указанной длины в C ++
Вопрос
У меня есть несколько чисел разной длины (например, 1, 999, 76492 и т. д.), и я хочу преобразовать их все в строки общей длины (например, если длина равна 6, тогда эти строки будут: «000001», «000999», «076492»). Р>
Другими словами, мне нужно добавить правильное количество ведущих нулей к числу.
int n = 999;
string str = some_function(n,6);
//str = '000999'
Есть ли такая функция в C ++?
Решение
или используя строковые потоки:
#include <sstream>
#include <iomanip>
std::stringstream ss;
ss << std::setw(10) << std::setfill('0') << i;
std::string s = ss.str();
Я собрал информацию, которую нашел на arachnoid.com , потому что мне нравится Безопасный способ iostreams больше. Кроме того, вы можете одинаково использовать этот код в любом другом потоке вывода.
Другие советы
char str[7];
snprintf (str, 7, "%06d", n);
См. snprintf
Одна вещь, о которой вы можете знать, это потенциальная блокировка, которая может возникнуть при использовании подхода stringstream
. В STL, поставляемом с Visual Studio 2008, по крайней мере, есть много блокировок, снятых и выпущенных, поскольку различная информация о локали используется во время форматирования. Это может или не может быть проблемой для вас, в зависимости от того, сколько у вас потоков, которые могут одновременно преобразовывать числа в строки ...
Версия sprintf
не берет никаких блокировок (по крайней мере, в соответствии с инструментом мониторинга блокировок, который я сейчас разрабатываю ...) и поэтому может быть «лучше» для использования в одновременные ситуации.
Я заметил это только потому, что мой инструмент недавно выплюнул блокировки 'locale' как одни из самых востребованных для блокировок в моей серверной системе; это стало неожиданностью и может заставить меня пересмотреть подход, который я использовал (то есть вернуться к sprintf
из stringstream
) ... р>
stringstream сделает ( как xtofl указал ). формат повышения более удобен замена для snprintf.
Этот метод не использует ни потоки, ни sprintf. Помимо проблем с блокировкой, потоки снижают производительность и действительно являются излишним. Для потоков накладные расходы обусловлены необходимостью создания буфера пара и потока. Для sprintf издержки возникают из-за необходимости интерпретировать строку формата. Это работает, даже когда n отрицательно или когда строковое представление n длиннее, чем len . Это самое быстрое решение.
inline string some_function(int n, int len)
{
string result(len--, '0');
for (int val=(n<0)?-n:n; len>=0&&val!=0; --len,val/=10)
result[len]='0'+val%10;
if (len>=0&&n<0) result[0]='-';
return result;
}
Есть много способов сделать это. Самый простой будет:
int n = 999;
char buffer[256]; sprintf(buffer, "%06d", n);
string str(buffer);
sprintf - это C-подобный способ сделать это, который также работает в C ++.
В C ++ - сочетание форматирования потока строк и потока (см. http: // www .arachnoid.com / cpptutor / student3.html ) выполнит эту работу.
Это старая ветка, но, как fmt может сделать ее стандартной, здесь это дополнительное решение:
#include <fmt/format.h>
int n = 999;
const auto str = fmt::format("{:0>{}}", n, 6);
Обратите внимание, что fmt :: format (" {: 0 > 6} " ;, n)
работает одинаково хорошо, когда желаемая ширина известна во время компиляции. Другой вариант - abseil :
#include <absl/strings/str_format.h>
int n = 999;
const auto str = absl::StrFormat("%0*d", 6, n);
И снова возможен abs :: StrFormat ("% 06d " ;, n)
. расширенный формат - еще один инструмент для решения этой проблемы:
#include <boost/format.hpp>
int n = 999;
const auto str = boost::str(boost::format("%06d") % n);
К сожалению, спецификатор переменной ширины в качестве аргументов, связанных с оператором %
, не поддерживается, это требует настройки строки формата (например, const std :: string fmt = "% 0 " + std :: to_string (6) + " d " ;;
).
С точки зрения производительности abseil и fmt утверждают, что они очень привлекательны и быстрее, чем надстройка. В любом случае все три решения должны быть более эффективными, чем подходы std :: stringstream
, и, кроме семейства std :: * printf
, они не жертвуют безопасностью типов. р>