I have a string "14 22 33 48"
. I need to insert each of the values in the string into the respective location in the array:
int matrix[5];
so that
matrix[0] = 14;
matrix[1] = 22;
matrix[2] = 33;
matrix[3] = 48;
How do I do this?
I have a string "14 22 33 48"
. I need to insert each of the values in the string into the respective location in the array:
int matrix[5];
so that
matrix[0] = 14;
matrix[1] = 22;
matrix[2] = 33;
matrix[3] = 48;
How do I do this?
You can use sscanf:
sscanf(val,
"%d %d %d %d",
&matrix[0],
&matrix[1],
&matrix[2],
&matrix[3]
);
const char *p = input;
int i = 0, len;
while (i < sizeof(matrix)/sizeof(matrix[0])
&& sscanf(p, "%d%n", &matrix[i], &len) > 0) {
p += len;
i++;
}
For extra credit, dynamically reallocate matrix to make is as large as it needs to be ...
Robust string processing in C is never simple.
Here's a procedure that popped immediately to mind for me. Use strtok()
to break the string into individual tokens, then convert each token to an integer value using strtol()
.
Things to be aware of: strtok()
modifies its input (writes 0 over the delimiters). This means we have to pass it a writable string. In the example below, I create a buffer dynamically to hold the input string, and then pass that dynamic buffer to strtok()
. This guarantees that strtok()
is operating on writable memory, and as a bonus, we preserve our input in case we need it later.
Also, strtol()
allows us to catch badly formed input; the second argument will point to the first character in the string that wasn't converted. If that character is anything other than whitespace or 0, then the string was not a valid integer, and we can reject it before assigning it to our target array.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
/**
* Convert a space-delimited string of integers to an array of corresponding
* integer values.
*
* @param str [in] -- input string
* @param arr [in] -- destination array
* @param arrSize [in] -- max number of elements in destination array
* @param count [out] -- number of elements assigned to destination array
*/
void stringToIntList(char *str, int *arr, size_t arrSize, size_t *count)
{
/**
* The token variable holds the next token read from the input string
*/
char *token;
/**
* Make a copy of the input string since we are going to use strtok(),
* which modifies its input.
*/
char *localStr = malloc(strlen(str) + 1);
if (!localStr)
{
/**
* malloc() failed; we're going to treat this as a fatal error
*/
exit(-1);
}
strcpy(localStr, str);
/**
* Initialize our output
*/
*count = 0;
/**
* Retrieve the first token from the input string.
*/
token = strtok(localStr, " ");
while (token && *count < arrSize)
{
char *chk;
int val = (int) strtol(token, &chk, 10);
if (isspace(*chk) || *chk == 0)
{
arr[(*count)++] = val;
}
else
{
printf("\"%s\" is not a valid integer\n", token);
}
/**
* Get the next token
*/
token = strtok(NULL, " ");
}
/**
* We're done with the dynamic buffer at this point.
*/
free(localStr);
}
int main(void)
{
int values[5];
char *str = "14 22 33 48 5q";
size_t converted;
stringToIntList(str, values, sizeof values / sizeof values[0], &converted);
if (converted > 0)
{
size_t i;
printf("Converted %lu items from \"%s\":\n", (unsigned long) converted, str);
for (i = 0; i < converted; i++)
printf("arr[%lu] = %d\n", (unsigned long) i, arr[i]);
}
else
{
printf("Could not convert any of \"%s\" to equivalent integer values\n", str);
}
return 0;
}
I would recommend strtol
, which provides better error handling than atoi
or sscanf
. This version will stop if it encounters a bad character or runs out of space in the array. Of course if there aren't enough integers in the string to fill the array, then the remainder of it will remain uninitialized.
#include <stdio.h>
#include <stdlib.h>
#define ARRAY_SIZE 5
int main(int argc, char *argv[])
{
/* string to convert */
const char * str = "14 22 33 48";
/* array to place converted integers into */
int array[ARRAY_SIZE];
/* this variable will keep track of the next index into the array */
size_t index = 0;
/* this will keep track of the next character to convert */
/* unfortunately, strtol wants a pointer to non-const */
char * pos = (char *)str;
/* keep going until pos points to the terminating null character */
while (*pos && index < ARRAY_SIZE)
{
long value = strtol(pos, &pos, 10);
if (*pos != ' ' && *pos != '\0')
{
fprintf(stderr, "Invalid character at %s\n", pos);
break;
}
array[index] = (int)value;
index++;
}
}