2014-11-11 2 views
2

Я хочу сказать strtok(), чтобы использовать в качестве разделителей все, кроме буквенно-цифровых символов.Разбор слов с strtok

Моих попыток являются примером ref:

/* strtok example */ 
#include <stdio.h> 
#include <string.h> 

int main() 
{ 
    char str[] ="- This, a sample string."; 
    char * pch; 
    printf ("Splitting string \"%s\" into tokens:\n",str); 
    pch = strtok (str," ,.-"); 
    while (pch != NULL) 
    { 
    printf ("%s\n",pch); 
    pch = strtok (NULL, " ,.-"); 
    } 
    return 0; 
} 

Однако я собираюсь разобрать реальные текстовые файлы (которые содержат обзоры на сайт). В настоящее время я проверяю, что происходит с другими дериметрами, и увеличиваю второй аргумент strtok(). Например, я видел [, поэтому я сделал это " ,.-[" и так далее, но ОК, я мог бы что-то пропустить, и, возможно, новый текстовый файл содержит новый делиметр.

Не могу ли я сделать что-то умнее (и на самом деле правильно, потому что это не так)?

Например, если я получаю:

[Hello_sir I'm George]

Я хотел бы получить эти маркеры:

Hello 
sir 
I 
m 
George 

Проблема заключается в том, что я не знаю, которые являются разделители.

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


EDIT

Я думал идти посимвольна и проверить, если это буквенно-цифровое, но я надеялся на что-то встроенное, как кормление желаемой strtok().

+0

может быть, вы можете просто использовать 'isalpha' полукокса по полукокса ? http://www.cplusplus.com/reference/cctype/isalpha/ – user2485710

+0

О да, я тоже об этом подумал, позвольте мне обновить @ user2485710 – gsamaras

+2

http://stackoverflow.com/a/26243667/971127 Сделать, потому что нет , – BLUEPIXY

ответ

2

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

static char delims[256]; /* this is oversized */ 

... 

void 
initdelims() 
{ 
    int i; 
    int j = 0; 
    for (i = 1; i<256; i++) 
    { 
     if (!isalnum(i)) 
      delims[j++] = i; 
    } 
    delims[j] = 0; /* this is unnecessary as statics are initialised to zero */ 
} 

Затем используйте delims в качестве разделителя строки.

Однако это и уродливое, и неэффективное. Вам лучше написать ручной парсер, заимствуя source to strtok, если необходимо.

+0

Это именно то, о чем я думал. Однако для соображений переносимости вы должны использовать '1 << CHAR_BIT' вместо' 256'.Кроме того, почему это было бы «неэффективно» - я не уверен, что это даже имеет значение. Скорее всего, нет. –

+0

'strtok' будет для каждого символа перебирать 200-нечетные символы строки разделителя. 'isalpha' IIRC выглядит в фиксированном растровом изображении. Таким образом, 'strtok' с разделителем символов с 200 символами, вероятно, будет в 200 раз медленнее, чем что-то ручное, что не очень весело. – abligh

+0

Это не сработает, я только что протестировал. Однако в комментариях к вопросу я получил пользовательскую реализацию, которая делает именно то, что я хочу, поэтому я думал, что мы, возможно, должны удалить мой вопрос (что может быть сделано только в том случае, если вы удалите свой ответ). – gsamaras

1

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

char delims[(1 << CHAR_BIT) + 1] = { 0 }; 
for (int i = 0, j = 0; i < sizeof delims - 1; i++) { 
    if (!isalnum(i)) { 
     delims[j++] = i; 
    } 
} 

pch = strtok(str, delims); 
while (pch != NULL) 
{ 
    printf ("%s\n",pch); 
    pch = strtok(NULL, delims); 
} 
+0

Хорошо поймать использование isalnum() ', но обратите внимание на это: CHAR_BIT': http://stackoverflow.com/questions/ 19708810/фиксированной символ-бит-на-различных систем. Я использовал 256 + 1, и код не работал. – gsamaras

+0

Я использовал 256 + 1, и код не работал, я только что протестировал. Однако в комментариях к вопросу я получил пользовательскую реализацию, которая делает именно то, что я хочу, поэтому я думал, что мы, возможно, должны удалить мой вопрос (что может быть сделано только в том случае, если вы удалите свой ответ). – gsamaras

+0

+1 для использования 'isalnum()'. – gsamaras

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