Convert integer to char array function - c++

I want to convert a number into a not zero-terminated char array without any predifined C / C++ function (e.g itoa).
I don't have much space left (working on an embedded application with 5KB pgm space total of which I'm allready using 4.862KB) and my output function doesn't accept zero-terminated char arrays; only an array and the length.
EDIT 1: I'm not working for a company :P
EDIT 2: Doesn't accept means that for no reason it won't send if there's a 0-byte inside the array.
EDIT 3: I solved it using a modified version of the method from 'Vlad from Moscow' below. Still thanks to all of you, who tried helping me :)
EDIT 4: If anybody cares: The project is setting an AVR based alarm clock using bluetooth.

As my hourly rate is equal to zero $ (I am unemployed) then I will show a possible approach.:)
In my opinion the simplest way is to write a recursive function. For example
#include <iostream>
size_t my_itoa( char *s, unsigned int n )
{
const unsigned base = 10;
unsigned digit = n % base;
size_t i = 0;
if ( n /= base ) i += my_itoa( s, n );
s[i++] = digit + '0';
return i;
}
int main()
{
unsigned x = 12345;
char s[10];
std::cout.write( s, my_itoa( s, x ) );
return 0;
}
The output is
12345
Though I used unsigned int you can modify the function that it would accept objects of type int.
If you need to allocate the character array in the function then it will be even simpler and can be non-recursive.

A general algorithm:
Personally I can't recommend a recursive algorithm unless I knew the stack limits the embedded system imposes (PICs for example have a very limited stack depth) and what your current stack usage is.
orignumber = 145976
newnumber = orignumber
newnumber = new number / 10
remainder = new number % 10 answer: 6
digit = remainder + 30 hex -> store into array answer:0x36 ascii 6
increment array location
newnumber = new number / 10
remainder = new number % 10 answer: 7
digit = remainder + 30 hex -> store into array answer:0x37 ascii 7
increment array location
newnumber = new number / 10
remainder = new number % 10 answer: 9
digit = remainder + 30 hex -> store into array answer:0x39 ascii 9
increment array location
repeat these 4 steps while new number > 0
Array will contain: 0x36 0x37 0x39 0x35 0x34 0x31
null terminal array,
null termination allows easy calculation of string length and string reversal.
Another option would be to fill the array from the end by decrementing a pointer to avoid reversing the string.
Array will contain: 0x36 0x37 0x39 0x35 0x34 0x31 0x00
finally reverse array
Array will contain: 0x31 0x34 0x35 0x39 0x37 0x36 0x00

Related

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));
}

Sum of binary numbers in C++ and overflow bit?

I need help with adding the 16 bits that are concatenated in 'bits'. Every time a set of 16 bits is concatenated, I want them to be added (binary addition) to an array...till all sets of 16 are complete in my string. If there is an overflow, length of final sum >16...then add that extra bit to the final sum as 0000000000000001 (where 1 is the 16th bit).
For a string entered: "hello"
std::vector<std::string> bitvec;
std::string bits;
for (int i = 0; i < s.size(); i += 2) {
bits = std::bitset<8>(s[i]).to_string() + std::bitset<8>(s[i + 1]).to_string();
bitvec.push_back(bits);
}
Possible problems:
If s holds "hello", then std::bitset<8>(s[i]) will be 0. You need to pass a string containing only "1"s and "0"s to the bitset constructor
Once your bitsets are initialized properly, you can't add them together by using the to_string() function, that will just concatenate the representations: "1011" + "1100" will become "10111100"
Oh, wait, maybe that's what you do want.
It sort of sounds like you are inventing a complicated way to sum the pairs of ascii values interpreted as 16 bit numbers, but it's not clear. Your code is roughly equivalent to something like:
std::vector<uint16_t> bitvec;
unsigned char* cp = s.c_str()+1;
while (*cp) {
uint16_t bits = *(cp-1)>>8 + *(cp);
bitvec.push_back(bits);
}
//sum over the numbers contained in bitvec here?
uint32_t sum=0;
for(std::vector<int16_t>::iterator j=bitvec.begin();j!=bitvec.end();++j) {
sum += *j;
uint16_t overflow = sum>>16; //capture the overflow bit, move it back to lsb
sum &= (1<<16)-1; //clear the overflow
sum += overflow; //add it back as lsb
}

Storing data on device

I have not many experience with operations/storage of binary data so I would greatly appreciate if someone could clarify some things for me.
I have a device say where you have to store 16 bytes. e.g., you should send it an array of bytes proceeded probably with header information. e.g., smth like this:
unsigned char sendBuffer[255];
sendBuffer[0] = headerInfo1;
sendBuffer[1] = headerInfo1;
sendBuffer[2] = headerInfo1;
sendBuffer[3] = headerInfo1;
sendBuffer[4] = data;
sendBuffer[5] = data;
sendBuffer[6] = data;
sendBuffer[7] = data;
sendBuffer[8] = data;
...
sendBuffer[20] = data;
Let's say send operation is easy, you just use Send(sendBuffer, length).
My question is say I want to store an integer in the device - what is the best way to do this?
I have a sample code which does it and I was not sure if it was ok and how it was doing it. It confused me too. I basically enter the number I want to store in text box. Say I want to store 105 in decimal. I enter "00000000000000000000000000000105" (I am not sure how program interprets this yet, as decimal or as hex), then there is this code:
for(int i=0,m=0; i < size; i+=2,m++)
{
char ch1, ch2;
ch1=(char)str[i]; // str contains the number I entered above as string, padded
ch2=(char)str[i+1];
int dig1, dig2;
if(isdigit(ch1)) dig1 = ch1 - '0';
else if(ch1>='A' && ch1<='F') dig1 = ch1 - 'A' + 10;
else if(ch1>='a' && ch1<='f') dig1 = ch1 - 'a' + 10;
if(isdigit(ch2)) dig2 = ch2 - '0';
else if(ch2>='A' && ch2<='F') dig2 = ch2 - 'A' + 10;
else if(ch2>='a' && ch2<='f') dig2 = ch2 - 'a' + 10;
// Contains data to write as a byte array; this is basically the 'data' part as mentioned in my above snippet
array1[m] = (char)(dig1*16 + dig2);
}
And this array1[m] is written to the device using Send as above. But when I debug array1 contains: 0000000000000015
When I do the read the value I get is correct, it is 00000000000000000000000000000105. How come this works?
You're reinventig a few wheels here, but that's to be expected if you're new to C++.
std::cin >> yourInteger will read an integer, no need to convert that yourself.
Leading zeroes are usually not written out, but in a C++ integer type they're always present. E.g. int32_t always has 32 bits. If it stores 105 (0x69), it really stores 0x00000069.
So, the best way is probably to memcpy that integer to your sendBuffer. You should copy sizeof(yourInteger) bytes.
Seems there are a few questions hiding in here, so some extra answers:
You say that array1 contains: 0000000000000015, not 105.
Well, it's an array, and each member is shown as an 8 bits integer in its own right.
E.g. the last value is 5 or 05, that's the same after all. Similarly, the penultimate integer is 1 or 01.
You also wrote "Say I want to store 105 in decimal. I enter 00000000000000000000000000000105". That doesn't actually store 105 decimal. It stores 105 hexadecimal, which is 261 decimal. It is the string to integer conversion which determines the final value. If you would use base 18 (octodecimal), the string "105" becomes the integer 1*18*18 + 0 + 5 = 329 (decimal), and that would be stored as 000000101001001 binary.

Issues with circular bit-shift in C++

I'm attempting to implement circular bit-shifting in C++. It kind of works, except after a certain point I get a bunch of zeroes.
for (int n=0;n<12;n++) {
unsigned char x=0x0f;
x=((x<<n)|(x>>(8-n))); //chars are 8 bits
cout<<hex<<"0x"<<(int)x<<endl;
}
My output is:
0xf
0x1e
0x3c
0x78
0xf0
0xe1
0xc3
0x87
0xf
0x0
0x0
0x0
As you can see, I start getting 0x0's instead of the expected 0x1e, 0x3c, etc.
If I expand the for loop to iterate 60 times or so, the numbers come back correctly (after a bunch of zeroes.)
I'm assuming that a char houses a big space, and the "gaps" of unused data are zeroes. My understanding is a bit limited, so any suggestions would be appreciated. Is there a way to toss out those zeroes?
Shifting by a negative amount is undefined behavior.
You loop from 0 to 12, but you have an 8 - n in your shifts. So that will go negative.
If you want to handle n > 8, you'll need to take a modulus by 8. (assuming you want 8-bit circular shift.)
for (int n=0; n < 12; n++) {
unsigned char x = 0x0f;
int shift = n % 8; // Wrap modulus
x = ((x << shift) | (x >> (8 - shift))); //chars are 8 bits
cout << hex << "0x" << (int)x << endl;
}
Shifting a byte left by more than 7 will always result in 0.
Also, shifting by a negative amount is not defined.
In order to fix this you have to limit the shift to the size of the type.
Basically:
unsigned char x = 0xf;
int shift = n&7;
x=((x<<shift)|(x>>(8-shift)))

how values are stored in char

I am adding values into the combo box as a string. Below is my code.
Platform Windows XP and I am using Microsoft Visual Studio 2003
language C++
error encountered -> "Run-Time Check Failure #2 - Stack around the variable 'buffer' was corrupted."
If I increase the size of the buffer to say 4 and above then I won't get this error.
My question is not related to how to fix that error, but I am wondering why I got this error if buffer size = 2.
According to my logic I have given buffer size = 2 as char[0] will store the valve of char[1] = null terminated character.
Now since char can store values from 0 to 255 , I thought this should be ok as my inserted values are from 1 to 63 and then from 183 to 200.
CComboBox m_select_combo;
const unsigned int max_num_of_values = 63;
m_select_combo.AddString( "ALL" );
for( unsigned int i = 1; i <= max_num_of_values ; ++i )
{
char buffer[2];
std::string prn_select_c = itoa( i, buffer, 10 );
m_select_combo.AddString( prn_select_c.c_str() );
}
const unsigned int max_num_of_high_sats = 202 ;
for( unsigned int i = 183; i <= max_num_of_high_sats ; ++i )
{
char buffer[2];
std::string prn_select_c = itoa( i, buffer, 10 );
m_select_combo.AddString( prn_select_c.c_str() );
}
Could you guys please give me an idea as to what I'm not understanding?
itoa() zero-terminates it's output, so when you call itoa(63, char[2], 10) it writes three characters 6, 3 and the terminating \0. But your buffer is only two characters long.
itoa() function is best avoided in favour of snprintf() or boost::lexical_cast<>().
You should read the documentation for itoa.
Consider the following loop:
for( unsigned int i = 183; i <= max_num_of_high_sats ; ++i )
{
char buffer[2];
std::string prn_select_c = itoa( i, buffer, 10 );
m_select_combo.AddString( prn_select_c.c_str() );
}
The first iteration converts the integer 183 to the 3 character string "183", plus a terminating null character. That's 4 bytes, which you are trying to cram into a two byte array. The docs tell you specifically to make sure your buffer is large enough to hold any value; in this case it should be at least the number of digits in max_num_of_high_sats long, plus one for the terminating null.
You might as well make it large enough to hold the maximum value you can store in an unsigned int, which would be 11 (eg. 10 digits for 4294967295 plus a terminating null).
the ito function is used to convert a int to a C sytle string based on the 3rd parameter base.
As a example, it just likes to print out the int 63 in printf. you need two ASII byte, one is used to storage CHAR 6, the other is used to storage CHAR 3. the 3rd should be NULL. So in your case the max int is three digital. you need 4 bytes in the string
You are converting an integer to ASCII, that is what itoa does. If you have a number like 183 that is four chars as a string, '1', '8', '3', '\0'.
Each character takes one byte, for example character '1' is the value 0x31 in ASCII.