C turning char arrays into int behaving weird - c

I have a much longer char array that I am turning into integers, but I cannot figure out why it behaves weird in some spots.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main ()
{
char x[60] = "08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08";
printf("%lu\n\n", strlen(x));
for ( int i = 0; i < strlen(x); i+=3 ) {
char num[2];
num[0] = (char)x[i];
num[1] = (char)x[i+1];
printf("%d, ", atoi(num));
}
}
The Output:
8, 2, 22, 97, 38, 15, 0, 40, 0, 75, 4, 5, 7, 78, 52, 12, 500, 773, 916, 89,
Everything is great until.....500, 773, 916, 89...what is happening?

As you can see atoi wants a C-String: a null terminated array of character.
So, this
char num[2];
num[0] = (char)x[i];
num[1] = (char)x[i+1];
Have to be
char num[3] = {0};
num[0] = (char)x[i];
num[1] = (char)x[i+1];
num[2] = '\0'; // this could be avoided in your specific case

The need for a proper string with its null character has been posted by many.
Just wanted to add another coding idea: compound literal. (char[]) { x[i], x[i + 1], '\0' } to implement that.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char x[] = "08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08";
size_t len = strlen(x);
printf("%zu\n\n", len);
for (size_t i = 0; i < len; i += 3) {
printf("%d, ", atoi((char[] ) { x[i], x[i + 1], '\0' }));
}
}
Output
59
8, 2, 22, 97, 38, 15, 0, 40, 0, 75, 4, 5, 7, 78, 52, 12, 50, 77, 91, 8,
Some other fixes made too.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main ()
{
char num[3]; // 3rd byte is the null character
num[3]='\0';
char x[60] = "08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08";
printf("%lu\n\n", strlen(x));
for ( int i = 0; i < strlen(x); i+=3 ) {
strncpy ( num, x+i, 2 ); // Copies two characters starting from x+i
// You get a null terminated string num here.
printf("%d, ", atoi(num));
}
printf("\n");
}

num[0] = (char)x[i];
num[1] = (char)x[i+1];
printf("%d, ", atoi(num)
This assumes that the number of digits in your input will always be 2(for which num should be declared as char num[3]. Do a dry run of your logic with a smaller input set, for eg:"01 50"
i=0
num[0] = *(num+0) = 0
num[1] = *(num+1) = <space>
num[2] = *(num + 2) = ????? Since this memory is not allocated for num
printf("%d, ", atoi("1<space>")) = 1 (atoi stops after looking at num[1] which is a non-digit character)
i = 3
num[0] = *(num+0) = 0
num[1] = *(num + 1) = 0
num[2] = *(num + 2) = ?????
printf("%d ", atoi("00<garbage>...")) // this is UB since atoi will definitely read memory at `(num + 2)` which is beyond the bounds of what the compiler allocated for it.
Try using sscanf to parse the input rather than relying on the number of digits. That would be much more cleaner and less prone to errors.
int main ()
{
char x[60] = "08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08";
const char *y = x;
char outputBuffer[10];
for(;sscanf(y, "%s", outputBuffer) > 0; y+=strlen(outputBuffer)) printf("%d, ", atoi(outputBuffer));
}

The answer to your question has already been provided, i.e. that a C string is by definition a NULL terminated char array. Without room for the NULL terminator, at best the results from a string passed to a string function cannot be trusted.
I am offering this just to highlight some additional ideas on reading a char array into int array, where the NULL terminator becomes almost a non-issue.
The following method includes simple string parsing and dynamic memory usage, where the string contents get read directly into int memory, bypassing any need for an intermediate string buffer, resulting in the ability to read any legal integer length from the string, and convert directly into int:
see inline comments for suggestions:
int main(void)
{
//leave array index blank, the compiler will size it for you
char x[] = "08 0223 22 97 382345 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08 1000";
// ^
int size = sizeof(x)/sizeof(x[0]);//use sizeof macro to get number of elements in array
char *tok = NULL;
int i = 0;
int count=0;
for(i=0;i<size;i++)
{
if(x[i]==' ')count++;//get count to size int array
}
int *array = malloc((count+1)*sizeof(int));
if(array)
{
i=0;//reinitialize to 0 for use here
tok = strtok(x, " \n");
while(tok)//test after each parse before processing
{
if((i>0)&&(i%6==0))printf("\n");//newlines to format
array[i++] = atoi(tok);
printf("%6d, ", array[i]);
// ^ provide spacing in output
tok = strtok(NULL, " \n");
}
free(array);
}
return 0;
}

Related

Write a function that shows all the different combinations of n numbers in ascending ascending order

By logic it would have to go from 09, to 12, 13, 14, ..., 23,24, ..., 34, 35, ..., 79, 89.
However, I can't create the logic for the second decimal place to zero and get increasing. I cannot have 11, 22, 33, 44, 55, 66, 77, 88.
The functions allowed are just writing, while I finish if other functions.
MY CODE:
void ft_putchar(char a)
{
write(1, &a, 1);
}
void ft_print_combn(int n)
{
int combn[n];
int p;
if (n <= 0 || n >= 10)
return ;
else
{
p = 0;
while (p < n)
{
combn[p] = p;
p++;
}
while (p > 0)
{
int maxdigit = 10;
p = 0;
while (p < n)
{
ft_putchar(combn[p] + '0');
p++;
}
p = n;
while (p--)
{
int digit = combn[p];
if (digit < --maxdigit)
{
combn[p++] = ++digit;
if (p <= n)
{
ft_putchar(',');
ft_putchar(' ');
break;
}
}
}
}
}
}
int main()
{
ft_print_combn(2);
}
A corrected answer, based upon your comment follows.
This solution uses a two-character string to build the digits and print the values. This solution is written using Ada. You can translate the algorithm to C. You can also modify this algorithm to work with n digits, but n must not exceed 9 or you will not be able to meet your requirements.
procedure print_digits is
subtype digit_values is Character range '0' .. '9';
subtype digit_sequence is String (1 .. 2);
sequence : digit_sequence;
begin
for first_digit in
digit_values'First .. digit_values'Pred (digit_values'Last)
loop
sequence (1) := first_digit;
for second_digit in Character'Succ (first_digit) .. digit_values'Last
loop
sequence (2) := second_digit;
Put_Line (sequence);
end loop;
end loop;
end print_digits;
In Ada I start by creating a subtype of the type Character limited to the character representation of decimal digits ('0' through '9');
I then create a two-character string to build the increasing value sequences from left to right as you describe above.
The logic is accomplished in two nested for loops. The first for loop increments through the values '0' through '8'. The value '9' cannot be in the first string position because nothing can increment past 9 in this problem.
Each time through the outer loop the value of the first string element is assigned the new value of the variable first_digit.
The inner loop increments from the value succeeding the value of first_digit to '9'. Each iteration that value is assigned to the second element of the sequence array.
The sequence array is then output to standard output, one sequence per line.
The output of a program calling print_digits is:
01
02
03
04
05
06
07
08
09
12
13
14
15
16
17
18
19
23
24
25
26
27
28
29
34
35
36
37
38
39
45
46
47
48
49
56
57
58
59
67
68
69
78
79
89

reading and printing matrix from stdin

Well I posted this before but it's kinda improved now, and I only have one problem (I guess).
The assignment was to write a function which reads an integer matrix given in a ‘.txt file’ using
I/O redirection, then write another function to print it.
I read txt into a 1D array (arr) then create 2D matrix (mat) out of it, before those, I allocated memory dynamically bc our professor asked to do it that way. The problem is that arr seems to be changing when I put it on for loop and try to address it for the matrix. I would appreciate any ideas... Also, it would be helpful if you guys can comment on my way of allocating memory. (Don't forget we have 3 different input.txts some of them has -5.58234 like values or they are not seperated by "," in this example, so I want to make my code usable in any cases)
example txt file:
16, 11, 10, 16, 24, 40, 51, 61,
12, 12, 14, 19, 26, 58, 60, 55,
14, 13, 16, 24, 40, 57, 69, 56,
14, 17, 22, 29, 51, 87, 80, 62,
18, 22, 37, 56, 68, 109, 103, 77,
24, 35, 55, 64, 81, 104, 113, 92,
49, 64, 78, 87, 103, 121, 120, 101,
72, 92, 95, 98, 112, 100, 103, 99
my code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int readMatrix(int *arr, int **mat);
void printMatrix(int **mat, int size);
int main(){
// declare 1D array and allocate memory
int *arr;
arr = malloc(sizeof(stdin)*sizeof(int));
// declare 2D Matrix and allocate memory
int **mat;
mat = (int **)malloc(sizeof(stdin)*sizeof(int));
// function implementations
int size;
size = readMatrix(arr, mat);
printMatrix(mat,size);
return 0;
}
int readMatrix(int *arr, int **mat){
// reading
int i=0, size=0; // loop var i and size to count the elements of array
while(scanf("%d,", &arr[i]) != EOF)
{
i++;
size++;
}
printf("arr[63] = %d \n\n",arr[63]); // VALUE IS CORRECT HERE
// finding row and column numbers
int rows = sqrt(size), cols = rows;
// appending 1d array into matrix
int m = 0;
// test printf("rows = %d, cols = %d\n", rows, cols);
for(int i=0; i<rows; i++){
for(int j=0; j<cols; j++){
printf("arr[%d] = %d\n",m, arr[m]); // VALUES OF arr[] BECAME WEIRD AFTER arr[12]
//mat[i][j] = arr[m]; // segmentation fault
//*(*(mat+i)+j) = arr[m]; // segmentation fault
//*(*(mat+i)+j) = &arr[m]; // segmentation fault
*(mat + i*cols + j) = &arr[m]; // I don't know if this is the proper way but it works
m++;
}
}
printf("\narr[63] = %d\n",arr[63]); // HOWWWWW
// return size for further implementations
//
return size;
}
void printMatrix(int **mat, int size){
int rows = sqrt(size), cols = rows;
printf("\nMATRIX A:\n");
for(int i=0; i<rows; i++){
for(int j=0; j<cols; j++)
{
printf("%d ", mat[i][j]);
//if(mat[i][j]>=10 && mat[i][j]<100 ){printf("%d ", mat[i][j]);}
//else if(mat[i][j]>=100 ){printf("%d ", mat[i][j]);}
//else{printf("%d ", mat[i][j]);}
}
printf("\n");
}
}
output:
$ ./secondtry < input1.txt
arr[63] = 99
arr[0] = 16
arr[1] = 11
arr[2] = 10
arr[3] = 16
arr[4] = 24
arr[5] = 40
arr[6] = 51
arr[7] = 61
arr[8] = 12
arr[9] = 12
arr[10] = 14
arr[11] = 19
arr[12] = 976
arr[13] = 8
arr[14] = 980
arr[15] = 8
arr[16] = 984
arr[17] = 8
arr[18] = 988
arr[19] = 8
arr[20] = 992
arr[21] = 8
arr[22] = 996
arr[23] = 8
arr[24] = 1000
arr[25] = 8
arr[26] = 1004
arr[27] = 8
arr[28] = 1008
arr[29] = 8
arr[30] = 1012
arr[31] = 8
arr[32] = 1016
arr[33] = 8
arr[34] = 1020
arr[35] = 8
arr[36] = 1024
arr[37] = 8
arr[38] = 1028
arr[39] = 8
arr[40] = 1032
arr[41] = 8
arr[42] = 1036
arr[43] = 8
arr[44] = 1040
arr[45] = 8
arr[46] = 1044
arr[47] = 8
arr[48] = 1048
arr[49] = 8
arr[50] = 1052
arr[51] = 8
arr[52] = 1056
arr[53] = 8
arr[54] = 1060
arr[55] = 8
arr[56] = 1064
arr[57] = 8
arr[58] = 1068
arr[59] = 8
arr[60] = 1072
arr[61] = 8
arr[62] = 1076
arr[63] = 8
arr[63] = 8
MATRIX A:
16 11 10 16 24 40 51 61
11 10 16 24 40 51 61 12
10 16 24 40 51 61 12 12
16 24 40 51 61 12 12 14
24 40 51 61 12 12 14 19
40 51 61 12 12 14 19 976
51 61 12 12 14 19 976 8
61 12 12 14 19 976 8 980
Because we're reading from stdin, we can not do simple things like:
read/parse the first to determine number of columns
rewind file
read/parse all lines and store in matrix (allocating space as we go)
Note that using sqrt on the count to get number of rows/columns is a bit "unique". This is the first time I've seen that done.
When handling a 2D matrix that has dynamic dimensions, it helps to define a control struct to be able to store the dimensions. Then, all relevant info for the matrix is available to everyone.
In general, I really prefer fgets/strtok/strtol over scanf.
In this use case, I'm not sure if scanf("%d,",&val) can parse both (e.g.) 103, and 99. That is, the last number of the input file has no comma after it.
So, I had to refactor the code quite a bit. It is annotated:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef DEBUG
#define dbgprt(_fmt...) \
printf(_fmt)
#else
#define dbgprt(_fmt...) \
do { } while (0)
#endif
// matrix control
typedef struct {
int mtx_cols; // number of columns
int mtx_rows; // number of rows (input lines)
int *mtx_base; // pointer to matrix data
} mtx_t;
// helper macro to access a given matrix coordinate
#define MTX(_mtx,_irow,_icol) \
_mtx->mtx_base[((_irow) * _mtx->mtx_cols) + _icol]
// newMatrix -- get new matrix control
mtx_t *
newMatrix(void)
{
mtx_t *mtx;
mtx = calloc(1,sizeof(*mtx));
return mtx;
}
// readMatrix -- read in matrix from stream
void
readMatrix(mtx_t *mtx,FILE *xfin)
{
char *bp;
char *cp;
char buf[1000];
// get first line as a special case to calculate the number of columns
fgets(buf,sizeof(buf),xfin);
// we need to preserve the original data for the second loop below
char tmp[1000];
strcpy(tmp,buf);
// calculate number of columns
bp = tmp;
while (1) {
char *cp = strtok(bp," ,\n");
bp = NULL;
if (cp == NULL)
break;
mtx->mtx_cols += 1;
}
// read in row by row
while (1) {
// get current row index and advance the row count
int irow = mtx->mtx_rows++;
dbgprt("BUF/%d: %s",irow,buf);
// add space for this row
mtx->mtx_base = realloc(mtx->mtx_base,
sizeof(*mtx->mtx_base) * mtx->mtx_rows * mtx->mtx_cols);
if (mtx->mtx_base == NULL) {
perror("realloc");
exit(2);
}
// parse this row
bp = buf;
for (int icol = 0; icol < mtx->mtx_cols; ++icol) {
char *cp = strtok(bp," ,\n");
bp = NULL;
if (cp == NULL)
break;
MTX(mtx,irow,icol) = strtol(cp,&cp,10);
dbgprt(" %d\n",MTX(mtx,irow,icol));
}
// get data for next row
if (fgets(buf,sizeof(buf),xfin) == NULL)
break;
}
}
void
printMatrix(const mtx_t *mtx)
{
printf("\nMATRIX A:\n");
for (int irow = 0; irow < mtx->mtx_rows; ++irow) {
for (int icol = 0; icol < mtx->mtx_cols; ++icol)
printf(" %d",MTX(mtx,irow,icol));
printf("\n");
}
}
int
main(int argc,char **argv)
{
--argc;
++argv;
FILE *xfin;
if (argc > 0)
xfin = fopen(*argv,"r");
else
xfin = stdin;
if (xfin == NULL)
exit(1);
// declare 1D array and allocate memory
mtx_t *mtx = newMatrix();
readMatrix(mtx,xfin);
printMatrix(mtx);
return 0;
}

Separating a string into a substring then that substring into another string in C

I have to read the arguments that I introduce when I run a program on linux.
./myprog 10 20 30, 20 54 12, 31 42 51
I have a problem finding out how to separate the arguments into a substring and then that substring in other string.
10 20 30, 20 54 12, 31 42 51
I want to separate this string into another string with "," being the separator and then that substring to separate into another string with " " being the separator.
a[0]="10 20 30"
a[1]="20 55 12"
a[2]="31 42 51"
Then I want it to be like that:
b[0]="10" b[1]="20" b[2]="30" and so on...
Here I make this code to separate the arguments into a substring.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *str = "10 20 30, 20 54 12, 31 42 51";
char **a = calloc(sizeof(char*),strlen(str));
int x = 0;
int y = 0;
int i = 0;
while (str[i] != '\0')
{
x = 0;
a[y] = calloc(sizeof(char),9);
while(str[i] != ',' && str[i] != '\0')
{
a[y][x] = str[i];
i++;
x++;
}
y++;
i += 2;
}
//this code below for test
y--;
for (int t = 0; t < y; t++)
printf("%s\n",a[t]);
}
now try to make the other one :).

Trying to print out useful data from Memory

void update_memblock(MEMBLOCK *mb)
{
static unsigned char tempbuf[128 * 1024];
SIZE_T bytes_left;
SIZE_T total_read;
SIZE_T bytes_to_read;
SIZE_T bytes_read;
bytes_left = mb->size;
total_read = 0;
while (bytes_left)
{
bytes_to_read = (bytes_left > sizeof(tempbuf)) ?
sizeof(tempbuf) : bytes_left;
ReadProcessMemory(mb->hProc, mb->addr + total_read,
tempbuf, bytes_to_read, &bytes_read);
if (bytes_read != bytes_to_read) break;
memcpy(mb->buffer + total_read, tempbuf, bytes_read);
bytes_left -= bytes_read;
total_read += bytes_read;
}
mb->size = total_read;
}
This is the current code I have, I am initially reading another process' memory using ReadProcessMemory. Now I have the temporary data stored in tempbuf. I am able to output the data from tempbuf in hexadecimal form. But I was planning to display it as shown in the picture, also another complexity I'm facing here is if bytes_left > sizeof(tempbuf) I'm only reading enough data equivalent to the size of tempbuf. How do I read more data as the array I defined can only support as much data?
If I understand correctly, your main question is about how to mimic the output from hex editors.
This can be broken up into 3 parts:
Printing the address
Printing the hex value of each byte
Printing the ASCII value for each byte
Printing an address in hex is easy. We can use %p to print the address of a pointer like this:
char* mem = malloc(99);
printf("%p\n", (void*)mem);
// output: 0xc17080
Next you can print the hex value of a byte using %02x on a char (1 byte). The 02 specifies a zero padded field width of 2. In this case it's just to make 0 print as 00 to make things line up and look pretty.
printf("%02x", mem[0]);
// output: 0A
Lastly, printing ASCII is the easiest of all... almost. We can use %c to print a byte for some ASCII values, but we don't want to print things like \nor \t. To solve this we can limit the use of %c to the character/symbol region of the ASCII table and print . for everything else.
char c = mem[0];
if ( ' ' <= c && c <= '~' ) {
printf("%c", c);
}
else {
printf(".");
}
//output: .
Now we just need to combine these all together. You can decide how many bytes you want to display per line and print "[address] [n hex bytes] [n ascii bytes]" and repeat until you've gone through the entire memory region. I've given a sample function below and you can run it for yourself here.
void display_mem(void* mem, int mem_size, int line_len) {
/*
mem - pointer to beggining of memory region to be printed
mem_size - number of bytes mem points to
line_len - number of bytyes to display per line
*/
unsigned char* data = mem;
int full_lines = mem_size / line_len;
unsigned char* addr = mem;
for (int linno = 0; linno < full_lines; linno++) {
// Print Address
printf("0x%x\t", addr);
// Print Hex
for (int i = 0; i < line_len; i++) {
printf(" %02x", data[linno*line_len + i]);
}
printf("\t");
// Print Ascii
for (int i = 0; i < line_len; i++) {
char c = data[linno*line_len + i];
if ( 32 < c && c < 125) {
printf(" %c", c);
}
else {
printf(" .");
}
}
printf("\n");
// Incremement addr by number of bytes printed
addr += line_len;
}
// Print any remaining bytes that couldn't make a full line
int remaining = mem_size % line_len;
if (remaining > 0) {
// Print Address
printf("0x%x\t", addr);
// Print Hex
for (int i = 0; i < remaining; i++) {
printf(" %02x", data[line_len*full_lines + i]);
}
for (int i = 0; i < line_len - remaining; i++) {
printf(" ");
}
printf("\t");
// Print Hex
for (int i = 0; i < remaining; i++) {
char c = data[line_len*full_lines + i];
if ( 32 < c && c < 125) {
printf(" %c", c);
}
else {
printf(" .");
}
}
printf("\n");
}
}
Sample output:
0x1e79010 74 65 73 74 79 2a 6e t e s t y * n
0x1e79017 0c 3e 24 45 5e 33 27 . > $ E ^ 3 '
0x1e7901e 18 51 09 2d 76 7e 4a . Q . - v . J
0x1e79025 12 53 0f 6e 0b 1a 6d . S . n . . m
0x1e7902c 31 6e 03 2b 01 2f 2c 1 n . + . / ,
0x1e79033 72 59 1c 76 18 38 3c r Y . v . 8 <
0x1e7903a 6e 6b 5b 00 36 64 25 n k [ . 6 d %
0x1e79041 2d 5c 6f 38 30 00 27 - \ o 8 0 . '
0x1e79048 33 12 15 5c 01 18 09 3 . . \ . . .
0x1e7904f 02 40 2d 6c 1a 41 63 . # - l . A c
0x1e79056 2b 72 18 1a 5e 74 12 + r . . ^ t .
0x1e7905d 0d 51 38 33 26 28 6b . Q 8 3 & ( k
0x1e79064 56 20 0b 0b 32 20 67 V . . . 2 . g
0x1e7906b 34 30 68 2e 70 0f 1c 4 0 h . p . .
0x1e79072 04 50 . P
As for the second part of your question, if you cannot increase the size of tempbuf then you are stuck dealing with that amount of memory at any moment in time.
However, if all you want to do is display the memory as described above you can display each section of memory in chunks. You can get a chunk of memory, display it, then get a new chunk, display the new chunk, repeat.
Something along the lines of
while (bytes_left) {
ReadProcessMemory(mb->hProc, mb->addr + total_read, tempbuf, bytes_to_read, &bytes_read);
// Get new chunk
memcpy(mb->buffer + total_read, tempbuf, bytes_read);
// Display chunk
display_mem(tempbuf, bytes_read);
bytes_left -= bytes_read;
}
You will need to do a little more work to check for errors and make everything look nice but hopefully that gives you a good idea of what could be done.
There is no way to store more data than you have space allocated. If you need to store more data, you will need to allocate more space somewhere (more RAM, a disk file, etc). Compression will allow you to store a bit more data in the space allocated, but you aren't going to gain all that much. For virtually unlimited storage, you are going to need to write to disk.
Alternatively, if you just need to display once and then can forget, read in 16 bytes, display the line, and then read the next 16 bytes into the same memory.

How to get hex values from string?

I have a function with an input parameter "text" , which consists of a string containing unknown number of 2-character Hexadecimal numbers separated by space. I need to read them and put them in separate array indexes or read them in for loop and work with them one by one. Each of these values represents an encrypted char(the hex values are ascii values of the characters). How could i do that? I think i should use sscanf(); but i can't figure out how to do it.
char* bit_decrypt(const char* text){
int size=strlen(text)/3;
unsigned int hex[size];
char*ptr;
for(int i=0; i<size+1; i++){
hex[i] = strtoul(text, &ptr, 16);
printf("%x ",hex[i]);
}
return NULL;
}
output is: "80 80 80 80 80 80 80 80 80 80 80 80"
should be: "80 9c 95 95 96 11 bc 96 b9 95 9d 10"
You scan always the first value of text, because you forgot to move the input for strtoul right after the end of the previous scan. That's what the **end-parameter of strtoul is good for: it points to the character right after the last digit of a successful scan. Note: if nothing could have been read in, the end-pointer is equal the input pointer, and this indicates a "wrongly formated number" or the end of the string. See the following program illustrating this. Hope it helps.
int main() {
const char* input = "80 9c 95 95 96 11 bc 96 b9 95 9d 10";
const char *current = input;
char *end = NULL;
while (1) {
unsigned long val = strtoul(current, &end, 16);
if (current == end) // invalid input or end of string reached
break;
printf("val: %lX\n", val);
current = end;
}
}
This is also possible solution with the use of strchr, and strtoul(tmp,NULL,16);
In your solution remember that size_t arr_len = (len/3) + 1; since the last token is only 2 bytes long.
Input text tokens are converted to bytes and stored in char array:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char text[] = "80 9c 95 95 96 11 bc 96 b9 95 9d 10";
size_t len = strlen(text);
size_t arr_len = (len/3) + 1;
printf("len= %zu arr_len= %zu\n", len, arr_len);
printf("Text:\n%s\n", text);
char array[arr_len];
const char *p1 = text;
char tmp[3];
tmp[2] = 0;
printf("Parsing:\n");
for(size_t i=0; i< arr_len; i++)
{
p1 = strchr(p1,' ');
if(p1)
{
tmp[0] = *(p1-2);
tmp[1] = *(p1-1);
array[i]= (char)strtoul(tmp,NULL,16);
printf("%2x ", (unsigned char) array[i]);
p1++;
if(strlen(p1) == 2 ) // the last char
{
i++;
tmp[0] = *(p1);
tmp[1] = *(p1+1);
array[i]= (char)strtoul(tmp,NULL,16);
printf("%2x", (unsigned char) array[i]);
}
}
}
printf("\nArray content:\n");
for(size_t i=0; i< arr_len; i++)
{
printf("%2x ", (unsigned char) array[i]);
}
return 0;
}
Test:
len= 35 arr_len= 12
Text:
80 9c 95 95 96 11 bc 96 b9 95 9d 10
Parsing:
80 9c 95 95 96 11 bc 96 b9 95 9d 10
Array content:
80 9c 95 95 96 11 bc 96 b9 95 9d 10

Resources