|
Программирование >> Динамические структуры данных
for (unsigned int i = 0: i < end: i++) { if (plineEi] == ) ( k++: if (plineCi + 1] != *) inter++: int blank amount - к + maxljine - end: if (!k) { basejnt = 0: addjnt = 0: } else { basejnt = blank amount / inter: addjnt = blank amount % inter: return: int PutWord (FILE* fout. const char* pline. const int startpos. int& n){ int i = startpos: char c: n++: while ((c = pline[i++]) != ) { fprintf(fout. %c . c): if ((c == Vn) II (c == XO )) { i = 0: break: } return i - 1: void PutlntervaKFILE* fout. const int k) { for (int i = 0: i < k: i++) fprintf(fout. ); return: llllllllllllllllllllllllllllllllllllllllllllllllllllllffllf Об)атите внимание, что имена функций мы здесь записали (для разнообразия) в стиле Microsoft, с использованием пролисных букв для выделения осмысленных частей имени. Константу maxl i пе следует задавать большей, чем максимальная длина строки исходного файла. В качестве самостоятельного упражнения измените программу так, чтобы можно было форматировать текст и в более узкую колонку, чем в исходном файле. Приведем результаты тестирования этой программы. Содержимое входного файла unfonnt.txt: Текст взят из афоризмов Б. Грасиана ( Карманный оракул , 1647 г.). 23. Не терпеть и малого своего недостатка - вот признак совершенства. От изъянов духовных и телесных редко кто свободен, но часто их лелеют, когда от них легко бы исцелиться. Вчуже досадно видеть разумному, как ничтожный изъян порой портит великолепное сочетание достоинств. - довольно и облачка, чтобы затмить солнце. Родимые пятна на доброй славе злоба людская сразу подметит - и упорно в них метит. Особенно ценно искусство скрывать свой недостаток, обращая его в преимущество. Так. Цезарь скрывал свою плешь лавровым венком. Содержимое выходного файла formatd.txt: 23. Не терпеть и малого своего недостатка - вот признак совершенства. От изъянов духовных и телесных редко кто свободен, но часто их лелеют, кога от них легко бы исцелиться. Вчуже досадно видеть разумному, как ничтожный изъян порой портит великолепное сочетание достоинств, - довольно и облачка, чтобы затмить солнце. Родимые пятна на доброй славе злоба людская сразу подметит - и упорно в них метит. Особенно ценно искусство скрывать свой недостаток. обращая его в преимущество. Так. Цезарь скрывал свою плешь лавровым венком. Протестируйте эту программу на других текстах. Давайте повторим наиболее важные моменты этого семинара. 1. Функция - это именованная последовательность операторов, выполняющая-законченное действие. Функции нужны для упрощения структуры программы. 2. Интерфейс грамотно написанной функции определяется ее заголовком. 3. Для вызова функции надо указать ее имя и набор аргументов. 4. В определении, в объявлении и при вызове функции типы и порядок следования аргументов и параметров должны совпадать. 5. Передача параметров в функцию может выполняться по значению или по адресу. 6. Входные данные функции надо передавать по значению или по константной ссылке, результаты ее работы - через возвращаемое значение, а при необходимости передать более одной величины - через параметры по ссылке или указателю. 7. При написании функции нужно предусмотреть все возможные ошибки и обеспечить пользователя функции средствами их диагностики. 8. Печать диагностических сообщений внутри функции нежелательна. 9. Функция может иметь несколько параметров со значениями по умолчанию. Они должны находиться в конце списка параметров. 10. Массивы всегда передаются в функцию по адресу. Количество элементов в массиве должно передаваться отдельным параметром. 11. Рекурсивная функция должна содержать хотя бы одну нерекурсивную ветвь. При использовании рекурсии следует учитывать возникающие при этом проблемы и накладные расходы. 12. В многофайловых проектах важно грамотно разбить задачу на подзадачи и распределить функции по файлам. 13. Для предотвращения ощибок компиляции, связанных с повторным включением заголовочных файлов, следует использовать так называемые стражи включения. Задания Функции и массивы Выполнить задания третьего семинара ( Одномерные массивы ) и четвертого семинара ( Двумерные массивы ), оформив каждый пункт задания в виде функции. Все необходимые данные для функций должны передаваться им в качестве параметров. Использование глобальных переменных в функциях не допускается. Функции, строки и файлы Выполнить задания пятого семинара ( Строки и файлы ), оформив в виде функций законченные последовательности действий. Все необходимые данные для функций должны передаваться им в качестве параметров. Использование глобальных переменных в функциях не допускается. Функции, структуры и бинарные файлы Выполнить задания, приведенные в Учебнике на с. 151 (раздел Функции и файлы ) и на с. 165 (раздел Модульное программирование ). СЕМИНАР 8 Перегрузка и шаблоны функций Теоретический материал: с. 83-87. Перегрузка функций Перегрузкой функций называется использование нескольких функций с одним и тем же именем, но с различными списками параметров. Перегруженные функции должны отличаться друг от друга либо типом хотя бы одного параметра, либо количеством параметров, либо и тем и другим одновременно. Перегрузка является видом полиморфизма и применяется в тех случаях, когда одно и то же по смыслу действие реализуется по-разному для различных типов или структур данных. Компилятор сам определяет, какой именно вариант функции вызвать, руководствуясь списком аргзентов. Если же алгоритм не зависит от типа данных, лучше реализовать его не в виде группы перегруженных функций для различных типов, а в виде шаблона функции. В этом случае компилятор сам сгенерирует текст функции для конкретных типов данных, с которыми выполняется вызов, и программисту не придется поддерживать несколько практически одинаковых функций. Небольшие перегруженные функции удобно применять при отладке программ. Допустим, вам требуется промежуточная печать различного вида: в одном месте требуется выводить на экран структуру, в другом - пару целых величин с пояснениями или вещественный массив. Забота о ясной промежуточной печати - это забота о своем комфорте при отладке программы, а что может быть важнее для настоящего программиста ? Поэтому проще сразу оформить печать в виде функций, например таких: void print( char* str. const int i. const int j) { б Зв.784 cout str I Oct setw(4) i * setw(4) j I endl: void printCfloat mas[]. const int n) { cout Массив: endl: cout.setf(ios::fixed): cout.precision(2): for (int i = 0: i < n: i++) { cout mas[i] : if ((i + 1) X 4 - 0) cout endl: cout endl: void print(Man m) { cout.setf(ios:ifixed): cout.precision(2): cout setw(40) m.name m.birth year m.pay endl: В первой из этих функций на экран выводятся строка и два целых числа в восьмеричной форме, разделенных вертикальными черточками для читаемости. Под каждое число отводится по 4 позиции (действие манипулятора setw распространяется только на ближайшее выводимое поле). Во второй функции для вывода вещественных значений по четыре числа на строке задается вид вывода с фиксированной точкой и точностью в два десятичных знака после запятой. Для этого используются методы установки флагов setf, установки точности preci si on и константа fixed, определенная в классе ios. Точность касается только вещественных чисел, ее действие продолжается до следующей установки. Третья функция выводит поля знакомой нам по шестому семинару структуры так, чтобы они не склеивались между собой. Манипулятор setw устанавливает ширину следующего за ним поля. Это приведет к тому, что фамилии будут выведены с отступом от края экрана. Вызов этих функций в программе может выглядеть, например, так: print( После цикла . i. п): print(a, п): print(m): По имени функции сразу понятно, что она делает, кроме того, при необходимости вызов функции легче закомментировать или перенести в другое место, чем группу операторов печати. Конечно, промежуточная печать - не единственный метод отладки, но зато универсальный, потому что отладчик не всегда доступен. При написании перегружённых функций основное внимание следует обращать на то, чтобы в процессе поиска нужного варианта функции по ее вызову не возникало неоднозначности. Неоднозначность может возникнуть по нескольким причинам. Во-первых, из-за преобразований типов, которые компилятор выполняет по умолчанию. Правила преобразования арифметических типов аналогичны описанным в Учебнике на с. 390. Их смысл сводится к тому, что более короткие типы преобразуются в более длинные. Если соответствие между формальными параметрами и аргументами функции на одном и том же этапе может быть получено более чем одним способом, вызов считается неоднозначным и выдается сообщение об ошибке. Неоднозначность может также возникнуть из-за параметров по умолчанию и ссылок. Рассмотрим создание перегруженных функций на примере. Задача 8.1. Перегрузка функций Написать программу, которая для базы сотрудников, описанной в задаче 6.1, выдает по запросу список сотрудников либо родившихся раньше заданного года, либо имеюищх оклад больше введенного с клавиатуры. Варианты выборки из базы по различным запросам оформим в виде перегруженных функций. Мы от природной лени и для простоты рассматриваем базу с Минимальным количеством полей; в реальных ситуациях их может быть гораздо больше, соответственно, больше будет и вариантов перегруженных функций. Также оформим в виде отдельной функции чтение базы из файла - и для лучшего структурирования программы, и для того, чтобы в случае необходимости было легче заменить эту функцию на другую, например на чтение из бинарного файла. #include <fstream.h> #include <string.h> #include <stdlib.h> #include <iomanip.h> const int l name = 30. l year - 5. l pay = 10. l buf - l name + l year + l pay; struct Man { int birth year: char name[l name + 1]: float pay: int read dbase(const char * filename. Man dbase[]. const int l dbase. int &n record); void print(Man m): void select(Man dbase[]. const int n record. const int year): void select(Man dbase[]. const int n record. const float pay); int main(){ const int l dbase = 100: Man dbase[l dbase]: int n record = 0:
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |