Convert a char Array to a time structure - c++

I use in my current project a structure: for time information
struct SFileDateTime
{
uint8 nYear; // Years since 1900
uint8 nMonth; // Month [1, 12]
uint8 nDay; // Day of month [1, 31]
uint8 nHour; // Hours [0, 23]
uint8 nMinute; // Minutes [0, 59]
uint8 nSecond; // Seconds [0, 59]
};
typedef unsigned char uint8;
In some situations I get from external calls just a date char array
char [17] "1998012609260000"
I have now the problem to bring the char array to the SFileDateTime structure. I tried a memcpy call but this will cause a crash.
I currently do not understand why memcpy will not work. Is there any other way to convert it?
Is casting the right choice?

U have 2 great answers in comments below your question. Hope this helps you a bit.
typedef unsigned char uint8; //Max size is 255 in decimal ( 1111 1111 )
struct SFileDateTime
{
uint8 nYear; // Years since 1900
uint8 nMonth; // Month [1, 12]
uint8 nDay; // Day of month [1, 31]
uint8 nHour[20]; // Hours [0, 23]
uint8 nMinute[]; // Minutes [0, 59]
uint8 nSecond; // Seconds [0, 59]
};
int main()
{
SFileDateTime nene;
nene.nYear = 33; // ASCII code for !
nene.nMonth = 'M'; // One char which is 77 in ASCII
nene.nDay = 255; // max number in ASCII which is space
nene.nSecond = 256 ; // No go||=== warning: large integer
//implicitly truncated to unsigned type [-Woverflow]|
char one[] = "Hello";
cout<<one<<endl;
nene.nHour[0] = 'A';
nene.nHour[1] = 'b';
nene.nHour[2] = 'b';
nene.nHour[3] = 'y';
return 0;
}
if u want to use strcpy use typedef char
U should convert it to single chars if you want to use your struct.
Here you can find a good reference : https://en.cppreference.com/w/c/chrono/localtime

Related

Sending Integer from Processing to Arduino, bytes cannot be read

I am trying to display 4 separate digits on my 7 segment display. These numbers are made from a program and Processing receives a number like 9561, and through math, I isolate 9 5 6 1 into individual digits.
since a single digit is 4 bits, I use an integer to sequentially compress the numbers, which in it's full decimal form appears to be 5721. I then send this integer to the Arduino, where I have 2 bytes sequencially running Serial.read();
My issue is that my 7 segment 4 digit display only displays 9500 meaning that x2 is 00 meaning that the 61 get lost in translation.
Even more so, when I speed up time (t) or the time for multiplexing, the 95 will flash over 00 and I confirmed it when I made seg0 and seg1 of the array 0 and 0.
When t = 3 this occurs, but anything higher than say, 8 doesn't have this issue.
I should also mention in my switch() the default case displays a 0.
Processing
void draw()
{
seg[0] = 9;
seg[1] = 5;
seg[2] = 6;
seg[3] = 1;
int x = (seg[pos+3] & 0x000f)<<12|((seg[pos+2]) & 0x000f)<<8|(seg[pos+1] & 0x000f )<<4|((seg[pos] & 0x000f)); //3210
myPort.write(x);
//0123
int disp1 = x;
int disp2 = (x & 0x00f0)>>4;
int disp3 = (x & 0x0f00)>>8;
int disp4 = (x & 0xf000)>>12;
//0123
print(disp1, '\n', disp2, '\n', disp3, '\n', disp4, '\n', '\n');
}
Arduino (Relevant areas, its a lot of code
void digitdisplay(byte x,byte x2)
{
//unsigned char tn = int (num/1000);
//if (tn>10)
//{
// tn = tn - 10;
//}
//
//unsigned char hn = int (num/100)%10;
//unsigned char tenn = int (num/10)%10;
//unsigned char on = int (num%10);
int disp[4];
disp[0] = ( x & 0x0f);
disp[1] = ( x & 0xf0)>>4;
disp[2] = ( x2 & 0x0f);
disp[3] = ( x2 & 0xf0)>>4;
numberselect(disp[0]);
digitselect(1);
delay(t);
numberselect(disp[1]);
digitselect(2);
delay(t);
numberselect(disp[2]);
digitselect(3);
delay(t);
numberselect(disp[3]);
digitselect(4);
delay(t);
}
void loop()
{
int sen = analogRead(A0);
int maxrange = (sen*maxval);
byte x,x2;
if (Serial.available()>2)
{ // If data is available to read,
x=Serial.read();
x2=Serial.read();
}
//shiftlight(maxrange);
digitdisplay(x,x2);
}
Supposing that myPort is an OutputStream, your one invocation of myPort.write(int) writes just one byte, extracted from the lowest-order 8 bits of its argument. The higher-order bits are lost. That's why you're seeing only the 9 and 5.
I cannot explain from the code presented why you display 9500 instead of 9595, but that seems consistent with your claim that at higher update rates you see the 95 alternating with 00. Both lead me to think that some other part of your code is writing zeroes to the serial port.
Java's String representation is UTF-16. That means that each character is represented by 2 bytes. For ASCII-letters one of them is 0x00. This could be the reason why you don't get the 61 out of the stream at the expected position.
You can either skip each second byte on the Arduino or convert the characters to plain ASCII before sending using getBytes(Charset charset) https://docs.oracle.com/javase/7/docs/api/java/nio/charset/Charset.html

Converting a [char] variable to [int] then back to [char]

I am using Visual C 6
I am trying to convert a character array (single-quotation) into an integer, then incrementing the value by 1, then storing the result back into a different character array..
But I keep getting an unexpected value when converting back to character..
Here is my code
char char_array[4];
char_array[0] = '1';
char_array[1] = '2';
char_array[2] = '3';
char_array[3] = '\0'; //Terminating character
int my_number = atoi(char_array);
printf("my_number = %d" , my_number); // output is 123
my_number++; // works and my_number is incremented =124
printf("now: my_number = %d" , my_number); // output is 124
char result[4]; //declared to store the result
result = itoa(my_number); // Output is unexpected.
printf("%c", result[0]); // Output is 2 instead of 1
printf("%c", result[1]); // Output is 2
printf("%c", result[2]); // Output as 3 instead of 4
It seems that the function itoa() somehow knows the original value 123 and in some weird way knows that I have incremented that value.. but the addition is done to the wrong digit. Instead of adding 1 to the least significant digit, the addition is done to the most significant digit.
I find it really difficult to believe that your compiler is letting this code through:
char result[4]; //declared to store the result
result = itoa(my_number); // Output is unexpected.
For one reason, you're attempting to reseat an array. Which shouldn't be allowed. For another, itoa() normally takes three arguments. It's prototype should look like:
char *itoa(int value, char * str, int base);
So you should be calling it as:
char result[4];
itoa(my_number, result, 10);
Or, if you'd like to use portable functions that don't have possible buffer overflows:
char result[4];
snprintf(result, 4, "%d", my_number);
itoa is not a standard C library function.
You can use
char result[sizeof(int) * CHAR_BIT / 10 * 3 + 4]; // '-1', '\0', max sizeof int on my 4 byte machine
// 10 bits are roughly equal to 3 digits at decimal base, extra 4 for '-', '\0', extra digit and safe character
sprintf(result, "%d", my_number);
If you still want to use itoa, consult the documentation of this function (in library/compiler documentation)
my_number is incremented and hence if you are using itoa() then it will know the new value of my_number which is 124.
Check the code below:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
char char_array[4];
char_array[0] = '1';
char_array[1] = '2';
char_array[2] = '3';
char_array[3] = '\0'; //Terminating character
int my_number = atoi(char_array);
printf("my_number = %d" , my_number); // output is 123
my_number++; // works and my_number is incremented =124
printf("now: my_number = %d" , my_number); // output is 124
char result[4]; //declared to store the result
snprintf(result,4,"%d",my_number);
printf("%c", result[0]);
printf("%c", result[1]);
printf("%c", result[2]);
return 0;
}
First the itoa(my_number) maybe wrong, I only know the followed function:
char * itoa ( int value, char * str, int base );
str should be an array long enough to contain any possible value:
(sizeof(int)*8+1) for radix=2 i.e. 17 bytes in 16-bits platforms and
33 in 32-bits platforms.

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

modifying array values using location in c++

lets suppose I have an unsigned int* val and unsigned char mat[24][8]. Now the val stores the location of the variable mat. Is it possible to modify the bits in the mat variable using the location in val?
for ex:
val = 0x00000001 and location of val in memory is 0x20004000
the first element of mat is located at 0x00000001.
Now i want to modify the value of mat at, say, 10,4. Is it possible to do this using C++?
Yes, it is possible, unless either of the array members or the pointer target is const.
For example:
int array[3][2] = { { 0, 1 }, { 2, 3 }, { 4, 5 } };
int *p = &array[1][1];
*p = 42;
// array is now: { { 0, 1 }, { 2, 42 }, { 4, 5 } };
Yes, you can change the value of your matrix using the address(what you called location), but you have to calculate the right offset from the start. The offset calculation should be something like this :
(matrix_x_len * Y + X) * sizeof(unsigned int) + offset to the beggining of the matrix
then when you have the offset you can change mat like this : *(val + offset) = new_value.
can do it but making val as unsigned char*
val = &mat;
will make easy to do modification of bits
You can of course modify the bits since unsigned char mat[24][8] gives you a memory chunk with 24*8*sizeof(char) bytes.
(I assume that unsigned char is 1 byte (=8 bits) in size and unsigned int is 4 Bytes (=32 bits) from here but this may be dependant on your system.
But accessing memory elements of 1 byte width using a pointer to elements with 4 bytes width is tricky and can easily produce errors.
If you set element 0 of the int array to 1 for example
#define ROWS 24
#define COLS 8
unsigned char mat[ROWS][COLS];
unsigned int * val = (unsigned int*)&mat;
val[0] = 1;
You will see that mat[0][0] is 0, mat[0][1] is 0, mat[0][2] is 0 and mat[0][3] is 1.
Please not that you cannot edit the elements of mat directly using their offset in memory via such a "miss-typed" pointer.
Accessing val[10*8+4] for example will access byte 336 from the beginning of your memory chunk which has only 192 bytes.
You will have to calculate your index correctly:
size_t byte_index = (10*COLS+4)*sizeof(unsigned char); // will be 84
size_t int_index = byte_index / sizeof(unsigned int); // will be 21
size_t sub_byte = byte_index%sizeof(unsigned int); // will be 0
Therefore you can access val[int_index] or val[21] to access the 4 bytes that contain the data of element mat[10][4] which is byte number sub_byte of the refered unsigned int value.
If you have the same types there is no problem except that you need to calculate the correct offset.
#define ROWS 24
#define COLS 8
unsigned char mat[ROWS][COLS];
unsigned char * val = &mat;
val[10*8+4] = 12; // set mat[10][4] to 12
*(val+10*8+5) = 13; // set mat[10][5] to 13

Assigning multiple integers to a character array in binary

I have three integers (4 bytes of memory for each integer) and I want to assign each of their binary values to a character array with 12 elements. So, if each integer had a value of let's say 2, then I want the character array to have these values:
2 0 0 0 2 0 0 0 2 0 0 0
I have tried:
memcpy(cTemp, &integer1 + &integer2 + &integer3, 12);
but I receive an "invalid operands" compiler error.
I have also found the function strcat referenced here: http://www.cplusplus.com/reference/clibrary/cstring/
However it is mentioned as: "The terminating null character in destination is overwritten by the first character of source" which I obviously don't want since most of the times integers will have a null character at the end unless the value is really large. Does anybody know of a better working method? Any help is appreciated.
It is probably simpler (if you are on a x86 at least :P) to just cast the pointer and assign directly. i.e.
int* p = (int*) cTemp;
p[0] = a;
p[1] = b;
p[2] = c;
You can also do a union hack:
union translate {
char c[sizeof(int) * 3];
int i[3];
};
translate t;
t.i[0] = 2;
t.i[1] = 2;
t.i[2] = 2;
// access t.c[x] to get the chars
... and read the chars...
If you want to see how a variable is represented as a sequence of bytes, you can do the following.
int i[3] = {2, 2, 2};
char cTemp[sizeof i];
memcpy(cTemp, &i, sizeof i);
Note however that the representation will be different on different platforms. What are you trying to solve?
Edit:
I'm just writing a program to edit [a file], and the file happens to store integers in binary.
Why didn't you say so in the first place? If you know the program will only run on platforms where int has the correct memory-layout, you can simply store the integer.
fout.write((char const *)&i, sizeof i);
However, if you want to be portable, you need to properly serialize it.
void store_uint32_le(char * dest, unsigned long value)
{
for (int i = 0; i < 4; ++i)
{
*dest++ = value & 0xff;
value >>= 8;
}
assert(value == 0);
}
int main()
{
char serialized[12];
store_uint32_le(serialized, 2);
store_uint32_le(serialized + 4, 2);
store_uint32_le(serialized + 8, 2);
std::ofstream fout("myfile.bin", std::ios::binary);
fout.write(serialized, sizeof serialized);
}
I think this should work:
int i,j,k;
char a[12];
*((int*)a) = i;
*(((int*)a)+1) = j;
*(((int*)a)+2) = k;