#c
#c
Вопрос:
Я хочу добавить переменную с начальными нулями в строку. Я ничего не смог найти в Google, чтобы кто-нибудь не упомянул (s)printf
, но я хочу сделать это без (s)printf
.
Кто-нибудь из читателей знает способ?
Ответ №1:
Я могу предложить это однострочное решение, если вам нужно поле с n_zero
нулями:
auto new_str = std::string(n_zero - std::min(n_zero, old_str.length()), '0') old_str;
Например, для std::string old_str = "45"; size_t n_zero = 4;
вы получаете new_str == "0045"
.
Комментарии:
1. Мне это нравится. Это означает, что мне не нужно создавать stringstream, у которого есть довольно большой багаж в отношении внутренних компонентов.
2. Очень хорошее решение! Что происходит, когда (n_zero — old_string. длина()) отрицательна? РЕДАКТИРОВАТЬ: Только что протестировал, похоже, что он все еще работает, передавая отрицательное значение.
3. @Castaa Аргументом для количества символов является
std::string::size_type
, который, как и большинство типов размера в stdlib, не имеет знака. Итак, если пользователь передает отрицательное число, оно оборачивается и приводит к большому положительному числу. Итак, это должно «работать», но, вероятно, не делать ожидаемую / полезную вещь (следовательно, почему типы размера без знака плохие, м’кей).4. добавлено исправление, касающееся переполнения целых чисел
5. @lys добавил уточнение для ожидаемых типов, в частности, n_zero должно иметь тип size_t, тогда он также совместим с используемым нами конструктором std::string.
Ответ №2:
Вы могли бы использовать std::string::insert
, std::stringstream
с потоковыми манипуляторами или Boost.Форматировать :
#include <string>
#include <iostream>
#include <iomanip>
#include <boost/format.hpp>
#include <sstream>
int main() {
std::string s("12");
s.insert(0, 3, '0');
std::cout << s << "n";
std::ostringstream ss;
ss << std::setw(5) << std::setfill('0') << 12 << "n";
std::string s2(ss.str());
std::cout << s2;
boost::format fmt("dn");
fmt % 12;
std::string s3 = fmt.str();
std::cout << s3;
}
Комментарии:
1. Приложение: Для заполнения целого числа до 20 символов:
auto padded = std::to_string(num); padded.insert(0, 20U - std::min(std::string::size_type(20), padded.length()), '0');
Этоmin
предотвращает обтекание, если строка, которую вы пытаетесь дополнить, слишком длинная. (20 символов не будут иметь этой проблемы для любого целого числа младше 64 бит). Приведение кsize_type
необходимо, потому что min жалуется на несоответствия на некоторых платформах.2. Я хотел бы, чтобы вы могли объяснить этот первый пример, используя
std::string
Ответ №3:
Вы могли бы сделать что-то вроде:
std::cout << std::setw(5) << std::setfill('0') << 1;
Это должно быть напечатано 00001
.
Однако обратите внимание, что символ заполнения является «липким», поэтому, когда вы закончите заполнять нулем, вам придется использовать std::cout << std::setfill(' ');
, чтобы снова получить обычное поведение.
Комментарии:
1. Нет, спасибо за ваш вклад, но это тот же способ, что и при использовании sprintf (:
2. не кажется липким.
std::cout << std::setw(5) << std::setfill('0') << 1 << 1 << std::endl;
выдает:000011
3. @AleksanderFular
std::setw
не является липким.std::setfill
является липким, но от него мало толку без слишком большой ширины, чтобы дать ему что-то делать. Итак, ваш первый1
получаетsetw(5)
и, следовательно, имеет начальные нули перед собой, но затемsetw
возвращается к значению по умолчанию, так что ваш второй1
просто печатается как1
. Итак,00001
1
=000011
. Дело в том, что если вы позже установитеsetw
, вы обнаружите, что предыдущийsetfill
символ все еще действовал, потому чтоsetfill
is not sticky => не сбрасывается значение пробела по умолчанию.4. Именно то, что мне было нужно. Спасибо.
Ответ №4:
// assuming that `original_string` is of type `std:string`:
std::string dest = std::string( number_of_zeros, '0').append( original_string);
Комментарии:
1. Разве это не просто добавит нули без учета длины «original_string»?
number_of_zeros = 4 original_string = "99" dest will become: 000099 (and not 0099)
. Пожалуйста, поправьте меня, если я ошибаюсь, или я, возможно, не понимаю, что на самом деле означают «начальные нули»…2. @lepe Это отвечает на вопрос, как написано. Написал ли OP то, что они на самом деле имели в виду, это другой вопрос.
Ответ №5:
У меня это хорошо работает. Вам не нужно переключать setfill обратно на ‘ ‘, поскольку это временный поток.
std::string to_zero_lead(const int value, const unsigned precision)
{
std::ostringstream oss;
oss << std::setw(precision) << std::setfill('0') << value;
return oss.str();
}
Ответ №6:
Если вы хотите изменить исходную строку вместо создания копии, вы можете использовать std::string::insert()
.
std::string s = "123";
unsigned int number_of_zeros = 5 - s.length(); // add 2 zeros
s.insert(0, number_of_zeros, '0');
Результат:
00123
Ответ №7:
memcpy(target,'0',sizeof(target));
target[sizeof(target)-1] = 0;
Затем вставьте любую строку, с которой вы хотите, с префиксом нуля в конце буфера.
Если это целое число, помните, что log_base10(number) 1
(иначе ln(number)/ln(10) 1
) дает вам длину числа.
Комментарии:
1. Нет, спасибо за попытку, но я хочу иметь возможность добавлять переменное количество нулей.
2. @Guus: Это является переменным числом нулей. Однако вы можете заменить (sizeof(target)) каким-либо другим числом, если это вас устроит.
3. @Guus: В частности, судя по вашему комментарию ниже, вы хотели d, верно? Если буфер имеет длину в шесть символов, это именно то, что мой код сделал бы для вас (по крайней мере, часть заполнения нулем, с указанием числа в конце, была оставлена для вас).