Двойной раскол в C - PullRequest
       37

Двойной раскол в C

7 голосов
/ 10 апреля 2010

OK. Например, у меня есть эта строка в моем текстовом файле:

1|1,12;7,19;6,4;8,19;2,2
Как видите, он состоит из 2 частей, разделенных |. У меня нет проблем с получением обеих частей и разделением второй части 1,12;7,19;6,4;8,19;2,2 с использованием ; разделителя. НО у меня есть проблемы с дальнейшим разделением на ,, чтобы получить первое и второе число каждого набора.

Это мой текущий код:

  result = strtok(result, ";");

  while(result != NULL ) {
      printf("%s\n", result);
      result = strtok(NULL, ";");
  }

Это выводит меня:

1,12
7,19
6,4
8,19
2,2

ОК, отлично. Но когда я пытаюсь «strtok» (я использую этот метод для разделения) как это:

 result = strtok(result, ";");

 while(result != NULL ) {
     //printf("%s\n", result);
     help    = strtok(result, ",");    
     while(help != NULL) {
         printf("<%s>", help);
         help = strtok(NULL, ",");
     }

     result  = strtok(NULL, ";");
 }

Я получаю только «<1>, <12>», как будто в этом наборе чисел только один набор. Я не понимаю, где остальные номера. Вместо этого выходные данные должны быть: <1>, <12>, <7>, <19>, <6>, <4>, <8>, <19>, <2>, <2>. Может ли кто-нибудь дать решение, как получить КАЖДЫЙ номер каждого набора этого набора чисел. Может быть есть другие способы или я что-то не так делаю :)

Спасибо!

Ответы [ 5 ]

6 голосов
/ 10 апреля 2010

В дополнение к тому, что Нейл указал относительно изменения исходной строки, функция strtok() не предназначена для использования во вложенном порядке, как вы описали. Вы можете изучить функцию strtok_r() или вообще не использовать семейство strtok*.

3 голосов
/ 10 апреля 2010

char * strtok (char * str, const char * delim); (из справочных страниц)
Аргумент delim указывает набор символов, которые разделяют токены в анализируемой строке. Вызывающая сторона может указывать разные строки в delim в последовательных вызовах, которые анализируют одну и ту же строку.

Итак, используйте оба ; и , в качестве разделителя для получения всех чисел.

//this will delimit result whenever ";" or "," is found
result = strtok(result, ";,"); 

while(result != NULL ) {
    printf("%s\n", result);
    result = strtok(NULL, ";,");
}
1 голос
/ 10 апреля 2010

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

Если у вас есть реентерабельная версия strtok_r(), вы можете изменить свой код, чтобы использовать его следующим образом:

char *st_result, *st_help;
result = strtok_r(result, ";", &st_result);

while (result) {
     printf("[%s]", result);
     help = strtok_r(result, ",", &st_help);    
     while (help) {
         printf("<%s>", help);
         help = strtok_r(NULL, ",", &st_help);
     }

     result = strtok_r(NULL, ";", &st_result);
}
1 голос
/ 10 апреля 2010

Первый strtok разбивает оригинал на несколько строк с нулевым символом в конце.Второй strtok применяется только к первой из этих строк - он останавливается на первом нулевом терминаторе, созданном первым вызовом strtok.Вам нужно вызвать второй код strtok для КАЖДОЙ из строк, созданных первой.

0 голосов
/ 10 апреля 2010

C strtok довольно злой, поскольку он изменяет исходную строку, вставляя NULL вместо вашего разделителя. Таким образом, ваш второй цикл останавливается, когда он достигает значения NULL, вставленного внешним циклом. Вам нужно сохранить указатели в ваших ; разделенных строках где-то еще, а затем strtok каждая из них в отдельности.

Или, если вы хотите использовать вложенные циклы, см. Здесь .

...