Большая часть строки исчезла после разделения с помощью strtok?

e: Всем спасибо, не знал, что strtok на самом деле изменяет саму строку. Надеюсь, в будущем я буду менее глупым.

Недавно я начал изучать C++ по книге. Сейчас я перешел к главе о разборе строк.

Мое следующее задание — собрать вместе токены строки после их разделения с помощью strtok, но я не понимаю, куда делась остальная часть строки после первого разделителя! Имейте в виду, что я очень новичок в этом, поэтому извините, если это глупый вопрос.

В основном происходит следующее: 1. Я ввожу строку "привет, как дела?" 2. Распечатайте, выходит нормально. 3. Затем я разбиваю его на токены (используя разделители и пробел) 4. Все они печатаются аккуратно 5. Напечатайте строку еще раз, и все, что осталось, это «привет».

Итак, как мне вернуть остальную часть строки?

Это мой код:

char the_string[ 81], *p;

cout << the_string << endl;

cout << "Input a string to parse: ";
cin.getline(the_string, 81);
p = strtok(the_string, ", ");
while (p != NULL) {
  cout << p << endl;
  p = strtok(NULL, ", ");
} 

cout << the_string << endl;

person vanamerongen    schedule 14.08.2012    source источник
comment
Попробуйте man strtok и получите основную информацию.   -  person Rohan    schedule 14.08.2012
comment
Почему не Zoidb...^H^H^H^H^H^H^H^H^H std::string и std::stringstream?   -  person Griwes    schedule 14.08.2012


Ответы (5)


strtok() изменяет строку, с которой он работает:

Если str != NULL, функция ищет первый символ, который не является разделителем. Этот символ является началом токена. Затем функция ищет первый символ-разделитель. Этот символ является концом токена. Функция завершается и возвращает NULL, если конец строки встречается до того, как найден конец токена. В противном случае указатель на конец маркера сохраняется в статическом месте для последующих вызовов. Затем этот символ заменяется символом NULL, и функция возвращает указатель на начало токена.

Сделайте копию строки перед передачей в strtok().

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

person hmjd    schedule 14.08.2012

strtok() изменяет строку, с которой он работает, вставляя '\0' всякий раз, когда находит токен.

Таким образом, строка "one two three\0" (явная '\0' для справки) при маркировке пробелом изменяется на "one\0two\0three\0", и большинство строковых операций видят ее как "one" (сейчас я удалил '\0')

person pmg    schedule 14.08.2012

В следующий раз, когда вы будете использовать функцию, прочтите ее справочную страницу (более внимательно). Strtok() размечает строку, заменяя первый символ разделителя нулевым символом. Ваша строка будет изменена. Что-то вроде этого (\0 указывает на символ NUL):

Hey\0 how\0 are\0 you?\0

Strdup() строку перед передачей в strtok().

person Community    schedule 14.08.2012

Способ работы strtok() заключается в том, что он заменяет символы-разделители символом конца строки. Итак, "привет, как дела?" стать "эй,\0как\0ты\0?"

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

person bames53    schedule 14.08.2012

Как указано в документации strtok:

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

Это означает, что когда вы печатаете строку, функция для ее печати останавливается после того, как она проходит первый токен и встречает нулевой символ. NULL обычно означает «конец строки» для строк C.

person David Grayson    schedule 14.08.2012