Как разбить вложенные строки с разделителями в c?

Мне было интересно, как я могу разделить такие строки.

Например, у меня есть следующая строка: "80,8080,27001-27010,90"

Сначала я хочу разделить запятую, но если в этой подстроке есть минус, я хочу разделить ее и получить разницу между двумя числами, преобразовав их с помощью atoi(). Строка, которую я хочу разделить, представляет собой список портов, и я хочу создать массив целых чисел со всеми перечисленными портами. Функция strtok кажется не подходящей для этой проблемы, есть ли какое-нибудь простое решение для этого?

Пример использования strtok_r:

 substr1 = strtok_r(portlist, delim1, &saveptr1);
 while(substr1 != NULL){
    substr2 = strtok_r(substr1, delim2, &saveptr2);
    substr1 = strtok_r(NULL, delim2, &saveptr1);
 }

person lt_katana    schedule 19.11.2014    source источник
comment
strtok-function seems not suitable... сообщите, почему?   -  person Sourav Ghosh    schedule 19.11.2014
comment
strtok сохраняет подготовленные строки, если я снова использую strtok для разделения подстроки 27001-27010, я потеряю прогресс, который я ранее сделал, поэтому я не смогу проанализировать порт 90.   -  person lt_katana    schedule 19.11.2014


Ответы (2)


В вашем конкретном случае вы можете использовать strchr, чтобы найти точку разделения токена, тем самым избегая потери прогресса.

Другой способ — использовать strtok_r, реентерабельную версию strtok, не имеющую внутреннего состояния.

Изменить:

strtok_r не является частью стандарта C. Это часть POSIX.1-2001. Я думаю, что большинство основных компиляторов поддерживают его. В Windows соответствующая функция называется strtok_s. Хороший способ сделать это портативным

#if defined(_WIN32) || defined(_WIN64)
/* We are on Windows */
# define strtok_r strtok_s
#endif

Как описано в ответе Иоахима Пилеборга на В чем разница между strtok_r и strtok_s в C?

person Klas Lindbäck    schedule 19.11.2014
comment
Поэтому мне нужно создать два указателя сохранения. Один, когда я хочу сохранить основной прогресс, а другой - сохранить прогресс подстроки, это правильно? Я разместил пример в исходном вопросе - person lt_katana; 19.11.2014
comment
Да. Вам нужен второй цикл, чтобы получить все (оба) значения из strtok_r на delim2. Кроме того, последний strtok_r должен использовать delim1. - person Klas Lindbäck; 19.11.2014
comment
Спасибо, вы спасли мой день, я действительно заржавел в программировании на C. - person lt_katana; 19.11.2014

Я предпочитаю sscanf для разбора строк в C

char *text =  "80,8080,,,27001-27010,+tt90";
int p[10];
int offset = 0, i = 0;
char bufDel[32], bufDigit[16];
while (sscanf(text+offset, "%[0-9]%[^0-9]", bufDigit, bufDel) != EOF) {
    offset += strlen(bufDigit) + strlen(bufDel);
    sscanf(bufDigit, "%d", &p[i]);
    ++i;
    bufDigit[0] = '\0';
    bufDel[0] = '\0';
}

%*[^0-9] читает все символы, кроме цифр 0-9, и отбрасывает их. Выход 80 8080 27001 27010 90

person Walter    schedule 19.11.2014
comment
Проблема в том, что мне нужно динамическое решение, в котором список портов может отличаться, диапазон также может быть в другой позиции, поэтому это не сработает. - person lt_katana; 19.11.2014
comment
Это хорошо, если у вас фиксированный формат. В этом случае я думаю, что строка является просто примером и что количество , и - является переменным. - person Klas Lindbäck; 19.11.2014
comment
Но спасибо, что поделились этим, на самом деле я не могу использовать strtok_r для своей программы, из-за данной конфигурации компилятора мне приходится анализировать свою подстроку по-другому. - person lt_katana; 19.11.2014
comment
Я предполагаю, что вы хотите прочитать целые числа из строки, а разделители не являются цифрами. Точное количество целых чисел неизвестно. Конечно, это возможно с помощью sscanf, см. отредактированную программу. - person Walter; 19.11.2014