|
Программирование >> Динамические структуры данных
Можно записать это выражение и по-другому, просто изменив порядок действий: eels - 5 * (fahr - 32) /9: 5 В этом случае будет выполнено преобразование констант к типу float, как к наиболее длинному из участвующих в выражении. . Теперь программа работает верно и выдает в результате, например, следующее: Введите температуру по Фаренгейту 451 По Фаренгейту: 451. в градусах Цельсия: 232.778 Обратите внимание, что на экран наряду с результатом вычислений мы вывели и исходные данные. Это правильная привычка, и надеемся, что вы тоже буДете ей следовать. СОВЕТ --- Начинающие часто тратят время на поиск ошибки в алгоритме, не удостоверившись, что программа работает с правильными данными. Рекомендуется для контроля выводить исходные данные сразу же после ввода, чтобы исключить ошибки. Попробуйте при вводе температуры задать нецифровые символы и проинтерпретировать полученный результат. Как видите, даже в таком простом примере можно допустить ошибки! В данном случае заметить их легко, но так происходит далеко не всегда, поэтому запомните важное правило: надо всегда заранее знать, что должна выдать программа. Добиться этого можно разными способами, например, вычислением результатов в уме, на бумаге или с помощью калькулятора, а в более сложных случаях - расчетами по альтернативной или упрощенной методике. Это убережет вас от многих часов, бесплодно и безрадостно проведенных за компьютером. Не поленимся повторить еще раз: ВНИМАНИЕ - Перед запуском программы необходимо иметь тестовые примеры, содержащие исходные данные и ожидаемые результаты. Количество этих примеров зависит от алгоритма. Мы будем неоднократно возвращаться к обсуждению состава тестовых примеров, поскольку самое важное качество любой программы - надежность. Программы, работающие только с определенными исходными данными, да и то лишь в бережных руках хозяина, никому не нужны. Давайте теперь напишем ту же программу вторым способом, с использованием функций библиотеки С++, унаследованных из языка С. Этот способ также применяется достаточно часто, потому что в использовании этих функций есть свои преимущества. Когда вы их оцените, то сможете выбирать для каждой программы наиболее подходящий способ ввода-вывода. #inelude <stdio.h> int main(){ 1 float fahr. eels: 2 printf( \n Введите температуру по ФаренгейтуХп ): 3 seanfCXf . &fahr): 4 eels - 5 * (fahr - 32) /9: II Ъ printfC По Фаренгейту: a;6.2f. в градуеах Цельсия: a;6.2f\n . fahr. eels): 6 return 0: 111 Как видите, к программе подключается другой заголовочный файл - <stdio.h>. Он содержит описание функций, констант и других элементов, относящихся ко вводу-выводу в стиле С . Рассмотрим отличия этой программы от предыдущей. Функция printf в операторе 3 выполняет вывод переданного ей в качестве параметра строкового литерала, то есть последовательности любых символов в кавычках, на стандартное устройство вывода (дисплей). Символы \п называются управ-ляющей последовательностью. Есть разные управляющие последовательности, все они начинаются с обратной косой черты. Эта последовательность задает переход на следующую строку. Для ввода исходных данных в операторе 4 используется функция seanf. В ней требуется указать формат вводимых значений, а также адреса переменных, которым они будут присвоены. Параметры любой функции перечисляются через запятую. В первом параметре функции seanf в виде строкового литерала задается спецификация формата вводимой величины, соответствующая типу переменной. Спецификация %f соответствует типу float. В качестве второго Г1араметра функции передается адрес переменной, по которому будет помещено вводимое значение. Операция взятия адреса обозначается &. Для вывода результата в операторе 6 применяется уже знакомая нам функция printf. Теперь в ней три параметра. Первый, имеющий вид строкового литерала, задает вид и формат выводимой информации. Второй и третий параметры представляют собой имена переменных. Все символы литерала, кроме спецификаций формата %f и управляющей последовательности \п, выводятся на дисплей без изменений. При выводе форматные спецификации будут заменены конкретными значениями переменных fahr и eels. Формат вывода чисел можно уточнить при помощи так называемых л/оЭмфм;сато-ров формата - чисел, которые записаны перед спецификацией. Первое число задает минимальное количество позиций, отводимых под выводимую величину, второе - сколько из этих позиций отводится под дробную часть величины. Необходимо учитывать, что десятичная точка тоже занимает одну позицию. Если заданного количества позиций окажется недостаточно для размещения числа, компилятор простит нам этот промах и автоматически выделит поле достаточной длины. На наш взгляд, в данном случае первый вариант программы (с использованием классов) более прост и нагляден, а также лучше защищен от ошибок кодирования. Приведем еще две наиболее употребительные спецификации: %д - для величин целого типа в десятичной системе счисления, *lf - для величин типа double. Более полный список спецификаций см. в Учебнике на с. 387. С другой стороны, с помощью функций в стиле С легче управлять видом выводимой информации. Однако при записи форматов легко ошибиться, и, к сожалению, компилятор ничего об этом не сообщит; вы будете ломать голову в поисках алгоритмической ошибки, в то время как источником неприятностей будет функция printf. Надо сказать, что при использовании классов также можно задавать любую форму представления информации, но мы пока не будем вдаваться в подобные детали. Мы не рекомендуем начинающим изучать на этом семинаре теоретический материал по классам ввода/вывода, поскольку для их полного понимания требуется освоить большой объем материала. Всему свое время! Для каждой программы необходимо выбрать один наиболее удобный способ вывода (либо с помощью функций, либо с помощью классов), поскольку смешивать оба варианта не рекомендуется. СОВЕТ --- Используйте функции ввода/вывода в тех программах, где требуется тщательное форматирование результатов, а классы - в остальных случаях. Рассмотрим в более общем виде очень важный для дальнейшей работы вопрос - описание переменных. Описание переменных Любая переменная обладает двумя основными характеристиками: временем жизни и областью действия. Они зависят от места и способа описания переменной. Если переменная описана вне любого блока (в частности, функции), она называется глобальной, размещается в сегменте данных* и изначально обнуляется, если вы не предусмотрели ее инициализацию каким-то другим значением. Время жизни глобальной переменной - с начала выполнения программы и до ее окончания, а область действия (область, в которой эту переменную можно использовать, обратившись к ней по имени) - весь файл, в котором она описана, начиная с точки описания. Переменная, описанная внутри блока (в частности, внутри функции mai п), является локальной, память под нее выделяется в сегменте стека в момент выполнения оператора описания. Для локальных переменных автоматическое обнуление не производится. Областью действия локальной переменной является блок, в котором она описана, начиная с точки описания. Время ее жизни также ограничено этим блоком. Сколько раз выполняется блок, столько раз рождается и умирает локальная переменная. Есть один вид локальных переменных, которые, подобно глобальным, размещаются в сегменте данных, существуют на всем протяжении выполнения программы и инициализируются однократно. Это статические переменные. С другой стороны, они, как локальные переменные, видны только в своем блоке. Для описания статических переменных используется ключевое слово static. Ниже приведен пример описания трех переменных и таблица, в которой суммируются сведения о видах переменных: int а: глобальная переменная int main(){ static int b = 1: локальная статическая переменная int С: локальная переменная
В IBM PC-совместимых компьютерах память представляется разделенной на сегменты. Исполняемая программа состоит из сегментов кода, в которых расположены машинные команды, сегментов данных и сегмента стека. Остальная доступная программе память называется динамической (а также хилом или кучей). Память под все эти переменные выделяет компилятор. Кроме перечисленных, существуют динамические переменные, память под которые резервируется во время выполнения программы с помощью операции new в динамической области памяти, или хипе (heap). Доступ к таким переменным осуществляется не по имени, а через указатели. Мы рассмотрим их на третьем семинаре. Во всех рассмотренных выше программах переменные являются локальными. Вариант с глобальными переменными выглядит так: #include <iostream.h> float fahr. eels: глобальные переменные int main(){ cout endl Введите температуру по Фаренгейту endl: cin fahr; eels = 5 * (fahr - 32) / 9: cout По Фаренгейту: fahr . в градусах Цельсия: eels endl: return 0; Для данной простой программы разницы в этих способах нет, но в общем случае глобальные переменные нужно стремиться использовать как можно реже. Запомните, что переменная должна иметь минимальную из возможных областей действия, поскольку это значительно облегчает поиск ошибок. На следующих семинарах нам предстоит неоднократно в этом убедиться. Задача 1.2. Временной интервал Заданы моменты начала и конца некоторого промежутка времени в часах, минутах и секундах (в щ>еделах одних суток). Найти продолжительность этого промежутка в тех же единицах. Исходными данными для этой задачи являются шесть целых величин, задающих моменты начала и конца интервала, результатами - три целых величины. Вы уже знаете, что тип переменной выбирается, исходя из диапазона и требуемой точности представления данных, а имя дается в соответствии с ее содержимым. Нам потребуется хранить исходные данные, не превышающие величины 60 для минут и секунд и величины 24 для часов, поэтому можно ограничиться коротким целым типом (short int, сокращенно short). Назовем переменные для хранения начала интервала hourl, mini и seel, для хранения конца интервала - hour2, min2 и sec2, а результирующие величины - hour, min и sec. Для решения этой задачи необходимо преобразовать оба момента времени в секунды, вычесть первый из второго, а затем преобразовать результат обратно в часы, минуты и секунды. Следовательно, нам потребуется промежуточная переменная, в которой будет храниться интервал в секундах. Она может иметь весьма большие значения, ведь в сутках 86400 секунд. В величинах типа short могут храниться значения, не превышающие 32767 для величин со знаком (signed short) и 65535 для величин без знака (unsigned short), поэтому тип short здесь использовать нельзя. Вот почему для этой переменной следует выбрать ;1линный целый тип (long int, сокращенно long). Обычный целый тип int в зависимости от архитектуры компьютера может совпадать либо с коротким, либо с длинным целым типом. Ниже приведен текст программы: linclude <iostream.h> int main(){ short hourl. mini. seel. hour2. min2. sec2. hour. min. sec: eout endl Введите вреия начала интервала (чае нин еек) endl: ein hourl mini seel: eout endl Введите вреия конца интервала (чае иин еек) endl: ein hour2 min2 sec2: long sum sec - (hour2 - hourl) * 3600 + (min2 - mini) * 60 + sec2 - seel: hour - sum see / 3600: min - (sum see - hour * 3600) / 60: sec - sum sec - hour * 3600 - min * 60: cout Продолжительность проие)1тка от hourl hour2 hour return 0: mini min2 miri seel до sec2 endl равна sec endl: Для перевода результата из секунд обратно в часы и минуты используется уже знакомый нам эффект отбрасывания дробной части при делении целого числа на целое. ВНИМАНИЕ - Данные при вводе разделяются пробелами, символами перевода строки или табуляции (но не запятыми!). Протестируйте программу на различных наборах исходных данных. Для обладателей старых компиляторов приведем текст программы с использованием функций ввода-вывода в стиле С: #inelude <stdio.h> int main(){ short hourl. mini. seel. hour2. min2. sec2. hour. min. see: printf( Введите вреия начала интервала (чае иин еек)\п ): seanfCXiXiXi . &hourl. &minl. Ssecl): printf( Введите вреия конца интервала (чае иин еек)\п ): seanfCXiXiXi . &hour2. &min2. &sec2): long sum sec - (hour2 - hourl) * 3600 + (min2 - mini) * 60 + sec2 - seel: hour - sum sec / 3600: min - (sum see - hour * 3600) / 60: see - sum sec - hour * 3600 - min * 60: hourl. Задача позаимствована из книги: iip)pKU i4. Г. Задачник по программированию. - СПб.: Питер, 2002. printf( Длительность проие)(тка от 3;2i :!i;2i:3;2i до %2\:%2\.%2л\х\ mini. seel. hour2. min2. sec2): printfC равна 3;2i:li;2i:!l;2i\n . hour. min. sec): return 0: Давайте повторим наиболее важные моменты этого семинара. 1. Выбирайте тип переменных с учетом диапазона и требуемой точности представления данных. 2. Давайте переменным имена, отражающие их назначение. 3. Ввод с клавиатуры предваряйте приглашецием. Для контроля сразу же после ввода выводите исходные данные на дисплей (по крайней мере, в процессе отладки). 4. До запуска программы подготовьте тестовые примеры, содержащие исходные данные и ожидаемые результаты. Отдельно проверьте реакцию прохраммы на неверные исходные данные. 5. При записи выражений обращайте внимание на приоритет операций. 6. В функциях pri ntf и seanf для каждой переменной указывайте спецификацию формата, соответствующую ее типу. Не забывайте, что в seanf передается адрес переменной, а не ее значение.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |