I've a function that can convert an hexadecimal string (ex. "02AFA1253...ecc.") into an uint8_t array. I would need to do the opposite, which is to convert the uint8_t array to a string of hexadecimal characters. How to do it? Here is the code of the function that converts hex string to uint8_t array: Thank you everybody for your help!
size_t convert_hex(uint8_t *dest, size_t count, const char *src) {
size_t i = 0;
int value;
for (i = 0; i < count && sscanf(src + i * 2, "%2x", &value) == 1; i++) {
dest[i] = value;
}
return i;
}
You want to do the opposite, so do the opposite.
size_t convert_hex_inv(char *dest, size_t count, const uint8_t *src) {
size_t i = 0;
for (i = 0; i < count && sprintf(dest + i * 2, "%02X", src[i]) == 2; i++);
return i;
}
Note that the buffer pointed at by dest has to be at least count * 2 + 1 elements. Don't forget the +1 for terminating null-character.
Related
I want to repeat a string - for example hello - for a specific number of imes - for example 3 times -, but it doesnt work :) The example should look like this: hellohellohello, but I get no output or i get HHHHHHHHHHH...
here is my code:
char *repeat_str(size_t count, char *src) {
int length = strlen(src);
int z = length;
char *ausgabe = calloc((length*(count+1)), sizeof(char));
for(int i = 0; i<=((int) count);i++){
for(int j =0; j< length; j++){
ausgabe[i+j+z] = src[j];
}
z=z*2;
}
//printf("%s\n", ausgabe);
return(ausgabe);
}
If i remove the 'z' in the brackets of 'ausgabe', i get the output HHHHHHHH%, with the z I just get no output. Could bdy pls help me change this behavoiur - and more important, understant why it does that?
As you are always referring *src, which is fixed to the first letter of src,
the result looks like repeating it. Would you please try instead:
char *repeat_str(size_t count, char *src) {
int length = strlen(src);
char *ausgabe = calloc(length * count + 1, sizeof(char));
for (int i = 0; i < count; i++) {
for (int j = 0; j < length; j++) {
ausgabe[i * length + j] = src[j];
}
}
//printf("%s\n", ausgabe);
return ausgabe;
}
The strcat function is your friend. We can calloc a buffer long enough for n source strings, plus one for the null terminator, and then just concatenate the source string onto that buffer n times.
char *repeat_string(int n, const char *s) {
int len = strlen(s) * n + 1;
char *result = calloc(len, 1);
if (!result) return NULL;
for (int i = 0; i < n; i++) {
strcat(result, s);
}
return result;
}
I am trying to convert an array of chars into an array of hexadecimal numbers.
Each char in the input array will be converted to two chars that represent the corresponding hexadecimal number.
This is my input:
char input[3] = "over";
This would be the output:
char output[6] = "6f766572";
How can I achieve this conversion in C without libraries? Thanks in advance.
My code is currently as follows:
void convert(char *input, int inputsize) {
char c;
char output[inputsize * 2];
for (int i = 0; i < inputsize; i++) {
c = input[i]
// change c to hex here
// put each letter of the hex into output[i * 2] and output[i * 2 + 1]
}
}
Create a loop running until it finds \0 in the input buffer.
For each character number [i] in the input string, mask out the upper and lower nibble of that byte. Make sure to use unsigned types.
Run each of the two nibbles through a lookup table such as const char HEX_LOOKUP [16] = "0123456789ABCDEF";, where the value of the nibble is used as index.
Store the result in output index [i*2] and [i*2+1], since the output will be exactly twice as large as the input.
Null terminate the output string.
If you don't wanna use library functions, you'll have to build a simple lookup table yourself:
#include <stdio.h> // only for printing the result
const char table[] = "0123456789abcdef";
int main(void) {
char src[5 + 1] = "hello";
char dst[5 * 2 + 1];
char *s, *d;
for (s = src, d = dst; *s != '\0'; s++, d += 2) {
const unsigned char lo = *s & 0xf;
const unsigned char hi = *s >> 4;
*d = table[hi];
*(d + 1) = table[lo];
}
*d = '\0';
puts(dst);
return 0;
}
You can try this one:
void toHex(const char *in, int len, char *out)
{
for(int i = 0; i < len; i++)
{
sprintf(&out[i * 2], "%x", in[i]);
}
}
int main(int argc, const char * argv[])
{
char input[] = "over";
char output[32];
memset(output, 0, sizeof(output));
toHex(input, sizeof(input), output);
puts(output);
return 0;
}
Taking an input as hex string and then converting it to char string in C. The hex string can contain 0x00 which translates to an 0 in Ascii when converted. This terminates the string. I have to store the value in an char string because the API uses that.
My code so far:
int hex_to_int(unsigned char c) {
int first =0;
int second =0;
int result=0;
if(c>=97 && c<=102)
c-=32;
first=c / 16 - 3;
second =c % 16;
result = first*10 + second;
if(result > 9) result--;
return result;
}
unsigned char hex_to_ascii(unsigned char c, unsigned char d){
unsigned char a='0';
int high = hex_to_int(c) * 16;
int low = hex_to_int(d);
a= high+low;
return a;
}
unsigned char* HextoString(unsigned char *st){
int length = strlen((const char*)st);
unsigned char* result=(unsigned char*)malloc(length/2+1);
unsigned char arr[500];
int i;
unsigned char buf = 0;
int j=0;
for(i = 0; i < length; i++)
{
if(i % 2 != 0)
{
arr[j++]=(unsigned char)hex_to_ascii(buf, st[i]);
}
else
{
buf = st[i];
}
}
arr[length/2+1]='\0';
memcpy(result,arr,length/2+1);
return result;
}
You can store any values in a char array. But if you want to store a value of 0x00, you cannot use the string functions on this array. So you have to use an integer variable to store the length of the data you want to store. You can then write functions that use this integer.
As you provided more information now, I can tell you that your function doesn't cut anything as it loops through the whole C-string which you provided for example as input "0a12345600a0020b12". The "problem" is that if you want to get the length (strlen()) of the output string after the conversion for example then it will stop at '\0' and you will get a "wrong" length in terms of your original input string.
It is exacly like it's written in the answer of Xaver save the length information and the string to work with that length and not the one you would get by the C-string functions like strlen().
To show that and in order to provide a right length information I've added a struct definition to your code that defines a string type consisting of a size_t len and an unsigned char* str called HexString. With the additional length information you can handle a 0 byte. Also I made little changes to your code, e.g. you don't need that character buffer arr on the stack.
With your input: "0a12345600a0020b12"
the following output you will see: <0a> <12> <34> <56> <00> <a0> <02> <0b> <12> <00>
if you print the C-string hexadecimal every single character. The last <00> is the null termination.
Look here on ideone for a live example.
The code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
size_t len; /* C-string length + '\0' */
unsigned char* str;
} HexString;
int hex_to_int(unsigned char c)
{
int first =0;
int second =0;
int result=0;
if (c >= 97 && c <= 102) /* 97 = 'a'; 102 = 'f' */
c -= 32;
first = c / 16 - 3;
second = c % 16;
result = first * 10 + second;
if (result > 9) result--;
return result;
}
unsigned char hex_to_ascii(unsigned char c, unsigned char d)
{
unsigned char a = '0';
int high = hex_to_int(c) * 16;
int low = hex_to_int(d);
a = high + low;
return a;
}
HexString HextoString(const char* const st)
{
HexString result;
size_t length = strlen(st);
result.len = length/2+1;
result.str = malloc(length/2+1);
size_t i;
size_t j = 0;
unsigned char buf = 0;
for (i = 0; i < length; i++)
{
if (i % 2 != 0)
{
result.str[j++] = hex_to_ascii(buf, st[i]);
}
else
{
buf = (unsigned char)st[i];
}
}
result.str[length/2+1] = '\0';
return result;
}
int main()
{
size_t i;
HexString hexString = HextoString("0a12345600a0020b12");
for (i = 0; i < hexString.len; ++i)
{
printf("<%02x> ", hexString.str[i]);
}
free(hexString.str);
return 0;
}
I'm supposed to copy char orig[] to char reversed[] and reverse it. My function works but doesn't properly reset the string as evidenced by the fact that a blank string returns the prior test results. How can I fix this?
void reverse(char orig[], char reversed[]) {
int lastChar = strlen(orig) - 1;
int lastCopy = lastChar;
int i;
for(i = 0; i < lastChar; i++){
reversed[lastCopy] = orig[i];
reversed[i] = orig[lastCopy];
lastCopy--;
reversed[lastChar+1] = '\0';
}
return ;
}
This is what I get as output:
Test "software" (Pass, returns: erawtfos)
Test the empty string
Assertion failure
Have: <erawtfos>
Expect: <>
Test a long string (Pass)
Test a simple palindrome (Pass)
4 assertions: 3 passed 1 failed
OP problem: When the original string orig has length 0 or 1, the null character is never set in reversed.
Instead create a simple loop pulling 1 char at a time.
// As `orig` elements are not changed, good C style to make it `const`
void reverse(const char orig[], char reversed[]) {
// use `size_t` as `int` may be too narrow
size_t length = strlen(orig);
size_t i;
for(i = 0; i < length; i++) {
reversed[i] = orig[length - i - 1];
}
reversed[i] = '\0';
}
If orig and reversed might overlap, a temporary copy is needed.
void reverse(const char orig[], char reversed[]) {
size_t length = strlen(orig);
char tmp[length+1]; // Add 1 because an array of size 0 is UB
memcpy(tmp, orig, length);
size_t i;
for(i = 0; i < length; i++) {
reversed[i] = tmp[length - i - 1];
}
reversed[i] = '\0';
}
Simplify:
void reverse(char orig[], char reversed[]) {
int len = strlen(orig);
int last = len - 1;
reversed[len] = '\0';
for (int i = 0; i < len; i += 1) {
reversed[last] = orig[i];
last -= 1;
}
return;
}
you can use built in functions like string::rbegin(),string::rend()
in order to copy string reversely.
string copy(orig.rbegin(),orig.rend());
don't forget to include < string.h >
The definition of library function strspn is:
size_t strspn(const char *str, const char *chars)
/* Return number of leading characters at the beginning of the string `str`
which are all members of string `chars`. */
e.g. if str is "fecxdy" and chars is "abcdef" then the function would return 3, since f, e and c all appear somewhere in chars, giving 3 leading characters of str, and x is the first character of str which is not a member of chars.
Could someone help me write an implementation of strspn in C. The only library function I am allowed to call from the implementation is strlen?
The basic idea is to step through the string, one character at a time, and test if it's in the character set. If it's not, stop and return the answer. In pseudocode, that would look like:
count = 0
for each character c in str
if c is not in chars
break
count++
return count
The if c is not in chars test can be implemented by iterating through all of the characters of chars and testing if c matches any of the characters. Note that this is not the fastest implementation, since it involves stepping through the chars string for each character in str. A faster implementation would use a lookup table to test if c is not in chars.
I found this question while going over old exams. You weren't allowed to use indexing or any standard functions. Here's my attempt at a solution:
#include <stdio.h>
size_t myStrspn(const char *str1, const char *str2){
size_t i,j;
i=0;
while(*(str1+i)){
j=0;
while(*(str2+j)){
if(*(str1+i) == *(str2+j)){
break; //Found a match.
}
j++;
}
if(!*(str2+j)){
return i; //No match found.
}
i++;
}
return i;
}
void main(){
char s[] = "7803 Elm St.";
int n = 0;
n = myStrspn(s,"1234567890");
printf("The number length is %d. \n",n);
}
Here's the solution from the exam:
#include<stdio.h>
size_t strspn(const char* cs, const char* ct) {
size_t n;
const char* p;
for(n=0; *cs; cs++, n++) {
for(p=ct; *p && *p != *cs; p++)
;
if (!*p)
break;
}
return n;
}
For loops made it much more compact.
I think this should be pretty fast
size_t strspn(const unsigned char *str, const unsigned char *chars){
unsigned char ta[32]={0};
size_t i;
for(i=0;chars[i];++i)
ta[chars[i]>>3]|=0x1<<(chars[i]%8);
for(i=0;((ta[str[i]>>3]>>(str[i]%8))&0x1);++i);
return i;
}
Thanks to others for sanity checks.
A naive implementation of strspn() would iterate on the first string, as long as it finds the corresponding character in the second string:
#include <string.h>
size_t strspn(const char *str, const char *chars) {
size_t i = 0;
while (str[i] && strchr(chars, str[i]))
i++;
return i;
}
Given that you are not allowed to call strchr(), here is a naive native implementation:
size_t strspn(const char *str, const char *chars) {
size_t i, j;
for (i = 0; str[i] != '\0'; i++) {
for (j = 0; chars[j] != str[i]; j++) {
if (chars[j] == '\0')
return i; // char not found, return index so far
}
}
return i; // complete string matches, return length
}
Scanning the second string repeatedly can be costly. Here is an alternative that combines different methods depending on the length of chars, assuming 8-bit bytes:
size_t strspn(const char *str, const char *chars) {
size_t i = 0;
char c = chars[0];
if (c != '\0') { // if second string is empty, return 0
if (chars[1] == '\0') {
// second string has single char, use a simple loop
while (str[i] == c)
i++;
} else {
// second string has more characters, construct a bitmap
unsigned char x, bits[256 / 8] = { 0 };
for (i = 0; (x = chars[i]) != '\0'; i++)
bits[x >> 3] |= 1 << (x & 7);
// iterate while characters are found in the bitmap
for (i = 0; (x = str[i]), (bits[x >> 3] & (1 << (x & 7))); i++)
continue;
}
}
return i;
}
int my_strspn(const char *str1,const char *str2){
int i,k,counter=0;
for(i=0;str1[i]!='\0';i++){
if(counter != i) break;
for(k=0;str2[k]!='\0';k++){
if(str1[i]==str2[k])
counter++;
}
}
return counter;
}
Create a lookup table (a poor man's set) for all possible ASCII chars, and just lookup each character in str. This is worst case O(max(N,M)), where N is the number of characters in str and M is the number of characters in chars.
#include <string.h>
size_t strspn(const char *str, const char *chars) {
int i;
char ch[256] = {0};
for (i = 0; i < strlen(chars); i++) {
ch[chars[i]] = 1;
}
for (i = 0; i < strlen(str); i++) {
if (ch[str[i]] == 0) {
break;
}
}
return i;
}
This could also be solved without using strlen at all, assuming both strings are zero-terminated. The disadvantage of this solution is that one needs 256 bytes of memory for the lookup table.
Without touching a C-compiler for the last couple of years. From the top of my head something like this should work:
int spn = 0;
while(*str++ != '\0')
{
char *hay = chars;
bool match = false;
while(*hay++ != '\0')
{
if(*hay == *str)
{
match = true;
break;
}
}
if(match)
spn++;
else
return spn;
}
return spn;
Well, implementing a standard library for my OS, here is my solution (C++).
KCSTDLIB_API_FUNC(size_t DECL_CALL strspn(const char * str1, const char * str2))
{
size_t count = 0;
auto isin = [&](char c)
{
for (size_t x = 0; str2[x]; x++)
{
if (c == str2[x])
return true;
};
return false;
};
for (; isin(str1[count]); count++);
return count;
}