Программирование >>  Разработка устойчивых систем 

1 ... 45 46 47 [ 48 ] 49 50 51 ... 196


ющего вида вызов конструктора 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:



1 ... 45 46 47 [ 48 ] 49 50 51 ... 196

© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика