|
Программирование >> Разработка устойчивых систем
ющего вида вызов конструктора Fixw создает временный объект, который затем передается оператору : cout Fixw(str1ng, 1) endl; Результат получается тем же, что и при использовании манипулятора с аргументами. Временный объект Fixw существует до конца выполнения команды. Работа эффектора Bin основана на том факте, что при сдвиге беззнакового числа вправо старщие биты заполняются нулями. Сначала мы с помощью конструкции numeric limits<unsigned long>::max() (наибольшее значение типа unsigned long из стандартного заголовка <limits>) создаем маску со старшим установленным битом, а затем последовательно маскируем каждый бит выводимого числа (слева направо). Строковые литералы разделены в программе для удобства чтения; компилятор объединяет строковые компоненты в одну строку. Традиционно считалось, что у этого решения есть недостаток: после создания класса Fixw для char* или Bin для unsigned long никто больше не сможет создать другой класс Fixw или Bin для своего типа. Однако с введением пространств имен эта проблема исчезла. Эффекторы и манипуляторы не эквивалентны, хотя они достаточно часто используются для решения одних и тех же задач. Если эффектор вас почему-либо не устраивает, вам придется разбираться во всех сложностях самостоятельного программирования манипуляторов. Примеры использования потоков ввода-вывода в этом разделе приводятся примеры, иллюстрирующие все то, о чем рассказывалось в данной главе. Существует немало программ для работы с байтовыми потоками; вероятно, наибольшей известностью пользуются потоковые редакторы, такие, как sed и awk в Unix, но текстовые редакторы тоже входят в эту категорию. И все же подобные программы обычно обладают определенными недостатками. Редакторы sed и awk относительно медлительны и способны обрабатывать строки лишь в одном направлении, а текстовые редакторы обычно требуют участия пользователя (или по крайней мере изучения специализированного макроязыка). Программы, написанные с использованием потоков ввода-вывода, лишены этих недостатков: они быстры, переносимы и гибки. Сопровождение исходного кода библиотеки классов Обычно создание класса рассматривается с позиций формирования библиотеки: вы создаете заголовочный файл Name.h с объявлением класса и файл Name.срр, содержащий реализации функций этого класса. Эти файлы должны подчиняться некоторым требованиям: они кодируются в определенном стиле (так, приведенная далее программа соответствует общему формату программ в этой книге), а код заголовочного файла заключается в препроцессорную конструкцию, предотвращающую повторное включение классов (повторные включения сбивают с толку компилятор, который не знает, какую из версий выбрать; при наличии расхождений компилятор сдается и выдает сообщение об ошибке). Следующий пример создает новую пару файлов (заголовочный файл и файл реализации) или изменяет существующую пару. Если файлы уже существуют, программа проверяет их и, возможно, вносит изменения. Но если файлы не существуют, они создаются в заранее определенном формате. : C04:Cppcheck.cpp Создание заготовок файлов .h и .срр с учетом требований стиля. Существующие файлы проверяются на соответствие. #1nclude <fstream> #include <sstream> #1nclude <string> #include <cstddef> #1nclude ../require.h using namespace std; bool startsWith(const strings base, const strings key) { return base.compare(0. key.sizeO. key) == 0; void cppCheck(string fileName) { enum bufs { BASE. HEADER, IMPLEMENT. HLINEl, GUARDl, GUARD2, GUARDS. CPPLINEl. INCLUDE, BUFNUM }: string part[BUFNUM]; part[BASE] = fileName; Поиск вхождений . в строке: size t loc = part[BASE].find(.); ifCloc != string; mpos) part[BASE].erased ОС); Удаление расширения Преобразование к верхнему регистру: for(size t i = 0; i < part[BASE].size(); i++) part[BASE][i] = toupper(part[BASE][i]): Создание имен файлов и обязательных строк: part[HEADER] = part[BASE] + .h ; part[IMPLEMENT] = part[BASE] + .cpp : part[HLINEl] = : + part[HEADER]; part[6UARDl] = #ifndef + part[BASE] + H : part[GUARD2] = #def1ne + part[BASE] + H ; part[GUARD3] = #endif + part[BASE] + H : part[CPPLINEl] = string( ) + : + part[IMPLEMENT]; part[INCLUDE] = #include \ + part[HEADER] + \ : Сначала пытаемся открыть существующие файлы: ifstream existh(part[HEADER].c str()), existcpp(part[IMPLEMENT].c str()): ifdexisth) { Файл не существует: создать его ofstream newheader(part[HEADER].c str()); assureCnewheader, part[HEADER].c str()); newheader part[HLINEl] endl part[GUARDl] endl part[GUARD2] endl endl part[GUARD3] endl: } else { Файл существует; проверить его содержимое stringstream hfile; Запись и чтение ostringstream newheader: Запись hfile existh.rdbufO: Убедиться в том, что первые три строки соответствуют стилевому стандарту: bool changed = false: string s: hfile.seekg(O): getline(hfile, s); bool lineUsed = false: Вызов goodO необходим для компилятора Microsoft (также см. далее) for (int line HLINEl: hf1le.good() && line <= GUARD2: ++11ne) { 1f(startsW1th(s. part[l1ne])) { newheader s endl: lineUsed = true: if (getl1ne(hf1le. s)) lineUsed = false: } else { newheader part[line] endl: changed = true: lineUsed = false: Копирование остатка файла if (IlineUsed) newheader s endl: newheader hfile.rdbufO: Проверка GUARDS string head = hfile.strO: if(head.find(part[GUARD3]) == string::npos) { newheader part[GUARD3] endl: changed = true: При наличии изменений файл перезаписывается: if(changed) { existh.closeO: ofstream newH(part[HEADER].c str()): assure(newH. part[HEADER].c str()): newH @ \n Признак модификации newheader.strO: if(lexistcpp) { Создание файла реализации ofstream newcpp(part[IMPLEMENT].c str()): assure(newcpp. part[IMPLEMENT].c str()): newcpp part[CPPLINEl] endl part[INCLUDE] endl: } else { Файл существует: проверить его содержимое stringstream cppfile: ostringstream newcpp: cppfile existcpp.rdbufO: Убедиться в том. что первые две строки соответствуют стилевому стандарту: bool changed = false: string s: cppfile.seekg(O): getline(cppfile. s): bool lineUsed = false: for (int line = CPPLINEl: cppfile.goodO && line <= INCLUDE: ++line) { if(startsWith(s. part[line])) { newcpp s endl: lineUsed = true: if (getline(cppfile, s)) lineUsed = false: } else { newcpp part[line] endl: changed = true:
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |