Reputation: 12187
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?
Upvotes: 6
Views: 562
Reputation: 23218
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;
}
Upvotes: 0
Reputation: 153498
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.
Upvotes: 1
Reputation: 4835
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));
}
Upvotes: 0
Reputation: 21965
#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");
}
Upvotes: 0
Reputation: 16223
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
Upvotes: 13