我有一点脑死亡的时刻。
我必须将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转换为该字符串表示就可以了。
答案 0 :(得分:5)
这可以通过std::ostringstream
和io操纵器的组合来实现,例如:std::setfill
,std::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);
}
}