|
Программирование >> Динамические структуры данных
Ниже приведены тексты очень простой многофайловой программы, в которой определены типы данных Точка (структура Point в файле Point.h) и Прямоугольник (структура Rect в файле Rect. h). Поскольку второй тип данных определяется через первый, в файле Rect. h имеется директива #i ncl ude Poi nt. h . В основном модуле main.cpp просто создается объект типа Прямоугольник * и выводятся координаты его левого верхнего и правого нижнего углов. В основном модуле используются как функции из модуля Point .срр, так и функции из модуля Rect. срр, поэтому в него включены оба заголовочных файла Poi nt. h и Rect. h. Но после обработки этих директив препроцессором окажется, что структура Poi nt определена дважды. В результате компилятор выдаст сообщение об ошибке наподобие следующего: еггог...: Point: struct type redefinition . тип III Файл Point.h llllllllll II Объявления типов struct Point { int x: int y: Прототипы функций void SetXY(Point& point, int x. int y): int GetX(Points point): int GetY(Points point): llllllllll Файл Rect.h llllllllll . #include Point.h Объявления типов struct Rect { Point leftTop: Point rightBottom: Прототипы функций void SetLTRB(Rect& rect. Point It. Point rb): void GetLT(Rect& rect. Point& It): void GetRB(Rect& rect. Pointb rb): llllllllll Файл Point.срр llllllllll #incl ude Point.h void SetXY(Point& point, int x. int y) { point.X = x: point.у = у: int GetX(Points point) { return point.x: Под объектом мы здесь понимаем переменную типа struct. int GetY(Points point) { return point.у: llllllllll Файл Rect.срр llllllllll #include Rect.h void SetLTRB(Rect& rect. Point It. Point rb) { rect.leftTop - It: rect.rightBottom - rb: void GetLT(Rect& rect. Points It) { It = rect.leftTop: void GetRB(Rect& rect. Point& rb) { rb - rect.rightBottom: #include <stdio.h> #include Point.h #include Rect.h llllllllll Файл Main.cpp llllllllll int main(){ Point ptl. pt2. It. rb: Rect recti: SetXY(ptl. 2. 5): SetXY(pt2. 10. 14): SetLTRB(recti, ptl. pt2): GetLT(recti. It): GetRB(recti, rb): printf( rect.It.x - Xd. rect.lt.y = Xd\n . It.x. It.y): printf( rect.rb.X - W. rect.rb.y - XdXn . rb.x, rb.y): return 0: Каков выход из этой ситуации? Бьерн Страуструп рекомендует использовать так называемые стражи включения, и этот способ нашел широкое применение. Он состоит в следующем: чтобы предотвратить повторное включение заголовочных файлов, содержимое каждого . h-файладолжно находиться между директивами условной компиляции #i f ndef и #endi f, как описано ниже: fifndef FILENAME Н #define FILENAME H /* содержимое заголовочного файла */ #endif /* FILENAME H */ Применительно к нашему примеру файл Point.h должен содержать следующий текст: Файл Point.h inillllll #ifndef POINT H #define POINT H Объявления типов struct Point { int x: int y: Прототипы функций void SetXYCPoints point, int x. int y): int GetX(Points point): int GetY(Points point); #endif /* POINT H */ Рекомендуем вам проверить рассмотренный пример на вашем компиляторе. Задача 7.7. Многофайловый проект - форматирование текста Написать программу форматирования текста, читаемого из файла unfomt.txt и состоящего из строк ограниченной длины. Слова в строке разделены произвольным количеством пробелов. Программа должна читать входной файл по строкам, форматировать каждую строку и выводить результат в выходной файл formatd. txt. Форматирование заключается в выравнивании границ текста слева и справа путем равномерного распределения пробелов между соседними словами, а также в отступе с левой стороны страницы на margin позиций, то есть результирующий текст должен находиться в позициях margin + 1 margin + maxTJine. Кроме этого, программа должна подсчитать общее количество слов в тексте. На примере этой задачи мы показываем технологию разработки многофайловых проектов. Алгоритм решения задачи не представляет особой сложности: 1. Открыть входной файл. 2. Читать файл построчно в текстовый буфер line, попутно удаляя возможные пробелы в начале строки (до первого слова). 3. Для каждой строки 1 i ne выполнить следующие действия: Вычислить величину интервала (количество пробелов), которую необходимо обеспечить между соседними словами для равномерного распределения слов в пределах строки. Вывести каждое слово из строки 1 i пе в выходной файл, вставляя между словами необходимое количество пробелов и одновременно увеличивая счетчик слов на единицу. 4. После обработки последней строки входного файла вывести на экран значение счетчика слов и закрыть выходной файл. Разбиение на подзадачи. В результате детализации описанного алгоритма определяем спецификации нужных нам функций: □ void Def Inter (const char* pi ine. int 8 basejnt. int & addjnt. int & inter) определяет для строки, на которую указывает pline, количество межсловных промежутков inter, требуемую величину основного интервала baseint для каждого промежутка (количество пробелов) и величину дополнительного интервала addi nt, определяемую как остаток от деления общего количества пробелов в строке на количество межсловных промежутков; последняя величина должна быть равномерно распределена путем добавления одного пробела в каждый из первых addint промежутков; □ void GetLine (FILE* finp. char* pline) читает очередную строку из входного файла в массив символов с адресом р1 ine, ликвидируя при этом пробелы в начале строки; □ void Put Interval (FILE* fout, const int к) выводит очередной интервал, состоящий из к пробелов; □ int PutWord (FILE* fout. const char* pline. const int startpos) выводит очередное слово в выходной файл, начиная с позиции startpos текущей строки р1 ine; возвращает номер позиции в строке pline, следующей за последним переданным символом, или О - если достигнут конец строки; □ int SearchNextWord (const char* pline. const int curpos) возвращает номер позиции, с которой начинается следующее слово в строке р1 ine, или О, если достигнут конец строки (поиск начинается с позиции curpos). Разбиение на модули. Наша программа будет располагаться в двух исходных файлах: taslc7 7. срр - с функцией mai п, edit .срр - с реализацией перечисленных выше функций, а также заголовочный файл edit .h с интерфейсом этих функций. Ниже приводится содержимое этих файлов. / Файл Task7 7.cpp #include <stdio.h> finclude <string.h> #include <stdlib.h> #include edit.h Глобальные переменные const int maxljine = 63: const int margin = 5: int main(){ FILE* finp: FILE* fout: char line[maxl line +1]: int b i. aj. start, next, inter: int nword = 0: printfC Работает программа Task7 7.\n ): if(!(finp- fopen( unformt.txt . r ))) { printf( Файл urformt.txt не найден.\n ): exit(O): printf( Читается файл unformt.txt.Vn ): if(!(fout - fopen( formatd.txt . w ))) { printf( Файл formatd.txt не создан.\n ): exit(O): printf( Выполняется запись в файл formatd.txt.\n ): while(GetLine(finp. line)) { Deflnterdine. b i. a i. inter): PutInterval(fout. margin): next = PutWordCfout. line. 0. nword): for (int i = 0: i < inter: i++) { start = SearchNextWorddine. next): PutInterval(fout. b i): if (a i) { aJ--: PutlntervaUfout. 1): } next - PutWord(fout. line, start, nword): if (!next) break: fprintf(fout. \n ): printf( \nKoличecтвo слов - XdVn . nword): fclose(fout): printf( Работа завершена An ): return 0: ll/lll/ll/IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIUinnnilll II Файл Edit.h Прототипы функций void DefInter(corst char* pline. int& basejnt..int& addjnt. int& inter): int GetLine(FILE*. char*): void PutlntervaKFILE*. const int): int PutWord(FILE*. const char*, const int. int&): int SearchNextWord(const char*, const int): Глобальные переменные extern const int maxljine: llllllllllllllllllllllllillllllllllllllllllllllllllllllltll II Файл Edit.срр #include <stdio.h> #include <string.h> #include edit.h int GetLine(FILE* finp. char* pline) ( int i = 0: char c: while ((c - fgetc(finp)) ) i++: if(c EOF) return 0: fseek(finp. -1. SEEK CUR): fgets (pi ine. maxljine - i + 1. finp): pline[strlen(pline) - 1] - 0: return 1; int SearchNextWord(const char* pline. const int curpos) { int i = curpos: while(pline[i] !-){ if (plineCi] - Xn ) return 0: i++: while (plineCi] -&& pline[i + 1] -= * *) i++; return i + 1: void DefInter(const char* pline. int& basejnt. int& addjnt. int& inter) { int к = 0. end: end = strlen(pline) - 1: while ((plineCend] = ) (plineCend] = Vn) (pline[end] Xr)) end--: inter = 0:
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |