printf int到char数组,左边填充空格

时间:2016-06-07 07:36:49

标签: c++ c++11

我有一点脑死亡的时刻。

我必须将int的字符串表示存储到char[],但ascii表示必须用空格填充。 snprintf将完成这项工作。

  char data     [6];
  int msg_len = 10;
  std::snprintf(data, 6, "%*d", 5, msg_len);
  //"   10" <-- OK

我只是想知道是否有更优雅的方式来做到这一点。 我有权访问C++11 还有一个问题,我认为snprintf还会添加一个终止字符,我必须避免这种情况。 我可以有一个中间缓冲区并将其复制到我的数据中,但这会增加额外的复杂性。

我需要这样做,因为这些数据结构是我必须发送到服务器的消息的一部分,该服务器接受以这种方式格式化的输入。

信息如下:

  struct
  {
    char first_field   [6];
    char second_field  [8];
    char data_field    [12];
  };

我可能需要在设置第一个之前设置second_field。此外,我还有更多的字段需要填写,因此我们将非常感谢通用的解决方案。 只要我可以将int转换为该字符串表示就可以了。

4 个答案:

答案 0 :(得分:5)

这可以通过std::ostringstream和io操纵器的组合来实现,例如:std::setfillstd::setw和其他:

std::ostringstream s;
s << std::setfill('0') << std::setw(7) << 1015;
std::string str = s.str();
std::cout << str << std::endl; // outputs "0001015"

答案 1 :(得分:1)

在您指定的限制范围内,这可能会改善您自己的答案:

#include <algorithm>
#include <cstddef>
#include <cassert>

inline void 
unsigned_to_decimal( unsigned long number, char* buffer, std::size_t size)
{
    std::size_t i = size;
    buffer[size - 1] = '0';
    for (unsigned long n ;(n = number) > 0 && i > 0 ;) {
        buffer[--i] = '0' + n - (10 * (number /= 10));
    }
    assert(number == 0);
    std::fill(buffer,buffer + (i - (i == size)),' ');
}

对于演示,请附加:

#include <iostream>
#include <string>
#include <climits>
#include <array>

constexpr std::size_t decimal_digits(unsigned long n)
{
    return n / 10 > 0 ? 1 + decimal_digits(n / 10) : 1;
}


int main()
{
    const std::size_t max_digits = decimal_digits(ULONG_MAX);
    std::cout << "Print decimal 0, UINT_MAX, ULONG_MAX "
        "from left-padded char buffer, size " << max_digits << ":-\n"; 
    for (auto ul : std::array<unsigned long,3>{0,UINT_MAX,ULONG_MAX}) {
        char buf[max_digits];
        std::fill(buf,buf + max_digits,'?');
        std::cout << '[' << std::string(buf,buf + max_digits) << "]\n";
        unsigned_to_decimal(ul,buf,max_digits);
        std::cout << '[' << std::string(buf,buf + max_digits) << "]\n";
    }
    return 0;
}

的运行方式如下:

Print decimal 0, UINT_MAX, ULONG_MAX from left-padded char buffer, size 20:-
[????????????????????]
[                   0]
[????????????????????]
[          4294967295]
[????????????????????]
[18446744073709551615]

(g ++ -Wall -std = c ++ 11 -pedantic,GCC 5.3.1)

答案 2 :(得分:0)

  

我只是想知道是否有一种更优雅的方式来做到这一点。

Andrei R.已经表现出优雅的方式,所以我不会重复它,但我会回答你的其他问题。

  

还有一个问题,我认为snprintf还会添加一个终止字符,我必须避免这种情况。

无法避免使用snprintf写入null。

  

我可以有一个中间缓冲区并将其复制到我的数据中,但这会增加额外的复杂性。

这是达到你想要的典型方式。也可以使用std::ostringstream作为中间缓冲区的结果来采用这种方法。

根据您打算使用非空终止字符串的内容,可能有方法。

答案 3 :(得分:0)

对于那些感兴趣的人,我推出了自己的简单解决方案,这符合我现在的需求。 我只处理无符号值而没有语言环境,但它适用于我需要做的事情。

inline void unsigned_to_decimal( unsigned long number, char* buffer, std::size_t size)
{
    char* start = buffer;
    char* end   = buffer + size;

    if(number == 0)
    {
        *buffer++ = '0';
    }
    else
    {
        while( number != 0 )
        {
            *buffer++ = '0' + number % 10;
            number /= 10;
        }
        std::reverse( start, buffer );

        //need to fill the remaining characters with spaces
        std::fill(buffer, end, ' ');
        std::rotate(start, start + std::distance(start, buffer), end);
    }
}
相关问题