how to search "n bits" in a byte array? - c++

i have a byte array. Now i need to know the count of appearances of a bit pattern which length is N.
For example, my byte array is "00100100 10010010" and the pattern is "001". here N=3, and the count is 5.
Dealing with bits is always my weak side.

You could always XOR the first N bits and if you get 0 as a result you have a match. Then shift the searched bit "stream" one bit to the left and repeat. That is assuming you want to get matches if those sub-patterns overlap. Otherwise you should shift by pattern length on match.

If N may be arbitrary large You can store the bit pattern in a vector
vector<unsigned char> pattern;
The size of the vector should be
(N + 7) / 8
Store the pattern shifted to the right. By this, I mean, that for example, if N == 19, Your vector should look like:
|<- v[0] ->|<- v[1] ->|<- v[2] ->|
0 0 0 0 0 0 1 1 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1
| |<- pattern ->|
If You have Your pattern originally shifted to the left, You can use the function I'll present below, to shift the bits to the right.
Define a vector of bytes, of the same length as the pattern, to store a part of Your bit stream for comparing it with the pattern. I'll call it window
vector<unsigned char> window;
If N is not an integer multiple of 8, You will need to mask some leftmost bits in Your window, when comparing it with the pattern. You can define the mask this way:
unsigned char mask = (1 << (N % 8)) - 1;
Now, assuming the window contains the bits, it should, You could theoretically compare the pattern with the window using vector's operator == like this
window[0] &= mask;
bool isMatch = (window == pattern);
But there are good reasons to be a little bit more sophisticated. If N is large and Your byte array, You look for the pattern in, is significantly larger, it's worth it, to process the pattern and build a vector of size N+1:
vector<int> shifts;
This vector will store the information, how many bits to shift the bit stream by, for the next comparison, based on the position, at which there is a mismatch in the current window.
Consider the pattern 0001001100. You should compare the bits with the window from right to left. If there is a missmatch at the first bit, You know it's 1 and the first occurrence of 1 in Your pattern is at the position 2 counting form 0 form the right to the left. So in that case, You know, that it doesn't make sense to make a comparison if the number of new bits shifted form the bit stream into the window is less than 2. Similarly if the mismatch occurs at the third bit (position 2 counting form 0), the window should be moved by 7, because 3 consecutive zeros in your pattern are at the end. If the mismatch is at the position 4, You can move the window by 8 and so on. The sifts vector, at an index i will hold number of bits, by which to move the window, if the mismatch occurs at the position i. If there is a match, the window should be moved by the number of bits stored in shifts[N]. In the example above, a match means a shift by 8.
In practice of course, You compare whole bytes form the pattern with the bytes from the window (going form right to left) and if there is a mismatch You examine the bits in the byte to find the mismatch position.
if(window[i] != pattern[i])
{
int j = 0;
unsigned char mismatches = window[i] ^ pattern[i];
while((mismatches & 1) == 0)
{
mismatches >>= 1;
++j;
}
mismatch_position = 8 * (window.size() - i - 1) + j;
}
Here is a function that might come handy, when You need to shift some bits from Your bit stream into the window. I wrote it in C#, but conversion to C++ should be trivial. C# makes some casts necessary, that are probably not necessary in C++. Use unsigned char instead of byte, vector<unsigned char> & instead of byte [], size() instead of Length and maybe some more minor tweaks. The function is probably a little more general than needed in Your scenario, as it doesn't use the fact, that consecutive calls retrieve consecutive chunks of Your byte array, which maybe could make it a bit simpler, but I don't think it hurts. In the current form, it can retrieve arbitrary bit substring form the byte array.
public static void shiftBitsIntoWindow_MSbFirst(byte[] window, byte[] source,
int startBitPosition, int numberOfBits)
{
int nob = numberOfBits / 8;
// number of full bytes from the source
int ntsh = numberOfBits % 8;
// number of bits, by which to shift the left part of the window,
// in the case, when numberOfBits is not an integer multiple of 8
int nfstbb = (8 - startBitPosition % 8);
// number Of bits from the start to the first byte boundary
// The value is from the range [1, 8], which comes handy,
// when checking if the substring of ntsh first bits
// crosses the byte boundary in the source, by evaluating
// the expression ntsh <= nfstbb.
int nfbbte = (startBitPosition + numberOfBits) % 8;
// number of bits from the last byte boundary to the end
int sbtci;
// index of the first byte in the source, from which to start
// copying nob bytes from the source
// The way in which the (sbtci) index is calculated depends on,
// whether nob < window.Length
if(nob < window.Length)// part of the window will be replaced
// with bits from the source, but some part will remain in the
// window, only moved to the beginning and possibly shifted
{
sbtci = (startBitPosition + ntsh) / 8;
//Loop below moves bits form the end of the window to the front
//making room for new bits that will come form the source
// In the corner case, when the number by which to shift (ntsh)
// is zero the expression (window[i + nob + 1] >> (8 - ntsh)) is
// zero and the loop just moves whole bytes
for(int i = 0; i < window.Length - nob - 1; ++i)
{
window[i] = (byte)((window[i + nob] << ntsh)
| (window[i + nob + 1] >> (8 - ntsh)));
}
// At this point, the left part of the window contains all the
// bytes that could be constructed solely from the bytes
// contained in the right part of the window. Next byte in the
// window may contain bits from up to 3 different bytes. One byte
// form the right edge of the window and one or two bytes form
// the source. If the substring of ntsh first bits crosses the
// byte boundary in the source it's two.
int si = startBitPosition / 8; // index of the byte in the source
// where the bit stream starts
byte byteSecondPart; // Temporary variable to store the bits,
// that come from the source, to combine them later with the bits
// form the right edge of the window
int mask = (1 << ntsh) - 1;
// the mask of the form 0 0 1 1 1 1 1 1
// |<- ntsh ->|
if(ntsh <= nfstbb)// the substring of ntsh first bits
// doesn't cross the byte boundary in the source
{
byteSecondPart = (byte)((source[si] >> (nfstbb - ntsh)) & mask);
}
else// the substring of ntsh first bits crosses the byte boundary
// in the source
{
byteSecondPart = (byte)(((source[si] << (ntsh - nfstbb))
| (source[si + 1] >> (8 - ntsh + nfstbb))) & mask);
}
// The bits that go into one byte, but come form two sources
// -the right edge of the window and the source, are combined below
window[window.Length - nob - 1] = (byte)((window[window.Length - 1] << ntsh)
| byteSecondPart);
// At this point nob whole bytes in the window need to be filled
// with remaining bits form the source. It's done by a common loop
// for both cases (nob < window.Length) and (nob >= window.Length)
}
else// !(nob < window.Length) - all bits of the window will be replaced
// with the bits from the source. In this case, only the appropriate
// variables are set and the copying is done by the loop common for both
// cases
{
sbtci = (startBitPosition + numberOfBits) / 8 - window.Length;
nob = window.Length;
}
if(nfbbte > 0)// The bit substring coppied into one byte in the
// window crosses byte boundary in the source, so it has to be
// combined form the bits, commming form two consecutive bytes
// in the source
{
for(int i = 0; i < nob; ++i)
{
window[window.Length - nob + i] = (byte)((source[sbtci + i] << nfbbte)
| (source[sbtci + 1 + i] >> (8 - nfbbte)));
}
}
else// The bit substring coppied into one byte in the window
// doesn't cross byte boundary in the source, so whole bytes
// are simply coppied
{
for(int i = 0; i < nob; ++i)
{
window[window.Length - nob + i] = source[sbtci + i];
}
}
}

Assuming your array fits into an unsigned int:
int main () {
unsigned int curnum;
unsigned int num = 0x2492;
unsigned int pattern = 0x1;
unsigned int i;
unsigned int mask = 0;
unsigned int n = 3;
unsigned int count = 0;
for (i = 0; i < n; i++) {
mask |= 1 << i;
}
for (i = 8 * sizeof(num) - n; i >= 0; i--) {
curnum = (num >> i) & mask;
if (! (curnum ^ pattern)) {
count++;
}
}
}

Convert your byte array and pattern each to a std::vector<bool>, then call std::search(source.begin(), source.end(), pattern.begin(), pattern.end());. Despite vector<bool>s idiosyncracies, this will work.

Related

How shifting operator works in finding number of different bit in two integer?

i was trying to find out number of different bit in two number. i find a solution here but couldn't understand how it works.it right shifting with i and and doing and with 1. actually what is happening behind it? and why do loop through 32?
void solve(int A, int B)
{
int count = 0;
// since, the numbers are less than 2^31
// run the loop from '0' to '31' only
for (int i = 0; i < 32; i++) {
// right shift both the numbers by 'i' and
// check if the bit at the 0th position is different
if (((A >> i) & 1) != ((B >> i) & 1)) {
count++;
}
}
cout << "Number of different bits : " << count << endl;
}
The loop runs from 0 up to and including 31 (not through 32) because these are all of the possible bits that comprise a 32-bit integer and we need to check them all.
Inside the loop, the code
if (((A >> i) & 1) != ((B >> i) & 1)) {
count++;
}
works by shifting each of the two integers rightward by i (cutting off bits if i > 0), extracting the rightmost bit after the shift (& 1) and checking that they're the same (i.e. both 0 or both 1).
Let's walk through an example: solve(243, 2182). In binary:
243 = 11110011
2182 = 100010000110
diff bits = ^ ^^^ ^ ^
int bits = 00000000000000000000000000000000
i = 31 0
<-- loop direction
The indices of i that yield differences are 0, 2, 4, 5, 6 and 11 (we check from the right to the left--in the first iteration, i = 0 and nothing gets shifted, so & 1 gives us the rightmost bit, etc). The padding to the left of each number is all 0s in the above example.
Also, note that there are better ways to do this without a loop: take the XOR of the two numbers and run a popcount on them (count the bits that are set):
__builtin_popcount(243 ^ 2182); // => 6
Or, more portably:
std::bitset<CHAR_BIT * sizeof(int)>(243 ^ 2182).count()
Another note: best to avoid using namespace std;, return a value instead of producing a print side effect and give the method a clearer name than solve, for example bit_diff (I realize this is from geeksforgeeks).

How to random flip binary bit of char in C/C++

If I have a char array A, I use it to store hex
A = "0A F5 6D 02" size=11
The binary representation of this char array is:
00001010 11110101 01101101 00000010
I want to ask is there any function can random flip the bit?
That is:
if the parameter is 5
00001010 11110101 01101101 00000010
-->
10001110 11110001 01101001 00100010
it will random choose 5 bit to flip.
I am trying make this hex data to binary data and use bitmask method to achieve my requirement. Then turn it back to hex. I am curious is there any method to do this job more quickly?
Sorry, my question description is not clear enough. In simply, I have some hex data, and I want to simulate bit error in these data. For example, if I have 5 byte hex data:
"FF00FF00FF"
binary representation is
"1111111100000000111111110000000011111111"
If the bit error rate is 10%. Then I want to make these 40 bits have 4 bits error. One extreme random result: error happened in the first 4 bit:
"0000111100000000111111110000000011111111"
First of all, find out which char the bit represents:
param is your bit to flip...
char *byteToWrite = &A[sizeof(A) - (param / 8) - 1];
So that will give you a pointer to the char at that array offset (-1 for 0 array offset vs size)
Then get modulus (or more bit shifting if you're feeling adventurous) to find out which bit in here to flip:
*byteToWrite ^= (1u << param % 8);
So that should result for a param of 5 for the byte at A[10] to have its 5th bit toggled.
store the values of 2^n in an array
generate a random number seed
loop through x times (in this case 5) and go data ^= stored_values[random_num]
Alternatively to storing the 2^n values in an array, you could do some bit shifting to a random power of 2 like:
data ^= (1<<random%7)
Reflecting the first comment, you really could just write out that line 5 times in your function and avoid the overhead of a for loop entirely.
You have 32 bit number. You can treate the bits as parts of hte number and just xor this number with some random 5-bits-on number.
int count_1s(int )
{
int m = 0x55555555;
int r = (foo&m) + ((foo>>>1)&m);
m = 0x33333333;
r = (r&m) + ((r>>>2)&m);
m = 0x0F0F0F0F;
r = (r&m) + ((r>>>4)&m);
m = 0x00FF00FF;
r = (r&m) + ((r>>>8)&m);
m = 0x0000FFFF;
return r = (r&m) + ((r>>>16)&m);
}
void main()
{
char input[] = "0A F5 6D 02";
char data[4] = {};
scanf("%2x %2x %2x %2x", &data[0], &data[1], &data[2], &data[3]);
int *x = reinterpret_cast<int*>(data);
int y = rand();
while(count_1s(y) != 5)
{
y = rand(); // let's have this more random
}
*x ^= y;
printf("%2x %2x %2x %2x" data[0], data[1], data[2], data[3]);
return 0;
}
I see no reason to convert the entire string back and forth from and to hex notation. Just pick a random character out of the hex string, convert this to a digit, change it a bit, convert back to hex character.
In plain C:
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
int main (void)
{
char *hexToDec_lookup = "0123456789ABCDEF";
char hexstr[] = "0A F5 6D 02";
/* 0. make sure we're fairly random */
srand(time(0));
/* 1. loop 5 times .. */
int i;
for (i=0; i<5; i++)
{
/* 2. pick a random hex digit
we know it's one out of 8, grouped per 2 */
int hexdigit = rand() & 7;
hexdigit += (hexdigit>>1);
/* 3. convert the digit to binary */
int hexvalue = hexstr[hexdigit] > '9' ? hexstr[hexdigit] - 'A'+10 : hexstr[hexdigit]-'0';
/* 4. flip a random bit */
hexvalue ^= 1 << (rand() & 3);
/* 5. write it back into position */
hexstr[hexdigit] = hexToDec_lookup[hexvalue];
printf ("[%s]\n", hexstr);
}
return 0;
}
It might even be possible to omit the convert-to-and-from-ASCII steps -- flip a bit in the character string, check if it's still a valid hex digit and if necessary, adjust.
First randomly chose x positions (each position consist of array index and the bit position).
Now if you want to flip ith bit from right for a number n. Find the remainder of n by 2n as :
code:
int divisor = (2,i);
int remainder = n % divisor;
int quotient = n / divisor;
remainder = (remainder == 0) ? 1 : 0; // flip the remainder or the i th bit from right.
n = divisor * quotient + remainder;
Take mod 8 of input(5%8)
Shift 0x80 to right by input value (e.g 5)
XOR this value with (input/8)th element of your character array.
code:
void flip_bit(int bit)
{
Array[bit/8] ^= (0x80>>(bit%8));
}

Get Integer From Bits Inside `std::vector<char>`

I have a vector<char> and I want to be able to get an unsigned integer from a range of bits within the vector. E.g.
And I can't seem to be able to write the correct operations to get the desired output. My intended algorithm goes like this:
& the first byte with (0xff >> unused bits in byte on the left)
<< the result left the number of output bytes * number of bits in a byte
| this with the final output
For each subsequent byte:
<< left by the (byte width - index) * bits per byte
| this byte with the final output
| the final byte (not shifted) with the final output
>> the final output by the number of unused bits in the byte on the right
And here is my attempt at coding it, which does not give the correct result:
#include <vector>
#include <iostream>
#include <cstdint>
#include <bitset>
template<class byte_type = char>
class BitValues {
private:
std::vector<byte_type> bytes;
public:
static const auto bits_per_byte = 8;
BitValues(std::vector<byte_type> bytes) : bytes(bytes) {
}
template<class return_type>
return_type get_bits(int start, int end) {
auto byte_start = (start - (start % bits_per_byte)) / bits_per_byte;
auto byte_end = (end - (end % bits_per_byte)) / bits_per_byte;
auto byte_width = byte_end - byte_start;
return_type value = 0;
unsigned char first = bytes[byte_start];
first &= (0xff >> start % 8);
return_type first_wide = first;
first_wide <<= byte_width;
value |= first_wide;
for(auto byte_i = byte_start + 1; byte_i <= byte_end; byte_i++) {
auto byte_offset = (byte_width - byte_i) * bits_per_byte;
unsigned char next_thin = bytes[byte_i];
return_type next_byte = next_thin;
next_byte <<= byte_offset;
value |= next_byte;
}
value >>= (((byte_end + 1) * bits_per_byte) - end) % bits_per_byte;
return value;
}
};
int main() {
BitValues<char> bits(std::vector<char>({'\x78', '\xDA', '\x05', '\x5F', '\x8A', '\xF1', '\x0F', '\xA0'}));
std::cout << bits.get_bits<unsigned>(15, 29) << "\n";
return 0;
}
(In action: http://coliru.stacked-crooked.com/a/261d32875fcf2dc0)
I just can't seem to wrap my head around these bit manipulations, and I find debugging very difficult! If anyone can correct the above code, or help me in any way, it would be much appreciated!
Edit:
My bytes are 8 bits long
The integer to return could be 8,16,32 or 64 bits wside
The integer is stored in big endian
You made two primary mistakes. The first is here:
first_wide <<= byte_width;
You should be shifting by a bit count, not a byte count. Corrected code is:
first_wide <<= byte_width * bits_per_byte;
The second mistake is here:
auto byte_offset = (byte_width - byte_i) * bits_per_byte;
It should be
auto byte_offset = (byte_end - byte_i) * bits_per_byte;
The value in parenthesis needs to be the number of bytes to shift right by, which is also the number of bytes byte_i is away from the end. The value byte_width - byte_i has no semantic meaning (one is a delta, the other is an index)
The rest of the code is fine. Though, this algorithm has two issues with it.
First, when using your result type to accumulate bits, you assume you have room on the left to spare. This isn't the case if there are set bits near the right boundry and the choice of range causes the bits to be shifted out. For example, try running
bits.get_bits<uint16_t>(11, 27);
You'll get the result 42 which corresponds to the bit string 00000000 00101010 The correct result is 53290 with the bit string 11010000 00101010. Notice how the rightmost 4 bits got zeroed out. This is because you start off by overshifting your value variable, causing those four bits to be shifted out of the variable. When shifting back at the end, this results in the bits being zeroed out.
The second problem has to do with the right shift at the end. If the rightmost bit of the value variable happens to be a 1 before the right shift at the end, and the template parameter is a signed type, then the right shift that is done is an 'arithmetic' right shift, which causes bits on the right to be 1-filled, leaving you with an incorrect negative value.
Example, try running:
bits.get_bits<int16_t>(5, 21);
The expected result should be 6976 with the bit string 00011011 01000000, but the current implementation returns -1216 with the bit string 11111011 01000000.
I've put my implementation of this below which builds the bit string from the right to the left, placing bits in their correct positions to start with so that the above two problems are avoided:
template<class ReturnType>
ReturnType get_bits(int start, int end) {
int max_bits = kBitsPerByte * sizeof(ReturnType);
if (end - start > max_bits) {
start = end - max_bits;
}
int inclusive_end = end - 1;
int byte_start = start / kBitsPerByte;
int byte_end = inclusive_end / kBitsPerByte;
// Put in the partial-byte on the right
uint8_t first = bytes_[byte_end];
int bit_offset = (inclusive_end % kBitsPerByte);
first >>= 7 - bit_offset;
bit_offset += 1;
ReturnType ret = 0 | first;
// Add the rest of the bytes
for (int i = byte_end - 1; i >= byte_start; i--) {
ReturnType tmp = (uint8_t) bytes_[i];
tmp <<= bit_offset;
ret |= tmp;
bit_offset += kBitsPerByte;
}
// Mask out the partial byte on the left
int shift_amt = (end - start);
if (shift_amt < max_bits) {
ReturnType mask = (1 << shift_amt) - 1;
ret &= mask;
}
}
There is one thing you certainly missed I think: the way you index the bits in the vector is different from what you have been given in the problem. I.e. with algorithm you outlined, the order of the bits will be like 7 6 5 4 3 2 1 0 | 15 14 13 12 11 10 9 8 | 23 22 21 .... Frankly, I didn't read through your whole algorithm, but this one was missed in the very first step.
Interesting problem. I've done similar, for some systems work.
Your char is 8 bits wide? Or 16? How big is your integer? 32 or 64?
Ignore the vector complexity for a minute.
Think about it as just an array of bits.
How many bits do you have? You have 8*number of chars
You need to calculate a starting char, number of bits to extract, ending char, number of bits there, and number of chars in the middle.
You will need bitwise-and & for the first partial char
you will need bitwise-and & for the last partial char
you will need left-shift << (or right-shift >>), depending upon which order you start from
what is the endian-ness of your Integer?
At some point you will calculate an index into your array that is bitindex/char_bit_width, you gave the value 171 as your bitindex, and 8 as your char_bit_width, so you will end up with these useful values calculated:
171/8 = 23 //location of first byte
171%8 = 3 //bits in first char/byte
8 - 171%8 = 5 //bits in last char/byte
sizeof(integer) = 4
sizeof(integer) + ( (171%8)>0?1:0 ) // how many array positions to examine
Some assembly required...

Why is the first code of a code length the number of codes of that length times 2?

I've been trying to make sense of an example inflate implementation and this is a bit confusing:
static int decode(struct state *s, struct huffman *h)
{
int len; /* current number of bits in code */
int code; /* len bits being decoded */
int first; /* first code of length len */
int count; /* number of codes of length len */
int index; /* index of first code of length len in symbol table */
code = first = index = 0;
for (len = 1; len <= MAXBITS; len++) {
code |= bits(s, 1); /* get next bit */
count = h->count[len];
if (code - count < first) /* if length len, return symbol */
return h->symbol[index + (code - first)];
index += count; /* else update for next length */
first += count;
first <<= 1;
code <<= 1;
}
return -10; /* ran out of codes */
}
In particular this part:
first += count;
first <<= 1;
Can someone explain how does a bitshift or a multiplication by a constant yield the actual first code of a particular code length? Basically, the difference between an index of the first code and the actual first code is "times 2"?
For simplicity, just consider it rolling off from 7 to 8 bits of length, where 7 yielded the first non-zero count, in a fixed version would be 24, I guess since the interval is [256, 280>.
My assumption is that it preserves orders of magnitude between the code and the first of the next length, since their subtractive relationship is more relevant than the absolute value to determine the symbol offset -- however - I'm not quite sure that is the case.
count[len] is the number of codes of each bit length. For the canonical code defined by the deflate format, the codes simply count up from zero. So the first code for the first non-zero count[len] is len zero bits. If count[len] is more than one, then the next code is one more than that, or just len-1 zero bits and a one bit.
When the codes of that length are used, add a zero bit at the end to go to the next length.
Therefore to make the step from the first code of length i to the first code of length i+1, you add count[i] and then shift left by one bit.
Example code:
length code
2 00
2 01
3 100
3 101
3 110
4 1110
4 1111
We start with 00 for the first code, which is of length 2. There are two codes of length 2, so we add two and shift left by one bit, i.e. multiply by two, and get the first code of length 3 which is (0 + 2) * 2 = 4 = 100. To get to the first code of length 4, its (4 + 3) * 2 = 14 = 1110.

Create a file that uses 4-bit encoding to represent integers 0 -9

How can I create a file that uses 4-bit encoding to represent integers 0-9 separated by a comma ('1111')? for example:
2,34,99 = 0010 1111 0011 0100 1111 1001 1001 => actually becomes without spaces
0010111100110100111110011001 = binary.txt
Therefore 0010111100110100111110011001 is what I see when I view the file ('binary.txt')in WINHEX in binary view but I would see 2,34,99 when view the file (binary.txt) in Notepad.
If not Notepad, is there another decoder that will do '4-bit encoding' or do I have a write a 'decoder program' to view the integers?
How can I do this in C++?
The basic idea of your format (4 bits per decimal digit) is well known and called BCD (Binary Coded Decimal). But I doubt the use of 0xF as an encoding for a coma is something well established and even more supported by notepad.
Writing a program in C++ to do the encoding and decoding would be quite easy. The only difficulty would be that the standard IO use byte as the more basic unit, not bit, so you'd have to group yourself the bits into a byte.
You can decode the files using od -tx1 if you have that (digits will show up as digits, commas will show up as f). You can also use xxd to go both directions; it comes with Vim. Use xxd -r -p to copy hex characters from stdin to a binary file on stdout, and xxd -p to go the other way. You can use sed or tr to change f back and forth to ,.
This is the simplest C++ 4-bit (BCD) encoding algorithm I could come up with - wouldn't call it exactly easy, but no rocket science either. Extracts one digit at a time by dividing and then adds them to the string:
#include <iostream>
int main() {
const unsigned int ints = 3;
unsigned int a[ints] = {2,34,99}; // these are the original ints
unsigned int bytes_per_int = 6;
char * result = new char[bytes_per_int * ints + 1];
// enough space for 11 digits per int plus comma, 8-bit chars
for (int j=0; j < bytes_per_int * ints; ++j)
{
result[j] = 0xFF; // fill with FF
}
result[bytes_per_int*ints] = 0; // null terminated string
unsigned int rpos = bytes_per_int * ints * 2; // result position, start from the end of result
int i = ints; // start from the end of the array too.
while (i != 0) {
--i;
unsigned int b = a[i];
while (b != 0) {
--rpos;
unsigned int digit = b % 10; // take the lowest decimal digit of b
if (rpos & 1) {
// odd rpos means we set the lowest bits of a char
result[(rpos >> 1)] = digit;
}
else {
// even rpos means we set the highest bits of a char
result[(rpos >> 1)] |= (digit << 4);
}
b /= 10; // make the next digit the new lowest digit
}
if (i != 0 || (rpos & 1))
{
// add the comma
--rpos;
if (rpos & 1) {
result[(rpos >> 1)] = 0x0F;
}
else {
result[(rpos >> 1)] |= 0xF0;
}
}
}
std::cout << result;
}
Trimming the bogus data left at the start portion of the result according to rpos will be left as an exercise for the reader.
The subproblem of BCD conversion has also been discussed before: Unsigned Integer to BCD conversion?
If you want a more efficient algorithm, here's a bunch of lecture slides with conversion from 8-bit ints to BCD: http://edda.csie.dyu.edu.tw/course/fpga/Binary2BCD.pdf