Распечатать разделитель, используемый strtok_r

У меня есть, например, такой текст:

I know,, more.- today, than yesterday!

И я извлекаю слова с помощью этого кода:

while(getline(&line, &len, fpSourceFile) > 0) {
  last_word = NULL;
  word = strtok_r(line, delim, &last_word);

  while(word){
    printf("%s ", word);
    word = strtok_r(NULL, delim, &last_word);
    // delim_used = ;
  }
}

Результат:

I know more today than yesterday

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


person Christopher    schedule 22.11.2014    source источник
comment
Невозможно узнать после использования, потому что фактически используемый разделитель заменяется на 0.   -  person BLUEPIXY    schedule 22.11.2014


Ответы (2)


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

#include <string.h>

/* 
 * public domain strtok_ex() based on a public domain 
 *      strtok_r() by Charlie Gordon
 *
 *   strtok_r from comp.lang.c  9/14/2007
 *
 *      http://groups.google.com/group/comp.lang.c/msg/2ab1ecbb86646684
 *
 *     (Declaration that it's public domain):
 *      http://groups.google.com/group/comp.lang.c/msg/7c7b39328fefab9c
 */

 /*
    strtok_ex() is an extended version of strtok_r() that optinally 
    returns the delimited that was used to terminate the token

    the first 3 parameters are the same as for strtok_r(), the last
    parameter:

        char* delim_found

    is an optional pointer to a character that will get the value of
    the delimiter that was found to terminate the token.

 */
char* strtok_ex(
    char *str, 
    const char *delim, 
    char **nextp,
    char* delim_found)
{
    char *ret;
    char tmp;

    if (!delim_found) delim_found = &tmp;

    if (str == NULL)
    {
        str = *nextp;
    }

    str += strspn(str, delim);

    if (*str == '\0')
    {
        *delim_found = '\0';
        return NULL;
    }

    ret = str;

    str += strcspn(str, delim);

    *delim_found = *str;
    if (*str)
    {
        *str++ = '\0';
    }

    *nextp = str;

    return ret;
}


#include <stdio.h>
int main(void)
{
    char delim[] = " ,.-!";
    char line[] = "I know,, more.- today, than yesterday!";

    char delim_used;    
    char* last_word = NULL;
    char* word = strtok_ex(line, delim, &last_word, &delim_used);

    while (word) {
        printf("word: \"%s\" \tdelim: \'%c\'\n", word, delim_used);
        word = strtok_ex(NULL, delim, &last_word, &delim_used);
    }

    return 0;
}

Получение любых пропущенных разделителей было бы немного сложнее. Я не думаю, что это потребует много работы, но я думаю, что интерфейс будет громоздким (интерфейс strtok_ex() уже неуклюжий), так что вам придется немного подумать об этом.

person Michael Burr    schedule 22.11.2014

Нет, вы не можете идентифицировать разделитель (посредством вызова самого strtok_r()).

Из man strtok_r:

ОШИБКИ

[...]

  • Идентификация байта-разделителя теряется.
person alk    schedule 22.11.2014