Чтение онлайн

на главную - закладки

Жанры

C++. Сборник рецептов

Когсуэлл Джефф

Шрифт:

4.22. Автозамена текста при изменении буфера

Проблема

Имеется класс, который представляет некий тип текстового поля или документа, и по мере добавления в него текста требуется автоматически корректировать неправильно написанные слова, как это делает функция Autocorrect (Автозамена) в Microsoft Word.

Решение

Это можно реализовать в относительно небольшом коде, если использовать

map
, который определен в
<map>
,
string
и различные возможности стандартной библиотеки.
Пример 4.31 показывает, как это делается.

Пример 4.31. Автозамена текста

#include <iostream>

#include <string>

#include <cctype>

#include <map>

using namespace std;

typedef map<string, string> StrStrMap;

// Класс для хранения текстовых полей

class TextAutoField {

public:

 TextAutoField(StrStrMap* const p) : pDict_(p) {}

 ~TextAutoField {}

 void append(char c);

 void getText(string& s) {s = buf_;}

private:

 TextAutoField;

 string buf_;

 StrStrMap* const pDict ;

};

// Добавление с автозаменой

void TextAutoField::append(char c) {

 if ((isspace(c) || ispunct(c)) && // Выполнять автоза-

buf_.length > 0 && // мену, только когда вводятся

!isspace(buf_[buf_.length - 1])) { // ws или punct

string::size_type i = buf_.find_last_of(" \f\n\r\t\v");

i = (i == string::npos) ? 0 : ++i;

string tmp = buf_.substr(i, buf_.length - i);

StrStrMap::const_iterator p = DDict_->find(tmp);

if (p != pDict_->end) { // Нашли, так что стираем

buf_.erase(i, buf_.length - i); // и заменяем

buf_ += p->second;

}

 }

 buf_ += с;

}

int main {

 // Создаем map

 StrStrMap dict;

 TextAutoField txt(&dict);

 dict["taht"] = "that";

 dict["right"] = "wrong";

 dict["bug"] = "feature";

 string tmp = "He's right, taht's a bug.";

 cout << "Оригинальная версия: " << tmp << '\n';

 for (string::iterator p = tmp.begin; p != tmp.end; ++p) {

txt.append(*p);

 }

 txt.getText(tmp);

 cout << "Исправленная
версия. " << tmp << '\n';

}

Вывод примера 3.2 таков.

Оригинальная версия: He's right, taht's a bug.

Исправленная версия: He's wrong, that's a feature.

Обсуждение

string
и
map
удобны в ситуациях, когда требуется отслеживать ассоциации
string
.
TextAutoField
— это простой текстовый буфер, использующий
string
для хранения данных. Интересной
TextAutoField
делает ее метод
append
, который «слушает» пробелы или знаки пунктуации и при их появлении выполняет обработку.

Чтобы сделать автозамену работающей, требуется две вещи. Во-первых, требуется некий словарь, который содержит неправильно написанные варианты слов и связанные с ними правильные написания, map хранит пары ключ/значение, где ключ и значение могут быть любого типа, так что он является идеальным кандидатом на эту роль. В начале примера 4.31 имеется

typedef
для пар
string
:

typedef map<string, string> StrStrMap;

За более подробным описанием map обратитесь к рецепту 4.18.

TextAutoField
хранит указатель на
map
, так как, вероятнее всего, для всех полей потребуется только один общий словарь.

Предполагая, что клиентский код помещает в

map
что-то осмысленное,
append
просто должен периодически проверять
trap
. В примере 4.31
append
ждет появления пробела или знака пунктуации. Для проверки на пробел можно использовать
isspace
, а для поиска знаков пунктуации можно использовать ispunct. Обе эти функции для узких символов определены в
<cctype>
(см. табл. 4.3).

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

string tmp
содержит последний фрагмент текста, который был добавлен в
TextAutoField
. Чтобы увидеть, был ли он написан с ошибками, поищите его в словаре вот так.

StrStrMap::iterator p = pDict->find(tmp);

if (p != pDict_->end) {

Здесь важно то, что

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

Поделиться:
Популярные книги

Барон играет по своим правилам

Ренгач Евгений
5. Закон сильного
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Барон играет по своим правилам

Сердце Дракона. нейросеть в мире боевых искусств (главы 1-650)

Клеванский Кирилл Сергеевич
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
7.51
рейтинг книги
Сердце Дракона. нейросеть в мире боевых искусств (главы 1-650)

Герцогиня в ссылке

Нова Юлия
2. Магия стихий
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Герцогиня в ссылке

Ну привет, заучка...

Зайцева Мария
Любовные романы:
эро литература
короткие любовные романы
8.30
рейтинг книги
Ну привет, заучка...

На Ларэде

Кронос Александр
3. Лэрн
Фантастика:
фэнтези
героическая фантастика
стимпанк
5.00
рейтинг книги
На Ларэде

Сердце Дракона. Том 12

Клеванский Кирилл Сергеевич
12. Сердце дракона
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
7.29
рейтинг книги
Сердце Дракона. Том 12

Истинная поневоле, или Сирота в Академии Драконов

Найт Алекс
3. Академия Драконов, или Девушки с секретом
Любовные романы:
любовно-фантастические романы
6.37
рейтинг книги
Истинная поневоле, или Сирота в Академии Драконов

Кодекс Охотника. Книга VI

Винокуров Юрий
6. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга VI

Гардемарин Ее Величества. Инкарнация

Уленгов Юрий
1. Гардемарин ее величества
Фантастика:
городское фэнтези
попаданцы
альтернативная история
аниме
фантастика: прочее
5.00
рейтинг книги
Гардемарин Ее Величества. Инкарнация

Сама себе хозяйка

Красовская Марианна
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Сама себе хозяйка

Душелов. Том 3

Faded Emory
3. Внутренние демоны
Фантастика:
альтернативная история
аниме
фэнтези
ранобэ
хентай
5.00
рейтинг книги
Душелов. Том 3

Газлайтер. Том 10

Володин Григорий
10. История Телепата
Фантастика:
боевая фантастика
5.00
рейтинг книги
Газлайтер. Том 10

Стеллар. Заклинатель

Прокофьев Роман Юрьевич
3. Стеллар
Фантастика:
боевая фантастика
8.40
рейтинг книги
Стеллар. Заклинатель

Возвышение Меркурия. Книга 5

Кронос Александр
5. Меркурий
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 5