printf int to char array with left padded spaces - c++

I have a bit of a brain dead moment.
I have to store the string representation of an int to a char[], but the ascii representation will have to be left padded by spaces.
A snprintf will do the job.
char data [6];
int msg_len = 10;
std::snprintf(data, 6, "%*d", 5, msg_len);
//" 10" <-- OK
I just wonder if there is a more elegant way to do it.
I have access to C++11
Also there's a a bit of a problem, I think snprintf will add also a terminating character, and I have to avoid that.
I could have an intermediary buffer and copy that one into my data, but it would add additional complexity.
I need to do it in place, because those data structures are part of a message I have to send to a server that accepts input formatted that way.
The message looks like:
struct
{
char first_field [6];
char second_field [8];
char data_field [12];
};
And I might need to set the second_field before having set the first one. Also I have a lot more fields to fill in, so a generic solution would be appreciated.
As long as I can convert an int to that string representation would be fine.

this can be achived by combination of std::ostringstream, and io manipulators, such as: std::setfill, std::setw and other:
std::ostringstream s;
s << std::setfill('0') << std::setw(7) << 1015;
std::string str = s.str();
std::cout << str << std::endl; // outputs "0001015"

Within your indicated constraints this may improve on your own answer:
#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)),' ');
}
For a demo, append:
#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;
}
which runs like:
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)

I just wonder if there is a more elegant way to do it.
Andrei R. already showed an elegant way, so I won't repeat it, but I'll answer your other questions.
Also there's a a bit of a problem, I think snprintf will add also a terminating character, and I have to avoid that.
There is no way to avoid writing null with snprintf.
I could have an intermediary buffer and copy that one into my data, but it would add additional complexity.
That is the typical way to achieve what you want. This approach can also be taken using the result from std::ostringstream as the intermediary buffer.
Depending on what you intend to use the non null terminated string for, there might be approaches.

For those interested I rolled out my own simplistic solution, which fits my needs for now.
I only handle unsigned values and no locale, but it works for what I need to do.
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);
}
}

Related

C++: Format String Containing Hex Value

Working with C++ on Visual Studio 2010.
Trying to come up with a robust function that will take a hex value as string and size as integer and then output the formatted hex value.
For e.g.,
If the input string is "A2" and size is 1, then the output is "0xA2"
If the input string is "800" and size is 2, then the output is "0x0800"
If the input string is "DEF" and size is 4, then the output is "0x00000DEF"
If the input string is "00775" and size is 4, then the output is "0x00000775"
If the input string is "FB600" and size is 3, then the output is "0x0FB600"
The basic idea is, multiply size by 2 and then if the string length is less than that, then add leading zeros to the hex value and then append it with "0x".
"0x" is appended irrespective of whether leading zeros are added.
As you see in 1st example, there's no zeros to add as the string already contains 2 characters.
I came up with below function, but it's having memory corruption. Also when i try to process large amount of data by calling this function few hundrend times, it crashes. Seems my logic has memory holes in it.
So am hoping that someone can come up with a robust intelligent code for this function.
What i tried:
void formatHexString(char* inputHex, int size, char* outputFormattedHex)
{
int len = size * 2;
int diff = len - strlen(inputHex);
char * tempHex = new char [diff + 2]; //"2" is for holding "0x"
tempHex[0] = '0';
tempHex[1] = 'x';
if (len > strlen(inputHex))
{
for (int i = 2; i < ((len - strlen(inputHex)) + 2); i++)
{
tempHex[i] = '0';
}
}
strcat(tempHex, inputHex);
sprintf(outputFormattedHex, "%s", tempHex);
delete [] tempHex;
cout <<outputFormattedHex <<endl;
}
int main
{
char bbb1[24];
formatHexString("23", 1, bbb1);
char bbb2[24];
formatHexString("A3", 2, bbb2);
char bbb3[24];
formatHexString("0AA23", 4, bbb3);
char bbb4[24];
formatHexString("7723", 4, bbb4);
char bbb5[24];
formatHexString("AA023", 4, bbb5);
return 0;
}
UPDATED:
I cannot modify the arguments to original function as this function is called from a different application. So i modified my original function with your code, but this is not working. Any ideas?
void formatHexString(char* inputHex, int size, char* outputFormattedHex)
{
string input(inputHex);
std::size_t const input_len(input.length());
if (!size || (size * 2 < input_len))
size = input_len / 2 + input_len % 2;
std::stringstream ss;
ss << "0x" << std::setw(2 * size) << std::setfill('0') << input;
sprintf(outputFormattedHex, "%s", ss.str());
}
#include <iostream>
#include <sstream>
#include <iomanip>
#include <string>
#include <cstddef>
std::string formatHexString(std::string const & input, std::size_t size = 0)
{
std::size_t const input_len(input.length());
// always round up to an even count of digits if no size is specified
// or size would cause the output to be truncated
if (!size || (size * 2 < input_len))
size = input_len / 2 + input_len % 2;
std::stringstream ss;
ss << "0x" << std::setw(2 * size) << std::setfill('0') << input;
return ss.str();
}
int main()
{
std::cout << formatHexString( "23") << '\n'
<< formatHexString( "A3", 2) << '\n'
<< formatHexString( "AA23", 4) << '\n'
<< formatHexString( "7723", 4) << '\n'
<< formatHexString("AA023", 4) << '\n';
}
Solution without std::stringstream:
#include <string>
#include <cstddef>
std::string formatHexString(std::string const & input, std::size_t size = 0)
{
std::size_t const input_len(input.length());
// always round up to an even count of digits if no size is specified
// or size would cause the output to be truncated
if (!size || (size * 2 < input_len))
size = input_len / 2 + input_len % 2;
std::string result("0x");
for (std::size_t i = 0, leading_zeros = size * 2 - input_len; i < leading_zeros; ++i)
result += '0';
result += input;
return result;
}
Updated:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <iomanip>
#include <sstream>
#include <cstddef>
#include <cstdio>
void formatHexString(char const * inputHex, int size, char * outputFormattedHex)
{
int const input_len(std::strlen(inputHex));
if (!size || (size * 2 < input_len))
size = input_len / 2 + input_len % 2;
std::stringstream ss;
ss << "0x" << std::setw(2 * size) << std::setfill('0') << inputHex;
std::strcpy(outputFormattedHex, ss.str().c_str());
}
int main()
{
char output[24];
formatHexString("23", 1, output);
std::cout << output << '\n';
formatHexString("A3", 2, output);
std::cout << output << '\n';
formatHexString("0AA23", 4, output);
std::cout << output << '\n';
formatHexString("7723", 4, output);
std::cout << output << '\n';
formatHexString("AA023", 4, output);
std::cout << output << '\n';
}
It is unclear from your question, what you expect to happen with leading zeros on the input: I.e. either input "00000000EA" Size 2 turns to "00EA", or it keeps all its leading zeros.
This simple solution is for both cases (bTrim = true, for the 1st case):
#include <string>
void formatHexString(std::string & strHex, unsigned int nSize, bool bTrim = true)
{
if (bTrim) // Trim leading-zeros:
strHex = strHex.substr(strHex.find_first_not_of('0'));
if (nSize > strHex.length()) // Pad with leading-zeros to fit nSize:
strHex.insert(0, std::string(nSize - strHex.length(), '0').c_str());
strHex.insert(0, "0x"); // Insert prefix
}
-
If it's important to keep the original signature, wrap the above formatHexString with:
void formatHexString(char* inputHex, int size, char* outputFormattedHex)
{
std::string strHex(inputHex);
formatHexString(strHex, size * 2);
strcpy_s(outputFormattedHex, strHex.length()+1, strHex.c_str()); // Visual Studio
}

Convert string of hex to char array c++ [duplicate]

This question already has answers here:
Converting a hex string to a byte array
(22 answers)
Closed 3 years ago.
I have a string that represents an hexadecimal number:
std::string hex = "3371";
I want to convert it to a char array:
char hex[2] {0x33, 0x71};
Is there any convenient way to do it? I can use c++11 features, if it may help.
Motivation:
I need to save an integer (4 bytes), using 2 bytes char array.
The way how I thought it can be done is to convert it to string using std::hex, and then convert the string to the char array, but this is the point where I cannot continue..
If there is another simple way - I would like to hear :)
Important: I can assume that the hex number is less than 0xFFFF, and a positive number.
Just use std::stoi():
std::string hex = "3371";
uint16_t num = std::stoi( hex, nullptr, 16 );
uint8_t array[sizeof(num)];
memcpy( array, &num, sizeof( num ) );
note order of bytes will depend of endianness of your platform. If you need network order (as shown on your example) use htons() function:
uint16_t num = htons( std::stoi( hex, nullptr, 16 ) );
I found out a better way to convert a number to char array, as I needed. This solution works only for unsigned types!
template <typename T> bool ToByteArray(T num, unsigned char* ret, size_t size) {
if (ret == nullptr) {
std::cout << "Error in: " << __func__ << ": nullptr" << std::endl;
return false;
}
// drop the right-most bytes and convert to new right most byte.
for (int i = 0; i < size; i++) {
ret[i] = (int)((num >> (24 - 8*i)) & 0xFF);
}
return true;
}
This is more elegant way to do it.
If you want to convert it back - you might use:
long FormatBlock(const unsigned char* arr, size_t size) {
long num = 0;
for (int i = 0; i < size; i++) {
num += ((long)arr[i] << (24 - i*8));
}
return num;
}

Get the number of digits in an int

How do I detect the length of an integer? In case I had le: int test(234567545);
How do I know how long the int is? Like telling me there is 9 numbers inside it???
*I have tried:**
char buffer_length[100];
// assign directly to a string.
sprintf(buffer_length, "%d\n", 234567545);
string sf = buffer_length;
cout <<sf.length()-1 << endl;
But there must be a simpler way of doing it or more clean...
How about division:
int length = 1;
int x = 234567545;
while ( x /= 10 )
length++;
or use the log10 method from <math.h>.
Note that log10 returns a double, so you'll have to adjust the result.
Make a function :
int count_numbers ( int num) {
int count =0;
while (num !=0) {
count++;
num/=10;
}
return count;
}
Nobody seems to have mentioned converting it to a string, and then getting the length. Not the most performant, but it definitely does it in one line of code :)
int num = -123456;
int len = to_string(abs(num)).length();
cout << "LENGTH of " << num << " is " << len << endl;
// prints "LENGTH of 123456 is 6"
You can use stringstream for this as shown below
stringstream ss;
int i = 234567545;
ss << i;
cout << ss.str().size() << endl;
if "i" is the integer, then
int len ;
char buf[33] ;
itoa (i, buf, 10) ; // or maybe 16 if you want base-16 ?
len = strlen(buf) ;
if(i < 0)
len-- ; // maybe if you don't want to include "-" in length ?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
int i=2384995;
char buf[100];
itoa(i, buf, 10); // 10 is the base decimal
printf("Lenght: %d\n", strlen(buf));
return 0;
}
Beware that itoa is not a standard function, even if it is supported by many compilers.
len=1+floor(log10(n));//c++ code lib (cmath)
looking across the internet it's common to make the mistake of initializing the counter variable to 0 and then entering a pre-condition loop testing for as long as the count does not equal 0. a do-while loop is perfect to avoid this.
unsigned udc(unsigned u) //unsigned digit count
{
unsigned c = 0;
do
++c;
while ((u /= 10) != 0);
return c;
}
it's probably cheaper to test whether u is less than 10 to avoid the uneccessary division, increment, and cmp instructions for cases where u < 10.
but while on that subject, optimization, you could simply test u against constant powers of ten.
unsigned udc(unsigned u) //unsigned digit count
{
if (u < 10) return 1;
if (u < 100) return 2;
if (u < 1000) return 3;
//...
return 0; //number was not supported
}
which saves you 3 instructions per digit, but is less adaptable for different radixes inaddition to being not as attractive, and tedious to write by hand, in which case you'd rather write a routine to write the routine before inserting it into your program. because C only supports very finite numbers, 64bit,32bit,16bit,8bit, you could simply limit yourself to the maximum when generating the routine to benefit all sizes.
to account for negative numbers, you'd simply negate u if u < 0 before counting the number of digits. of course first making the routine support signed numbers.
if you know that u < 1000,
it's probably easier to just write, instead of writing the routine.
if (u > 99) len = 3;
else
if (u > 9) len = 2;
else len = 1;
Here are a few different C++ implementations* of a function named digits() which takes a size_t as argument and returns its number of digits. If your number is negative, you are going to have to pass its absolute value to the function in order for it to work properly:
The While Loop
int digits(size_t i)
{
int count = 1;
while (i /= 10) {
count++;
}
return count;
}
The Exhaustive Optimization Technique
int digits(size_t i) {
if (i > 9999999999999999999ull) return 20;
if (i > 999999999999999999ull) return 19;
if (i > 99999999999999999ull) return 18;
if (i > 9999999999999999ull) return 17;
if (i > 999999999999999ull) return 16;
if (i > 99999999999999ull) return 15;
if (i > 9999999999999ull) return 14;
if (i > 999999999999ull) return 13;
if (i > 99999999999ull) return 12;
if (i > 9999999999ull) return 11;
if (i > 999999999ull) return 10;
if (i > 99999999ull) return 9;
if (i > 9999999ull) return 8;
if (i > 999999ull) return 7;
if (i > 99999ull) return 6;
if (i > 9999ull) return 5;
if (i > 999ull) return 4;
if (i > 99ull) return 3;
if (i > 9ull) return 2;
return 1;
}
The Recursive Way
int digits(size_t i) { return i < 10 ? 1 : 1 + digits(i / 10); }
Using snprintf() as a Character Counter
⚠ Requires #include <stdio.h> and may incur a significant performance penalty compared to other solutions. This method capitalizes on the fact that snprintf() counts the characters it discards when the buffer is full. Therefore, with the right arguments and format specifiers, we can force snprintf() to give us the number of digits of any size_t.
int digits(size_t i) { return snprintf (NULL, 0, "%llu", i); }
The Logarithmic Way
⚠ Requires #include <cmath> and is unreliable for unsigned integers with more than 14 digits.
// WARNING! There is a silent implicit conversion precision loss that happens
// when we pass a large int to log10() which expects a double as argument.
int digits(size_t i) { return !i? 1 : 1 + log10(i); }
Driver Program
You can use this program to test any function that takes a size_t as argument and returns its number of digits. Just replace the definition of the function digits() in the following code:
#include <iostream>
#include <stdio.h>
#include <cmath>
using std::cout;
// REPLACE this function definition with the one you want to test.
int digits(size_t i)
{
int count = 1;
while (i /= 10) {
count++;
}
return count;
}
// driver code
int main ()
{
const int max = digits(-1ull);
size_t i = 0;
int d;
do {
d = digits(i);
cout << i << " has " << d << " digits." << '\n';
i = d < max ? (!i ? 9 : 10 * i - 1) : -1;
cout << i << " has " << digits(i) << " digits." << '\n';
} while (++i);
}
* Everything was tested on a Windows 10 (64-bit) machine using GCC 12.2.0 in Visual Studio Code .
As long as you are mixing C stdio and C++ iostream, you can use the snprintf NULL 0 trick to get the number of digits in the integer representation of the number. Specifically, per man 3 printf If the string exceeds the size parameter provided and is truncated snprintf() will return
... the number of characters (excluding the terminating null byte)
which would have been written to the final string if enough space
had been available.
This allows snprintf() to be called with the str parameter NULL and the size parameter 0, e.g.
int ndigits = snprintf (NULL, 0, "%d", 234567545)
In your case where you simply wish to output the number of digits required for the representation, you can simply output the return, e.g.
#include <iostream>
#include <cstdio>
int main() {
std::cout << "234567545 is " << snprintf (NULL, 0, "%d", 234567545) <<
" characters\n";
}
Example Use/Output
$ ./bin/snprintf_trick
234567545 is 9 characters
note: the downside to using the snprintf() trick is that you must provide the conversion specifier which will limit the number of digits representable. E.g "%d" will limit to int values while "%lld" would allow space for long long values. The C++ approach using std::stringstream while still limited to numeric conversion using the << operator handles the different integer types without manually specifying the conversion. Something to consider.
second note: you shouldn't dangle the "\n" of the end of your sprintf() conversion. Add the new line as part of your output and you don't have to subtract 1 from the length...

How to convert an int to a binary string representation in C++

I have an int that I want to store as a binary string representation. How can this be done?
Try this:
#include <bitset>
#include <iostream>
int main()
{
std::bitset<32> x(23456);
std::cout << x << "\n";
// If you don't want a variable just create a temporary.
std::cout << std::bitset<32>(23456) << "\n";
}
I have an int that I want to first convert to a binary number.
What exactly does that mean? There is no type "binary number". Well, an int is already represented in binary form internally unless you're using a very strange computer, but that's an implementation detail -- conceptually, it is just an integral number.
Each time you print a number to the screen, it must be converted to a string of characters. It just so happens that most I/O systems chose a decimal representation for this process so that humans have an easier time. But there is nothing inherently decimal about int.
Anyway, to generate a base b representation of an integral number x, simply follow this algorithm:
initialize s with the empty string
m = x % b
x = x / b
Convert m into a digit, d.
Append d on s.
If x is not zero, goto step 2.
Reverse s
Step 4 is easy if b <= 10 and your computer uses a character encoding where the digits 0-9 are contiguous, because then it's simply d = '0' + m. Otherwise, you need a lookup table.
Steps 5 and 7 can be simplified to append d on the left of s if you know ahead of time how much space you will need and start from the right end in the string.
In the case of b == 2 (e.g. binary representation), step 2 can be simplified to m = x & 1, and step 3 can be simplified to x = x >> 1.
Solution with reverse:
#include <string>
#include <algorithm>
std::string binary(unsigned x)
{
std::string s;
do
{
s.push_back('0' + (x & 1));
} while (x >>= 1);
std::reverse(s.begin(), s.end());
return s;
}
Solution without reverse:
#include <string>
std::string binary(unsigned x)
{
// Warning: this breaks for numbers with more than 64 bits
char buffer[64];
char* p = buffer + 64;
do
{
*--p = '0' + (x & 1);
} while (x >>= 1);
return std::string(p, buffer + 64);
}
AND the number with 100000..., then 010000..., 0010000..., etc. Each time, if the result is 0, put a '0' in a char array, otherwise put a '1'.
int numberOfBits = sizeof(int) * 8;
char binary[numberOfBits + 1];
int decimal = 29;
for(int i = 0; i < numberOfBits; ++i) {
if ((decimal & (0x80000000 >> i)) == 0) {
binary[i] = '0';
} else {
binary[i] = '1';
}
}
binary[numberOfBits] = '\0';
string binaryString(binary);
http://www.phanderson.com/printer/bin_disp.html is a good example.
The basic principle of a simple approach:
Loop until the # is 0
& (bitwise and) the # with 1. Print the result (1 or 0) to the end of string buffer.
Shift the # by 1 bit using >>=.
Repeat loop
Print reversed string buffer
To avoid reversing the string or needing to limit yourself to #s fitting the buffer string length, you can:
Compute ceiling(log2(N)) - say L
Compute mask = 2^L
Loop until mask == 0:
& (bitwise and) the mask with the #. Print the result (1 or 0).
number &= (mask-1)
mask >>= 1 (divide by 2)
I assume this is related to your other question on extensible hashing.
First define some mnemonics for your bits:
const int FIRST_BIT = 0x1;
const int SECOND_BIT = 0x2;
const int THIRD_BIT = 0x4;
Then you have your number you want to convert to a bit string:
int x = someValue;
You can check if a bit is set by using the logical & operator.
if(x & FIRST_BIT)
{
// The first bit is set.
}
And you can keep an std::string and you add 1 to that string if a bit is set, and you add 0 if the bit is not set. Depending on what order you want the string in you can start with the last bit and move to the first or just first to last.
You can refactor this into a loop and using it for arbitrarily sized numbers by calculating the mnemonic bits above using current_bit_value<<=1 after each iteration.
There isn't a direct function, you can just walk along the bits of the int (hint see >> ) and insert a '1' or '0' in the string.
Sounds like a standard interview / homework type question
Use sprintf function to store the formatted output in the string variable, instead of printf for directly printing. Note, however, that these functions only work with C strings, and not C++ strings.
There's a small header only library you can use for this here.
Example:
std::cout << ConvertInteger<Uint32>::ToBinaryString(21);
// Displays "10101"
auto x = ConvertInteger<Int8>::ToBinaryString(21, true);
std::cout << x << "\n"; // displays "00010101"
auto x = ConvertInteger<Uint8>::ToBinaryString(21, true, "0b");
std::cout << x << "\n"; // displays "0b00010101"
Solution without reverse, no additional copy, and with 0-padding:
#include <iostream>
#include <string>
template <short WIDTH>
std::string binary( unsigned x )
{
std::string buffer( WIDTH, '0' );
char *p = &buffer[ WIDTH ];
do {
--p;
if (x & 1) *p = '1';
}
while (x >>= 1);
return buffer;
}
int main()
{
std::cout << "'" << binary<32>(0xf0f0f0f0) << "'" << std::endl;
return 0;
}
This is my best implementation of converting integers(any type) to a std::string. You can remove the template if you are only going to use it for a single integer type. To the best of my knowledge , I think there is a good balance between safety of C++ and cryptic nature of C. Make sure to include the needed headers.
template<typename T>
std::string bstring(T n){
std::string s;
for(int m = sizeof(n) * 8;m--;){
s.push_back('0'+((n >> m) & 1));
}
return s;
}
Use it like so,
std::cout << bstring<size_t>(371) << '\n';
This is the output in my computer(it differs on every computer),
0000000000000000000000000000000000000000000000000000000101110011
Note that the entire binary string is copied and thus the padded zeros which helps to represent the bit size. So the length of the string is the size of size_t in bits.
Lets try a signed integer(negative number),
std::cout << bstring<signed int>(-1) << '\n';
This is the output in my computer(as stated , it differs on every computer),
11111111111111111111111111111111
Note that now the string is smaller , this proves that signed int consumes less space than size_t. As you can see my computer uses the 2's complement method to represent signed integers (negative numbers). You can now see why unsigned short(-1) > signed int(1)
Here is a version made just for signed integers to make this function without templates , i.e use this if you only intend to convert signed integers to string.
std::string bstring(int n){
std::string s;
for(int m = sizeof(n) * 8;m--;){
s.push_back('0'+((n >> m) & 1));
}
return s;
}

base32 conversion in C++

does anybody know any commonly used library for C++ that provides methods for encoding and decoding numbers from base 10 to base 32 and viceversa?
Thanks,
Stefano
[Updated] Apparently, the C++ std::setbase() IO manipulator and normal << and >> IO operators only handle bases 8, 10, and 16, and is therefore useless for handling base 32.
So to solve your issue of converting
strings with base 10/32 representation of numbers read from some input to integers in the program
integers in the program to strings with base 10/32 representations to be output
you will need to resort to other functions.
For converting C style strings containing base 2..36 representations to integers, you can use #include <cstdlib> and use the strtol(3) & Co. set of functions.
As for converting integers to strings with arbitrary base... I cannot find an easy answer. printf(3) style format strings only handle bases 8,10,16 AFAICS, just like std::setbase. Anyone?
Did you mean "base 10 to base 32", rather than integer to base32? The latter seems more likely and more useful; by default standard formatted I/O functions generate base 10 string format when dealing with integers.
For the base 32 to integer conversion the standard library strtol() function will do that. For the reciprocal, you don't need a library for something you can easily implement yourself (not everything is a lego brick).
Here's an example, not necessarily the most efficient, but simple;
#include <cstring>
#include <string>
long b32tol( std::string b32 )
{
return strtol( b32.c_str(), 0, 32 ) ;
}
std::string itob32( long i )
{
unsigned long u = *(reinterpret_cast<unsigned long*>)( &i ) ;
std::string b32 ;
do
{
int d = u % 32 ;
if( d < 10 )
{
b32.insert( 0, 1, '0' + d ) ;
}
else
{
b32.insert( 0, 1, 'a' + d - 10 ) ;
}
u /= 32 ;
} while( u > 0 );
return b32 ;
}
#include <iostream>
int main()
{
long i = 32*32*11 + 32*20 + 5 ; // BK5 in base 32
std::string b32 = itob32( i ) ;
long ii = b32tol( b32 ) ;
std::cout << i << std::endl ; // Original
std::cout << b32 << std::endl ; // Converted to b32
std::cout << ii << std::endl ; // Converted back
return 0 ;
}
In direct answer to the original (and now old) question, I don't know of any common library for encoding byte arrays in base32, or for decoding them again afterward. However, I was presented last week with a need to decode SHA1 hash values represented in base32 into their original byte arrays. Here's some C++ code (with some notable Windows/little endian artifacts) that I wrote to do just that, and to verify the results.
Note that in contrast with Clifford's code above, which, if I'm not mistaken, assumes the "base32hex" alphabet mentioned on RFC 4648, my code assumes the "base32" alphabet ("A-Z" and "2-7").
// This program illustrates how SHA1 hash values in base32 encoded form can be decoded
// and then re-encoded in base16.
#include "stdafx.h"
#include <string>
#include <vector>
#include <iostream>
#include <cassert>
using namespace std;
unsigned char Base16EncodeNibble( unsigned char value )
{
if( value >= 0 && value <= 9 )
return value + 48;
else if( value >= 10 && value <= 15 )
return (value-10) + 65;
else //assert(false);
{
cout << "Error: trying to convert value: " << value << endl;
}
return 42; // sentinal for error condition
}
void Base32DecodeBase16Encode(const string & input, string & output)
{
// Here's the base32 decoding:
// The "Base 32 Encoding" section of http://tools.ietf.org/html/rfc4648#page-8
// shows that every 8 bytes of base32 encoded data must be translated back into 5 bytes
// of original data during a decoding process. The following code does this.
int input_len = input.length();
assert( input_len == 32 );
const char * input_str = input.c_str();
int output_len = (input_len*5)/8;
assert( output_len == 20 );
// Because input strings are assumed to be SHA1 hash values in base32, it is also assumed
// that they will be 32 characters (and bytes in this case) in length, and so the output
// string should be 20 bytes in length.
unsigned char *output_str = new unsigned char[output_len];
char curr_char, temp_char;
long long temp_buffer = 0; //formerly: __int64 temp_buffer = 0;
for( int i=0; i<input_len; i++ )
{
curr_char = input_str[i];
if( curr_char >= 'A' && curr_char <= 'Z' )
temp_char = curr_char - 'A';
if( curr_char >= '2' && curr_char <= '7' )
temp_char = curr_char - '2' + 26;
if( temp_buffer )
temp_buffer <<= 5; //temp_buffer = (temp_buffer << 5);
temp_buffer |= temp_char;
// if 8 encoded characters have been decoded into the temp location,
// then copy them to the appropriate section of the final decoded location
if( (i>0) && !((i+1) % 8) )
{
unsigned char * source = reinterpret_cast<unsigned char*>(&temp_buffer);
//strncpy(output_str+(5*(((i+1)/8)-1)), source, 5);
int start_index = 5*(((i+1)/8)-1);
int copy_index = 4;
for( int x=start_index; x<(start_index+5); x++, copy_index-- )
output_str[x] = source[copy_index];
temp_buffer = 0;
// I could be mistaken, but I'm guessing that the necessity of copying
// in "reverse" order results from temp_buffer's little endian byte order.
}
}
// Here's the base16 encoding (for human-readable output and the chosen validation tests):
// The "Base 16 Encoding" section of http://tools.ietf.org/html/rfc4648#page-10
// shows that every byte original data must be encoded as two characters from the
// base16 alphabet - one charactor for the original byte's high nibble, and one for
// its low nibble.
unsigned char out_temp, chr_temp;
for( int y=0; y<output_len; y++ )
{
out_temp = Base16EncodeNibble( output_str[y] >> 4 ); //encode the high nibble
output.append( 1, static_cast<char>(out_temp) );
out_temp = Base16EncodeNibble( output_str[y] & 0xF ); //encode the low nibble
output.append( 1, static_cast<char>(out_temp) );
}
delete [] output_str;
}
int _tmain(int argc, _TCHAR* argv[])
{
//string input = "J3WEDSJDRMJHE2FUHERUR6YWLGE3USRH";
vector<string> input_b32_strings, output_b16_strings, expected_b16_strings;
input_b32_strings.push_back("J3WEDSJDRMJHE2FUHERUR6YWLGE3USRH");
expected_b16_strings.push_back("4EEC41C9238B127268B4392348FB165989BA4A27");
input_b32_strings.push_back("2HPUCIVW2EVBANIWCXOIQZX6N5NDIUSX");
expected_b16_strings.push_back("D1DF4122B6D12A10351615DC8866FE6F5A345257");
input_b32_strings.push_back("U4BDNCBAQFCPVDBL4FBG3AANGWVESI5J");
expected_b16_strings.push_back("A7023688208144FA8C2BE1426D800D35AA4923A9");
// Use the base conversion tool at http://darkfader.net/toolbox/convert/
// to verify that the above base32/base16 pairs are equivalent.
int num_input_strs = input_b32_strings.size();
for(int i=0; i<num_input_strs; i++)
{
string temp;
Base32DecodeBase16Encode(input_b32_strings[i], temp);
output_b16_strings.push_back(temp);
}
for(int j=0; j<num_input_strs; j++)
{
cout << input_b32_strings[j] << endl;
cout << output_b16_strings[j] << endl;
cout << expected_b16_strings[j] << endl;
if( output_b16_strings[j] != expected_b16_strings[j] )
{
cout << "Error in conversion for string " << j << endl;
}
}
return 0;
}
I'm not aware of any commonly-used library devoted to base32 encoding but Crypto++ includes a public domain base32 encoder and decoder.
I don't use cpp, so correct me if I'm wrong. I wrote this code for the sake of translating it from C# to save my acquaintance the trouble. The original source, that which I used to create these methods, is on a different post, here, on stackoverflow:
https://stackoverflow.com/a/10981113/13766753
That being said, here's my solution:
#include <iostream>
#include <math.h>
class Base32 {
public:
static std::string dict;
static std::string encode(int number) {
std::string result = "";
bool negative = false;
if (number < 0) {
negative = true;
}
number = abs(number);
do {
result = Base32::dict[fmod(floor(number), 32)] + result;
number /= 32;
} while(number > 0);
if (negative) {
result = "-" + result;
}
return result;
}
static int decode(std::string str) {
int result = 0;
int negative = 1;
if (str.rfind("-", 0) == 0) {
negative = -1;
str = str.substr(1);
}
for(char& letter : str) {
result += Base32::dict.find(letter);
result *= 32;
}
return result / 32 * negative;
}
};
std::string Base32::dict = "0123456789abcdefghijklmnopqrstuvwxyz";
int main() {
std::cout << Base32::encode(0) + "\n" << Base32::decode(Base32::encode(0)) << "\n";
return 0;
}