Надежная обработка строк в C никогда не бывает простой.
Вот процедура, которая сразу пришла мне в голову. Используйте strtok()
, чтобы разбить строку на отдельные токены, затем преобразуйте каждый токен в целочисленное значение, используя strtol()
.
Что нужно знать: strtok()
изменяет свой ввод (записывает 0 через разделители). Это означает, что мы должны передать ему записываемую строку. В приведенном ниже примере я динамически создаю буфер для хранения входной строки, а затем передаю этот динамический буфер в strtok()
. Это гарантирует, что strtok()
работает на доступной для записи памяти, и в качестве бонуса мы сохраняем наш ввод на случай, если он понадобится нам позже.
Кроме того, strtol()
позволяет нам ловить плохо сформированные данные; второй аргумент будет указывать на первый символ в строке, который не был преобразован. Если этот символ является чем-то отличным от пробела или 0, тогда строка не была допустимым целым числом, и мы можем отклонить его, прежде чем назначить его в наш целевой массив.
#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;
}