2015-03-13 4 views
0

Я использую функцию, которая was posted as an answer on another Stackoverflow question. Пользователь, который разместил это, отмечает, что: it does not handle consecutive delimiters.Как вы изменяете функцию разделения строк, чтобы игнорировать последовательные разделители?

Мне интересно, как я могу изменить это, чтобы он мог обрабатывать последовательные разделители? Я хочу по существу игнорировать его, когда у меня есть дополнительный delminator.

Например у меня есть что-то вроде этого:

h2,3 d3,4 j3,3 y4,1 g4,3

Я хочу, чтобы разделить это на массив строк в каждом пространстве, однако, как вы можете видеть в некоторых случаях есть несколько пробелов. Я просто хочу игнорировать дополнительные разделители.

Edit: Просто чтобы было ясно, что это код, я использую от ответа я связан выше:

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

char** str_split(char* a_str, const char a_delim) 
{ 
    char** result = 0; 
    size_t count  = 0; 
    char* tmp  = a_str; 
    char* last_comma = 0; 
    char delim[2]; 
    delim[0] = a_delim; 
    delim[1] = 0; 

    /* Count how many elements will be extracted. */ 
    while (*tmp) 
    { 
     if (a_delim == *tmp) 
     { 
      count++; 
      last_comma = tmp; 
     } 
     tmp++; 
    } 

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

    /* Add space for terminating null string so caller 
     knows where the list of returned strings ends. */ 
    count++; 

    result = malloc(sizeof(char*) * count); 

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

     while (token) 
     { 
      assert(idx < count); 
      *(result + idx++) = strdup(token); 
      token = strtok(0, delim); 
     } 
     assert(idx == count - 1); 
     *(result + idx) = 0; 
    } 

    return result; 
} 

int main() 
{ 
    char months[] = "JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC"; 
    char** tokens; 

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

    tokens = str_split(months, ','); 

    if (tokens) 
    { 
     int i; 
     for (i = 0; *(tokens + i); i++) 
     { 
      printf("month=[%s]\n", *(tokens + i)); 
      free(*(tokens + i)); 
     } 
     printf("\n"); 
     free(tokens); 
    } 

    return 0; 
} 
+0

Игнорирование может быть неправильным в зависимости от случая. Два разделителя в последовательности только означают, что между ними есть пустая строка. – Havenard

+0

@Havenard Вот где 'strsep()' отличается? Используйте соответствующую функцию. –

ответ

2

T его следует сделать трюк:

char** str_split(const char *str, char delimiter) 
{ 
    int len, i, j; 
    char* buf; 
    char** ret; 

    len = strlen(str); 
    buf = malloc(len + 1); 
    memcpy(buf, str, len + 1); 

    j = 1; 
    for (i = 0; i < len; ++i) 
     if (buf[i] == delimiter) 
     { 
      while (buf[i + 1] == delimiter) i++; 
      j++; 
     } 

    ret = malloc(sizeof(char*) * (j + 1)); 
    ret[j] = NULL; 

    ret[0] = buf; 
    j = 1; 
    for (i = 0; i < len; ++i) 
     if (buf[i] == delimiter) 
     { 
      buf[i] = '\0'; 
      while (buf[i + 1] == delimiter) i++; 
      ret[j++] = &buf[i + 1]; 
     } 
    return ret; 
} 

Бросьте две строки while (buf[i + 1] == delimiter) i++;, если вы хотите, чтобы отключить Sequenced разделители overruning.

+0

Могу ли я спросить, почему вы используете 'const' во входной строке? – ComputerLocus

+0

@Fogest Это означает, что эта функция может использоваться со строковыми литералами. Он не будет изменять буфер, который вы предоставляете. – Havenard

0

Я думаю strtok() способен обрабатывать ваши требования. Из man page

Последовательность из двух или более смежных разделителей байтов в строке разобранного считается один разделитель.

+0

Вы посмотрели код, который я фактически использую? Потому что он уже использует strtok .... – ComputerLocus

1

Сильно проголосовал ответ на ваш вопрос SO говорит примечание он не обрабатывает последовательные разделители, «JAN ,,, февраль, MAR» - но не подтверждает замечание вкладчика.

Функции strsep() рассматривает последовательные разделители как содержащие пустое поле, но функция strtok()делают игнорировать несколько экземпляров (в любой комбинации) множество разделителей. С MSVC, я для этой программы

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

int main(void) 
{ 
    char months[]= "JAN, ,\t , ,FEB,MAR"; 
    char seps[] = ", \t\r\n"; 
    char *sptr; 
    sptr = strtok(months, seps); 
    while (sptr) { 
     printf ("Month is: %s\n", sptr); 
     sptr = strtok(NULL, seps); 
    } 
    return 0; 
} 

выход:

Month is: JAN 
Month is: FEB 
Month is: MAR 

В вашем конкретном примере (я подозреваю, что может содержать вкладки), это было бы

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

int main(void) 
{ 
    char stuff[]= "h2,3  d3,4 j3,3 y4,1 g4,3"; 
    char seps[] = " \t"; 
    char *sptr; 
    sptr = strtok(stuff, seps); 
    while (sptr) { 
     printf ("Stuff is: %s\n", sptr); 
     sptr = strtok(NULL, seps); 
    } 
    return 0; 
} 

выход :

Stuff is: h2,3 
Stuff is: d3,4 
Stuff is: j3,3 
Stuff is: y4,1 
Stuff is: g4,3 
+0

Итак, вы говорите, что я должен использовать этот код вместо этого? Потому что я пытаюсь хранить каждый элемент в массиве. Используя примерную строку данных, которую я предоставил, я должен получить массив, похожий на: «[» h2,3 "," d3,4 "," j3,3 "," y4,1 "," g4,3 "]' – ComputerLocus

+0

Добавлен ваш конкретный пример. –

+0

Не видел его там? – ComputerLocus

Смежные вопросы