Получить числа, разделенные запятыми - PullRequest
2 голосов
/ 25 февраля 2012

Я получил следующую строку:

"312 ,22 ,+12 , -12 , 5331"

возможно иметь более 1 пробела между числами.

Мне нужно преобразовать его в массиввот так:

int arr[] = {312,22,-12,12,5331};

Есть ли красивый и элегантный способ сделать это с C89?

Ответы [ 6 ]

5 голосов
/ 25 февраля 2012

Использование strtok + atoi:

# include <stdio.h>
# include <stdlib.h>
# include <string.h>

int main(int argc, char const *argv[])
{
    char numbers_str[] = "312 ,22 ,+12 ,-12 ,5331", *currnum;
    int numbers[5], i = 0;

    while ((currnum = strtok(i ? NULL : numbers_str, " ,")) != NULL)
        numbers[i++] = atoi(currnum);

    printf("%d\n", numbers[3]);
    return 0;
}
1 голос
/ 25 февраля 2012

Предлагайте:

  1. Используйте strtok(), чтобы разбить строку на токены.
  2. Используйте atoi() для преобразования токенов в int с.

Чтобы выделить массив для хранения int s, вы можете:

  1. Распределяйте при обработке каждого токена, используя realloc() или
  2. Выполните два прохода через строку, причем первый проход подсчитывает токены в строке и malloc() массив в одной операции.
* * 1 022 Пример: * 1 023 *
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

int* make_int_array(char* a_str, size_t* const a_elem_count)
{
    int* result      = 0;
    char* tmp        = a_str;
    char* last_comma = 0;

    /* Count how many ints will be extracted. */
    *a_elem_count = 0;
    while (*tmp)
    {
        if (',' == *tmp)
        {
            (*a_elem_count)++;
            last_comma = tmp;
        }
        tmp++;
    }

    /* Add space for trailing int. */
    *a_elem_count += last_comma < (a_str + strlen(a_str) - 1);

    result = malloc(sizeof(int) * (*a_elem_count));

    if (result)
    {
        size_t idx  = 0;
        char* token = strtok(a_str, ",");

        while (token)
        {
            assert(idx < *a_elem_count);
            *(result + idx++) = atoi(token);
            token = strtok(0, ",");
        }
    }

    return result;
}

int main()
{
    char s[] = "312 ,22 ,+12 ,-12 ,5331";
    int* int_list;
    size_t int_list_count = 0;

    printf("s=[%s]\n\n", s);

    int_list = make_int_array(s, &int_list_count);

    if (int_list)
    {
        size_t i;
        for (i = 0; i < int_list_count; i++)
        {
            printf("%d\n", *(int_list + i));
        }
        printf("\n");
        free(int_list);
    }

    return 0;
}

Выход:

s=[312 ,22 ,+12 ,-12 ,5331]

312
22
12
-12
5331
0 голосов
/ 25 февраля 2012

Не думаю, что для этого есть какая-либо стандартная функция. Это настолько распространенная операция, что большинство программистов имеют в своем личном наборе что-то вроде следующего кода. Ответ заключается в использовании функции strtol (). Я быстро взломал следующее со страницы руководства для strtol:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int
main (int argc, char *argv[])
{

  char sep = ',';  
  char string[] = "  312 ,, 22 ,+12 ,-12 ,5331";
  /*
   * count separators
   */
  char *str = string;
  int j = 0;
  while (*str)
    {
      printf ("str=%c\n", *str);
      if (*str == sep)
    j++;
      str++;
    }
  int n = j + 1;
  printf ("n=%d\n", n);
  long int *arr = malloc (n * sizeof (long int));

  char *endptr = NULL;
  str = string;
  j = 0;
  do
    {
      arr[j++] = strtol (str, &endptr, 10);
      if (*endptr != '\0')
    {
      while (*endptr != sep)
        endptr++;
      str = endptr + 1;
    }
    }
  while (j < n && *endptr);
  for (j = 0; j < n; j++)
    {
      printf ("%d:%ld\n", j, arr[j]);
    }
  exit (EXIT_SUCCESS);

} / * main * /

Надеюсь, это полезно

0 голосов
/ 25 февраля 2012

Почему бы не использовать sscanf(str+offset, "%d,%n", &newValue, &offset) несколько раз, пока не произойдет сбой.

0 голосов
/ 25 февраля 2012

Я не программист на C, но ANSI C (или C89) имеет функцию "split", называемую strtok.

#include <string.h>
#include <stddef.h>

...

char string[] = "words separated by spaces -- and, punctuation!";
const char delimiters[] = " .,;:!-";
char *token;

...

token = strtok (string, delimiters);  /* token => "words" */
token = strtok (NULL, delimiters);    /* token => "separated" */
token = strtok (NULL, delimiters);    /* token => "by" */
token = strtok (NULL, delimiters);    /* token => "spaces" */
token = strtok (NULL, delimiters);    /* token => "and" */
token = strtok (NULL, delimiters);    /* token => "punctuation" */
token = strtok (NULL, delimiters);    /* token => NULL */
0 голосов
/ 25 февраля 2012

Да, вы можете использовать функцию sscanf, чтобы получить целые числа в элементах массива. Я предполагаю, что здесь есть небольшое фиксированное число целых чисел в вашей строке.

...