I have been trying to convert a binary number into a char, I use the following code to convert the char into binary:
void bin(char x){
int y;
for(y = 0; y < sizeof(char) * 8; y++){
fprintf(f2,"%c", ( x & (1 << y) ) ? '1' : '0' );
}}
And it works fine.
The problem is that I don't know how to undo it, I want to get this binary number and convert it to the initial char. I'm using the folliwing code but it generates a core problem.
char subbuff[9];
memcpy( subbuff, &fichero[0], 8 );
subbuff[8] = '\0';
for(int k=8;k<fichero_len;k+=8){
char c = strtol(subbuff, 0, 2);
printf("%s = %c = %d = 0x%.2X\n", subbuff, c, c, c);
memcpy( subbuff, &fichero[k], k+8 );
subbuff[8] = '\0';
}
for exaple if i convert the string "hola" the first code shows "00010110111101100011011010000110"
but if i put that into the second code:
const char *hola="00010110111101100011011010000110";
char subbuff[16];
memcpy( subbuff, hola[0], 8 );
subbuff[8] = '\0';
for(int k=8;k<strlen(hola);k+=8){
char c = strtol(subbuff, 0, 2);
printf("%s = %c = %d = 0x%.2X\n", subbuff, c, c, c);
memcpy( subbuff, &hola[k], k+8 );
subbuff[8] = '\0';
}
it generates a core problem
EDIT 1:
One problem is that you are copying too many bytes into subbuff with
memcpy( subbuff, &fichero[k], k+8 );
Another is that you pass a bad pointer to memcpy with
memcpy( subbuff, hola[0], 8 );
which will cause a segfault. Please enable compiler warnings.
There is no need even to do that first, outside of the loop. It can be done similar like this
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void) {
const char *hola = "01101000011011110110110001100001";
char subbuff[9];
char result [256] = "";
unsigned char c;
int k;
int index = 0;
int fichero_len = (int)strlen(hola);
for(k = 0; k < fichero_len; k += 8) {
memcpy(subbuff, &hola[k], 8); // <--- copy 8 butes only
subbuff[8] = '\0';
c = (unsigned char)strtol(subbuff, 0, 2);
printf("%s = %c = %d = 0x%.2X\n", subbuff, c, c, c);
result[index++] = c;
result[index] = '\0';
}
printf("Result = %s\n", result);
return 0;
}
Finally your bit sequences are reversed, so you won't get the char back that you started with!
EDIT 2: after adding a few lines to the above code and reversing the bits in the hola definition, I get this output. Obviously you must make sure that result[] is long enough.
Program output:
01101000 = h = 104 = 0x68
01101111 = o = 111 = 0x6F
01101100 = l = 108 = 0x6C
01100001 = a = 97 = 0x61
Result = hola
Related
I started learning C language about 1 week, and I'm trying to build my first programs. I'm coming from Python, so the C syntax isn't very clear for me, and I haven't understand the solutions that I found online.
So, if I have this string:
char str[50] = "dimension[1080,720];"
and i want to create two integer variables that containes 1080 and 720 and string var that contains the first string. But these two numbers can change, and they can have random cifras. So, i wanted my output is
int x = 1080
int y = 720
*the values are always two, but the lenght can change.
How can i do that?
Second version:
So, if I have this string:
char str[50] = "dimension["string",1080,720];"
and i want to create two integer variables that containes 1080 and 720 and string var that contains the first string. But these two numbers can change, and they can have random cifras. So, i wanted my output is
char str[1000] = "string";
int x = 1080
int y = 720
the values are always three, but the lenght can change.
How can i do that?
use sscanf function
int main(void)
{
char str[] = "dimension[1080,720];";
int x,y;
if(sscanf(str, "dimension[%d,%d", &x, &y) != 2) {printf("Error\n");}
else printf("X=%d Y=%d", x, y);
}
Question two:
int main(void)
{
char str[] = "dimension[\"string\",1080,720];";
char str1[20];
int x,y;
char *ptr = strstr(str, "[");
char *ptr1;
size_t len;
memcpy(str1, ptr + 2, len = (ptr1 = strchr(ptr + 2, '"')) - (ptr + 2));
str[len] = 0;
if(sscanf(ptr1 + 2, "%d,%d", &x, &y) != 2) {printf("Error\n");}
else printf("Str = %s X=%d Y=%d", str1, x, y);
}
The sscanf answer is perfect, but not very flexible. I add this in case you want more flexibility to parse strings. You can do it with regular expressions and in your case would be something like:
Piece of code taken from https://gist.github.com/ianmackinnon/3294587
I have added some modification to extract the numbers to the variables
#include <stdio.h>
#include <string.h>
#include <regex.h>
#include <stdlib.h>
int main ()
{
// Define regexp and input
char * source = "dimension[\"string\",1080,720];";
char * regexString = "[a-z]+\\[\"([a-z]+)\",([0-9]+),([0-9]+)\\]";
size_t maxMatches = 3;
size_t maxGroups = 4;
// Variables we want to extract from the input
char* str;
int n1;
int n2;
regex_t regexCompiled;
regmatch_t groupArray[maxGroups];
unsigned int m;
char * cursor;
if (regcomp(®exCompiled, regexString, REG_EXTENDED))
{
printf("Could not compile regular expression.\n");
return 1;
};
m = 0;
cursor = source;
for (m = 0; m < maxMatches; m ++)
{
if (regexec(®exCompiled, cursor, maxGroups, groupArray, 0))
break; // No more matches
unsigned int g = 0;
unsigned int offset = 0;
for (g = 0; g < maxGroups; g++)
{
if (groupArray[g].rm_so == (size_t)-1)
break; // No more groups
if (g == 0)
offset = groupArray[g].rm_eo;
char cursorCopy[strlen(cursor) + 1];
strcpy(cursorCopy, cursor);
cursorCopy[groupArray[g].rm_eo] = 0;
printf("Match %u, Group %u: [%2u-%2u]: %s\n",
m, g, groupArray[g].rm_so, groupArray[g].rm_eo,
cursorCopy + groupArray[g].rm_so);
switch (g)
{
case 1:
// Copy to the string now that we know the length
str = malloc(strlen(cursor)+1);
strcpy(str,cursorCopy + groupArray[g].rm_so);
break;
case 2:
n1 = (int) strtol(cursorCopy + groupArray[g].rm_so, (char **)NULL, 10); //(cursorCopy + groupArray[g].rm_so,10);
break;
case 3:
n2 = (int) strtol(cursorCopy + groupArray[g].rm_so, (char **)NULL, 10); //(cursorCopy + groupArray[g].rm_so,10);
break;
}
}
cursor += offset;
}
regfree(®exCompiled);
printf("Matches in variables: %s - %d - %d \n",str,n1,n2);
return 0;
}
This for me prints
Match 0, Group 0: [ 0-28]: dimension["string",1080,720]
Match 0, Group 1: [11-17]: string
Match 0, Group 2: [19-23]: 1080
Match 0, Group 3: [24-27]: 720
Matches in variables: string - 1080 - 720
I'm using the library OpenSSL for encrypting through AES. Since AES is a block cipher, I need to split the data in chunks of 16 bytes. Thus, if I want to recover the message, I need to unite the chunks at the end of the program.
This is my code:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <openssl/aes.h>
char key[] = "secretkey123";
int main() {
unsigned char text_slice[128];
unsigned char enc_slice[128];
unsigned char dec_slice[128];
unsigned char in[160];
unsigned char enc_out[160] = "";
unsigned char dec_out[160] = "";
int i;
int k = 10;
for (i = 0; i < 16 * k; i++) {
in[i] = 'A' + (rand() % 26);
}
in[160] = '\0';
printf("IN:%s\n", in);
AES_KEY enc_key, dec_key;
AES_set_encrypt_key(key, 128, &enc_key);
AES_set_decrypt_key(key, 128, &dec_key);
for (i = 0; i < k; i++) {
text_slice[0] = '\0';
enc_slice[0] = "\0";
dec_slice[0] = "\0";
memcpy(&text_slice[0], &in[15 * i], 15);
text_slice[16] = "\0";
printf("TEXT SLICE: %s \n", text_slice);
AES_encrypt(text_slice, enc_slice, &enc_key);
memcpy(&enc_out[16 * i], &enc_slice[0], 16);
}
printf("ENC:%s\n", enc_out);
for (i = 0; i < k; i++) {
text_slice[0] = '\0';
enc_slice[0] = "\0";
dec_slice[0] = "\0";
memcpy(enc_slice, &enc_out[16 * i], 16);
enc_slice[16] = "\0";
AES_decrypt(enc_slice, dec_slice, &dec_key);
printf("Dec slice:%s \n", dec_slice);
memcpy(&dec_out[16 * i], &dec_slice[0], 16);
}
printf("DEC OUT:%s\n", dec_out);
return 0;
}
The output of the program is the following:
IN:NWLRBBMQBHCDARZOWKKYHIDDQSCDXRJMOWFRXSJYBLDBEFSARCBYNECDYGGXXPKLORELLNMPAPQFWKHOPKMCOQHNWNKUEWHSQMGBBUQCLJJIVSWMDKQTBXIXMVTRRBLJPTNSNFWZQFJMAFADRRWSOFSBCNUVQHFF
TEXT SLICE: NWLRBBMQBHCDARZ
TEXT SLICE: OWKKYHIDDQSCDXR
TEXT SLICE: JMOWFRXSJYBLDBE
TEXT SLICE: FSARCBYNECDYGGX
TEXT SLICE: XPKLORELLNMPAPQ
TEXT SLICE: FWKHOPKMCOQHNWN
TEXT SLICE: KUEWHSQMGBBUQCL
TEXT SLICE: JJIVSWMDKQTBXIX
TEXT SLICE: MVTRRBLJPTNSNFW
TEXT SLICE: ZQFJMAFADRRWSOF
ENC:j�Q���
𢨫�7֡���*n���R ��m7�zI#4��=v�#�(��V7��ח9.R�q����:C�%��_��!q��(��l��j�3�1�h��
Dec slice:NWLRBBMQBHCDARZ
Dec slice:OWKKYHIDDQSCDXR
Dec slice:JMOWFRXSJYBLDBE
Dec slice:FSARCBYNECDYGGX
Dec slice:XPKLORELLNMPAPQ
Dec slice:FWKHOPKMCOQHNWN
Dec slice:KUEWHSQMGBBUQCL
Dec slice:JJIVSWMDKQTBXIX
Dec slice:MVTRRBLJPTNSNFW
Dec slice:ZQFJMAFADRRWSOF
DEC OUT:NWLRBBMQBHCDARZ
While dec_slice works as expected, dec_out just get a copy of the memory of the first chunk. What is more surprising for me, is that enc_out performs correctly when following the same logic as dec_out. What am I missing?
The key must have at least 16 bytes since you pass a number of bits equal to 128 in:
AES_set_encrypt_key(key, 128, &enc_key);
AES_set_decrypt_key(key, 128, &dec_key);
You have undefined behavior here:
in[160] = '\0';
These lines don't make sense:
enc_slice[0] = "\0";
dec_slice[0] = "\0";
text_slice[16] = "\0";
enc_slice[16] = "\0";
Why do you encode chunks of 15 characters instead of 16?
memcpy(&text_slice[0], &in[15 * i], 15);
Here is a modified version:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <openssl/aes.h>
char key[] = "secretkey1234567";
int main() {
unsigned char text_slice[128];
unsigned char enc_slice[128];
unsigned char dec_slice[128];
unsigned char in[160];
unsigned char enc_out[160];
unsigned char dec_out[160];
int i, k = 10;
for (i = 0; i < 16 * k; i++) {
in[i] = 'A' + (rand() % 26);
}
printf("IN: \"%.160s\"\n", (char *)in);
AES_KEY enc_key, dec_key;
AES_set_encrypt_key(key, 128, &enc_key);
AES_set_decrypt_key(key, 128, &dec_key);
for (i = 0; i < k; i++) {
memcpy(text_slice, &in[16 * i], 16);
printf("TEXT SLICE: %.16s\n", (char *)text_slice);
AES_encrypt(text_slice, enc_slice, &enc_key);
memcpy(&enc_out[16 * i], enc_slice, 16);
}
printf("ENC:");
for (i = 0; i < 16 * k; i++) {
printf(" %02X\n", enc_out[i]);
}
printf("\n");
for (i = 0; i < k; i++) {
memcpy(enc_slice, &enc_out[16 * i], 16);
AES_decrypt(enc_slice, dec_slice, &dec_key);
printf("Dec slice: %.16s \n", (char *)dec_slice);
memcpy(&dec_out[16 * i], dec_slice, 16);
}
printf("DEC OUT: \"%.160s\"\n", (char *)dec_out);
return 0;
}
There are many problems in that code.
The AES_set_encrypt_key and AES_set_decrypt_key are not key derivation functions, the second parameter is supposed to represent the length in bits of the first parameter (userKey).
If you provide an arbitrary string constant like "secretkey123" with a length that is not 128 in bits, it may cause memory corruption or create a very insecure context for your encryption.
In general, for user password based encryption, we generate a key from any password using a key derivation function (for example PBKDF2, or scrypt).
This line is also bad:
in[160] = '\0';
Since the buffer has a size of 160, the last index should be 160 - 1. If you write at index 160, you are actually overflowing.
Also, you must really notice the difference between single quote and double quotes when writing C code.
This is bad:
enc_slice[0] = "\0";
dec_slice[0] = "\0";
If you use double quotes, you are not actually writing the value 0 at the first index of enc_slice and dec_slice. You are writing the address of an empty read-only constant string.
Also this:
unsigned char enc_out[160] = "";
unsigned char dec_out[160] = "";
If you want to have empty buffers, you should just do:
unsigned char enc_out[160] = {0};
unsigned char dec_out[160] = {0};
Hopefully this is a good start to improve your code and make it work.
Following on an old question Converting hex to string in C?
The approved answer suggests to use sprintf to convert each hex to string.
I have two question on this -
1) When i have a hex like 0a i want my string to have 0a too, but following the above solution the result will have a.
2) What am i doing wrong here?
#include <stdio.h>
int main(void)
{
unsigned char readingreg[10];
readingreg[0] = 0x4a;
readingreg[1] = 0xab;
readingreg[2] = 0xab;
readingreg[3] = 0x0a;
readingreg[4] = 0x40;
unsigned char temp[10];
int i = 0;
while (i < 5)
{
sprintf(temp + i, "%x", readingreg[i]);
i++;
}
printf("String: %s\n", temp);
return 0;
}
The o/p seems to - String: 4aaa40
3) Combining both the both questions, i want my result string to be 4aabab0a40
TIA
Your code has several problems.
First unsigned char temp[10]; should be unsigned char temp[11]; to contain a string terminator.
Next is the format spec "%x" should be "%02x" so each value is 2 digits.
Then temp + i should be temp + i*2 so each pair of digits is written in the right place.
Correcting those mistakes:
#include <stdio.h>
int main(void)
{
unsigned char readingreg[10];
readingreg[0] = 0x4a;
readingreg[1] = 0xab;
readingreg[2] = 0xab;
readingreg[3] = 0x0a;
readingreg[4] = 0x40;
unsigned char temp[11];
int i = 0;
while (i < 5)
{
sprintf(temp + i*2, "%02x", readingreg[i]);
i++;
}
printf("String: %s\n", temp);
return 0;
}
Program output is now the required
String: 4aabab0a40
i wanted to split this hexstring, convert em, and store em in an array.
but it seems there is something off from my work, and i don't know what.
I intend to split this string
27CA6B
to
27
CA
6B
but the output is always only the first string.
like
27
51819
0
please somebody help, here is my code
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main(void)
{
char bc[] = "27CA6B";
char *theEnd;
long result;
long resulta;
long resultb;
long resultc;
result = strtol (bc, &theEnd, 0);
resulta = strtol (theEnd, &theEnd, 16 );
resultb = strtol (theEnd, NULL, 0);
//int i = 0;
//printf("%c%c%c%c%c%c\n", bc[0], bc[1], bc[2], bc[3], bc[4], bc[5]);
printf("%ld\n", result, &bc[0]);
printf("%ld\n", resulta, &bc[1]);
printf("%ld\n", resultb, &bc[2]);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void){
char bc[] = "27CA6B";
unsigned char result[(sizeof(bc)-1)/2] = {0};
int i = 0;
for(char *p = bc; *p; p += 2){
char part[3] = {0};
memcpy(part, p, 2);//Extract 2 characters
result[i++] = strtoul(part, NULL, 16);
}
for(i = 0; i < sizeof(result); ++i){
printf("%3u %c%c\n", result[i], bc[i*2], bc[i*2+1]);
}
return 0;
}
expand loop
unsigned char result1,result2,result3;
int i = 0;
char part[3] = {0};
memcpy(part, bc + i, 2); i += 2;
result1 = strtoul(part, NULL, 16);
memcpy(part, bc + i, 2); i += 2;
result2 = strtoul(part, NULL, 16);
memcpy(part, bc + i, 2); i += 2;
result3 = strtoul(part, NULL, 16);
i = 0;
printf("%3u %c%c\n", result1, bc[i], bc[i+1]); i += 2;
printf("%3u %c%c\n", result2, bc[i], bc[i+1]); i += 2;
printf("%3u %c%c\n", result3, bc[i], bc[i+1]); i += 2;
The "issue" that you see in because of this line
resulta = strtol (theEnd, &theEnd, 16 );
there, theEnd points to CA6B which, as per the base 16, is a valid input as whole, so the whole string is consumed and converted. The decimal representation value is 51819, which you see as output.
The best way to achieve this would be (based on your approach) to take a pointer to the starting of the array, and "clip" it on alternate indexes.
That said, all your printf() statements are logically wrong, as you have only one format specifier but you supply two arguments, so as the last one will be ignored silently.
I am trying to convert a string e.g. (LOCL) into binary and back to string. Although my script seems to be working fine I can not solve the last part. I have managed to get the characters converted one by one correctly. I can not find a way to concatenate them, because they are not integers or strings they are characters. I tried to convert them from int to strings, did not work. I tried the opposite I get pure integers. Where I am going so wrong? What I am missing so important?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_CHARACTERS 32
typedef struct rec {
char process[MAX_CHARACTERS];
}RECORD;
char b2c(char *s); /* Define funcrion */
char b2c(char *s) {
return (char) strtol(s, NULL, 2);
}
char *c2b(char *input); /* Define function */
char *c2b(char *input) {
RECORD *ptr_record;
ptr_record = malloc (sizeof(RECORD));
if (ptr_record == NULL) {
printf("Out of memmory!\nExit!\n");
exit(0);
}
char *temp;
char str[2] = {0};
for (temp = input; *temp; ++temp) {
int bit_index;
for (bit_index = sizeof(*temp)*8-1; bit_index >= 0; --bit_index) {
int bit = *temp >> bit_index & 1;
snprintf(str, 2, "%d", bit);
strncat(ptr_record->process , str , sizeof(ptr_record->process) );
}
}
return ptr_record->process;
}
int main(void) {
RECORD *ptr_record;
ptr_record = malloc (sizeof(RECORD));
if (ptr_record == NULL) {
printf("Out of memmory!\nExit!\n");
exit(0);
}
char *temp = "LOCL";
char *final = c2b(temp);
printf("This is the return: %s\n",final);
printf("This is the strlen of return: %zu\n",strlen(final));
char binary2char[24][9] = {{0}};
int i;
char loop;
char conversion[2] = {0};
//char word[5] = {0};
for( i = 0; i <= 24; i += 8 ) {
memcpy( binary2char[i] , &final[i] , 8 * sizeof(char) );
printf("ONE by ONE: %s , i: %i\n",binary2char[i],i);
loop = b2c(binary2char[i]);
printf("This is loop: %c\n",loop);
sprintf( conversion , "%d" , loop );
printf("This is conversion: %s\n",conversion);
//strncat( word , loop , sizeof(word) );
}
//printf("Miracle: %s\n",word);
free ( ptr_record );
return 0;
}
Here is a sample of the output:
This is the return: 01001100010011110100001101001100
This is the strlen of return: 32
ONE by ONE: 01001100 , i: 0
This is loop: L
This is conversion: 76
ONE by ONE: 01001111 , i: 8
This is loop: O
This is conversion: 79
ONE by ONE: 01000011 , i: 16
This is loop: C
This is conversion: 67
ONE by ONE: 01001100 , i: 24
This is loop: L
This is conversion: 76
To "concatenate" characters, allocate enough space and assign one by one e.g.,
size_t size = (binary_string_size + CHAR_BIT - 1) / CHAR_BIT + 1;
char* s = malloc(size);
if (!s)
error;
s[size-1] = '\0';
//...
s[i / CHAR_BIT] = b2c(binary2char[i]);