Д. Стефенс - C++. Сборник рецептов
- Название:C++. Сборник рецептов
- Автор:
- Жанр:
- Издательство:КУДИЦ-ПРЕСС
- Год:2007
- Город:Москва
- ISBN:5-91136-030-6
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Д. Стефенс - C++. Сборник рецептов краткое содержание
Данная книга написана экспертами по C++ и содержит готовые рецепты решения каждодневных задач для программистов на С++. Один из авторов является создателем библиотеки Boost Iostreams и нескольких других библиотек C++ с открытым исходным кодом. В книге затрагивается множество тем, вот лишь некоторые из них: работа с датой и временем; потоковый ввод/вывод; обработка исключений; работа с классами и объектами; сборка приложений; синтаксический анализ XML-документов; программирование математических задач. Читатель сможет использовать готовые решения, а сэкономленное время и усилия направить на решение конкретных задач.
C++. Сборник рецептов - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Но это не всё, что требуется сделать; также требуется сравнить размеры. Рассмотрим объявление equal.
template
typename BinaryPredicate>
bool equal(InputIterator1 first, InputIterator1 last1,
InputIterator2 first2, BinaryPredicate pred);
Пусть n — это расстояние между first1и last1, или, другими словами, длина первого диапазона. equalвозвращает true, если первые nэлементов обеих последовательностей равны. Это означает, что если есть две последовательности, где первые nэлементов равны, но вторая содержит больше чем nэлементов, то equalвернет true. Чтобы избежать такой ошибки требуется проверять размер.
Эту логику не обязательно инкапсулировать в функцию. Ваш или клиентский код может просто вызвать алгоритм напрямую, но проще запомнить и написать такое:
if (caseInsCompare(s1, s2)) { // они равны, делаем что-нибудь
чем такое:
if ((s1.size() == s2.size()) &&
std::equal(s1.begin(), s1.end(s2.begin(), caseInsCharCompare)) {
// они равны, делаем что-нибудь
когда требуется выполнить сравнение строк без учета регистра.
4.14. Выполнение поиска строк без учета регистра
Требуется найти в строке подстроку, не учитывая разницу в регистре.
Используйте стандартные алгоритмы transformи search, определенные в , а также свои собственные функции сравнения символов, аналогичные уже показанным. Пример 4.22 показывает, как это делается.
Пример 4.22. Поиск строк без учета регистра
#include
#include
#include
#include
#include
using namespace std;
inline bool caseInsCharCompSingle(char a. char b) {
return(toupper(a) == b);
}
string::const_iterator caseInsFind(string& s, const string& p) {
string tmp;
transform(p.begin( ), p.end(), // Преобразуем шаблон
back_inserter(tmp), // к верхнему регистру
toupper);
return(search(s.begin(), s.end(), // Возвращаем итератор.
tmp.begin(), tmp.end(), // возвращаемый из
caseInsCharCompSingle)); // search
}
int main() {
string s = "row, row, row, your boat";
string p = "YOUR";
string::const_iterator ir = caseInsFind(s, p);
if (it != s.end()) {
cout << "Нашли!\n;
}
}
Возвращая итератор, который указывает на элемент целевой строки, где начинается шаблонная строка, мы обеспечиваем совместимость с другими стандартными алгоритмами, так как большинство из них принимают в качестве аргумента итератор.
Пример 4.22 демонстрирует обычный ход действий при работе со стандартными алгоритмами. Создайте функцию, которая выполняет работу, а затем подключите ее как объект функции к наиболее подходящему алгоритму. Здесь работу выполняет функция charInsCharCompSingle, но в отличие от примера 4.21 эта функция сравнения символов переводит к верхнему регистру только первый аргумент. Это сделано потому, что немного далее в caseInsFindя перед использованием строки шаблона в поиске преобразую ее к верхнему регистру полностью и тем самым избегаю многократного преобразования символов строки шаблона к верхнему регистру.
После того как функция сравнения будет готова, используйте для поиска стандартные алгоритмы transformи search. transformиспользуется для преобразования к верхнему регистру всего шаблона (но не целевой строки). После этого используйте для поиска места вхождения подстроки search совместно с функцией сравнения.
Помните, что стандартные алгоритмы работают с последовательностями , а не со строками. Это общие алгоритмы, которые в основном (но не только) работают со стандартными контейнерами, но не делают никаких предположений о содержимом этих контейнеров. Все стандартные алгоритмы требуют передачи им функции сравнения (а в случае их отсутствия используют операторы по умолчанию), которые тем или иным способом сравнивают два элемента и возвращают bool, указывающий, дало ли сравнение истину или ложь.
В примере 4.22 есть одна вещь, которая выглядит странно. Вы видите, что caseInsCompareвозвращает const_iterator, как в
string::const_iterator caseInsFind(const string& s,
const string& p)
Что, если требуется изменить элемент, на который указывает возвращенный итератор? Тому есть причина. Она состоит в том, что константный итератор используется потому, что строки, которые передаются в caseInsFind, также передаются как const, и, следовательно, невозможно получить не- constитератор на const-строку. Если требуется итератор, который можно использовать для изменения строки, удалите constиз параметров и измените объявление функции так, чтобы она возвращала string::iterator.
4.15. Преобразование между табуляциями и пробелами в текстовых файлах
Имеется текстовый файл, содержащий табуляции или пробелы, и требуется преобразовать одни в другие. Например, может потребоваться заменить все табуляции на последовательности из трех пробелов или сделать наоборот и заменить все вхождения некоторого числа пробелов на табуляции.
Независимо от того, производится ли замена табуляций на пробелы или пробелов на табуляции, используйте классы ifstreamи ofstreamиз . В первом (более простом) случае прочтите данные по одному символу с помощью входного потока, изучите их и, если очередной символ — это табуляция, запишите в выходной поток некоторое количество пробелов. Пример 4.23 демонстрирует, как это делается.
Пример 4.23. Замена табуляций на пробелы
#include
#include
#include
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);
char c;
while (in.get(c)) {
if (c == '\t')
out << " "; // 3 пробела
else
out << c;
}
out.close();
if (out)
return(EXIT_SUCCESS);
else
return(EXIT_FAILURE);
}
Если же требуется заменить пробелы на табуляции, обратитесь к примеру 4.24. Он содержит функцию spacesToTabs, которая читает из входного потока по одному символу, ища три последовательных пробела. Когда они найдены, она записывает в выходной поток табуляцию. Для всех остальных символов или меньшего количества пробелов в выходной поток записывается то, что было прочитано во входном.
Пример 4.24. Замена пробелов на табуляции
#include
#include
#include
#include
#include
using namespace std;
void spacesToTabs(istream& in, ostream& out, int spaceLimit) {
int consecSpaces = 0;
char c;
while (in.get(c)) {
if (c != ' ') {
if (consecSpaces > 0) {
for (int i = 0; i < consecSpaces; i++) {
out.put(' ');
Интервал:
Закладка: