C++ для начинающих. Строки. Разбить строку на слова

Начинающим программистам полезно поупражняться в решении задачи разбиения предложения на слова.
К решению задачи разбиения предложений на слова могут быть разные требования, в которых, например, могут быть требования запрета использования функции strtok и ей подобных, запрет на использование строковых потоков и другие запреты. Эти ограничения обусловлены тем, что дающий такие задания хочет научить своего студента немного работать с текстом.
Но пока что отложим решения с ограничениями, будем использовать наиболее простые способы:
В простейшем случае в предложении все слова написаны полностью и в учебных целях не нужно предусматривать чуть более сложные случаи, чем простые. Например, если в предложении слова объединяются апострофом, как в английском языке: I’m, то это два слова: I am. Новичкам не нужно на таких моментах запариваться, и имеет смысл выдавать два слова как есть, т. е. слово I и слово m. Что нашли в тексте, о том и сказали, это нормально для новичков.
Самый простой и короткий способ деления предложений на слова — это использование строковых потоков.
Современный стиль:

Стиль эпохи динозавров:

Это самый быстрый для программиста способ написания кода, разбивающего строку на слова, например, для подсчёта количества слов в строке. Сейчас я вывожу слова, но это чтобы было вам видно, что для обработки отдельных слов в дальнейшем требуются дополнительные затраты времени на написание кода, ведь многие ненужные слову символы прилипают к словам, нужно их подчищать.
Принцип работы очень прост: внести в поток, забирать из потока. При отборе у потока данных используется операция <<, из-за неё поток отдаёт все символы, идущие до первого пробела, а сами пробелы игнорируется. Поэтому получается, что в поток вы отдали всю строку, а забираете из потока отдельные слова.
Для того, чтобы работать над словами строки, можно использовать способ, применяемый в языке С: использовать функцию strtok. В таком случае нам можно будет указывать символы-разделители, которыми определяется, что символ делит слово. В самом обычном виде слова делятся знаками препинания: пробел, точка, запятая, восклицательный знак и др. Есть и неудобства, но на некоторые осложняющие случаи чаще все закрывают глаза: например, дефис и тире требует дополнительной обработки, хотя в типографии дефис и тире разные символы, мы часто используем символ дефиса в качестве тире. Я не буду усложнять показываемый код дополнительными обработками, чтобы новички могли понять основное, да и всех случаев возможных проблем я просто не могу предвидеть. Будем считать, что для анализа нам подаются простые строки.
  • Функция strtok это стандартная функция языка С, она позволяет разбивать строки на части
  • Чтобы разбить строку на части функцией strtok, нужно функции подсказать набор символов-разделителей, по которым видно, что идёт несколько слов, а не одно.
  • Для того, чтобы иметь возможность работы с функцие strtok, нужно заинклюдить заголовочный файл string.h

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

Это strtok и делает.
Почему в strtok отдаётся именно ноль для дальнейшего анализа, мне объяснить вам сложно. Скорее всего написавшие функцию программисты немного прогадали с интуитивно-понятным вариантом, решили, что если не другая строка, то пусть будет нулевой указатель. Я усложнять ничего не хочу, поэтому на первое время предлагаю запомнить, что в случае работы с strtok, если нужно продолжать работу с той же строкой, то нужно отдавать нулевой указатель и разделители, а при первом обращении нужно обязательно отдать анализируемую строку и разделители.
Чтобы слова поочерёдно выбирались, мы делаем цикл:

  • Функция strtok разрушает анализируемую строку.
Я уже писал, что функция strtok принудительно пишет символ-признак окончания строки в строку, из-за этого оригинальная строка бьётся.

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

Когда вы будете смотреть в другие источники, то будете встречать такие термины: лексема и токен. Мне эти термины выносили мозг. Если углубляться в лингвистику, то слово лексема не очень уместно для русского человека из-за наличия падежей в русском языке, а токены — это просто выбираемые по какому-то признаку кусочки текста, в случае со словами токенами оказываются просто слова. Если бы массив состоял из цифр, а делителем была бы цифра 5, то токеном было бы любое число, отделённое символом 5:
3 4 4 3 5 6 2 3 5 3 5 2 1 1 2 5
Токены: 3443, 623, 3, 2112 — ведь словами их трудно назвать.
Все комментарии на сайте проверяются, поэтому ваш комментарий может появиться не сразу. Для вставки кода в комментарий используйте теги: [php]ВАШ_КОД[/php]

11 комментариев: C++ для начинающих. Строки. Разбить строку на слова

  • Sergio говорит:

    А как разбить строку на слова и записать каждое полученное слово в отдельную переменную?
    Покажите, пожалуйста, хотя бы на примере 2х слов.




    0



    0
    • admin говорит:

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

      подойдет такой пример?
      =====================
      немного подрихтуете. пример основан на примере из темы, но в другой среде разработки.

      Если вы под отдельными переменными имели ввиду элементы массива, то извиняйте. Как был задан вопрос, так я и ответил.




      0



      0
    • admin говорит:

      Если в предложение неизвестное количество слов и оно может быть разным, то для того, чтобы описывать каждое слово в отдельной переменной, нужно каждую переменную создавать во время выполнения программы. Это работа с указателями и выделением памяти. Но все равно все сводится к тому, что после работы программы надо будет очищать выделенную память своими руками, а чтобы ее очищать, нужно где-то хранить адреса. Объяснять долго. Всё сведется к тому что нужен массив, в котором будут храниться занятые системой адреса для их освобождения после завершения работы программы. Это геморрно, неудобно и неэффективно. Или же надо лезти в деревья (стеки, деревья, очереди 🙂 )




      0



      0
  • валя говорит:

    здравствуйте! я е знаю кому задать вопрос я хочу ищучить си++ и тут наткнулась на пример
    http://codeserfer.com/3615-primer-raboty-s-klassami-i-nasledovaniem.html
    как в этом разобраться???? Препод на курсах задала разобраться с инкапсуляцией, а я много проспустил а и вообще ничего не понимаю в ооп… помогите пожалуйста




    0



    0
    • admin говорит:

      здравствуйте. я быстро не могу помочь никак, да и непонятно зачем пропускали если хотите изучить С++
      ваш пример — перегрузка операторов. Перегрузка операторов почти ничего не объясняет в икнапсуляции.




      0



      0
    • admin говорит:

      Инкапсуляция

      Инкапсуляция
      Как понимать классы в С++ http://ci-plus-plus-snachala.ru/?p=35
      Немного о private http://ci-plus-plus-snachala.ru/?p=44
      Еще немного о private http://ci-plus-plus-snachala.ru/?p=44
      Инкапсуляция — это то, что к private относится (я бы назвал ее приватизацией, т.к. под слово хорошо подходит и произношением и смыслом, но злые технари не любят когда вещи называют не теми именами, которые им даны)




      0



      0
  • Nazar говорит:

    Здравствуйте! Не могли бы вы мне помочь? Как разбить файл(.txt) на части по указанным строкам и записать эти части на отдельные файлы. Помогите пожалуйста…..




    0



    0
  • Nazar говорит:

    на с++




    0



    0
  • Guardian говорит:

    Извините, а причём тут С++? Ваш пример — дикая смесь двух языков. Из всего С++ здесь только std::cout всё остальное — С. Почему не используются строковые потоки, кода было бы раз в 5 меньше.

    Уважаемые новички! Помните, что если вы компилите .cpp, это ещё не значит, что вы пишете на С++. Если вы не знаете стандартной библиотеки, вы не знаете С++. Если вы не используете виртуальные функции, вы даже не приступили к ООП. Вы используете мощнейший язык на полпроцента.




    0



    0
    • admin говорит:

      На занятиях часто ограничивают задания делать без STL и что, это значит учат уже не С++?
      Не зная STL не знаешь С++ — дикая чушь. STL не есть С++, С++ способно жить и без STL
      C++ — это не ООП язык, а мультипарадигменный язык, он поддерживает ООП и только.
      Ну и что, что пример смешан? C++ задумывался как язык, который включает в себя Си.




      0



      0
  • Hazatdum говорит:

    Здравствуйте, очень интересная статья!
    А можно ли как-нибудь записать еще и сами разделители отдельно? Например есть строка «А=В+С» и вывод был бы
    А
    =
    В
    +
    С

    Помогите, пожалуйста!




    0



    0

Добавить комментарий

Ваш e-mail не будет опубликован.

Поиск

 
     

Случайная книга в электронном формате

Яндекс.Метрика
НАГРАДИ АВТОРА САЙТА
WEBMONEY
R375024497470
U251140483387
Z301246203264
E149319127674

- Что за ошибка? Врубиться не могу никак. Помоги, а? core.cpp(252): error C2059: syntax error : ')' - Это компилятор уже не знает что тебе сказать. Дословный перевод: "я плакалъ".

Выражаю свою признательность

  • Максиму очень признателен за указание на мои ошибки и неточности.
  • Sergio ===> за оказание помощи в исправлении моих ошибок
  • Gen ===> за правильное стремление помочь другим новичкам и выявления моих ошибок