string concatenation with "\x" hex character escape - c

How do I create a string that contain multiple '\x41' or with arbitrary '\xnn' by copy from some give string for example:
char * string1 = "4141414141414141";
or char * string2 = "bde54d7ee10a2122";
And I would like my char * string3 become something like:
char * string3 = "\xbd\xe5\x4d\x7e\xe1\x0a\x21\x22";
or char * string3 = "\x41\x41\x41\x41\x41\x41\x41\x41";
Here is the code that I am trying to do, but it doesn't work.
char * string1 = "4141414141414141";
char c;
char * slash_x = "\\x";
int len = strlen(string1);
char * string3 = (char *) malloc(9);
for (i = 0; i < len; i++) {
if (0 == i % 2) {
printf("start\n");
j = i;
strcat(salt_empty, slash_x);
c = string[j];
printf("%c\n", c);
strncat(salt_empty, &c, 1);
j++;
c = string[j];
printf("%c\n", c);
strncat(salt_empty, &c, 1);
}
}
printf("%s\n", string3);
So the output with string3 will be "\x41\x41\x41\x41\x41\x41\x41\x41" instead of "AAAAAAAA" at console.
How could I fix the code in order to get "AAAAAAAA"
If the string1 is "bde54d7ee10a2122", then the string3 output at console would be ��M~
!"

You cannot convert the string by re-interpreting it from its source form. Use this instead (inefficient, but simple):
char *string1 = "4141414141414141";
int i, j, len = strlen(string1) & ~1;
char string3[len / 2 + 1];
for (i = j = 0; i < len; i += 2, j++) {
char buf[3];
memcpy(buf, string1 + i, 2);
buf[2] = '\0';
string3[j] = strtol(buf, NULL, 16);
}
string3[j] = '\0';
printf("%s\n", string3);

You want:
char string1[] = {0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0};

For each pair of characters in the source string, determine the hex value of each character in the pair, combine them to come up with the encoded character, then store the result in your destination string.

Related

How to write() hexadecimal representation of \n?

I'm trying to write() hexadecimal representation of \n without any success.
The code I have ft_putstr_non_printable.c:
#include <unistd.h>
void ft_putstr_non_printable(char *str)
{
int i;
unsigned char a;
char c;
i = 0;
a = 0x0;
while (str[i] != '\0')
{
if (str[i] <= 31 || str[i] == 127)
{
a = str[i];
write(1, &a, 1);
}
else
{
c = str[i];
write(1, &c, 1);
}
i++;
}
}
And main.c:
#include <stdio.h>
#include <string.h>
#include "ft_putstr_non_printable.c"
int main(void)
{
char a[] = "\n au revoir\a";
char b[] = "omellette du fromage\b";
char c[] = "coeuf#ca6va\e fef";
char d[] = " Batata \x7F rfg";
char e[] = "roquefort`[e{forte-e_tem,bolor \n feff";
char f[] = " we 9are 78familly \x1F rgfenf";
ft_putstr_non_printable(a);
ft_putstr_non_printable(b);
ft_putstr_non_printable(c);
ft_putstr_non_printable(d);
ft_putstr_non_printable(e);
ft_putstr_non_printable(f);
}
Am I doing something wrong? How do I get \x0a?
Edit: I can't use printf(). I'm limited to write().
Instead writing one character when str[i] is out of the printable range, form a little string and write that.
// if (str[i] <= 31 || str[i] == 127)
if (str[i] <= 31 || str[i] >= 127) {
unsigned char a = str[i];
char buf[5];
int len = sprintf(buf, "\\x%02X", a);
// write(1, &a, 1);
write(1, buf, len);
}
I'm limited to write()
If sprintf() not available:
// int len = sprintf(buf, "\\x%02X", a);
buf[0] = '\\';
buf[1] = 'x';
buf[2] = "0123456789ABCDEF"[a/16];
buf[3] = "0123456789ABCDEF"[a%16];
buf[4] = '\0';
len = 4;
Advanced:
char may be unsigned, so values above 127 are possible.
To well reverse the process it might make sense to print the \\ in hex.
if (str[i] <= 31 || str[i] >= 127 || str[i] == '\\') {
Notice:
I recommend the answer from chux - Reinstate Monica due to the nice conversion from 0..15 to hex.
See https://stackoverflow.com/a/68307913/4386427
I'll leave this answer as-is just in case someone should prefer this code-wise longer way of doing the conversion
Answer
Given all your restriction (which prevents normal code), you may be looking for:
char a = '\n'; // Or any other char
char h;
unsigned char tmp;
tmp = a;
tmp = tmp / 16;
if (tmp < 10)
{
h = '0' + tmp;
}
else
{
h = 'a' + tmp - 10;
}
write(1,&h,1);
tmp = a
tmp = tmp % 16;
if (tmp < 10)
{
h = '0' + tmp;
}
else
{
h = 'a' + tmp - 10;
}
write(1,&h,1);
Output
0a
Yet another option:
void ft_putstr_non_printable(const char *str) {
static const char hex[] = "0123456789ABCDEF";
int outfd = fileno(stdout);
char buf[4] = {'0', 'x'};
unsigned char ch; // used to convert the usually signed `char` to unsigned
for(; (ch = *str) != '\0'; ++str) { // loop until null terminator
if (ch < ' ' || ch > '~') { // outside printable ASCII range?
// pick the last two chars in `buf` from the hex array:
buf[2] = hex[ch >> 4]; // the high nibble
buf[3] = hex[ch & 0xF]; // the low nibble
write(outfd, buf, sizeof buf); // ex: writes 0x7F if ch == 127
} else {
write(outfd, &ch, 1);
}
}
ch = '\n';
write(outfd, &ch, 1);
}
I have wrapped the hex output into [] to make them mo distinct.
#include <unistd.h>
void ft_putstr_non_printable(const char *s)
{
const char *hex = "0123456789ABCDEF";
const unsigned char *str = s;
while (*str)
{
if (*str <= 31 || *str >= 127)
{
char hexrep[] = {'[','0','x', hex[*str >> 4], hex[*str & 0x0f],']'};
write(1, hexrep, sizeof(hexrep));
}
else
{
write(1, str, 1);
}
str++;
}
write(1, (char[]){'\n'},1);
}
int main(void)
{
char a[] = "\n au revoir\a";
char b[] = "omellette du fromage\b";
char c[] = "coeuf#ca6va\e fef";
char d[] = " Batata \x7F rfg";
char e[] = "roquefort`[e{forte-e_tem,bolor \n feff";
char f[] = " we 9are 78familly \x1F rgfenf";
ft_putstr_non_printable(a);
ft_putstr_non_printable(b);
ft_putstr_non_printable(c);
ft_putstr_non_printable(d);
ft_putstr_non_printable(e);
ft_putstr_non_printable(f);
}
https://godbolt.org/z/zq7sPfM6q
Output:
[0x0A] au revoir[0x07]
omellette du fromage[0x08]
coeuf#ca6va[0x1B] fef
Batata [0x7F] rfg
roquefort`[e{forte-e_tem,bolor [0x0A] feff
we 9are 78familly [0x1F] rgfenf
If you want to have \xHH format suimply change one line to:
char hexrep[] = {'\\','x', hex[*str >> 4], hex[*str & 0x0f]};
https://godbolt.org/z/6GonenfK7
Output:
\x0A au revoir\x07
omellette du fromage\x08
coeuf#ca6va\x1B fef
Batata \x7F rfg
roquefort`[e{forte-e_tem,bolor \x0A feff
we 9are 78familly \x1F rgfenf
What does write() actually do? It's defined in <unistd.h> as:
ssize_t write(int fildes, const void *buf, size_t nbyte);
It writes to a filedescriptor. It writes from a buffer and writes nbytes bytes from that memory location.
Thus when you pass &i to it, write just sees memory addresses. It doesn't see an int. Likewise with &c. What you need to do is turn each character (as a number) into a string representing the character. The code for ft_putstr_non_printable would look something like:
void ft_putstr_non_printable(char *str)
{
int i;
unsigned char a;
i = 0;
const char[] hexchars = "0123456789ABCDEF";
for (int ii = 0;str[i]!='\0';ii++)
{
a = str[i];
if (str[i]> 31 && str[i] < 127)
write(1, &a, 1);
else
{
write(1,'[',1);
if (a<=16
while (a!=0)
{
write(1,hexchars+(a%16),1);
a/=16;
}
write(1,']',1);
}
}
}
This is basically how itoa() works. #4386427's answer is more elegant for single byte characters, but I wanted to explicitly show how one would do it in a while loop.

How to convert Hex char into bytes like \x90\x90?

I am searching a way to convert hex char to bytes like \x90\x0d\x41 and when I use printf(), binary data are printed?
char *hex = "909090904241";
when I need to get \x90\x90\x90\x90\x42\x42 and when I print I get binary data.
int hex_to_bytes(const char* hex, uint8_t** buf_ptr, size_t** len_ptr) {
size_t len = strlen(hex);
if (len % 2)
goto error1;
len /= 2;
char* buf = malloc(len);
char hex_byte[3];
hex_byte[2] = 0;
for (size_t i=len; i--; ) {
hex_byte[0] = *(hex++);
hex_byte[1] = *(hex++);
char* end_ptr;
buf[i] = strtoul(hex_byte, &end_ptr, 16);
if (end_ptr != hex_byte+2)
goto error2;
}
*buf_ptr = buf;
*len_ptr = len;
return 1;
error2:
free(buf);
error1:
*buf_ptr = NULL;
*len_ptr = 0;
return 0;
}
uint8_t* buf;
size_t len;
if (!hex_to_bytes(hex, &buf, &len)) {
... handle error ...
}
... Use buf and len ...
free(buf);
Notes that buf isn't nul-terminated. I didn't see the point of making it nul-terminated string when the input could be "000000".
For each character in the string, first convert it to a number by subtracting its ASCII by either the character '0' or 'A'. Then assign each value into the target array, shifting as necessary.
The below assumes ASCII, and that the input string contains only characters in the range 0-9 and A-F.
char *str="909090904241";
unsigned char a[strlen(str)/2+1] = {0};
int i;
for (i=0;i<strlen(str);i++) {
unsigned char num = (str[i] >= '0' && str[i] <= '9') ? str[i] - '0' : str[i] - 'A' + 10;
a[i/2] |= num << (4 * (1 - (i % 2))); // shift even index bits by 4, odd index by 0
}
for (i=0;i<strlen(str)/2+1;i++) {
printf("%02x ", a[i]);
}
printf("\n");
Output:
90 90 90 90 42 41
so basically I have a variable which contains hex bytes and when I print them I obtain binary representation
#include<stdio.h>
char *hex_bytes = "\x90\x90\x90\x41";
int main () {
printf(hex_bytes);
return 0 ;
}
I wanna do the same with hex chars like that
char *hex = "9090904241";
Thank you , HM
Loop through the string and append to a new string a piece with \x added infront like this:
const char *hex = "909090904241";
char* result = malloc((strlen(hex) * 2 + 1)* sizeof(char));
result[0] = 0;
char piece[] = "\\x00";
for (int i = 0; i < strlen(hex); i+=2) {
piece[2] = hex[i];
piece[3] = hex[i+1];
strcat(result, piece);
}

How to concatenate char and string / How to make char to string

#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#define MAX_SIZE 20
void main()
{
int i, j;
char *str1, *str2, *str3, *str_mid;
bool **lcs1, **lcs2;
int len1, len2, len3, len_mid;
char *ch = (char*)malloc(sizeof(char) * 3);
str1 = (char*)malloc(sizeof(char)*MAX_SIZE); //applicatian
str2 = (char*)malloc(sizeof(char)*MAX_SIZE); //apiasn
str3 = (char*)malloc(sizeof(char)*MAX_SIZE); //apun
str_mid = (char*)malloc(sizeof(char)*MAX_SIZE); //apn
str_mid = "";
scanf("%s", str1);
scanf("%s", str2);
scanf("%s", str3);
len1 = strlen(str1);
len2 = strlen(str2);
len3 = strlen(str3);
//str2, str3 ->str_mid (lcs1)
lcs1 = (bool**)malloc(sizeof(bool*)*(len3 + 1));
for (i = 0; i < len3 + 1; i++)
lcs1[i] = (bool*)malloc(sizeof(bool)*(len2 + 1));
for (i = 0; i < len3 + 1; i++)
for (j = 0; j < len2 + 1; j++)
lcs1[i][j] = false;
for (i = 1; i < len3 + 1; i++)
for (j = 1; j < len2 + 1; j++)
if (str3[i-1] == str2[j-1])
lcs1[i][j] = true;
for (i = 1; i < len3 + 1; i++)
{
for (j = 1; j < len2 + 1; j++)
if (lcs1[i][j])
{
//<--- error
ch = str3[i - 1];
strcat(str_mid, ch);
//--->
break;
}
}
//printf("%s", str_mid);
//str_mid, str1 (lcs2)
}
In <--- error ---> part,
I want to concatenation str3[i-1] and str_mid but, str3[i-1] is character type.
So make temporary string is ch and do concatenate.
But, the access error is occurred.
How to make char to string or, how to concatenate char and string?
So long as MAX_SIZE is large enough that str_mid will be able to hold the extra character, you can use strcat() and a compound literal (for C99 or later):
strcat(str_mid, (char[2]){ str3[i - 1], '\0' });
Note that in your code, str3[i - 1] is a char, while you have declared ch as a pointer to char.
How to concatenate char and string
There is no need to call any library function at all, nor to dynamically allocate any memory.
Assuming str_mid is large enough just do:
{
size_t tmp_len = strlen(str_mid);
str_mid[tmp_len] = str3[i - 1];
str_mid[tmp_len + 1] = '\0';
}
To still have the feeling to use a function you might want to wrap the above code into a macro like this:
#define STRCATCHAR(s, c) \
do { \
assert(s != NULL); \
size_t tmp_len = strlen(s); \
(s)[tmp_len] = (c); \
(s)[tmp_len + 1] = '\0'; \
} while (0)
and use it like this:
STRCATCHAR(str_mid, str3[i - 1]);
To concatenate char and string (first char, then string) do:
const char* conc_char_string(const char ch, const char* str, int len) {
const char* out = malloc(len + 2); /* 1 char from ch, len chars from str, and zero character, totally len+2 */
out[0] = ch; /* copy the character */
strcpy(out+1, str); /* copy the string */
return out;
}
Here len should be strlen(str)
The statement str_mid = ""; assigns the address of costant string "" to pointer str_mid, which will cause segmentfault later. Use str_mid[0] = '\0'; instead.
In statement ch = str3[i - 1];, you are assigning char to char pointer, which will cause segmentfault.
If all you want is simply appending a character to the string, you can keep track of length of string, like this:
len_mid = strlen(str_mid);
for (i = 1; i < len3 + 1; i++)
{
for (j = 1; j < len2 + 1; j++)
if (lcs1[i][j])
{
str_mid[len_mid++] = str3[i - 1];
str_mid[len_mid] = '\0';
break;
}
}
First rule of the C-club, create your own string buffer, second rule of the C-club create your own string buffer.
Each programmer has it's own string buffer. Minimal requirement is :
#define STRINGSTRTSZ 256
typedef struct string
{
char *str;
size_t n;
size_t buf_sz;
}String,*pString;
pString new_string()
{
pString res;
res=malloc(sizeof(String)); ///i leave to you the error handling
res->bus_sz=STRINGSTRSZ;
res->n=0;
res->str=malloc(res->bus_sz);
}
char*concatbase(pString *string,char*s,size_t len)
{
if(len+1>=string->buf_sz-string->n)
{
res->buf_sz+=len+res->buf_sz;
char *tmp=realloc(string->str,res->buf_sz);
if(tmp)
string->str=tmp;
else
...
}
memcpy(string->str+string->n,s,len);
string->n+=len;
*(string->str+string->n)='\0';
return string->str;
}
#define concatNllPtr(string,nllptr) concatbase(string,nllptr,strlen(nllptr))
#define concatString(string,str2) concatbase(string,(str2)->str,(str2)->n)
End so on...

How to retrieve multiple substrings of a string and write them into one string in C?

How can I split a const char * string in the fastest possible way.
char *inputStr="abcde";
char buff[500];
I would like to have in buffer the following formatted string, format of which must be:
IN('a','ab','abc','abcd','abcde')
I'm learning C and new to the language. I have no clue where to start on this splitting problem.
I don't think you can do this particularly "fast", it seems like it's quite heavily limited since it needs to iterate over the source string many times.
I'd do something like:
void permute(char *out, const char *in)
{
const size_t in_len = strlen(in);
char *put;
strcpy(out, "IN(");
put = out + 3;
for(i = 1; i < in_len; ++i)
{
if(i > 1)
*put++ = ',';
*put++ = '\'';
memcpy(put, in, i);
put += i;
*put++ = '\'';
}
*put++ = ')';
*put++ = '\0';
}
Note that this doesn't protect against buffer overrun in the output.
You could use strcpy, strcat/strncat and a simple loop:
#include <stdio.h>
#include <string.h>
int main(void) {
char* inputStr = "abcde";
char buff[500];
// start the formatted string:
strcpy(buff,"IN(");
int i, len = strlen(inputStr);
for (i = 0; i < len; ++i) {
strcat(buff, "'");
strncat(buff, inputStr, i + 1);
strcat(buff, "'");
// if it is not last token:
if (i != len - 1)
strcat(buff, ",");
}
// end the formatted string:
strcat(buff,")");
printf("%s", buff);
return 0;
}
outputs the desired IN('a','ab','abc','abcd','abcde')
To give you a start, consider the following code:
char buffer[64];
const char str[] = "abcde";
for (size_t i = 1; i <= strlen(str); ++i)
{
strncpy(buffer, str, i);
buffer[i] = '\0'; /* Make sure string is terminated */
printf("i = %lu, buffer = \"%s\"\n", i, buffer);
}
The above code should print
i = 1, buffer = "a"
i = 2, buffer = "ab"
i = 3, buffer = "abc"
i = 4, buffer = "abcd"
i = 5, buffer = "abcde"
If you are looking for something like this in C++:-
#include <iostream>
#include <string.h>
using namespace std;
int main() {
const char *inputStr = "abcde"; //const to remove warning of deprecated conversion
char buff[500];
int count = 0;
for (int i = 0; i < (int) strlen(inputStr); i++) { //cast it to int to remove
// warning of comparison between signed and unsigned
for (int j = 0; j <= i; j++) {
buff[count++] = inputStr[j];
}
buff[count++] = ',';
}
buff[--count] = '\0';
cout << buff;
return 0;
}
Output - a,ab,abc,abcd,abcde

Swapping endiannes in C

I have this string
c1eb044f0708015b267913fc4dff5aabe3dd4a97f10f7ba935cd360000000000
How does one swap it so it becomes
000000000036cd35a97b0ff1974adde3ab5aff4dfc1379265b0108074f04ebc1
Those two are basically examples, but that is what i need to do, but not know how as i have very little knowledge of C.
The above two strings are actually unsigned char[] in the C program
P.S
Don't think i didn't go through google. I did, but i found very little of what i needed so every attempt to do that failed.
for (int i = 0; i < size; i += 2) {
myNewStr[size - i - 2] = myStr[i];
myNewStr[size - i - 1] = myStr[i + 1];
}
Something like this; probably not perfect but gives you the idea. You'll want appropriate error checking, initialization of your buffer, etc.
Edit: I made an assumption I shouldn't have, possibly. I interpreted your string as hex representations of bytes, so I took c1 as an unsigned char and switched it with 00, for example. If your string is actually lowercase c, the number 1, etc., then Micah's answer is what you want, not mine.
void reverse_string(unsigned char *buf, int length)
{
int i;
unsigned char temp;
for (i = 0; i < length / 2; i++)
{
temp = buf[i];
buf[i] = buf[length - i - 1];
buf[length - i - 1] = temp;
}
}
This seems to do what you want, include at least string.h and stdlib.h.
unsigned char *stringrev(const unsigned char *s) {
size_t n = strlen((const char *)s);
unsigned char *r = malloc(n + 1);
if (r != NULL && !(n & 1)) {
const unsigned char *fp = s;
unsigned char *rp = r + n;
for(*rp = '\0'; n > 1; n -= 2) {
*--rp = fp[1];
*--rp = fp[0];
fp += 2;
}
}
return r;
}
Slight alternative to Micah's answer. I assume that the size is precalculated and even, and check that it's greater than 0 because s-2 is potentially UB. I modify the string in-place just for variety.
static inline void swap_uchar(unsigned char *l, unsigned char *r) {
unsigned char tmp = *l;
*l = *r;
*r = tmp;
}
void reverse_pairs(unsigned char *s, size_t size) {
if (size > 0) {
for (unsigned char *l=s, *r=s+size-2; l < r; l += 2, r -= 2) {
swap_uchar(l, r);
swap_uchar(l+1, r+1);
}
}
}
If you have a string: "12ab\0" then the reverse endian of this string would be "\0ba21" .
If you have a numeric: 0x12ab then the reverse endian of this numeric would be 0xab12 .
Which one do you want.
Here is a function for converting between endian, which will handle the passed argument as a block of memory and change the endian.
Code
#include <stdio.h>
typedef struct _test {
unsigned int a, b;
} test;
/* x: base address of the memory
* n: length of the memory
*/
void reverse_endian (void *x, int n)
{
char *arr_conv, *arr, t;
arr = arr_conv = (char *) x;
arr += (n-1);
n/=2;
while (n)
{
t = *arr_conv;
*arr_conv = *arr;
*arr = t;
n--;
arr_conv++;
arr--;
}
}
int main (void)
{
char str1[] = "c1eb044f0708015b267913fc4dff5aabe3dd4a97f10f7ba935cd360000000000";
char str2[] = "hellio";
/* Assigns the str1 as hex values */
unsigned char str3[] = {0xc1, 0xeb, 0x04, 0x4f, 0x07, 0x08, 0x01, 0x5b, 0x26, 0x79, 0x13, 0xfc, 0x4d, 0xff, 0x5a, 0xab, 0xe3, 0xdd, 0x4a, 0x97, 0xf1, 0x0f, 0x7b, 0xa9, 0x35, 0xcd, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00};
test x;
char q = 0x12;
int v = 0x1234abcd;
int i, n;
x.a = 0x12ab34cd;
x.b = 0x98ef76af;
printf ("\nNormal : x.a = %x x.b = %x", x.a, x.b);
reverse_endian (&x, sizeof (x));
printf ("\nReverse: x.a = %x x.b = %x", x.a, x.b);
printf ("\nNormal : q = %x", q);
reverse_endian (&q, sizeof (q));
printf ("\nReverse: q = %x", q);
printf ("\nNormal : q = %x", v);
reverse_endian (&v, sizeof (v));
printf ("\nReverse: q = %x", v);
printf ("\nNormal : str1 = %s", str1);
/* minus 1 to avoid the trailing nul character */
reverse_endian (str1, sizeof (str1) - 1);
printf ("\nReverse: str1 = %s", str1);
printf ("\nNormal : str2 = %s", str2);
/* minus 1 to avoid the trailing nul character */
reverse_endian (str2, sizeof (str2) - 1);
printf ("\nReverse: str2 = %s", str2);
printf ("\nNormal : str3 = ");
n = sizeof (str3);
for (i=0; i < n; i++)
{
printf ("%x", (str3[i]>>4)&0x0f);
printf ("%x", str3[i]&0x0f);
}
reverse_endian (str3, sizeof (str3));
printf ("\nReversed: str3 = ");
for (i=0; i < n; i++)
{
printf ("%x", (str3[i]>>4)&0x0f);
printf ("%x", str3[i]&0x0f);
}
printf ("\n");
return 0;
}
Output
Normal : x.a = 12ab34cd x.b = 98ef76af
Reverse: x.a = af76ef98 x.b = cd34ab12
Normal : q = 12
Reverse: q = 12
Normal : q = 1234abcd
Reverse: q = cdab3412
Normal : str1 = c1eb044f0708015b267913fc4dff5aabe3dd4a97f10f7ba935cd360000000000
Reverse: str1 = 000000000063dc539ab7f01f79a4dd3ebaa5ffd4cf319762b5108070f440be1c
Normal : str2 = hellio
Reverse: str2 = oilleh
Normal : str3 = c1eb044f0708015b267913fc4dff5aabe3dd4a97f10f7ba935cd360000000000
Reversed: str3 = 000000000036cd35a97b0ff1974adde3ab5aff4dfc1379265b0108074f04ebc1
Note that the strings str1, str2 are simply reversed, because each character of the string is one byte. The same character string you have provided is represented as byte string in str3. Its hex values are shown as output. The operations for all the data are identical, as it is only concerned to memory byte ordering.

Resources