insertи append— это методы шаблона класса basic_string, описанного в заголовочном файле ( string— это typedefдля basic_string, a wstring — это typedefдля basic_string), так что они работают как для строк из узких, так и широких символов. Их использование по мере необходимости, как в предыдущем примере, прекрасно работает, но при использовании методов basic_stringв собственных вспомогательных функциях общего назначения эти функции следует создавать, используя общий существующий дизайн стандартной библиотеки и шаблоны функций. Рассмотрим код примера 4.1, который определяет общий шаблон функции pad, который работает для строк типа basic_string.
Пример 4.1. Общий шаблон функции pad
#include
#include
using namespace std;
// Общий подход
template
void pad(basic_string& s,
typename basic_string::size_type n, T c) {
if (n > s.length())
s.append(n - s.length(), c);
}
int main() {
string s = "Appendix A";
wstring ws = L"Acknowledgments"; // "L" указывает, что
// этот литерал состоит из
pad(s, 20. "*"); // широких символов
pad(ws, 20, L'*');
// cout << s << std::endl; // He следует пытаться выполнить это
wcout << ws << std::endl; // одновременно
}
padв примере 4.1 дополняет данную строку sдо длины n, используя символ c. Так как шаблон функции использует параметризованный тип элементов строки ( T), он будет работать для basic_stringиз любых символов: char, wchar_tили любых других, определенных пользователем.
Проблема
Требуется обрезать несколько символов в конце или начале строки, обычно пробелов.
Решение
Для определения позиции строки, которую требуется удалить, используйте итераторы, а для ее удаления — метод erase. Пример 4.2 показывает функцию rtrim, которая удаляет символ в конце строки.
Пример 4.2. Обрезка символов строки
#include
#include
// Подход для строк из узких символов
void rtrim(std::string& s, char с) {
if (s.empty()) return;
std::string::iterator p;
for (p = s.end(); p != s.begin() && *--p == c;);
if (*p != c) p++;
s.erase(p, s.end());
}
int main() {
std::string s = "zoo";
rtrim(s, 'o');
std::cout << s << '\n';
}
Обсуждение
Пример 4.2 выполняет все необходимое для строк длины char, но работает только для них. Аналогично тому, что показано в примере 4.1, можно использовать общий дизайн basic_stringи шаблон функции. Пример 4.3 использует для удаления символов в конце строки любого типа шаблон функции.
Пример 4.3. Обобщенная версия rtrim
#include
#include
using namespace std;
// Общий подход к обрезке отдельных
// символов строки
template
void rtrim(basic_string& s, T с) {
if (s.empty()) return;
typename basic_string::iterator p;
for (p = s.end(); p != s.begin() && *--p == c;);
if (*p != c) p++;
s.erase(p, s.end());
}
int main() {
string s = "Great!!!!";
wstring ws = L"Super!!!!";
rtrim(s, '!');
rtrim(ws, L'!');
cout << s << '\n';
wcout << ws << L'\n';
}
Эта функция работает точно так же, как и предыдущая, необобщенная версия из примера 4.2, но так как она параметризована по типу символов, она будет работать для basic_stringлюбого типа.
Примеры 4.2 и 4.3 удаляют из строки последовательность одного символа. Однако обрезка пробелов выглядит по-другому, так как пробельный символ может быть представлен одним из нескольких символов. Для удобства стандартная библиотека предоставляет простейший способ справиться с этим: функцию isspaceиз заголовочного файла (и ее wchar_t-эквивалент iswspaceиз ). Пример 4.4 определяет общую функцию, которая обрезает концевые пробелы.
Пример 4.4. Удаление концевых пробелов
#include
#include
#include
#include
using namespace std;
template
void rtrimws(basic_string& s, F f) {
if (s.empty()) return;
typename basic_string::iterator p;
for (p = s.end(); p ! = s.begin() && f(*--p););
if (!f(*p))
p++;
s.erase(p, s.end());
}
// Перегрузка для облегчения вызовов в клиентском коде
void rtrimws(string& s) {
rtrimws(s, isspace);
}
void rtrimws(wstring& ws) {
rtrimws(ws, iswspace);
}
int main() {
string s = "zing ";
wstring ws = L"zong ";
rtrimws(s) rtrimws(ws);
cout << s << "|\n";
Читать дальше