singlepost

[C++] Работа со string-ом. << На главную или назад  

И так, перешел от чара к стрингу, появились вопросы.

1) Есть такой вот стринг:

***
Всем привет, это Денис, шмокжмафгыкормхклкфыы!
Желаю приятного блждыыыыгогогогогогоахах дня.
***

Нужно найти слова длиннее 20 символов (тут их 2) и заменить на VAU!!!

Слово может быть, как в середине теста, так и первым/последним. Количество знаков препинания фиксировано: .,!?:;

Желательно пример кода, так как у меня нет идей (помимо полного уж изврата).

2) Дальше идут 3 задания:
// b. Не должно идти подряд более одного пробела
// c. Между словом и знаком препинания не должно быть пробела
// d. После знака препинания всегда должен идти пробел

Тут код не нужен, просто подсказка. Чем тут пользоваться? .find() ?

================

В общем, буду благодарен как за помощь, так и за ссылку на толковую статью по string-у.

Всем спасибо.

16 ответов в теме “[C++] Работа со string-ом.”

  1. 16
    Пашка Джиоев ответил:

    Я не про поиск подстроки написал, а про поиск разделителей, которые образуют некоторое множество символов.

  2. 15
    Антон Кононов ответил:

    Алгоритм поиска подстроки в строке не меняется. Я знаю принцип его работы.

    Но в данном случае я предложил метод именно поиска одного символа. То есть моим методом сложность будет O(n) где n – кол-во символов в строке. (разумеется без учета работы алгоритма замены, но если можно использовать вторую строку, то тоже O(n))

  3. 14
    Пашка Джиоев ответил:

    Один символ да, а группу символов? Я не думаю, что в библиотеке тупо сравнивается текущий символ с каждым символом из образца, ведь тогда сложность будет O(m*n),
    а можно и за O(log(m)*n) это реализовать(m – кол-во символов в образце, n – длина строки). replace – перемещает блоки памяти,
    делает реаллокацию, самому такое оптимально тоже не очень просто написать.

    А по регекспам даже не знаю, что посоветовать. Погугли.

  4. 13
    Антон Кононов ответил:

    ну насчет скорости что тут спорить :) один символ все равно быстрее не найдешь чем тупо перебор строки.

    Регэкспы это круто конечно. Есть толковая справка для нубов?

  5. 12
    Пашка Джиоев ответил:

    Насчет скорости можно поспорить.
    В стандартной библиотеке методы написаны оптимальным образом,
    и далеко не факт, что твоя реализация будет быстрее.

    Насчет регекспов – команды в vim:

    1) :%s/[^ .,!?:;]\{21,}/VAU!!!/g
    2) b) :%s/ \{2,}/ /g
    c) :%s/\([^,.!\?:;]\) \{1,}\([,.!\?:;]\)/\1\2/g
    d) :%s/\([,.!\?:;]\)\([^ ]\)/\1 \2/g

    Для awk они по-моему тоже подходят, хотя я не уверен.

  6. 11
    Вымышленнов Кузя ответил:

    Boost библиотеку себе установи.
    Наследуй класс string и добавь свои методы туда.

  7. 10
    Пашка Джиоев ответил:

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

  8. 9
    Антон Кононов ответил:

    забавно) но скорости это не добавит.
    Хотя, некоторой гламурности кода добавит. А как с регэкспами делать?

  9. 8
    Пашка Джиоев ответил:

    По ссылке смотри.
    Например первое задание:
    ======================
    #include <iostream>

    using namespace std;

    int main()
    {
    string str = "Всем привет, это Денис, шмокжмафгыкормхклкфыы!\n"
    "Желаю приятного блждыыыыгогогогогогоахах дня.";
    string separators = " ,.!?:;\"'\t\n";
    string replacement = "VAU!!!";
    cout << "====\n" << str << endl;
    size_t from = 0, to;
    size_t len;
    while ( from < str.length() )
    {
    to = str.find_first_of( separators, from);
    if ( to == string::npos )
    {
    to = str.length() – 1;
    }
    len = to – from;
    if ( len > 20 )
    {
    str.replace( from, len, replacement);
    from += replacement.length() + 1;
    } else
    {
    from = to + 1;
    }
    }
    cout << "====\n" << str << endl;
    return 0;
    }
    ========================
    Вывод:
    ====
    Всем привет, это Денис, шмокжмафгыкормхклкфыы!
    Желаю приятного блждыыыыгогогогогогоахах дня.
    ====
    Всем привет, это Денис, VAU!!!!
    Желаю приятного VAU!!! дня.

  10. 7
    Пашка Джиоев ответил:

    Блин, форматирование поплыло.
    См. тут:
    //webcodes.ru/publ/1-1-0-1511

  11. 6
    Пашка Джиоев ответил:

    Ну а вообще есть подходящий метод, find_first_of

    //www.cplusplus.com/reference/string/string/fin...

  12. 5
    Антон Кононов ответил:

    и как ей пользоваться? пример?

  13. 4
    Пашка Джиоев ответил:

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

  14. 3
    Денис Доманский ответил:

    А как еще можно?

  15. 2
    Ilya Burakov ответил:

    Это не объектный подход – вы предлагаете тот же char*

  16. 1
    Антон Кононов ответил:

    если пробел тоже понимать как знак препинания (в терминах программирования пробел+знаки_препинания=разделитель), то я бы делал так:
    * (можно сделать копию строки если она нам нужна в целости и сохранности)
    * бежим по строке (тупо цикл), ищем где разделитель меняется на не_разделитель.
    * это будет у нас начало слова
    * бежим дальше, ищем разделитель
    * это у нас будет конец слова
    * сразу находим длину слова, а координаты начала и конца уже есть
    * если надо удалить эту часть строки, то справитесь я думаю и без меня =)
    * повторяем бег по циклу пока строка не кончилась еще.

Клуб программистов работает уже ой-ой-ой сколько, а если поточнее, то с 2007 года.