将数字转换为填充字符串
Converting number to a padded string
我正在尝试将数字类型转换为具有前导“0”的固定长度字符串表示形式(在只能处理字符串的 GUI 中使用 - 数字的字典排序真的很尴尬)。
与其在需要的地方创建字符串,我认为应该可以制作一个不错的模板供其他人使用,该模板也适用于不同的算术类型。
template <typename T, typename std::enable_if<std::is_arithmetic<T>::value, T>::type* = nullptr>
std::string arithmeticToMaxLengthString(const T& value)
{
std::string number, result;
number = std::to_string( value );
result = lpad( '0', std::numeric_limits<decltype(value)>::digits10 + 1, number );
return result;
}
std::string lpad( char filler, std::string::size_type length, const std::string& input)
{
std::string result;
if( input.length() < length )
{
result.append( lenght - input.lenght(), filler ).append( input );
return result;
}
return input;
}
到目前为止一切顺利。
它编译,我可以使用它。
但是:
当我尝试使用它时,我得到了一个惊喜。
使用 int32_t 调用此函数是
typedef int int32_t;
值为 100 结果是字符串“100”,长度为 3。
我很确定代码库中不存在名称如此糟糕的其他模板(我搜索了所有模板以及所有链接库),但我似乎无法理解代码有什么问题我已经生产了。
为了验证代码是否正确,我刚刚将它复制粘贴到它被调用的地方,现在基本上看起来像这样:
myDataClass{
int32_t quantity;
std::string numberAsString;
}
void setNumberString( myDataClass data )
{
std::string result = arithmeticToMaxLengthString( data.quantity );
std::string reference = lpad( '0', std::numeric_limits<decltype(value)>::digits10 + 1, std::to_string(data.quantity) );
std::cout << "quantity<" << data.quantity << "> numericLimits<" << std::numeric_limits<decltype(value)>::digits10 + 1 << ">" << std::endl;
std::cout << "result template: length<" << result.lenght() << "> content<" << result << ">" << std::endl;
std::cout << "result reference: length<" << reference.lenght() << "> content<" << reference << ">" << std::endl;
}
现在据我了解,调用模板 "arithmeticToMaxLengthString" 时使用 int32_t 作为参数类型,这是一个普通的 int,其中 "numeric_limits::digits10 + 1" 给出了 10。
但是当现在调用这个函数的数量为 100 时,结果会有所不同。
quantity<100> numericLimits<10>
result template: length<3> content<100>
result reference: length<10> content<0000000100>
我是否遗漏了有关模板的内容,enable_if 或 numeric_limits?
模板有何不同(除了显而易见的 enable_if)?
这并不是您问题的真正答案,而是关于如何使用 STL
实现相同功能的建议。
#include <iomanip>
#include <sstream>
template <typename T, unsigned N = 5>
std::string to_string_with_leading_0(T element) {
std::stringstream ss;
ss << std::setw(N) << std::setfill('0') << element;
return ss.str();
}
您的问题发生是因为您正在传递对 arithmeticToMaxLengthString
函数的引用。由于另一个答案 中列出的原因,std::numeric_limits
不适用于引用。
因此,我建议您使用模板类型 T
来获取数值限制,而不是使用 decltype(value)
:
result = lpad('0', std::numeric_limits<T>::digits10 + 1, number);
不仅解决了问题,而且看起来优雅多了。
我正在尝试将数字类型转换为具有前导“0”的固定长度字符串表示形式(在只能处理字符串的 GUI 中使用 - 数字的字典排序真的很尴尬)。
与其在需要的地方创建字符串,我认为应该可以制作一个不错的模板供其他人使用,该模板也适用于不同的算术类型。
template <typename T, typename std::enable_if<std::is_arithmetic<T>::value, T>::type* = nullptr>
std::string arithmeticToMaxLengthString(const T& value)
{
std::string number, result;
number = std::to_string( value );
result = lpad( '0', std::numeric_limits<decltype(value)>::digits10 + 1, number );
return result;
}
std::string lpad( char filler, std::string::size_type length, const std::string& input)
{
std::string result;
if( input.length() < length )
{
result.append( lenght - input.lenght(), filler ).append( input );
return result;
}
return input;
}
到目前为止一切顺利。 它编译,我可以使用它。 但是:
当我尝试使用它时,我得到了一个惊喜。 使用 int32_t 调用此函数是
typedef int int32_t;
值为 100 结果是字符串“100”,长度为 3。
我很确定代码库中不存在名称如此糟糕的其他模板(我搜索了所有模板以及所有链接库),但我似乎无法理解代码有什么问题我已经生产了。 为了验证代码是否正确,我刚刚将它复制粘贴到它被调用的地方,现在基本上看起来像这样:
myDataClass{
int32_t quantity;
std::string numberAsString;
}
void setNumberString( myDataClass data )
{
std::string result = arithmeticToMaxLengthString( data.quantity );
std::string reference = lpad( '0', std::numeric_limits<decltype(value)>::digits10 + 1, std::to_string(data.quantity) );
std::cout << "quantity<" << data.quantity << "> numericLimits<" << std::numeric_limits<decltype(value)>::digits10 + 1 << ">" << std::endl;
std::cout << "result template: length<" << result.lenght() << "> content<" << result << ">" << std::endl;
std::cout << "result reference: length<" << reference.lenght() << "> content<" << reference << ">" << std::endl;
}
现在据我了解,调用模板 "arithmeticToMaxLengthString" 时使用 int32_t 作为参数类型,这是一个普通的 int,其中 "numeric_limits::digits10 + 1" 给出了 10。 但是当现在调用这个函数的数量为 100 时,结果会有所不同。
quantity<100> numericLimits<10>
result template: length<3> content<100>
result reference: length<10> content<0000000100>
我是否遗漏了有关模板的内容,enable_if 或 numeric_limits? 模板有何不同(除了显而易见的 enable_if)?
这并不是您问题的真正答案,而是关于如何使用 STL
实现相同功能的建议。
#include <iomanip>
#include <sstream>
template <typename T, unsigned N = 5>
std::string to_string_with_leading_0(T element) {
std::stringstream ss;
ss << std::setw(N) << std::setfill('0') << element;
return ss.str();
}
您的问题发生是因为您正在传递对 arithmeticToMaxLengthString
函数的引用。由于另一个答案 std::numeric_limits
不适用于引用。
因此,我建议您使用模板类型 T
来获取数值限制,而不是使用 decltype(value)
:
result = lpad('0', std::numeric_limits<T>::digits10 + 1, number);
不仅解决了问题,而且看起来优雅多了。