Для чтения непрерывной последовательности непробельных символов из потока в строку используйте шаблон функции operator>>
, определенный в <string>
. Затем используйте его двойника operator<<
, который записывает каждую из этих последовательностей в выходной поток, и после каждой из них добавьте по одному пробелу. Пример 4.30 дает краткий пример этой методики.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(int argc, char** argv) {
if (argc < 3)
return(EXIT_FAILURE);
ifstream in(argv[1]);
ofstream out(argv[2]);
if (!in || !out)
return(EXIT_FAILURE);
string tmp;
in >> tmp; // Прочитать первое слове
out << tmp; // Записать его в выходной поток
while (in >> tmp) { // operator>> игнорирует пробелы, так что все, что
out << ' '; // я должен сделать, - это записать пробел и каждую
out << tmp; // последовательность «непробелов»
}
out.close();
}
Это просто сделать, если использовать потоки и строки. Даже если требуется реализовать другой вариант этого — например, чтобы сохранить переходы на новую строку, — эта методика будет работать. Если требуется добавить переходы на новые строки, для их расстановки в нужных местах используйте решение, представленное в рецепте 4.16.
Рецепты 4.15 и 4.16.
4.22. Автозамена текста при изменении буфера
Имеется класс, который представляет некий тип текстового поля или документа, и по мере добавления в него текста требуется автоматически корректировать неправильно написанные слова, как это делает функция Autocorrect (Автозамена) в Microsoft Word.
Это можно реализовать в относительно небольшом коде, если использовать map
, который определен в <map>
, string
и различные возможности стандартной библиотеки. Пример 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
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 << '
';
for (string::iterator p = tmp.begin(); p != tmp.end(); ++p) {