Лекция: Общее знакомство
Вид материала | Лекция |
СодержаниеНеявное преобразование типа Арифметические преобразования Явные преобразования типов Синтаксис типов Ввод и вывод одного символа Функции ввода-вывода |
- Жизнь Клима Самгина (общее знакомство) утопия, 27.58kb.
- Лекция Общее знакомство с организмом человека Человек и окружающая среда, 81.53kb.
- Цель дисциплины, 24.29kb.
- Тема пояснения, 99.97kb.
- Общее знакомство с цветковыми растениями, 1421.63kb.
- Образовательные программы : дошкольное общее образование, начальное общее образование,, 549.09kb.
- План «курсы трейдинга» День 1 Вступительная лекция Знакомство. Базовые понятие о трейдинге., 56.64kb.
- Ю. Б. Введение в общую психологию. М., 2000. Лекция, 413.91kb.
- Урок литературы по рассказу саши черного "в лунную ночь", 85.66kb.
- Лекция со студентами асс, 33.36kb.
Неявное преобразование типа
Неявные преобразования типа выполняются главным образом для согласования аргументов оператора или функции (если это возможно) со значениями, предполагаемыми в этих операторах или функциях. Все
неявные преобразования типа, которые могут встретиться, перечислены ниже (слева указывается преобразуемый тип, а справа - список типов, в которые он может быть преобразован):
char - int, short int, long int (Преобразование к значению с большим числом двоичных разрядов может включать, а может не включать расширение знакового разряда - это зависит от реализации языка. Для элементов заданного набора знаков гарантируется преобразование в неотрицательные целые значения).
int - char, short int, long int ( преобразование к целому большей длины включает расширение знакового разряда. Преобразование к целому меньшей длины вызывает отбрасывание лишних старших разрядов). float, double, unsigned int (интерпретация комбинации битов в виде беззнакового целого значения).
short int - аналогично типу int.
long int - аналогично типу int.
float - double, int, short int, long int (машинно-зависимое преобразование, если преобразуемое значение слишком велико, то результат неопределен).
double - float (преобразование с округлением и последующим отбрасыванием лишних разрядов), int, short int, long int.
^
Арифметические преобразования
Арифметические операторы языка Си преобразуют операнды к соответствующим типам автоматически, если операнды не имели таких типов с самого начала. Схема преобразования, используемая этими операторами, называется обычные арифметические преобразования; это схема может быть описана следующими правилами:
- Преобразовать операнды типов char и short int к типу int; преобразовать операнды типа float к типу double.
- Если хотя бы один из операндов имеет тип double, то и другой операнд преобразуется к типу double (если он другого типа); результат имеет тип double.
- Если хотя бы один операнд имеет тип long, то и другой операнд преобразуется к типу long (если он другого типа); результат имеет тип long.
- Если хотя бы один из операндов имеет тип unsigned, то и другой операнд преобразуется к типу unsigned (если его тип не unsigned); результат имеет тип unsigned.
- Если ни один из случаев 1-4 не имеет места, то оба операнда должны иметь тип int; такой же тип будет и у результата.
Явные преобразования типов
Выражения могут быть преобразованы из одного типа в другой явным указанием. Выражение E может быть явно преобразовано к типу имя-типа с помощью записи вида
(имя - типа) Е
где имя типа представляется в форме
указатель-типа абстрактный-описатель
Абстрактный описатель аналогичен описателю, за исключением того, что он не содержит определяемого или описываемого идентификатора. Смысл слов имя-типа, представляемого в форме
Т абстрактный описатель
где Т является указателем типа, может быть определен одним из таких способов:
- форма абстрактного описателя - смысл слов "Т абстрактный описатель";
- пустой (абстрактный описатель) - абстрактный описатель типа Т;
- *(абстрактный описатель) - указатель на тип Т;
- абстрактный описатель ( ) - функция, возвращающая значение типа Т;
- абстрактный описатель [n] - массив с n элементами типа Т, n - выражение с постоянным значением;
Приведем примеры явного преобразования. Предположим, что даны следующие определения и описания:
int i;
char *pc, *name;
char *calloc( ), *strcpy( );
тогда можно привести следующие примеры явных преобразований типов:
(char) i - преобразует значение типа int в значение типа char.
pc=(char *) 0777 - преобразует восьмеричный литер 0777 в значение указателя на знак таким образом, что оно может быть присвоено переменной "pc".
(emp *) calloc(1,sizeof(emp)) - преобразует значение "знакового" указателя, возвращаемого функцией calloc, в значение указателя emp.
(void) strcpy(name,"gehani") - опускает значение, возвращенное функцией strcpy.
^
Синтаксис типов
Можно отметить, что синтаксис типов в языке Си нерегулярен и беспорядочен, чем свидетельствуют:
- Трудность создания форматеров.
- Большое число ошибок, допускаемых даже опытными программистами.
- Трудность создания синтаксических анализаторов для трансляторов с языка Си - не существует двух трансляторов с языка Си, синтаксис входного языка для которых полностью совпадал бы.
- Отсутствие формального описания синтаксиса языка Си - даже книга (Kernighan, B.W., and D.M. Ritchie, The C Programming Language, prentice-Hall, Engleewood Cliffs, NJ (1978)) может служить лишь черновым описанием такового. Сказанное касается в полной мере и синтаксиса типов. Имеется три случая, когда необходимо использовать типы:
- описания, связывающие тип с именем, как например, в случае описания (глобальных) переменных и формальных параметров;
- описания, связывающие значения (и тип) с именем, как, например, описания программ;
- приведения, обеспечивающие, например, возможность трактовки символов как целых.
- описания, связывающие тип с именем, как например, в случае описания (глобальных) переменных и формальных параметров;
6.Лекция: Функции и переключение ввода-вывода
^ Ввод и вывод одного символаВ данном разделе мы рассмотрим функции, применяемые при вводе и выводе. кроме того мы коснемся других аспектов этого понятия. Под функциями ввода-вывода подразумеваются функции, которые выполняют транспортировку данных в программу и из нее. Мы уже использовали две такие функции: printf( ) и scanf( ). Теперь рассмотрим несколько других возможностей, предоставляемых языком Си. ^ Функции ввода-вывода не входят в определение языка Си. Их разработка возложена на программистов, реализующих компилятор с языка Си. С другой стороны, выгода использования стандартного набора функций ввода-вывода на всех системах очевидна. Это дает возможность писать переносимые программы, которые легко можно применять на разных машинах. В языке Си имеется много функций ввода-вывода такого типа, например printf( ) и scanf( ). Ниже мы рассмотрим функции getchar( ) и putchar( ). Эти две функции осуществляют ввод и вывод одного символа при каждом обращении к ним. Этот способ ввода данных лучше соответствует возможностям машины. Более того, такой подход служит основой построения большинства программ обработки текстов, являющихся последовательностями обычных слов. Мы увидим, как можно применять эти функции в программах, занимающихся подсчетом символов, чтением и копированием файлов. Узнаем про буферы, эхо-печать и переключение ввода-вывода. Функция getchar( ) получает один символ, поступающий с пульта терминала (и поэтому имеющий название), и передает его выполняющейся в данной момент программе. Функция putchar( ) получает один символ, поступающий из программы, и пересылает его для вывода на экран. Рассмотрим пример программы, которая принимает один символ с клавиатуры, и выводит его на экран: /*ввод-вывод*/ #include main( ) { char ch; ch=getchar( ); /***1***/ putchar(ch); /***2***/ } Для большинства систем спецификации функции getchar и putchar содержатся в системном файле stdio.h, поэтому мы указали данный файл в программе. Функция getchar( ) аргументов не имеет, т.е. при ее вызове в круглые скобки не помещается никакая величина. Она просто получает очередной поступающий символ, и сама возвращает его значение выполняемой программе. Оператор, приведенный в строке 1, присваивает значение функции getchar( ) переменной ch. Функция putchar( ) имеет один аргумент. При ее вызове необходимо в скобках указать символ, который требуется вывести на печать. Аргументом может быть одиночный символ (включая знаки, представляемые управляющими последовательностями), переменная или функция, значением которой является одиночный символ. Правильным обращением к функции putchar( ) является указание любого из этих аргументов при ее вызове: putchar('D'); putchar('\n'); putchar('\007'); putchar(ch); /* переменная типа char */ putchar(getchar( )); Модифицируем нашу программу: #include main( ) { putchar(getchar( )); } Такая запись очень компактна и не требует введения вспомогательных переменных. В результате компиляции такая программа оказывается более эффективной. БуферыПри выполнении данной программы (любой из двух ее версий), вводимый символ в одних вычислительных системах немедленно появится на экране (эхо-печать), в других же вычислительных системах ничего не происходит до тех пор, пока мы не нажмем клавишу Enter. Первый случай относится к небуферизованному (прямому) вводу, означающему, что выводимый символ оказывается немедленно доступным ожидающей программе. Второй случай служит примером буферизованного ввода, когда вводимые символы собираются и помещаются в некоторой области временной памяти, называемую буфером. Нажатие клавиши Enter приводит к тому, что блок символов, или один символ, становится доступным программе. В нашей программе применяется только первый символ, поскольку функция getchar( ) вызывается в ней один раз. Зачем нужны буферы? Во-первых, оказывается, что передачу нескольких символов в виде одного блока можно осуществить гораздо быстрее, чем передавать их последовательно по одному. Во-вторых, если при вводе символов допущена ошибка, мы сможем воспользоваться корректирующими средствами терминала, чтобы ее исправить. И когда мы нажмем клавишу Enter, будет произведена передача откорректированной строки. Однако, для некоторых диалоговых программ небуферизованный ввод может оказаться приемлемым. Например, в программах обработки текстов было бы желательно, чтобы каждая команда вводилась, как только мы нажимаем соответствующую клавишу. Поэтому как буферизованный, так и небуферизованный ввод имеет свои достоинства. Рассмотрим вывод на печать групп символов. Желательно, чтобы в любой момент можно было остановить работу программы. Для этого напишем программу так, чтобы она прекращала работу при получении какого-нибудь специального символа, например "!": /* ввод-вывод */ /* ввод и печать символов до поступления завершающего символа */ #include #define STOP ! /*дает символу '!' символическое имя */ main( ) { char ch; ch=getchar( ); /***9***/ while(ch != STOP) { /***10***/ putchar( ch); /***11***/ ch=getchar( ); /***12***/ } } В данном примере при первом прохождении тела цикла функция putchar( ) получает значение своего аргумента в результате выполнения оператора, расположенного в строке 9. В дальнейшем, вплоть до завершения работы цикла, значением этого аргумента является символ, передаваемый программе функцией getchar, расположенной в строке 12. Цикл while будет осуществлять чтение и печать символов до тех пор, пока не поступит признак STOP.
|