Преобразовать число в строку указанной длины в C++
У меня есть несколько чисел разной длины (например, 1, 999, 76492 и т. Д.), И я хочу преобразовать их все в строки общей длины (например, если длина равна 6, то эти строки будут: '000001', "000999", "076492").
Другими словами, мне нужно добавить правильное количество ведущих нулей к числу.
int n = 999;
string str = some_function(n,6);
//str = '000999'
Есть ли такая функция в C++?
9 ответов
Или используя строковые потоки:
#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
версия не берет никаких блокировок (по крайней мере, в соответствии с инструментом мониторинга блокировок, который я сейчас разрабатываю...) и поэтому может быть "лучше" для использования в параллельных ситуациях.
Я заметил это только потому, что мой инструмент недавно выплюнул блокировку "локали" как одну из наиболее востребованных блокировок в моей серверной системе; это стало неожиданностью и может заставить меня пересмотреть подход, который я использовал (то есть вернуться к sprintf
от stringstream
)...
Это старый поток, но поскольку fmt может сделать его стандартным, вот дополнительное решение:
#include <fmt/format.h>
int n = 999;
const auto str = fmt::format("{:0>{}}", n, 6);
Обратите внимание, что fmt::format("{:0>6}", n)
одинаково хорошо работает, когда желаемая ширина известна во время компиляции. Еще один вариант:
#include <absl/strings/str_format.h>
int n = 999;
const auto str = absl::StrFormat("%0*d", 6, n);
Снова, abs::StrFormat("%06d", n)
возможно. Формат Boost является еще одним инструментом для решения этой проблемы:
#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 утверждают, что они очень привлекательны и быстрее, чем boost. В любом случае все три решения должны быть более эффективными, чем std::stringstream
подходы, и кроме std::*printf
семья, они не жертвуют типом безопасности.
Этот метод не использует ни потоки, ни 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);
stringstream сделает ( как указал xtofl). Boost формат - более удобная замена snprintf.
sprintf - это C-подобный способ сделать это, который также работает в C++.
В C++ сочетание строкового и потокового форматирования вывода (см. http://www.arachnoid.com/cpptutor/student3.html) сделает эту работу.
Из С++ 11 вы можете сделать:
string to_string(unsigned int number, int length) {
string num_str = std::to_string(number);
if(num_str.length() >= length) return num_str;
string leading_zeros(length - num_str.length(), '0');
return leading_zeros + num_str;
}
Если вам также нужно обрабатывать отрицательные числа, вы можете переписать функцию, как показано ниже:
string to_string(int number, int length) {
string num_str = std::to_string(number);
if(num_str.length() >= length) return num_str;
string leading_zeros(length - num_str.length(), '0');
//for negative numbers swap the leading zero with the leading negative sign
if(num_str[0] == '-') {
num_str[0] = '0';
leading_zeros[0] = '-';
}
return leading_zeros + num_str;
}