将数字转换为填充字符串

时间:2020-02-16 19:45:16

标签: c++ c++11 templates enable-if numeric-limits

我正在尝试将数字类型转换为定长字符串表示形式,并以'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之外)?

2 个答案:

答案 0 :(得分:2)

发生您的问题是因为您传递了对arithmeticToMaxLengthString函数的引用。由于另一个答案here中列出的原因,std::numeric_limits不适用于引用。

因此,建议您使用模板类型T来获取数值限制,而不要使用decltype(value)

result = lpad('0', std::numeric_limits<T>::digits10 + 1, number);

它不仅可以解决问题,而且看起来也更加优雅。

答案 1 :(得分:1)

这并不是您问题的真正答案,而是有关如何使用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();
}