Глава 1 переменные, выражения, присваивания


Содержание

Глава 1 переменные, выражения, присваивания

пРЕТБФПТ РТЙУЧБЙЧБОЙС ЪБНЕОСЕФ ФЕЛХЭЕЕ ЪОБЮЕОЙЕ РЕТЕНЕООПК ОПЧЩН ЪОБЮЕОЙЕН, ЪБДБЧБЕНЩН ЧЩТБЦЕОЙЕН. рЕТЕНЕООБС Ч МЕЧПК ЮБУФЙ ПРЕТБФПТБ РТЙУЧБЙЧБОЙС Й ЧЩТБЦЕОЙЕ Ч ЕЗП РТБЧПК ЮБУФЙ ДПМЦОЩ ВЩФШ ПДОПЗП Й ФПЗП ЦЕ ФЙРБ, ПДОБЛП ПО ОЕ ДПМЦЕО ВЩФШ МЙНЙФЙТХЕНЩН.

ПРЕТБФПТ-РТЙУЧБЙЧБОЙС ::= ЙНС-РЕТЕНЕООПК := ЧЩТБЦЕОЙЕ;

рТЙ ЧЩРПМОЕОЙЙ ПРЕТБФПТБ РТЙУЧБЙЧБОЙС ЧОБЮБМЕ ЧЩЮЙУМСАФУС ЙНС РЕТЕНЕООПК Й ЧЩТБЦЕОЙЕ Ч РПТСДЛЕ, ОЕ ПРТЕДЕМЕООПН Ч СЪЩЛЕ. ъБФЕН, ЕУМЙ РЕТЕНЕООБС ОЕ СЧМСЕФУС НБУУЙЧПН, РТПЧЕТСЕФУС РТЙОБДМЕЦОПУФШ ЪОБЮЕОЙС ЧЩТБЦЕОЙС РПДФЙРХ РЕТЕНЕООПК (ЕУМЙ ЦЕ РЕТЕНЕООБС — НБУУЙЧ, ФП РТЙ РТЙУЧБЙЧБОЙЙ РТПЙЪЧПДЙФУС РТЕПВТБЪПЧБОЙЕ РПДФЙРБ, ЛБЛ ПРЙУБОП Ч ТБЪД. 5.2.1). оБЛПОЕГ, ЪОБЮЕОЙЕ ЧЩТБЦЕОЙС УФБОПЧЙФУС ОПЧЩН ЪОБЮЕОЙЕН РЕТЕНЕООПК.

рТЙ ПФТЙГБФЕМШОПН ТЕЪХМШФБФЕ ХРПНСОХФПК ЧЩЫЕ РТПЧЕТЛЙ РТЙОБДМЕЦОПУФЙ РПДФЙРХ ЧПЪВХЦДБЕФУС ЙУЛМАЮЕОЙЕ CONSTRAINT_ERROR, Б ФЕЛХЭЕЕ ЪОБЮЕОЙЕ РЕТЕНЕООПК ОЕ ЙЪНЕОСЕФУС. чЩРПМОЕОЙЕ РТЙУЧБЙЧБОЙС ПЫЙВПЮОП, ЕУМЙ РЕТЕНЕООБС СЧМСЕФУС РПДЛПНРПОЕОФПК, ЪБЧЙУСЭЕК ПФ ДЙУЛТЙНЙОБОФПЧ ОЕПЗТБОЙЮЕООПК ЙНЕОХЕНПК РЕТЕНЕООПК, Й РТЙ ЬФПН ЧЩРПМОЕОЙЙ ЙЪНЕОСЕФУС ЪОБЮЕОЙЕ МАВПЗП ЙЪ ХРПНСОХФЩИ ДЙУЛТЙНЙОБОФПЧ.

рТЙНЕТЩ РТПЧЕТПЛ ПЗТБОЙЮЕОЙК:

рТЙНЕЮБОЙЕ. ъОБЮЕОЙС ДЙУЛТЙНЙОБОФПЧ ПВЯЕЛФБ, ХЛБЪБООПЗП УУЩМПЮОЩН ЪОБЮЕОЙЕН, ОЕ НПЗХФ ВЩФШ ЙЪНЕОЕОЩ (ДБЦЕ РТЙУЧБЙЧБОЙЕН УПУФБЧОПЗП ЪОБЮЕОЙС ЧУЕНХ ПВЯЕЛФХ), РПУЛПМШЛХ ФБЛЙЕ ПВЯЕЛФЩ, УПЪДБООЩЕ ЗЕОЕТБФПТБНЙ, ЧУЕЗДБ СЧМСАФУС ПЗТБОЙЮЕООЩНЙ (УН. 4.8); РПДЛПНРПОЕОФЩ ФБЛЙИ ПВЯЕЛФПЧ НПЗХФ Й ОЕ ВЩФШ ПЗТБОЙЮЕООЩНЙ.

еУМЙ ЧЩТБЦЕОЙЕ Ч РТБЧПК ЮБУФЙ СЧМСЕФУС ЮЙУМПЧЩН МЙФЕТБМПН, ЙНЕОПЧБООЩН ЮЙУМПН ЙМЙ БФТЙВХФПН, ЧЩТБВБФЩЧБАЭЙН ТЕЪХМШФБФ ФЙРБ ХОЙЧЕТУБМШОЩК-ГЕМЩК ЙМЙ ХОЙЧЕТУБМШОЩК-ЧЕЭЕУФЧЕООЩК, ФП РТПЙЪЧПДЙФУС ОЕСЧОПЕ РТЕПВТБЪПЧБОЙЕ ФЙРБ, ПРЙУБООПЕ Ч ТБЪД. 4.6.

пРТЕДЕМЕОЙЕ ФЙРБ РЕТЕНЕООПК Ч МЕЧПК ЮБУФЙ ПРЕТБФПТБ РТЙУЧБЙЧБОЙС НПЦЕФ РПФТЕВПЧБФШ ТБУУНПФТЕОЙС ЧЩТБЦЕОЙС, ЕУМЙ ЙНС РЕТЕНЕООПК НПЦЕФ ЙОФЕТРТЕФЙТПЧБФШУС ЛБЛ ЙНС РЕТЕНЕООПК, ХЛБЪБООПК УУЩМПЮОЩН ЪОБЮЕОЙЕН, ЧПЪЧТБЭБЕНЩН ЧЩЪПЧПН ЖХОЛГЙЙ, Б ФБЛЦЕ ЛБЛ ЛПНРПОЕОФБ ЙМЙ ПФТЕЪПЛ ФБЛПК РЕТЕНЕООПК (УН. ТБЪД. 8.7 П ЛПОФЕЛУФЕ ТБЪТЕЫЕОЙС УПЧНЕЭЕОЙС).

уУЩМЛЙ: ЧЩЪПЧ ЖХОЛГЙЙ 6.4, ЧЩТБЦЕОЙЕ 4.4, ЧЩЮЙУМЕОЙЕ 4.5, ЗЕОЕТБФПТ 4.8, ДЙУЛТЙНЙОБОФ 3.7.1, ЙНС 4.1, ЙУЛМАЮЕОЙЕ CONSTRAINT_ERROR 11.1, ЛПНРПОЕОФБ 3.6, 3.7, НБУУЙЧ 3.6, ОЕСЧОПЕ РТЕПВТБЪПЧБОЙЕ ФЙРБ 4.6, ПВЯЕЛФ 3.2, ПФТЕЪПЛ 4.1.2, ПЫЙВПЮОЩК 1.6, РЕТЕНЕООБС 3.2.1, РПДЛПНРПОЕОФБ 3.3, РПДФЙР 3.3, РТЕПВТБЪПЧБОЙЕ РПДФЙРБ 4.6, РТЙУЧБЙЧБОЙЕ НБУУЙЧБ 5.2.1, УПЧНЕЭЕОЙЕ 6.6, 8.7, УУЩМПЮОЩК ФЙР 3.8, ФЙР 3.3, ХЛБЪЩЧБФШ 3.8, ХОЙЧЕТУБМШОЩК-ЧЕЭЕУФЧЕООЩК ФЙР 3.5.6, ХОЙЧЕТУБМШОЩК-ГЕМЩК ФЙР 3.5.4, ЮЙУМПЧПК МЙФЕТБМ 2.4.

5.2.1. ртйучбйчбойс нбууйчпч

еУМЙ РЕТЕНЕООБС Ч МЕЧПК ЮБУФЙ ПРЕТБФПТБ РТЙУЧБЙЧБОЙС СЧМСЕФУС ЙОДЕЛУЙТХЕНПК (Ч ЮБУФОПУФЙ, ПФТЕЪЛПН), ЪОБЮЕОЙЕ ЧЩТБЦЕОЙС ОЕСЧОП РТЕПВТБЪХЕФУС Ч ЪОБЮЕОЙЕ РПДФЙРБ ЙОДЕЛУЙТХЕНПК РЕТЕНЕООПК, РПУМЕ ЮЕЗП ТЕЪХМШФБФ РТЕПВТБЪПЧБОЙС УФБОПЧЙФУС ОПЧЩН ЪОБЮЕОЙЕН РЕТЕНЕООПК.

ьФП ЪОБЮЙФ, ЮФП ОПЧПЕ ЪОБЮЕОЙЕ ЛБЦДПК ЛПНРПОЕОФЩ ЙОДЕЛУЙТХЕНПК РЕТЕНЕООПК ЪБДБЕФУС УПРПУФБЧМСЕНПК ЕК ЛПНРПОЕОФПК ЙОДЕЛУЙТХЕНПЗП ЪОБЮЕОЙС, РПМХЮЕООПЗП РТЙ ЧЩЮЙУМЕОЙЙ ЧЩТБЦЕОЙС (УН. ПРТЕДЕМЕОЙЕ УПРПУФБЧМСЕНЩИ ЛПНРПОЕОФ Ч 4.5.2). рТЙ РТЕПВТБЪПЧБОЙЙ РПДФЙРБ ДМС ЛБЦДПК ЛПНРПОЕОФЩ ЙОДЕЛУЙТХЕНПК РЕТЕНЕООПК РТПЧЕТСЕФУС ОБМЙЮЙЕ УПРПУФБЧМСЕНПК ЛПНРПОЕОФЩ ЙОДЕЛУЙТХЕНПЗП ЪОБЮЕОЙС, Й ОБПВПТПФ. рТЙ ПФТЙГБФЕМШОПН ТЕЪХМШФБФЕ ЬФПК РТПЧЕТЛЙ ЧПЪВХЦДБЕФУС ЙУЛМАЮЕОЙЕ CONSTRAINT_ERROR, Б ЪОБЮЕОЙЕ ЛБЦДПК ЛПНРПОЕОФЩ РЕТЕНЕООПК ОЕ ЙЪНЕОСЕФУС.

рТЙНЕЮБОЙЕ. рТЙУЧБЙЧБОЙЕ НБУУЙЧБ ПРТЕДЕМЕОП ДБЦЕ Ч УМХЮБЕ РЕТЕЛТЩЧБАЭЙИУС ПФТЕЪЛПЧ, РПУЛПМШЛХ ЧЩТБЦЕОЙЕ Ч РТБЧПК ЮБУФЙ ЧЩЮЙУМСЕФУС дП РТЙУЧБЙЧБОЙС ЛПНРПОЕОФ. фБЛ, Ч УМХЮБЕ РПУМЕДОЕЗП ЙЪ РТЙЧЕДЕООЩИ РТЙНЕТПЧ ТЕБМЙЪБГЙС, ЧЩТБВБФЩЧБАЭБС б(1 .. 12) = = «tartartartar», ВЩМБ ВЩ ОЕЛПТТЕЛФОПК^.

пРЙУБООПЕ ЧЩЫЕ СЧОПЕ РТЕПВТБЪПЧБОЙЕ РПДФЙРБ ЧЩРПМОСЕФУС ФПМШЛП ОБ ХТПЧОЕ ЪОБЮЕОЙС ЧУЕЗП ЧЩТБЦЕОЙС РТБЧПК ЮБУФЙ, ОП ОЕ ДМС ЕЗП РПДЛПНРПОЕОФ, СЧМСАЭЙИУС ЙОДЕЛУЙТХЕНЩНЙ ЪОБЮЕОЙСНЙ.

уУЩМЛЙ: ЙУЛМАЮЕОЙЕ CONSTRAINT_ERROR 11.1, НБУУЙЧ 3.6, ПФТЕЪПЛ 4.1.2, РЕТЕНЕООБС 3.2.1, РТЕПВТБЪПЧБОЙЕ РПДФЙРБ 4.6, РТЙУЧБЙЧБОЙЕ 5.2, УПРПУФБЧМСЕНЩЕ ЙОДЕЛУЙТХЕНЩЕ ЛПНРПОЕОФЩ 4.5.2, ФЙР 3.3.

1) рПЛПНРПОЕОФОБС РЕТЕУЩМЛБ ОЕДПРХУФЙНБ. — рТЙН. ТЕД.

Оператор присваивания. Арифметические выражения

Первый оператор, с которым мы познакомимся,– оператор присваивания.

Оператор присваивания — основной оператор любого языка программирования. Общая форма записи оператора:

имя величины := выражение

Например, V:=A; или V:=A+1;

При помощи оператора присваивания переменной могут присваиваться константы и выражения, значения переменных любого типа.

Как только в программе встречается переменная, для неё в памяти отводится место. Оператор присваивания помещает значение переменной или значение выражения в отведённое место.

Если в процессе выполнения программы встречается пере присваивание (т.е. та же самая переменная принимает другое значение), то старое значение переменной стирается, на свободное место записывается новое значение. Команда присваивания позволяет лучше понять смысл слова переменная (т.е. меняющая своё значение по ходу программы).

Выражение может быть арифметическим, логическим или литерным. Важно, чтобы тип величины был согласован с видом выражения.

Арифметические выражения должны быть записаны в так называемой линейной записи согласно следующим правилам:

• выражение должно быть записано в виде линейной цепочки символов;

• используемые операции приведены в таблице:

НАЗВАНИЕ ОПЕРАЦИИ ФОРМА ЗАПИСИ
сложение x + y
вычитание x — y
умножение x * y
деление x / y

• нельзя опускать знаки операций, например писать 5b. Для записи произведения чисел 5 и b надо писать 5*b;

• аргументы функций (sin, cos и др.) как и аргументы вспомогательных алгоритмов, записываются в круглых скобках, например sin(x), cos(4*x).

Не нашли то, что искали? Воспользуйтесь поиском:

Лучшие изречения: Сдача сессии и защита диплома — страшная бессонница, которая потом кажется страшным сном. 8774 — | 7145 — или читать все.

188.64.174.135 © studopedia.ru Не является автором материалов, которые размещены. Но предоставляет возможность бесплатного использования. Есть нарушение авторского права? Напишите нам | Обратная связь.

Отключите adBlock!
и обновите страницу (F5)

очень нужно

Глава 1 переменные, выражения, присваивания

Переменные и константы являются основными объектами данных, с которыми имеет дело программа. Переменные перечисляются в объявлениях, где устанавливаются их типы и, возможно, начальные значения. Операции определяют действия, которые совершаются с этими переменными. Выражения комбинируют переменные и константы для получения новых значений. Тип объекта определяет множество значений, которые этот объект может принимать, и операций, которые над ними, могут выполняться. Названные «кирпичики” и будут предметом обсуждения в этой главе.

Стандартом ANSI было утверждено значительное число небольших изменений и добавлений к основным типам и выражениям. Любой целочисленный тип теперь может быть со знаком, signed, и без знака, unsigned. Предусмотрен способ записи беззнаковых констант и шестнадцатеричных символьных констант. Операции с плавающей точкой допускаются теперь и с одинарной точностью. Введен тип long double, обеспечивающий повышенную точность. Строковые константы конкатенируются («склеиваются”) теперь во время компиляции. Частью языка стали перечисления (enum), формализующие для типа установку диапазона значений. Объекты для защиты их от каких-либо изменений разрешено помечать как const. В связи с введением новых типов расширены правила автоматического преобразования из одного арифметического типа в другой.

2.1 Имена переменных

Хотя мы ничего не говорили об этом в главе 1, но существуют некоторые ограничения на задание имен переменных и именованных констант.

Имена составляются из букв и цифр; первым символом должна быть буква. Символ подчеркивания «_» считается буквой; его иногда удобно использовать, чтобы улучшить восприятие длинных имен переменных. Не начинайте имена переменных с подчеркивания, так как многие переменные библиотечных программ начинаются именно с этого знака. Большие (прописные) и малые (строчные) буквы различаются, так что x и X — это два разных имени. Обычно в программах на Си малыми буквами набирают переменные, а большими — именованные константы.

Для внутренних имен значимыми являются первые 31 символ. Для имен функций и внешних переменных число значимых символов может быть меньше 31, так как эти имена обрабатываются ассемблерами и загрузчиками и языком не контролируются. Уникальность внешних имен гарантируется только в пределах 6 символов, набранных безразлично в каком регистре. Ключевые слова if, else, int, float и т. д. зарезервированы, и их нельзя использовать в качестве имен переменных. Все они набираются на нижнем регистре (т. е. малыми буквами).

Разумно давать переменным осмысленные имена в соответствии с их назначением, причем такие, чтобы их было трудно спутать друг с другом. Мы предпочитаем короткие имена для локальных переменных, особенно для счетчиков циклов, и более длинные для внешних переменных.

2.2 Типы и размеры данных

В Си существует всего лишь несколько базовых типов:

char — единичный байт, который может содержать один символ из допустимого символьного набора;
int — целое, обычно отображающее естественное представление целых в машине;
float — число с плавающей точкой одинарной точности;
double — число с плавающей точкой двойной точности.

Имеется также несколько квалификаторов, которые можно использовать вместе с указанными базовыми типами. Например, квалификаторы short (короткий) и long (длинный) применяются к целым:

В таких объявлениях слово int можно опускать, что обычно и делается. Если только не возникает противоречий со здравым смыслом, short int и long int должны быть разной длины, а int соответствовать естественному размеру целых на данной машине. Чаще всего для представления целого, описанного с квалификатором short, отводится 16 бит, с квалификатором long — 32 бита, а значению типа int — или 16, или 32 бита. Разработчики компилятора вправе сами выбирать подходящие размеры, сообразуясь с характеристиками своего компьютера и соблюдая следующие ограничения: значения типов short и int представляются по крайней мере 16 битами; типа long — по крайней мере 32 битами; размер short не больше размера int, который в свою очередь не больше размера long.

Квалификаторы signed (со знаком) или unsigned (без знака) можно применять к типу char и любому целочисленному типу. Значения unsigned всегда положительны или равны нулю и подчиняются законам арифметики по модулю 2 n , где n — количество бит в представлении типа. Так, если значению char отводится 8 битов, то unsigned char имеет значения в диапазоне от 0 до 255, a signed char – от -128 до 127 (в машине с двоичным дополнительным кодом). Являются ли значения типа просто char знаковыми или беззнаковыми, зависит от реализации, но в любом случае коды печатаемых символов положительны.

Тип long double предназначен для арифметики с плавающей точкой повышенной точности. Как и в случае целых, размеры объектов с плавающей точкой зависят от реализации; float, double и long double могут представляться одним размером, а могут — двумя или тремя разными размерами.

Именованные константы для всех размеров вместе с другими характеристиками машины и компилятора содержатся в стандартных заголовочных файлах и (см. приложение B).

Упражнение 2.1. Напишите программу, которая будет выдавать диапазоны значений типов char, short, int и long, описанных как signed и как unsigned, с помощью печати соответствующих значений из стандартных заголовочных файлов и путем прямого вычисления. Определите диапазоны чисел с плавающей точкой различных типов. Вычислить эти диапазоны сложнее.

2.3 Константы

Целая константа, например 1234, имеет тип int. Константа типа long завершается буквой l или L, например 123456789L: слишком большое целое, которое невозможно представить как int, будет представлено как long. Беззнаковые константы заканчиваются буквой u или U, а окончание ul или UL говорит о том, что тип константы — unsigned long.

Константы с плавающей точкой имеют десятичную точку (123.4), или экспоненциальную часть (1е-2), или же и то и другое. Если у них нет окончания, считается, что они принадлежат к типу double. Окончание f или F указывает на тип float, а l или L — на тип long double.

Целое значение помимо десятичного может иметь восьмеричное или шестнадцатеричное представление. Если константа начинается с нуля, то она представлена в восьмеричном виде, если с 0x или с 0X, то — в шестнадцатеричном. Например, десятичное целое 31 можно записать как 037 или как 0X1F. Записи восьмеричной и шестнадцатеричной констант могут завершаться буквой L (для указания на тип long) и U (если нужно показать, что константа беззнаковая). Например, константа 0XFUL имеет значение 15 и тип unsigned long.

Символьная константа есть целое, записанное в виде символа, обрамленного одиночными кавычками, например ‘x’. Значением символьной константы является числовой код символа из набора символов на данной машине. Например, символьная константа ‘0’ в кодировке ASCII имеет значение 48, которое никакого отношения к числовому значению 0 не имеет. Когда мы пишем ‘0’ , а не какое-то значение (например 46), зависящее от способа кодировки, мы делаем программу независимой от частного значения кода, к тому же она и легче читается. Символьные константы могут участвовать в операциях над числами точно так же, как и любые другие целые, хотя чаще они используются для сравнения с другими символами.

Некоторые символы в символьных и строковых константах записываются с помощью эскейп-последовательностей, например \n (символ новой строки); такие последовательности изображаются двумя символами, но обозначают один. Кроме того, произвольный восьмеричный код можно задать в виде

где ооо — одна, две или три восьмеричные цифры (0 … 7) или

где hh — одна, две или более шестнадцатеричные цифры (0. 9, а. f, A. F). Таким образом, мы могли бы написать

или в шестнадцатеричном виде:

Полный набор эскейп-последовательностей таков:

Символьная константа ‘\0’ — это символ с нулевым значением, так называемый символ null. Вместо просто 0 часто используют запись ‘\0’, чтобы подчеркнуть символьную природу выражения, хотя и в том и другом случае запись обозначает нуль.

Константные выражения — это выражения, оперирующие только с константами. Такие выражения вычисляются во время компиляции, а не во время выполнения, и поэтому их можно использовать в любом месте, где допустимы константы, как, например, в

Строковая константа, или строковый литерал, — это нуль или более символов, заключенных в двойные кавычки, как, например,

Кавычки не входят в строку, а служат только ее ограничителями. Так же, как и в символьные константы, в строки можно включать эскейп-последовательности; \», например, представляет собой двойную кавычку. Строковые константы можно конкатенировать («склеивать”) во время компиляции; например, запись двух строк

эквивалентна записи одной следующей строки:

Указанное свойство позволяет разбивать длинные строки на части и располагать эти части на отдельных строчках.

Фактически строковая константа — это массив символов. Во внутреннем представлении строки в конце обязательно присутствует нулевой символ ‘\0’ , поэтому памяти для строки требуется на один байт больше, чем число символов, расположенных между двойными кавычками. Это означает, что на длину задаваемой строки нет ограничения, но чтобы определить ее длину, требуется просмотреть всю строку. Функция strlen(s) вычисляет длину строки s без учета завершающего ее символа ‘\0’ . Ниже приводится наша версия этой функции:

Функция strlen и некоторые другие, применяемые к строкам, описаны в стандартном заголовочном файле .

Будьте внимательны и помните, что символьная константа и строка, содержащая один символ, не одно и то же: ‘x’ не то же самое, что «x». Запись ‘x’ обозначает целое значение, равное коду буквы x из стандартного символьного набора, а запись «x» — массив символов, который содержит один символ (букву x) и ‘\0’.

В Си имеется еще один вид константы — константа перечисления. Перечисление — это список целых констант, как, например, в

Первое имя в enum имеет значение 0, следующее — 1 и т.д. (если для значений констант не было явных спецификаций). Если не все значения специфицированы, то они продолжают прогрессию, начиная от последнего специфицированного значения, как в следующих двух примерах:

Имена в различных перечислениях должны отличаться друг от друга. Значения внутри одного перечисления могут совпадать.

Средство enum обеспечивает удобный способ присвоить константам имена, причем в отличие от #define значения констант при этом способе могут генерироваться автоматически. Хотя разрешается объявлять переменные типа enum, однако компилятор не обязан контролировать, входят ли присваиваемые этим переменным значения в их тип. Но сама возможность такой проверки часто делает enum лучше, чем #define. Кроме того, отладчик получает возможность печатать значения переменных типа enum в символьном виде.

2.4 Объявления

Все переменные должны быть объявлены раньше, чем будут использоваться, при этом некоторые объявления могут быть получены неявно — из контекста. Объявление специфицирует тип и содержит список из одной или нескольких переменных этого типа, как, например, в

Переменные можно распределять по объявлениям произвольным образом, так что указанные выше списки можно записать и в следующем виде:

Последняя форма записи занимает больше места, тем не менее она лучше, поскольку позволяет добавлять к каждому объявлению комментарий. Кроме того, она более удобна для последующих модификаций.

В своем объявлении переменная может быть инициализирована, как, например:

Инициализация неавтоматической переменной осуществляется только один раз — перед тем, как программа начнет выполняться, при этом начальное значение должно быть константным выражением. Явно инициализируемая автоматическая переменная получает начальное значение каждый раз при входе в функцию или блок, ее начальным значением может быть любое выражение. Внешние и статические переменные по умолчанию получают нулевые значения. Автоматические переменные, явным образом не инициализированные, содержат неопределенные значения («мусор”).

К любой переменной в объявлении может быть применен квалификатор const для указания того, что ее значение далее не будет изменяться.

Применительно к массиву квалификатор const указывает на то, что ни один из его элементов не будет меняться. Указание const можно также применять к аргументу- массиву, чтобы сообщить, что функция не изменяет этот массив:

Реакция на попытку изменить переменную, помеченную квалификатором const зависит от реализации компилятора.

2.5 Арифметические операторы

Бинарными (т. е. с двумя операндами) арифметическими операторами являются +, , *, /, а также оператор деления по модулю %. Деление целых сопровождается отбрасыванием дробной части, какой бы она ни была. Выражение


дает остаток от деления x на y и, следовательно, нуль, если x делится на y нацело. Например, год является високосным, если он делится на 4, но не делится на 100. Кроме того, год является високосным, если он делится на 400. Следовательно,

Оператор % к операндам типов float и double не применяется. В какую сторону (в сторону увеличения или уменьшения числа) будет усечена дробная часть при выполнении / и каким будет знак результата операции % с отрицательными операндами, зависит от машины.

Бинарные операторы + и имеют одинаковый приоритет, который ниже приоритета операторов *, / и %, который в свою очередь ниже приоритета унарных операторов + и . Арифметические операции одного приоритетного уровня выполняются слева направо.

В конце этой главы (параграф 2.12) приводится таблица 2.1,в которой представлены приоритеты всех операторов и очередность их выполнения.

2.6 Операторы отношения и логические операторы

Операторами отношения являются

Все они имеют одинаковый приоритет. Сразу за ними идет приоритет операторов сравнения на равенство:

Операторы отношения имеют более низкий приоритет, чем арифметические, поэтому выражение вроде i

2.7 Преобразования типов

Если операнды оператора принадлежат к разным типам, то они приводятся к некоторому общему типу. Приведение выполняется в соответствии с небольшим числом правил. Обычно автоматически производятся лишь те преобразования, которые без какой-либо потери информации превращают операнды с меньшим диапазоном значений в операнды с большим диапазоном, как, например, преобразование целого в число с плавающей точкой в выражении вроде f+i. Выражения, не имеющие смысла, например число с плавающей точкой в роли индекса, не допускаются. Выражения, в которых могла бы теряться информация (скажем, при присваивании длинных целых переменным более коротких типов или при присваивании значений с плавающей точкой целым переменным), могут повлечь за собой предупреждение, но они допустимы.

Значения типа char — это просто малые целые, и их можно свободно использовать в арифметических выражениях, что значительно облегчает всевозможные манипуляции с символами. В качестве примера приведем простенькую реализацию функции atoi, преобразующей последовательность цифр в ее числовой эквивалент.

Как мы уже говорили в главе 1, выражение

дает числовое значение символа, хранящегося в s[i], так как значения ‘0’, ‘1’ и пр. образуют непрерывную возрастающую последовательность.

Другой пример приведения char к int связан с функцией lower, которая одиночный символ из набора ASCII, если он является заглавной буквой, превращает в строчную. Если же символ не является заглавной буквой, lower его не изменяет.

В случае ASCII эта программа будет работать правильно, потому что между одноименными буквами верхнего и нижнего регистров — одинаковое расстояние (если их рассматривать как числовые значения). Кроме того, латинский алфавит — плотный, т. е. между буквами A и Z расположены только буквы. Для набора EBCDIC последнее условие не выполняется, и поэтому наша программа в этом случае будет преобразовывать не только буквы.

Стандартный заголовочный файл , описанный в приложении B, определяет семейство функций, которые позволяют проверять и преобразовывать символы независимо от символьного набора. Например, функция tolower(c) возвращает букву c в коде нижнего регистра, если она была в коде верхнего регистра, поэтому tolower — универсальная замена функции lower, рассмотренной выше. Аналогично проверку

Илон Маск рекомендует:  Как сделать кнопку внутри поля для поиска

можно заменить на isdigit(c)

Далее мы будем пользоваться функциями из .

Существует одна тонкость, касающаяся преобразования символов в целые числа: язык не определяет, являются ли переменные типа char знаковыми или беззнаковыми. При преобразовании char в int может ли когда- нибудь получиться отрицательное целое? На машинах с разной архитектурой ответы могут отличаться. На некоторых машинах значение типа char с единичным старшим битом будет превращено в отрицательное целое (посредством «распространения знака”). На других — преобразование char в int осуществляется добавлением нулей слева, и, таким образом, получаемое значение всегда положительно.

Гарантируется, что любой символ из стандартного набора печатаемых символов никогда не будет отрицательным числом, поэтому в выражениях такие символы всегда являются положительными операндами. Но произвольный восьмибитовый код в переменной типа char на одних машинах может быть отрицательным числом, а на других — положительным. Для совместимости переменные типа char, в которых хранятся несимвольные данные, следует специфицировать явно как signed или unsigned.

Отношения вроде i > j и логические выражения, перемежаемые операторами && и ||, определяют выражение-условие, которое имеет значение 1, если оно истинно, и 0, если ложно. Так, присваивание

установит d в значение 1, если c есть цифра, и 0 в противном случае. Однако функции, подобные isdigit, в качестве истины могут выдавать любое ненулевое значение. В местах проверок внутри if, while, for и пр. «истина” просто означает «не нуль”.

Неявные арифметические преобразования, как правило, осуществляются естественным образом. В общем случае, когда оператор вроде + или * с двумя операндами (бинарный оператор) имеет разнотипные операнды, прежде чем операция начнет выполняться, «низший” тип повышается до «высшего”. Результат будет иметь высший тип. В параграфе 6 приложения A правила преобразования сформулированы точно. Если же в выражении нет беззнаковых операндов, можно удовлетвориться следующим набором неформальных правил:

  • Если какой-либо из операндов принадлежит типу long double, то и другой приводится к long double.
  • В противном случае, если какой-либо из операндов принадлежит типу double, то и другой приводится к double.
  • В противном случае, если какой-либо из операндов принадлежит типу float, то и другой приводится к float.
  • В противном случае операнды типов char и short приводятся к int.
  • И наконец, если один из операндов типа long, то и другой приводится к long.

    Заметим, что операнды типа float не приводятся автоматически к типу double; в этом данная версия языка отличается от первоначальной. Вообще говоря, математические функции, аналогичные собранным в библиотеке , базируются на вычислениях с двойной точностью. В основном float используется для экономии памяти на больших массивах и не так часто — для ускорения счета на тех машинах, где арифметика с двойной точностью слишком дорога с точки зрения расхода времени и памяти.

    Правила преобразования усложняются с появлением операндов типа unsigned. Проблема в том, что сравнения знаковых и беззнаковых значений зависят от размеров целочисленных типов, которые на разных машинах могут отличаться. Предположим, что значение типа int занимает 16 битов, а значение типа long — 32 бита. Тогда -1L 1UL, так как -1L повышается до типа unsigned long и воспринимается как большое положительное число.

    Преобразования имеют место и при присвоениях: значение правой части присвоения приводится к типу левой части, который и является типом результата.

    Тип char превращается в int путем распространения знака или другим описанным выше способом.

    Тип long int преобразуются в short int или в значения типа char путем отбрасывания старших разрядов. Так, в

    значение c не изменится. Это справедливо независимо от того, распространяется знак при переводе char в int или нет. Однако, если изменить очередность присваиваний, возможна потеря информации.

    Если x принадлежит типу float, а i — типу int, то и x=i, и i=z вызовут преобразования, причем перевод float в int сопровождается отбрасыванием дробной части. Если double переводится во float, то значение либо округляется, либо обрезается; это зависит от реализации.

    Так как аргумент в вызове функции есть выражение, при передаче его функции также возможно преобразование типа. При отсутствии прототипа (функции аргументы тина char и short переводятся в int, a float — в double. Вот почему мы объявляли аргументы типа int или double даже тогда, когда в вызове функции использовали аргументы типа char или float.

    И наконец, для любого выражения можно явно («насильно”) указать преобразование его типа, используя унарный оператор, называемый приведением. Конструкция вида

    приводит выражение к указанному в скобках типу по перечисленным выше правилам. Смысл операции приведения можно представить себе так: выражение как бы присваивается некоторой переменной указанного типа, и эта переменная используется вместо всей конструкции. Например, библиотечная функция sqrt рассчитана на аргумент типа double и выдает чепуху, если ей подсунуть что-нибудь другое (sqrt описана в ). Поэтому, если n имеет целочисленный тип, мы можем написать

    и перед тем, как значение n будет передано функции, оно будет переведено в double. Заметим, что операция приведения всего лишь вырабатывает значение n указанного типа, но саму переменную n не затрагивает. Приоритет оператора приведения столь же высок, как и любого унарного оператора, что зафиксировано в таблице, помещенной в конце этой главы.

    В том случае, когда аргументы описаны в прототипе функции, как тому и следует быть, при вызове функции нужное преобразование выполняется автоматически. Так, при наличии прототипа функции sqrt:

    перед обращением к sqrt в присваивании

    целое 2 будет переведено в значение double 2.0 автоматически без явного указания операции приведения.

    Операцию приведения проиллюстрируем на переносимой версии генератора псевдослучайных чисел и функции, инициализирующей «семя”. И генератор, и функция входят в стандартную библиотеку.

    Упражнение 2.3. Напишите функцию htol(s), которая преобразует последовательность шестнадцатеричных цифр, начинающуюся с 0x или 0X, в соответствующее целое. Шестнадцатеричными цифрами являются символы 0. 9, a. f, А. F.

    2.8 Операторы инкремента и декремента

    В Си есть два необычных оператора, предназначенных для увеличения и уменьшения переменных. Оператор инкремента ++ добавляет 1 к своему операнду, а оператор декремента вычитает 1. Мы уже неоднократно использовали ++ для наращивания значения переменных, как, например, в

    Необычность операторов ++ и — в том, что их можно использовать и как префиксные (помещая перед переменной: ++n), и как постфиксные (помещая после переменной: n++) операторы. В обоих случаях значение n увеличивается на 1, но выражение ++n увеличивает n до того, как его значение будет использовано, а n++ — после того. Предположим, что n содержит 5, тогда

    установит x в значение 5, а

    установит x в значение 6. И в том и другом случае n станет равным 6. Операторы инкремента и декремента можно применять только к переменным. Выражения вроде (i+j)++ недопустимы.

    Если требуется только увеличить или уменьшить значение переменной (но не получить ее значение), как например

    то безразлично, какой оператор выбрать — префиксный или постфиксный. Но существуют ситуации, когда требуется оператор вполне определенного типа. Например, рассмотрим функцию squeeze(s, c), которая удаляет из строки s все символы, совпадающие с c:

    Каждый раз, когда встречается символ, отличный от c, он копируется в текущую j-ю позицию, и только после этого переменная j увеличивается на 1, подготавливаясь таким образом к приему следующего символа. Это в точности совпадает со следующими действиями:

    Другой пример — функция getline, которая нам известна по главе 1. Приведенную там запись

    можно переписать более компактно:

    В качестве третьего примера рассмотрим стандартную функцию strcat(s,t), которая строку t помещает в конец строки s. Предполагается, что в s достаточно места, чтобы разместить там суммарную строку. Мы написали strcat так, что она не возвращает никакого результата. На самом деле библиотечная strcat возвращает указатель на результирующую строку.

    При копировании очередного символа из t в s постфиксный оператор ++ применяется и к i, и к j, чтобы на каждом шаге цикла переменные i и j правильно отслеживали позиции перемещаемого символа.

    Упражнение 2.4. Напишите версию функции squeeze(s1,s2), которая удаляет из s1 все символы, встречающиеся в строке s2.

    Упражнение 2.5. Напишите функцию any(s1,s2), которая возвращает либо ту позицию в s1, где стоит первый символ, совпавший с любым из символов в s2, либо -1 (если ни один символ из s1 не совпадает с символами из s2). (Стандартная библиотечная функция strpbrk делает то же самое, но выдает не номер позиции символа, а указатель на символ.)

    2.9 Побитовые операторы

    В Си имеются шесть операторов для манипулирования с битами. Их можно применять только к целочисленным операндам, т. е. к операндам типов char, short, int и long, знаковым и беззнаковым.

    Оператор & (побитовое И) часто используется для обнуления некоторой группы разрядов. Например

    обнуляет в n все разряды, кроме младших семи.

    Оператор | (побитовое ИЛИ) применяют для установки разрядов; так,

    устанавливает единицы в тех разрядах x, которым соответствуют единицы в SET_ON.

    Оператор ^ (побитовое исключающее ИЛИ) в каждом разряде установит 1, если соответствующие разряды операндов имеют различные значения, и 0, когда они совпадают.

    Поразрядные операторы & и | следует отличать от логических операторов && и ||, которые при вычислении слева направо дают значение истинности. Например, если x равно 1, а y равно 2, то x & y даст нуль, а x && y — единицу.

    Операторы > сдвигают влево или вправо свой левый операнд на число битовых позиций, задаваемое правым операндом, который должен быть неотрицательным. Так, x > (р+1-n) сдвигает нужное нам поле к правому краю. Константа

    0 состоит из одних единиц, и ее сдвиг влево на n бит (

    2.10 Операторы и выражения присваивания

    в котором стоящая слева переменная повторяется и справа, можно написать в сжатом виде:

    Оператор +=, как и =, называется оператором присваивания.

    Большинству бинарных операторов (аналогичных + и имеющих левый и правый операнды) соответствуют операторы присваивания op=, где op — один из операторов

    с той лишь разницей, что выр1 вычисляется только один раз. Обратите внимание на скобки вокруг выр2:

    В качестве примера приведем функцию bitcount, подсчитывающую число единичных битов в своем аргументе целочисленного типа.

    Независимо от машины, на которой будет работать эта программа, объявление аргумента x как unsigned гарантирует, что при правом сдвиге освобождающиеся биты будут заполняться нулями, а не знаковым битом.

    Помимо краткости операторы присваивания обладают тем преимуществом, что они более соответствуют тому, как человек мыслит. Мы говорим «прибавить 2 к i» или «увеличить i на 2», а не «взять i, добавить 2 и затем вернуть результат в i», так что выражение i+=2 лучше, чем i=i+2. Кроме того, в сложных выражениях вроде

    благодаря оператору присваивания += запись становится более легкой для понимания, так как читателю при такой записи не потребуется старательно сравнивать два длинных выражения, совпадают ли они, или выяснять, почему они не совпадают. Следует иметь в виду и то, что подобные операторы присваивания могут помочь компилятору сгенерировать более эффективный код.

    Мы уже видели, что присваивание вырабатывает значение и может применяться внутри выражения: вот самый расхожий пример:

    В выражениях встречаются и другие операторы присваивания (+=, -= и т. д.), хотя и реже. Типом и значением любого выражения присваивания являются тип и значение его левого операнда после завершения присваивания.

    Упражнение 2.9. Применительно к числам, в представлении которых использован дополнительный код, выражение x &= (x-1) уничтожает самую правую 1 в x. Объясните, почему. Используйте это наблюдение при написании более быстрого варианта функции bitcount.

    2.11 Условные выражения

    пересылают в z большее из двух значений a и b. Условное выражение, написанное с помощью тернарного (т. е. имеющего три операнда) оператора «? : «, представляет собой другой способ записи этой и подобных ей конструкций. В выражении

    первым вычисляется выражение выр1. Если его значение не нуль (истина), то вычисляется выражение выр2, и значение этого выражения становится значением всего условного выражения. В противном случае вычисляется выражение выр3 и его значение становится значением условного выражения. Следует отметить, что из выражений выр2 и выр3 вычисляется только одно из них. Таким образом, чтобы установить в z большее из a и b, можно написать

    Следует заметить, что условное выражение и в самом деле является выражением, и его можно использовать в любом месте, где допускается выражение. Если выр2 и выр3 принадлежат разным типам, то тип результата определяется правилами преобразования, о которых шла речь в этой главе ранее. Например, если f имеет тип float, а n — тип int, то типом выражения

    будет float вне зависимости от того, положительно значение n или нет.


    Заключать в скобки первое выражение в условном выражении не обязательно, так как приоритет ?: очень низкий (более низкий приоритет имеет только присваивание), однако мы рекомендуем всегда это делать, поскольку благодаря обрамляющим скобкам условие в выражении лучше воспринимается.

    Условное выражение часто позволяет сократить программу. В качестве примера приведем цикл, обеспечивающий печать n элементов массива по 10 на каждой строке с одним про6елом между колонками; каждая строка цикла, включая последнюю, заканчивается символом новой строки:

    Символ новой строки посылается после каждого десятого и после n-го элемента. За всеми другими элементами следует пробел. Эта программа выглядит довольно замысловато, зато она более компактна, чем эквивалентная программа с использованием if-else. Вот еще один хороший пример :

    Упражнение 2.10. Напишите функцию lower, которая переводит большие буквы в малые, используя условное выражение (а не конструкцию if-else).

    2.12 Приоритет и очередность вычислений

    В таблице 2.1 показаны приоритеты и очередность вычислений всех операторов, включая и те, которые мы еще не рассматривали. Операторы, перечисленные на одной строке, имеют одинаковый приоритет: строки упорядочены по убыванию приоритетов; так, например, *, / и % имеют одинаковый приоритет, который выше, чем приоритет бинарных + и -. «Оператор” () относится к вызову функции. Операторы -> и . (точка) обеспечивают доступ к элементам структур; о них пойдет речь в главе 6, там же будет рассмотрен и оператор sizeof (размер объекта). Операторы * (косвенное обращение по указателю) и & (получение адреса объекта) обсуждаются в главе 5. Оператор «запятая” будет рассмотрен в главе 3.

    Таблица 2.1. Приоритеты и очередность вычислений операторов

    Операторы Выполняются
    () [] -> . слева направо
    ! ++ + * & (type) sizeof справа налево
    * / % слева направо
    + слева направо
    > слева направо
    >= слева направо
    == != слева направо
    & слева направо
    ^ слева направо
    | слева направо
    && слева направо
    || слева направо
    ?: справа налево
    = += -= *= /= %= &= ^= |= >= справа налево
    , слева направо

    Примечание. Унарные операторы +, , * и & имеют более высокий приоритет, чем те же бинарные операторы.

    Заметим, что приоритеты побитовых операторов &, ^ и | ниже, чем приоритет == и != , из-за чего в побитовых проверках, таких как

    чтобы получить правильный результат, приходится использовать скобки. Си подобно многим языкам не фиксирует очередность вычисления операндов оператора (за исключением &&, ||, ?: и ,). Например, в инструкции вида

    f может быть вычислена раньше g или наоборот. Из этого следует, что если одна из функций изменяет значение переменной, от которой зависит другая функция, то помещаемый в x результат может зависеть от очередности вычислений. Чтобы обеспечить нужную последовательность вычислений, промежуточные результаты можно запоминать во временных переменных.

    Очередность вычисления аргументов функции также не определена, поэтому на разных компиляторах

    может давать несовпадающие результаты. Результат вызова функции зависит от того, когда компилятор сгенерирует команды увеличения n — до или после обращения к power. Чтобы обезопасить себя от возможного побочного эффекта, достаточно написать

    Обращения к функциям, вложенные присвоения, инкрементные и декрементные операторы дают «побочный эффект”, проявляющийся в том, что при вычислении выражения значения некоторых переменных изменяются. В любом выражении с побочным эффектом может быть скрыта трудно просматриваемая зависимость результата выражения от очередности изменения значений переменных, входящих в выражение. В такой, например, типично неприятной ситуации

    возникает вопрос: массив a индексируется старым или измененным значением i? Компиляторы могут по-разному генерировать программу, что проявится в интерпретации данной записи. Стандарт сознательно устроен так, что большинство подобных вопросов оставлено на усмотрение компиляторов, так как лучший порядок вычислений определяется архитектурой машины. Стандартом только гарантируется, что все побочные эффекты при вычислении аргументов проявятся перед входом в функцию. Правда, в примере с printf это нам не поможет.

    Мораль такова: писать программы, зависящие от очередности вычислений, — плохая практика, какой бы язык вы ни использовали. Естественно, надо знать, чего следует избегать, но если вы не знаете, как образуются побочные эффекты на разных машинах, то лучше и не рассчитывать выиграть на особенностях частной реализации.

    Глава 2. Конструкции языка Perl

    Переменные, константы, выражения

    Общие сведения о переменных

    Поскольку в программе могут сосуществовать многие переменные, требуется способ, позволяющий обращаться к той или иной переменной. Таких способов два: имена и адреса.

    Для хранения значений переменные используют участки памяти (как правило, оперативной памяти). Таким образом, с переменной связывается адрес (номер самого первого байта переменной) и длина участка. Данные разных типов могут занимать участки разной длины. Поэтому во многих алгоритмических языках переменные различаются по типу данных, для хранения которых они предназначены. Такое явление называется типизацией. Другое предназначение типизации — определить перечень операций, которые допускаются над значениями. Например, для числовых данных разрешаются арифметические операции, для строковых — строковые операции, а для логических — логические.

    Приведём примеры, где могут встретиться массивы и структуры.

    Массив уместен для хранения квадратов первых десяти целых неотрицательных чисел. Тогда в ячейках (элементах) массива с индексами 0 , 1 , 2 , … , 9 будут храниться числа 0 , 1 , 4 , … , 81 . Во многих алгоритмических языках, в том числе в Perl, принята нумерация элементов массива, начиная с нуля, но в некоторых (Pascal) — с единицы.

    Таковы общие сведения о переменных в информатике. В последующих разделах будет рассказано, каковы особенности переменных в языке Perl.

    Переменные в Perl

    В языке Perl имеются и простые, и сложные переменные. Простые переменные ещё называются скалярными. Сложные переменные в Perl бывают двух видов — массивы и ассоциативные массивы ( хэши).

    Имена переменных, и простых, и сложных, могут состоять из букв, десятичных цифр и знака подчёркивания и не могут начинаться с цифры. Под буквами понимаются 26 букв английского алфавита, маленькие и большие.

    В программу на Perl можно включить инструкцию, которая расширит понятие буквы, после чего станет возможным включать в имена переменных буквы национальных алфавитов — русские, греческие, грузинские, армянские — вплоть до китайских иероглифов. Мы не приветствуем такую возможность, поскольку она противоречит традициям программирования. Мы считаем, что использование неанглийских букв в именах — mauvais ton .

    Заглавные и маленькие варианты буквы в именах считаются различными.

    Переменная в зависимости от своего вида получает знак отличия — значок перед своим именем. Для скалярных переменных это знак доллара $ ( Scalar [ˈskeılə] — $calar — скаляр). Для массивов это собака @ ( Array [əˈreı] — @rray — массив). Наконец, для ассоциативных массивов это знак процента % ( Hash [hæʃ] — %ash — хэш).

    Значки перед именами позволяют создавать одноимённые переменные разных видов: так, скалярная переменная $a не имеет ничего общего с переменной-массивом @a . Иными словами, в Perl имеются раздельные пространства имён для скаляров, массивов и ассоциативных массивов.

    Примечание

    В Perl имеются переменные, чьи имена не соответствуют приведённому правилу, поскольку включают не разрешённые символы или начинаются с цифры, например, $^O , или $0 , или $! . Это встроенные (специальные) переменные. Например, $^O содержит строку с названием операционной системы, в которой запущена программа (на моём компьютере это linux ). Переменная $0 содержит имя файла, содержащего текст исполняющейся программы. В переменную $! записывается текст сообщения о последней случившейся системной ошибке (к примеру, после попытки открыть несуществующий файл в переменной будет содержаться строка Нет такого файла или каталога , если система настроена под русский язык).

    Именование переменных (и не только переменных) — очень важный момент в программировании. Работающей программе всё равно, какие имена дал программист переменным или процедурам — важно лишь то, что различные сущности названы по-разному, а одинаковые — одинаково. Математик Давид Гильберт говорил:

    Справедливость аксиом и теорем ничуть не поколеблется, если мы заменим привычные термины «точка, прямая, плоскость» другими, столь же условными: «стул, стол, пивная кружка»!

    Однако представьте, какой вселенский хаос наступит, если сложение назвать вычитанием, а синус переименовать в тангенс! И в программировании нужно давать переменным, процедурам, классам, файлам с программами такие имена, которые отражают назначение соответствующего объекта.

    Часто случается так, что сущность переменной или процедуры получается выразить с использованием нескольких слов. Как составить имя из нескольких слов, если пробелы запрещены в именах? В разных языках программирования сложились определённые стили наименования объектов. В языке C наиболее распространён стиль, в котором отдельные слова в составе имени пишутся маленькими буквами и разделяются знаками подчёркивания. В языке Java знаки подчёркивания не вставляются, однако каждое слово, кроме первого, начинается с заглавной буквы. В языке Lisp, как и в C, слова в составе имени пишутся с маленькой буквы, но разделяются дефисом (дефис там разрешён в именах):

    Примечание
    язык примеры имён
    C line_count , draw_circle , open_file_for_reading
    Java lineCount , drawCircle , openFileForReading
    Lisp line-count , draw-circle , open-file-for-reading

    Мы предпочитаем стиль, принятый в Java (он называется camelCase) и будем последовательно использовать именно его в этой книге.

    Конечно, есть вещи и похуже.

    Какой бы стиль наименования ни использовал программист, правильно будет строго его придерживаться во всех программах. Трудно придумать что-то худшее, чем смешение различных стилей в программе.

    Скалярные переменные

    Скалярные переменные служат для хранения скалярных значений — чисел, строк, ссылок (о ссылках речь пойдёт в разделе «Ссылки»).

    Со скалярной переменной по большому счёту можно сделать две вещи: положить в неё на хранение скалярное значение или использовать хранящееся там значение. Первая операция, как мы уже упоминали, называется присваиванием. Присваивается значение переменной так:

    Знак равенства не должен нас обмануть: в языке Perl он означает не то, к чему мы привыкли в математике. Это обозначение для присваивания. В результате присваивания значение переменной, чьё имя указано слева от знака присваивания, становится равным значению выражения справа от знака.

    (звёздочка означает операцию умножения, так как значок, применяемый для умножения в математике, отсутствует на клавиатуре).

    Здесь следует подчеркнуть отличие равенства в математике и присваивания в информатике. Отношение равенства симметрично (утверждение x = y равносильно утверждению y = x ). В программировании это не так. Будет ужасной ошибкой написать в программе

    Слева от знака присваивания может стоять только переменная — нечто, чему можно присваивать значение.

    Кроме того, равенство x = x + 1 в математике никогда не выполняется. В случае присваивания, напротив, можно написать

    Между прочим, не только можно, но и зачастую нужно. Мы видим, что имя переменной здесь используется и справа от знака присваивания, в арифметическом выражении. Это вторая возможность использования переменной — для взятия хранящегося в ней значения. Смысл последнего присваивания — увеличение значения переменной $i на единицу.

    Если переменная, которой присваивается значение, не существовала, она молча создаётся. Если переменная уже использовалась, хранящееся в ней значение заменяется на новое.

    Цепочки присваиваний

    Любая команда в Perl — это выражение. Выполнение команды заключается в вычислении выражения. Присваивание не является исключением. Вычисляемым значением для присваивания является то, что присваивается.

    Этот факт позволяет делать цепочки присваиваний в случаях, когда требуется присвоить одно и то же значение сразу многим переменным:

    Если встречается цепочка присваиваний, они выполняются справа налево, как будто расставлены скобки:

    Значение выражения во внутренних скобках равно нулю (так как ноль присваивается переменной $z ), и оно присваивается переменной $y . Поэтому нулю будет равно и выражение во внешних скобках. Оно будет присвоено переменной $x .

    Списочное присваивание

    Есть возможность одной командой выполнить присваивания нескольких (не обязательно одинаковых) значений нескольким переменным. Нужно перечислить переменные через запятую в круглых скобках в левой части присваивания, а в правой точно так же перечислить предназначенные для присваивания значения:

    Такое списочное присваивание равносильно трём обычным:

    Иногда требуется обменять значения двух переменных. Пусть, к примеру, значения переменных $x и $y равны 2 и 3 соответственно. Наивное решение не сработает:

    Тут не обойтись без вспомогательной переменной $tmp , в которую предварительно запишем старое значение $x , а потом отправим в переменную $y :

    (имя $tmp происходит от английского temporary — временный; так часто называют переменные, которые нужны для однократного использования, как в нашем случае).

    Списочное присваивание избавляет нас от необходимости прибегать к вспомогательной переменной:

    Пока что мы иллюстрировали использование переменных на числовых примерах. Но переменные могут использоваться и для хранения строк. Строка — это конечная последовательность символов, то есть букв, цифр, знаков пунктуации и прочих значков. Одна и та же переменная может в разные моменты исполнения программы хранить то числа, то строки.

    Скалярные константы и выражения

    Константы в Perl бывают двух типов — числовые и строковые.

    Числа

    В Perl имеется несколько способов записи числовых констант:

    Обычная десятичная запись. В качестве разделителя целой и дробной части используется точка, а не запятая (так велит традиция английского языка):

    (в последнем примере нулевая целая часть числа не указана — это позволяется).

    Для очень больших или очень маленьких чисел оказывается удобной научная нотация:

    (в этих примерах показаны шестнадцатеричная, восьмеричная и двоичная запись одного и того же числа 54993153 ). Признаком шестнадцатеричной и двоичной записи являются приставки 0x и 0b , а восьмеричной — ведущий ноль.

    Текст будет позже.

    Строки

    Нужно понимать, что с точки зрения программы совершенно неважно, какое именно изображение у того или иного символа. Программа, работающая со строками, оперирует не изображениями символов, а их номерами. Поскольку все известные человечеству символы можно перенумеровать очень многими способами, есть проблема: одну и ту же строку (последовательность номеров символов) можно интерпретировать по-разному в зависимости от выбранного способа (от выбранной кодовой таблицы). Среди всевозможных способов перенумеровать символы имеется несколько стандартных, получивших широкое распространение. Однако отложим этот вопрос до лучших времён (см. раздел «Кодовые страницы»), а сейчас примем, что выбрана конкретная кодовая таблица, устанавливающая соответствие между символами и их номерами. Таким образом, строка представляет из себя что-то вроде массива целых неотрицательных чисел из ограниченного диапазона, но, в отличие от «настоящих» массивов языка Perl, о которых речь пойдёт в разделе «Массивы», размещается в памяти более компактно.

    Заключение строки в апострофы позволяет вводить в текст программы строковые константы (то есть неизменяемые, постоянные строки).

    Другой способ даёт возможность создавать строки, в которых есть изменяемая часть. Это строки в двойных кавычках » . Их использование почти такое же, что и использование апострофов, но есть отличия. Главное отличие состоит в том, что внутри таких строк происходит интерполяция переменных, то есть подстановка вместо имён переменных их значения.

    Поясним это явление на примере. Фрагмент программы

    напечатает строку Hello, cerebellum! , поскольку Perl, обнаружив между двойными кавычками имя скалярной переменной, подставит вместо имени значение. Впрочем, можно вполне обойтись и без двойных кавычек:

    Здесь мы соединяем (сцепляем) вместе две строки, константу ‘Hello, ‘ и строку в переменной $user , и печатаем командой print то, что получилось. Правда, так получается длинней, особенно если требуется поместить в строку несколько переменных, да и от кавычек и операторов конкатенации ( . ) рябит в глазах.

    Следующий пример иллюстрирует одну возможную неприятность во время интерполяции переменных:

    Вместо ожидаемой строки Total time: 3h 14m программа выведет

    Первые четыре предупреждения намекают нам, что переменные $hours , $minutes , $hoursh , $minutesm использованы только по одному разу, то есть без всякой пользы. Это, конечно, не криминал, но, как правило, свидетельствует об ошибке программирования (возможно, опечатке). Позвольте, а что это за переменные $hoursh , $minutesm ? Это результат близкого соседства имени переменной и единицы измерения времени внутри двойных кавычек. Perl видит «…$hoursh…» и пытается подставить вместо законного имени переменной $hoursh её значение. Но эта переменная упоминается здесь первый и последний раз, она ни разу не получала значение. Последние две жалобы как раз об этом. Откуда грамматическому анализатору знать, что имя подставляемой переменной, по нашему замыслу, $hours , а следующая буква h — это просто буква? Для борьбы с двусмысленностью поступаем так:


    Если после имён подставляемых переменных идёт символ, который запрещено использовать в именах, эта проблема не возникает.

    Другое затруднение возникает, если в строку в двойных кавычках требуется поместить знак доллара как таковой:

    Дело в том, что здесь выполняется нежелательная подстановка переменной $1 (да, это специальная переменная, и её имя не соответствует нашим канонам; она имеет отношение к регулярным выражениям, см. главу 30. «Регулярные выражения»). В данном случае были бы уместней апострофы:

    А можно «защитить» знак доллара, поставив перед ним наш любимый бэкслэш:

    Кстати, бэкслэш внутри строк в двойных кавычках открывает нам миллион новых возможностей. Сочетания этого знака со многими другими (не только \\ и \’ , как между апострофами) имеют особый смысл. Приведём таблицу, где перечисляются многие такие сочетания:

    комбинация значение
    \\ бэкслэш \
    \n символ конца строки
    \t символ табуляции
    \f символ конца страницы
    \e символ «Escape»
    \a символ «Bell», при печати на экран раздаётся гудок
    \x символ с заданным (в фигурных скобках) шестнадцатеричным номером, в данном случае ∰
    \N символ с заданным (в фигурных скобках) названием символа, в данном случае снова ∰

    Комбинации \x <…>и \N <…>бывают полезны, если символ неудобно или невозможно ввести в текст программы непосредственно, например, из-за отсутствия его на клавиатуре. Шестнадцатеричные номера и названия символов берутся из таблицы UCS .

    Помимо комбинаций, предназначенных для вставки символов, имеются комбинации особого назначения:

    комбинация значение
    \l делает следующий символ строчным (если это буква)
    \u делает следующий символ прописным (опять же если это буква)
    \L делает все последующие буквы строчными вплоть до ближайшего \E или же до конца строки
    \U делает все последующие буквы прописными вплоть до ближайшего \E или до конца строки
    \E обозначает конец действия команд \L и \U

    Спрашивается, а зачем могут понадобится эти команды? Почему бы не писать просто «Moscow» вместо «\umoscow» ? Конечно же полезными эти возможности становятся при использовании интерполяции переменных в «» -строках. Рассмотрим пример, в котором переменные $surname и $firstname содержат фамилию и имя, записанные целиком прописными буквами, а требуется вывести их в обычном формате (первая буква прописная, остальные — строчные):

    В Perl имеется конструкция, позаимствованная из командного языка операционной системы Linux . Это так называемые here-строки. Если в текст программы нужно поместить многострочный текст, удобно воспользоваться такой конструкцией:

    Поясним, что здесь происходит. Переменной $text присваивается строковое значение, которое занимает несколько строк. Вместо строки в правой части присваивания помещаются символы , за которыми следует маркер конца текста (в данном случае это __TEXT__ ). Само строковое значение считывается из последующих строк программы, пока не будет обнаружена строка программы, содержащая тот же самый маркер. Сам маркер при этом не становится частью строкового значения.

    Приведённый пример служит альтернативой следующего кода:

    Впрочем, если вам больше по душе последняя запись, пользуйтесь на здоровье.

    Для маркера можно выбрать любое имя, какое позволяется для имён переменных. Мы предпочитаем записывать маркеры заглавными буквами, обрамляя двойными знаками подчёркивания для лучшего зрительного выделения.

    Внутри -строк действуют те же правила, что и внутри «» -строк. Там точно так же производится интерполяция переменных и действуют комбинации, начинающиеся со знака бэкслэш:

    Этот пример показывает, что here-строки возможно использовать не только в правой части присваивания.

    Если требуется, чтобы внутри here-строк не производилась интерполяция переменных и обработка бэкслэш-комбинаций, заключим маркер в одиночные кавычки сразу после :

    Массивы

    Массивы в Perl — это упорядоченные списки скалярных значений (элементов). Значения в списке пронумерованы начиная с нуля. Номера (индексы) элементов, таким образом, принимают значения от 0 до n − 1 , где n — количество элементов в массиве.

    Создание массивов

    Создать массив в программе можно, перечислив явным образом его элементы. Список элементов заключается в круглые скобки, элементы разделяются запятой.

    Как показывает этот листинг, элементами массива могут быть как числа, так и строки.

    Ещё один способ создать массив — присвоить ему другое значение-массив:

    В результате такого присваивания получится массив @b — точная копия массива @a . Последующие изменения в массиве @b никак не отразятся на содержимом массива @a , и наоборот.

    Наконец, массив будет создан, если присвоить значение его отдельным элементам:

    Если массив @c не существовал, он будет создан, в нём будет шесть элементов. Все они, за исключением третьего и шестого, окажутся неопределёнными, а третий и шестой получат соответственно числовое и строковое значение. Иными словами, при присваивании значения ячейке, отсутствующей в массиве, он расширяется до нужного размера.

    Обратите внимание на знак $ в выражениях $c[2] и $c[5] . Хотя перед именем массива @c используется знак @ , здесь используется доллар в знак того, что мы имеем дело с отдельной ячейкой массива, содержащей скалярное значение.

    Отдельного разговора заслуживает создание массивов, заполненных идущими подряд целыми числами. Для построения таких массивов очень удобно использовать оператор последовательности .. :

    В результате такого присваивания массив будет заполнен первой сотней целых неотрицательных чисел. Между прочим, оператор .. позволяет создавать не только последовательности подряд идущих целых чисел, но и последовательности строк, упорядоченных сначала по длине, а затем в алфавитном порядке. В частности, список букв английского алфавита можно поместить в массив так:

    Определение размера массива

    Размер массива можно получить, использовав саму переменную-массив. Например, так:

    Имеется специальное обозначение для индекса последнего элемента массива. Для массива @a специальная переменная $#a содержит такой индекс. Для пустого массива значение этой переменной равно -1 . Переменную можно использовать и в левой части присваивания, если нужно явно укоротить или удлинить массив до нужной длины. Присваивание такой переменной значения -1 опустошает массив. Впрочем, того же результата можно добиться, присвоив массиву пустой список:

    Отрицательные индексы

    В Perl допускается обращение к элементам массива с отрицательными индексами. Индекс -1 указывает на последний элемент массива, -2 на предпоследний, и так далее. Таким образом, выражение $a [- 1 ] равносильно выражению $a [ $#a ] .

    Список слов в массиве

    Для людей ленивых, а также тех, которые не любят, когда от кавычек и запятых рябит в глазах, в Perl имеется оператор qw/…/ , позволяющий записывать короче массив строк. Пример с сокращёнными названиями дней недели можно было бы записать короче:

    Естественно, использование оператора qw/…/ ограничивается созданием массивов строк, чьи элементы не содержат пробелов, поскольку пробелы внутри оператора служат для разделения элементов. Если это необходимо для наглядности, можно в качестве разделителей использовать по нескольку пробелов подряд, или использовать вместо пробелов пробельные символы (например, символ табуляции или конца строки):

    Обращение к набору ячеек массива

    В отличие от многих других языков программирования, в Perl допустимо обращаться не только к отдельной ячейке массива, но и к целому набору ячеек. Например, скопировать из массива @a в массив @b ячейки с индексами 7 , 3 , 5 (именно в таком порядке) можно следующим образом:

    Мы не ошиблись. На этот раз перед именем массива @a , несмотря на последующие квадратные скобки, ставится именно @ , а не $ , поскольку выражение @a[7, 3, 5] даёт список скалярных значений.

    Выражения вида @a[…] , где в квадратных скобках указан список индексов, можно использовать и в левой части операции присваивания. Эта интересная возможность позволяет переставлять местами некоторые элементы массива без использования вспомогательных переменных. К примеру, поменять местами первый и последний элементы в массиве можно классическим способом

    Но можно сделать то же самое короче и яснее так:

    Команды для работы с массивами

    Команда shift ( shift [ʃıft] — сдвинуть) извлекает из массива самый первый элемент. При этом элемент из массива удаляется, а на его место сдвигаются его соседи справа. Команда unshift делает противоположное — добавляет в массив скалярное значение слева; при этом все элементы массива сдвигаются вправо. Аналогичные манипуляции с массивом осуществляют команды pop ( pop [pɔp] — вытолкнуть) и push ( push [puʃ] — втолкнуть), но только с правого конца массива:

    Команды unshift и push могут добавлять в массив (соответственно слева и справа) и по нескольку ячеек сразу.

    Реже используемая команда splice обобщает те возможности, которые предоставляются командами shift , pop , unshift , push . Она, во-первых, вырезает из массива кусок, начинающийся с заданного индекса и имеющий заданную длину, возвращая его. Во-вторых, при желании, на место вырезанной части вставляется новый список элементов.

    Чтобы прояснить поведение всех этих пяти команд, приведём таблицу эквивалентов:

    Удалить все элементы массива проще всего, присвоив ему пустой массив:

    Ассоциативные массивы

    Так же как и обычные массивы, ассоциативные массивы служат для хранения многих скалярных значений. В обычных массивах ключом доступа к отдельной ячейке (элементу) служит целое число — индекс. В ассоциативных массивах ключом является строка.

    В обычных массивах не может быть двух элементов с одинаковыми индексами. В ассоциативных массивах точно так же невозможны одинаковые ключи у двух элементов. Таким образом, ассоциативный массив представляет собой коллекцию пар «ключ — значение», в которой один и тот же ключ не может встречаться дважды.

    Создание ассоциативных массивов

    Ассоциативные массивы могут быть созданы присваиванием списка пар «ключ — значение» — массива, в котором чередуются ключи и значения:

    Элементы массива в правой части присваивания, имеющие чётные индексы, станут ключами в ассоциативном массиве, а следующие за ними элементы с нечётными индексами — соответствующими этим ключам значениями.

    Мы в вышеприведённом примере для наглядности разбили список в правой части присваивания на пары, разместив их на отдельных строках, хотя могли бы всё присваивание записать в одну строку или как-нибудь иначе. Для большей выразительности мы могли бы соединить вместе ключи и значения оператором => , оставив запятые как разделители пар:

    Конечно же остаётся возможность использовать оператор qw/…/ , если ни ключи, ни значения не содержат пробелов:

    Читателя, возможно, интересует: что будет, если ассоциативному массиву присваивается список нечётной длины? Ничего страшного не произойдёт — просто значение, соответствующее последнему ключу, останется неопределённым. А что если среди ключей (элементов с чётными индексами в массиве справа) встретятся одинаковые? И это не беда: каждый раз, когда повторно встречается какой-нибудь ключ, старое соответствующее ему значение заменяется новым.

    В обычном массиве кроме самих значений хранится также их порядок (все значения пронумерованы их индексами). Это обстоятельство позволяет мгновенно найти значение по индексу: место в памяти, где хранится нужное значение, легко определить с помощью простых арифметических операций, зная индекс и адрес начала массива. В ассоциативном массиве пары «ключ — значение» принципиально неупорядочены: они размещаются в памяти таким образом, чтобы поиск значения по ключу происходил бы как можно быстрее. Имеется возможность перебрать пары в ассоциативном массиве, однако не стоит ожидать, что они будут появляться при переборе в каком-нибудь определённом порядке (скажем, в алфавитном порядке ключей, или значений, или в порядке, в котором пары добавлялись в ассоциативный массив). Алгоритм, размещающий в памяти пары, может меняться от одной версии Perl к другой.

    Ассоциативные массивы можно присваивать:

    После присваивания ассоциативные массивы %i и %h не имеют никакой связи друг с другом, кроме того что содержат одно и то же множество пар, и могут в дальнейшем изменяться независимым образом.

    Доступ к элементам

    Отдельные элементы ассоциативного массива можно использовать в выражениях, в том числе для присваивания им значений:

    Точно так же, как и в случае обычных массивов, при обращении к одному элементу перед именем ассоциативного массива ставится значок доллара. После имени в фигурных скобках размещается ключ. Если ключ состоит только из латинских букв, цифр и знака подчёркивания, кавычки можно опустить. В следующем примере английские слова используются как ключи, а соответствующие им значения — их переводы на нидерландский язык:

    Если на момент присваивания значения ключ в ассоциативном массиве отсутствовал, он добавляется вместе с присваиваемым значением. Если же ключ был добавлен раньше, то соответствующее значение заменяется на новое.

    Если добавить значение в несуществующий ассоциативный массив, он тихо создаётся. Здесь ситуация такая же, как и обычными массивами.

    Обращение к набору элементов

    Подобно обычным массивам, ассоциативные массивы позволяют обратиться к набору элементов по списку ключей:

    Например, можно обменять значения, соответствующие двум ключам, при помощи параллельного присваивания без использования вспомогательных переменных:

    Команды для работы с ассоциативными массивами

    Команда keys позволяет получить список ключей из ассоциативного массива:

    После выполнения этого кода массив @names будет содержать строки ‘zero’ , ‘one’ , ‘two’ , ‘three’ в неизвестном порядке. Как мы уже упоминали, порядок, в котором хранятся пары ключ — значение в ассоциативном массиве, не определён, и полагаться на какой-то определённый порядок будет ошибкой. Если нужно работать с ключами или со значениями в ассоциативном массиве по порядку, потребуется сортировка, обсуждение которой мы отложили до главы 18. «Сортировка».

    Аналогичная команда values выдаёт список значений. После выполнения

    в массиве @numbers окажутся числа 0 , 1 , 2 и 3 , опять же в непредсказуемом порядке.

    Команда delete используется для удаления отдельного ключа или списка ключей. Вместе с ключом удаляется и связанное с ним значение. После выполнения

    в ассоциативном массиве останутся лишь пары ( zero => 0 , one => 1 , three => 3 ) , а затем, после выполнения

    останется лишь пара ( one => 1 ) .

    Можно опустошить ассоциативный массив %h вычурной командой

    Но короче и быстрее будет присвоить ассоциативному массиву пустой список:

    Глава 1 переменные, выражения, присваивания

    Отдельную группу операций в языке программирования Си составляют операции присваивания. Она производится над двумя операндами. Причем левый операнд может представлять только модифицируемое именованное выражение, например, переменную.

    Существует базовая операция присваивания = , которая позволяет присвоить значение правого операнда левому операнду:

    Выражение 2 + 5 представляет правый операнд, и его значение присваивается левому операнду.

    Стоит отметить, что тип значения правого операнда не всегда может совпадать с типом левого операнда. В этом случае компилятор пытается преобразовать значение правого операнда к типу левого операнда.

    Также можно выполнять множественное присваивание:

    Здесь сначала вычисляется значение выражения c = 34 +7 . Значение правого операнда — 34 +7 присваивается левому операнду с. То есть переменная c получает значение 41. Далее вычисляется выражение b = c : значение правого операнда c (41) присваивается левому операнду b . И в конце вычисляется выражение a = b : значение правого операнда b (41) присваивается левому операнду a .


    Все остальные операции присваивания являются сочетанием простой операции присваивания с другими операциями:

    += : присваивание после сложения. Присваивает левому операнду сумму левого и правого операндов: A += B эквивалентно A = A + B

    -= : присваивание после вычитания. Присваивает левому операнду разность левого и правого операндов: A -= B эквивалентно A = A — B

    *= : присваивание после умножения. Присваивает левому операнду произведение левого и правого операндов: A *= B эквивалентно A = A * B

    /= : присваивание после деления. Присваивает левому операнду частное левого и правого операндов: A /= B эквивалентно A = A / B

    %= : присваивание после деления по модулю. Присваивает левому операнду остаток от целочисленного деления левого операнда на правый: A %= B эквивалентно A = A % B

    : присваивание после сдвига разрядов влево. Присваивает левому операнду результат сдвига его битового представления влево на определенное количество разрядов, равное значению правого операнда: A эквивалентно A = A

    >>= : присваивание после сдвига разрядов вправо. Присваивает левому операнду результат сдвига его битового представления вправо на определенное количество разрядов, равное значению правого операнда: A >>= B эквивалентно A = A >> B

    &= : присваивание после поразрядной конъюнкции. Присваивает левому операнду результат поразрядной конъюнкции его битового представления с битовым представлением правого операнда: A &= B эквивалентно A = A & B

    |= : присваивание после поразрядной дизъюнкции. Присваивает левому операнду результат поразрядной дизъюнкции его битового представления с битовым представлением правого операнда: A |= B эквивалентно A = A | B

    ^= : присваивание после операции исключающего ИЛИ. Присваивает левому операнду результат операции исключающего ИЛИ его битового представления с битовым представлением правого операнда: A ^= B эквивалентно A = A ^ B

    Присваивание значений переменным

    Читайте также:

    1. В 2. Система обозначений в индексном анализе.
    2. Воздействие переменным магнитным полем
    3. Воздействие переменным электрическим полем
    4. Воздействие переменными (импульсными) токами
    5. Второй вопрос. Стадии развития значений слов. Методики образования искусственных понятий.
    6. Ескіз – кресленик, виконаний без дотримання масштабу і призначений для разового використання (ДСТУ 3321:2003).
    7. Запись значений в выходы
    8. Лекція №14. Визначений інтеграл
    9. Нахождение наибольшего и наименьшего значений функции, непрерывной на отрезке
    10. Определенное количество значений прогноза, которые необходимо получить.
    11. Отбор наибольших и наименьших значений
    12. Первісна функція та невизначений інтеграл. Основні поняття

    Совместимость целочисленных типов

    Большое количество доступных целочисленных типов дает возможность выбрать подходящий тип для каждой переменной. Часто несколько разных типов участвуют в одном и том же выражении, что может привести к ошибкам, связанным с несовмести­мостью типов.

    Некорректные присваивания могут принадлежать к одному из двух видов:

    · Исходная величина превышает верхний предел для типа назначения. Это назы­вается переполнением сверху (overflow). Например, попытка присваивания значения 300 переменной типа byte приведет к переполнению сверху.

    · Исходная величина меньше, чем нижний предел для типа назначения. Это назы­вается переполнением снизу (underflow). Например, попытка присваивания значения -40000 переменной типа short приведет к переполнению снизу.

    Рассмотрим пример использования различных типов в операторе присваивания.

    public class qqq

    public static void Main()

    При компиляции программа напишет, что невозможно конвертировать тип uint в int.

    Рассмотрим последовательность действий компилятора.

    В процессе компиляции, прежде чем программа станет фактически вы­полняться, компилятор не знает пределов величин, которые будут храниться в этих пе­ременных. Таким образом, поскольку “B” принадлежит к типу uint с диапазоном от 0 до 4294967295, она вполне может быть равной 4000000000. С другой сто­роны, переменная “A” имеет диапазон от -2147483648 до 2147483647 и, следовательно, не способна вместить значения 4000000000 из “B”. Резуль­татом стала бы потеря данных. Поэтому компилятор выдает сообщение об ошибке, несмотря на то, что в программе используется конкретное значение “B”, зна­чительно меньшее 2147483647.

    Если для переменной “A” вместо int выбрать uint, компилятор не выдаст ошибки, несмотря на наличие типа ushort справа и uint слева от операции присваивания. В этом случае происходит неявное преобразование (автоматически выполняемое ком­пилятором) типа ushort с диапазоном от 0 до 65535 в uint с большим диапазоном, поскольку при этом невозможна потеря данных.

    Следует отметить, что результат умножения в правой части оператора присваивания, все же, может превысить верхний предел (4294967295) для переменной слева. Это связано с тем, что компилятор рассматривает каж­дую переменную по отдельности и не учитывает возможный фактический результат вы­числения.

    Тема 3. Переменные, бинарные в языке программирования С#

    Переменная — это расположение в памяти объекта определенного типа. В приведенных выше примерах х, у, а, b, — переменные. Переменные могут иметь значения, которыми они проинициализированы, или эти значения могут быть изменены программно.

    Чтобы создать переменную, необходимо задать тип переменной, а затем дать этому типу имя. Можно проинициализировать переменную во время ее объявления или присвоить ей новое значение во время выполнения программы. С# требует определения значений переменных, то есть переменные перед использованием должны быть инициализированы. Нельзя использовать неинициализированную переменную в С#.

    Для объявления переменной используется следующий синтаксический блок:

    Для считывания в переменную ввода с клавиатуры используется следующий синтаксический блок:

    Если объявление переменной идёт непосредственно перед присвоением ей начального значения, эти две операции можно объединить:

    | следующая лекция ==>
    Идентификаторы | Операции сравнения и логические выражения

    Дата добавления: 2014-01-04 ; Просмотров: 316 ; Нарушение авторских прав? ;

    Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет

    Инструкции присваивания и выражения присваивания

    Ключевой момент: инструкция присваивания указывает значение для переменной. В Java инструкция присваивания может использоваться как выражение.

    Инструкция присваивания, оператор присваивания

    После объявления переменной, вы можете присвоить ей значения используя инструкцию присваивания. В Java знак равенства (=) используется как оператор присваивания. Синтаксис инструкции присваивания следующий:

    Выражение

    Выражение представляет собой числа, переменные и операторы, которые, взятые вместе, сводятся к определённому числу. Например, рассмотрим следующий код:

    В выражениях вы можете использовать переменные. Переменная также может использоваться с обоих сторон оператора =. Например:

    В этой инструкции присваивания, результат x + 1 присваивается x. Если перед выполнением инструкции x равен 1, тогда после выполнения инструкции он становится равным 2.

    Для присваивания значения переменной, вы должны разместить имя этой переменной слева от оператора присваивания. Таким образом, следующее утверждение неверно:

    Помните: в математике x = 2 * x + 1 означает уравнения. Тем не менее, в Java, x = 2 * x + 1 это инструкция присваивания, которая вычисляет выражение 2 * x + 1 и присваивает результат x.

    Выражение присваивания

    В Java, инструкция присваивания по существу является выражением, которое сводится к значению, присваиваемому левой части оператора присваивания. По этой причине инструкция присваивания также известна как выражение присваивания. Например, следующая инструкция является корректной:

    Если значение присваивается нескольким переменным, вы можете использовать следующий синтаксис:

    Помните: в инструкции присваивания, тип данных переменной в левой части должен быть совместимым с типом данных значения в правой. Например, int x = 1.0 будет неправильным, поскольку тип данных x это int (целые числа). Вы не можете присвоить значение double (1.0) к переменной int без смены типа. Смена типов будет представлена немного позже.

    Проверь себя:

    Найдите и исправьте ошибки в следующем коде:

    Глава 3. Оператор присваивания, ввод и вывод данных

    Оператор присваивания

    В результате выполнения оператора присваивания переменной, стоящей слева от него, присваивается значение выражения, стоящего справа от него. Обозначение оператора присваивания: двоеточие, за которым без разделителей следует равно :=.

    Синтаксис оператора присваивания:

    Левая и правая части оператора присваивания должны быть совместимы. Типы данных совместимы по оператору присваивания, если выполнены следующие условия:

    1) оба типа одинаковые;

    2) обе части имеют совместимые порядковые типы, при этом диапазон значений правой части попадает в диапазон возможных значений левой части;

    3) обе части вещественного типа, при этом диапазон значений правой части попадает в диапазон возможных значений левой части;

    4) левая часть имеет вещественный тип, а правая – целый;

    5) левая часть имеет строковый тип, а правая – символьный (char);

    6) обе части имеют совместимые множественные типы, при этом все значения правой части попадают в диапазон возможных значений левой части;

    7) обе части имеют совместимые типы указателей;

    8) правая частьимеет тип pchar, левая часть – строковая константа (при расширении синтаксиса директивой <$X+>);

    9) правая часть имееттип pchar, левая – символьный массив с нулевой базой вида array [0..X] ofchar (при расширении синтаксиса директивой <$X+>);

    10) обе части имеют совместимые процедурные типы;

    11) левая часть имеет процедурный тип, а правая – процедура или функция с идентичным типом результата и соответствующими параметрами.

    Рассмотрим порядок выполнения оператора присваивания. Сначала вычисляется значение выражения, стоящего справа от оператора присваивания. Затем результат заносится в ячейку памяти по адресу, который определяет имя переменной, стоящей слева от оператора присваивания.

    Пример. Задание значений переменных с помощью оператора присваивания.

    Ввод данных с клавиатуры

    Для ввода данных с клавиатуры в языке программирования Паскаль определены процедуры readиreadln (англ., read – читать, буквы ln – сокращение английского слова line – строка). Они позволяют вводить с клавиатуры данные целых, вещественных, символьного и строкового типов.

    Синтаксис процедур read и readln:

    В скобках через запятую перечисляются имена переменных, которым присвоятся введенные значения.

    При выполнении процедуры read исполнение программы останавливается и ожидается ввод данных с клавиатуры. Вводимые данные должны разделяться либо пробелами, либо переводом строки (нажатием клавиши Enter). Для завершения ввода данных нажимается клавиша Enter.

    Процедура readln после ввода всех значений осуществляет переход на новую строку, и следующий ввод данных будет выполняться с новой строки. В случае процедуры read следующий ввод данных будет выполняться с той же строки.

    Процедура readln без параметров просто ожидает нажатия клавиши Enter.

    Рассмотрим пример ввода данных. Пусть в программе определены переменные

    и программа содержит вызовы процедур

    read(x); //ввод одной переменной

    read(a,b,d); //ввод трех переменных

    readln; //ожидание нажатия клавиши Enter

    Допустим переменной x нужно задать значение 0,01, переменным a, b, d соответственно 1, 2, 5, переменной n значение 9. Для этого нужно ввести с клавиатуры через пробел

    Аналогичные результаты будут, если данные ввести, разделяя их переводом строки (нажатием клавиши Enter).

    При выполнении процедуры readln без параметров, программа остановится, и будет ожидать нажатия клавиши Enter.

    Рассмотрим порядок выполнения процедуры read. При нажатии на клавишу Enter данные заносятся в специальную область памяти, называемую буфером. Вначале данные представляются как список символов с разделителями. Далее символы преобразуются во внутреннее представление того типа данных, который имеет соответствующая им переменная. В конце, значения записываются в ячейку памяти, определяемую именем переменной.


    (При вводе символов и строк существуют особенности, которые в учебном пособии не рассматриваются.)

    Вывод данных на экран

    Для вывода данных на экран в языке программирования Паскаль определены процедуры write и writeln (англ., write – писать, буквы ln – сокращение английского слова line – строка). Они позволяют выводить на экран данные логических, целых, вещественных, символьного и строкового типов. При выводе данных происходит преобразования данных из внутреннего представления в символы, выводимые на экран.

    Синтаксис процедур writeиwriteln

    При выполнении процедуры write величины, указанные в списке вывода, выводятся на экран. Вывод осуществляется в одну строку. Процедура writeln после вывода всех значений осуществляет переход на новую строку, и следующий вывод данных будет выполняться с новой строки. Процедура writeln без параметров просто осуществляет переход на новую строку.

    В список вывода могут входить:

    1) имена переменных, в этом случае на экран выводятся значения переменных;

    2) вычислимые выражения, в этом случае сначала вычисляется значение выражения, а затем результат выводится на экран;

    3) строковые константы в апострофах (одинарные кавычки), которые выводятся на экран без изменений и используются в основном для пояснений.

    При отображении данных на экране под них отводится определенное число позиций. По умолчанию – это минимальное число позиций, необходимое для представления данных. Например, под вещественное число отводится 17 позиций, из них 10 – на дробную часть. На экране, внутри отведенных позиций, данные выравниваются по правому краю: если данные короче, то они сдвигаются к правому краю, если длиннее, количество позиций увеличивается до необходимых размеров.

    Если пользователя не устраивает число позиций на экране, отводимое под определенные данные, он может его изменить, т.е. задать формат отображения числа. Для целых чисел количество позиций указывается после названия переменной через двоеточие. Для вещественных чисел после названия переменной через двоеточие указывается количество позиций под целую часть, а затем через двоеточие – количество позиций под дробную часть числа.

    Рассмотрим несколько примеров вывода данных на экран. Пусть в программе определены переменные

    и в программе им присвоены следующие значения x:=0.01, a:=1, b:=2,n:=5,i:=1,flag:=true.

    Пример 1. Вывод на экран строковой константы. В результате выполнения оператора

    на экран выведется

    Пример 2. Вывод на экран значений переменных. В результате выполнения последовательности операторов

    //вывод на экран значения переменной x

    //вывод на экран значения переменной логического типа

    //вывод на экран значений двух переменных a и b с пояснениями

    на экран выведется

    а= 1.0000000000000000E+000 b= 2.0000000000000000E+000

    Пример 3. Вывод на экран значения вычислимого выражения. В результате выполнения оператора

    на экран выведется значение выражения cos(x)+sin(x)

    Пример 4. Результаты форматирования. В результате выполнения оператора

    на экран выведется

    а= 1.0000000000000000E+000 b=2.000 n=5 i= 1

    Рассмотрим несколько комплексных примеров на использование оператора присваивания, процедуры ввода данных с клавиатуры и процедуры вывода данных на экран.

    Пример 2.1. Даноa=–2, b=0,00005, c=100000.Записать a, b, cв экспоненциальной форме. Составить программу для вычисления значения выражения . Вывести значение на экран.

    programprog; //Заголовок программы
    const a=-2; b=5e-5; c=1e+5; //Описание констант
    vary:real; //Описание переменных
    begin //Начало программы
    <Основные вычисления>y:=(1+sqr(cos(pi-b)))/(a+exp(1/2*ln(c))+ln(abs(a)));
    writeln(‘y=’,y) //Вывод результата на экран
    end. //Конец программы

    Пример 2.2. Дано: , и – любые вещественные числа. Записать xв экспоненциальной форме. Составить программу для вычисления значения выражения , где . Вывести значения и на экран.

    programprog; //Заголовок программы
    constx=2e+2; //Описание констант
    var y,t,a,b:real; //Описание переменных
    begin //Начало программы
    writeln(‘Введите а, b’); //Вывод на экран подсказки
    read(a,b); //Ввод данных с клавиатуры
    t:=b*sin(x); y:=a*x+sqr(t); //Основные вычисления
    writeln(‘t=’,t, ‘y=’,y) //Вывод результата на экран
    end. //Конец программы

    Пример 2.3. Дано n=0,1241456, h – любое число. Составить программу для вычисления функций:

    var h:integer; a,b,c:real;

    Пример 2.4. Дан радиус круга. Вычислить длину окружности и площадь круга. Результаты вывести на экран.

    writeln (‘введитерадиус’); read(r);

    Контрольные вопросы

    1. Какой оператор в языке программирования Паскаль используется для задания значений переменных в программе?

    2. При каких условиях типы данных левой и правой частей оператора присваивания совместимы?

    3. Какая процедура в языке программирования Паскаль используется для ввода данных с клавиатуры?

    4. Замените последовательность процедур одной процедурой read(x), read(y), read(z).

    5. В чём заключается разница выполнения процедур read(список переменных), readln(список переменных) и readln?

    6. Какая процедура в языке программирования Паскаль используется для вывода данных на экран?

    7. Какие параметры могут входить в список вывода процедуры write?

    8. Замените последовательность процедур одной процедурой write(‘x=’),write(x),write(y).

    9. В чем заключается разница выполнения процедур write(список вывода), writeln(список вывода) и writeln?

    10. Для чего используется формат отображения чисел? Чем будут отличаться результаты вывода на экран вещественных чисел write(x) и write(x:4:2)?

    Рекомендуемая литература

    1. Павловская, Т.А. Паскаль. Программирование на языке высокого уровня / Т.А. Павловская. – СПб.: Питер, 2010. – 464 с.

    Поперечные профили набережных и береговой полосы: На городских территориях берегоукрепление проектируют с учетом технических и экономических требований, но особое значение придают эстетическим.

    Папиллярные узоры пальцев рук — маркер спортивных способностей: дерматоглифические признаки формируются на 3-5 месяце беременности, не изменяются в течение жизни.

    Механическое удерживание земляных масс: Механическое удерживание земляных масс на склоне обеспечивают контрфорсными сооружениями различных конструкций.

    Присваивание значения переменной

    Тип данных

    Описание

    8-разрядные (1 байт) числа без знака в диапазоне от 0 до 255. Тип данных можно использовать при анализе ASCII-кодов символов или простейших вычислениях, в том случае, если заранее известно, что результат не превысит значения 255. Например, с помощью переменной типа Byte можно хранить количество дней в месяце, поскольку максимальное значение не превышает числа 31.

    16-разрядные целые числа в интервале от -32768 до 32767. Числовой тип данных Integer часто используется для доступа к элементам массива или коллекции.

    32-разрядные целые числа (4 байта) в интервале от -2 147 483 648 до 2 147 483 647. Переменные этого типа позволяют сохранять результаты арифметических выражений, в которых используются достаточно большие целые числа. Например, тип данных Long может потребоваться при расчете больших простых чисел, чисел Фибоначчи, факториала числа и т.д.

    96-разрядные (12 байт) числа без знака. В дробной части записывает степень числа. При этом количество знаков после запятой может изменяться в интервале от 0 до 28. В переменных типа Decimal можно хранить сверхбольшие целые числа в интервале от -79*10 28 до 79*10 28 .

    64-разрядные числа (8 байт) с плавающей точкой двойной точности для работы с числами в интервалах от -1,798E+308 до -4,941E-324 для отрицательных значений и от 4,941E-324 до 1,798E+308 для положительных значений.

    Этот тип данных используется в тех случаях, когда необходима повышенная точность вычислений.

    32-разрядные (4 байта) числа с плавающей точкой в диапазоне от -3,403E38 до -1,401E-45 для отрицательных чисел и от 1,401E-45 до 3,403E38 для положительных чисел.

    Тип данных служит для хранения строковых значения переменной (до 2 миллиарда символов) или постоянной (64К символов) длины.

    Тип данных, позволяющий работать с календарными датами и временем. В памяти компьютера тип Date представляет собой 64-разрядное число с плавающей точкой, позволяющее хранить даты в диапазоне от 1 января 100 года до 32 декабря 9999 года и время в интервале от 0:00:00 до 23:59:59.

    16-разрядные числа, принимающие два значения True (все биты числа установлены в единицу, что соответствует -1) и False (все биты числа сброшены в ноль, что соответствует числу 0). Логические переменные используются при сравнении выражений, в условиях и некоторых видах циклов.

    Переменная для хранения ссылок на объекты Visual Basic и других приложений

    Позволяет хранить данные любых типов — числа, строки, даты и пустые значения.

    Объектный тип может быть разбит на типы-категории — формы, элементы, прин­теры и т. д.

    Для объявления новой переменной используется инструкция Dim, синтаксис которой таков:

    — допустимый тип данных.

    Например, следующая конструкция объявляет переменную V1:

    Dim V1 As Integer

    Тип переменной и соответственно конструкцию As можно опускать. В этом случае переменная является не типизированной. При одновременном объявлении нескольких переменных очень часто используется такая конструкция Dim A, B, C As Integer. Причем подразумевается, что все три переменные являются целыми. На самом деле это не так. Целой является лишь переменная C, а переменные B и C нетипизированы. Более правильный способ записи таков:

    Dim A As Integer, B As Integer, C As Integer

    Присваивание значения переменной

    Начальное значение переменной равно 0 для числовых типов данных и пустой строке «» для строковых значений. В большинстве случаев это значение вполне подходит условиям задачи. Так, можно составить программу суммирования строк массива A, не обнуляя значение переменной S:

    Dim S
    For I = 1 To 5
    S = S + A[I]
    Next

    Такая программа при исполнении не выдаст ошибки и правильно суммирует пять элементов массива. Но правила хорошего тона в программирования все-таки вынуждают перед использованием новой переменной присвоить ей начальное значение. К программе для суммирования элементов массива следует добавить еще одну строку:

    Dim S
    S = 0
    For I = 1 To 5
    S = S + A[I]
    Next

    Присвоить значение переменной можно двумя способами: в явной форме с помощью соответствующих инструкций языка Visual Basic for Application или в неявной форме, как, например, переменные цикла. В следующих примерах показаны различные способы присвоения значений переменным:

    · числовая переменная
    Dim Year As Integer
    Year = 2003

    · логическая переменная
    Dim IsTrue As Boolean
    IsTrue = True

    · переменная типа дата
    Dim BD As Date
    BD = #10/4/03#

    · расчет значения выражения
    B = (3*(3+4))/4

    · использование функций Visual Basic for Application
    S = InputBox(«Представьтесь, пожалуйста»)

    · начальное значение переменной равно 1, конечное — 5.
    For I = 1 to 5
    Debug.Print I
    Next

    · переменная I может использоваться и по завершении цикла

    Илон Маск рекомендует:  Как программно сделать eject для cd rom'a, zip'a
  • Понравилась статья? Поделиться с друзьями:
    Кодинг, CSS и SQL