Обработка синтаксических ошибок



 

Каждому программисту известно, насколько легко при вводе текста программы в компьютер вносятся случайные ошибки (опечатки). К счастью, при попытке скомпилировать такую программу компилятор "просигналит" сообщением о наличии синтаксических ошибок . Большинство С++‑компиляторов попытаются "увидеть" смысл в исходном коде программы, независимо от того, что вы ввели. Поэтому сообщение об ошибке не всегда отражает истинную причину проблемы. Например, если в предыдущей программе случайно опустить открывающую фигурную скобку после имени функции main() , компилятор укажет в качестве источника ошибки инструкцию cout . Поэтому при получении сообщения об ошибке просмотрите две‑три строки кода, непосредственно предшествующих строке с "обнаруженной" ошибкой. Ведь иногда компилятор начинает "чуять недоброе" только через несколько строк после реального местоположения ошибки.

Многие С++‑компиляторы выдают в качестве результатов своей работы не только сообщения об ошибках, но и предупреждения (warning). В язык C++ "от рождения" заложено великодушное отношение к программисту, т.е. он позволяет программисту практически все, что корректно с точки зрения синтаксиса. Однако даже "всепрощающим" С++‑компиляторам некоторые синтаксически правильные вещи могут показаться подозрительными. В таких ситуациях и выдается предупреждение. Тогда программист сам должен оценить, насколько справедливы подозрения компилятора. Откровенно говоря, некоторые компиляторы слишком уж бдительны и предупреждают по поводу совершенно корректных инструкций. Кроме того, компиляторы позволяют использовать различные опции, которые могут информировать об интересующих вас вещах. Иногда такая информация имеет форму предупреждающего сообщения даже несмотря на отсутствие "состава" предупреждения. Программы, приведенные в этой книге, написаны в соответствии со стандартом C++ и при корректном вводе не должны генерировать никаких предупреждающих сообщений.

Важно! Большинство С++‑компиляторов предлагают несколько уровней сообщений (и предупреждений) об ошибках. В общем случае можно выбрать тип ошибок, о наличии которых вы хотели бы получать сообщения. Например, большинство компиляторов по желанию программиста могут информировать об использовании неэффективных конструкций или устаревших средств. Для примеров этой книги достаточно использовать обычную настройку компилятора. Но вам все же имеет смысл заглянуть в прилагаемую к компилятору документацию и поинтересоваться, какие возможности по управлению процессом компиляции есть в вашем распоряжении. Многие компиляторы довольно "интеллектуальны" и могут помочь в обнаружении неочевидных ошибок еще до того, как они перерастут в большие проблемы. Знание принципов, используемых компилятором при составлении отчета об ошибках, стоит затрат времени и усилий, которые потребуются от программиста на их освоение.

 

Вторая С++‑программа

 

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

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

 

 

Что же нового в этой программе? Во‑первых, инструкция:

 

 

объявляет переменную с именем х целочисленного типа. В C++ все переменные должны быть объявлены до их использования. В объявлении переменной помимо ее имени необходимо указать, значения какого типа она может хранить. Тем самым объявляется тип переменной. В данном случае переменная х может хранить целочисленные значения, т.е. целые числа, лежащие в диапазоне ‑32 768 ‑‑32 767 . В C++ для объявления переменной целочисленного типа достаточно поставить перед ее именем ключевое слово int . Таким образом, инструкция int х; объявляет переменную х типа int . Ниже вы узнаете, что C++ поддерживает широкий диапазон встроенных типов переменных. (Более того, C++ позволяет программисту определять собственные типы данных.)

Во‑вторых, при выполнении следующей инструкции переменной присваивается конкретное значение:

 

 

В C++ оператор присваивания представляется одиночным знаком равенства (= ). Его действие заключается в копировании значения, расположенного справа от оператора, в переменную, указанную слева от него. После выполнения этой инструкции присваивания переменная x будет содержать число 1023 .

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

 

 

В общем случае для отображения значения переменной достаточно в инструкции cout поместить ее имя справа от оператора "<<" . Поскольку в данном конкретном случае переменная x содержит число 1023 , то оно и будет отображено на экране. Прежде чем переходить к следующему разделу, попробуйте присвоить переменной х другие значения (в исходном коде) и посмотрите на результаты выполнения этой программы после внесения изменений.

 

Более реальный пример

 

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

 

 

Эта программа сначала отображает на экране сообщение, предлагающее пользователю ввести число для преобразования галлонов в литры, а затем ожидает до тех пор, пока оно не будет введено. (Помните, вы должны ввести целое число галлонов, т.е. число, не содержащее дробной части.) Затем программа отобразит значение, приблизительно равное эквивалентному объему, выраженному в литрах. В действительности для получения точного результата необходимо использовать коэффициент 3,7854 (т.е. в одном галлоне помещается 3,7854 литра), но поскольку в этом примере мы работаем с целочисленными переменными, то коэффициент преобразования округлен до 4 .

Обратите внимание на то, что две переменные gallons и liters объявляются после ключевого слова int в форме списка, элементы которого разделяются запятыми. В общем случае можно объявить любое количество переменных одного типа, разделив их запятыми. (В качестве альтернативного варианта можно использовать несколько декларативных int ‑инструкций – результат будет тот же.)

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

 

 

Здесь применяется еще один встроенный идентификатор – cin – предоставляемый С++‑компилятором. Он составлен из частей слов console input и в большинстве случаев означает ввод данных с клавиатуры. В качестве оператора ввода используется символ ">>" . При выполнении этой инструкции значение, введенное пользователем (которое в данном случае должно быть целочисленным), помещается в переменную, указанную с правой стороны от оператора ">>"  (в данном случае это переменная gallons ).

В этой программе заслуживает внимания и эта инструкция:

 

 

Здесь интересно то, что в одной инструкции использовано сразу два оператора вывода "<<". При ее выполнении сначала будет выведена строка "Литров: " , а за ней – значение переменной liters . В общем случае в одной инструкции Можно соединять любое количество операторов вывода, предварив каждый элемент вывода "своим" оператором

 

Новый тип данных

 

Несмотря на то что для приблизительных подсчетов вполне сгодится рассмотренная выше программа преобразования галлонов в литры, для получения более точных результатов ее необходимо переделать. Как отмечено выше, с помощью целочисленных типов данных невозможно представить значения с дробной частью. Для них нужно использовать один из типов данных с плавающей точкой, например double (двойной точности). Данные этого типа обычно находятся в диапазоне 1,7Е‑308 ‑‑1,7Е+308 . Операции, вы‑полняемые над числами с плавающей точкой, сохраняют любую дробную часть результата и, следовательно, обеспечивают более точное преобразование.

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

 

 

Для получения этого варианта в предыдущую программу было внесено два изменения. Во‑первых, переменные gallons и liters объявлены на этот раз с использованием типа double . Во‑вторых, коэффициент преобразования задан в виде числа 3.7854 , что позволяет получить более точные результаты. Если С++‑компилятор встречает число, содержащее десятичную точку, он автоматически воспринимает его как константу с плавающей точкой. Обратите также внимание на то, что инструкции cout и cin остались такими же, как в предыдущем варианте программы, в которой использовались переменные типа int . Это очень важный момент: С++‑система ввода‑вывода автоматически настраивается на тип данных, указанный в программе.

Скомпилируйте и выполните эту программу. На приглашение указать количество галлонов введите число 1 . В качестве результата программа должна отобразить 3,7854 литра.

 

Повторим пройденное

 

Итак, подытожим самое важное из уже прочитанного материала.

1. Каждая С++‑программа должна иметь функцию main() , которая означает начало выполнения программы.

2. Все переменные должны быть объявлены до их использования.

3. C++ поддерживает различные типы данных, включая целочисленные и с плавающей точкой.

4. Оператор вывода данных обозначается символом "<<" , а при использовании в инструкции cout он обеспечивает отображение информации на экране компьютера.

5. Оператор ввода данных обозначается символом ">>" , а при использовании в инструкции cin он считывает информацию с клавиатуры.

6. Выполнение программы завершается с окончанием функции main() .

 

Функции

 

Любая С++‑программа составляется из "строительных блоков", именуемых функциями. Функция – это подпрограмма, которая содержит одну или несколько С++‑инструкий и выполняет одну или несколько задач. Хороший стиль программирования на C++ предполагает, что каждая функция выполняет только одну задачу.

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

Функцииэто "строительные блоки" С++‑программы.

В C++ ни одна функция не может быть встроена в другую. В отличие от таких языков программирования, как Pascal, Modula‑2 и некоторых других, которые позволяют использование вложенных функций, в C++ все функции рассматриваются как отдельные компоненты. (Безусловно, одна функция может вызывать другую.)

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

В уже рассмотренных примерах программ функция main() была единственной. Как упоминалось выше, функция main() – первая функция, выполняемая при запуске программы. Ее должна содержать каждая С++‑программа. Вообще, функции, которые вам предстоит использовать, бывают двух типов. К первому типу относятся функции, написанные программистом (main() – пример функции такого типа). Функции другого типа находятся в стандартной библиотеке С++‑компилятора. (Стандартная библиотека будет рассмотрена ниже, а пока заметим, что она представляет собой коллекцию встроенных функций.) Как правило, С++‑программы содержат как функции, написанные программистом, так и функции, предоставляемые компилятором.

Поскольку функции образуют фундамент C++, займемся ими вплотную.

 

Программа с двумя функциями

 

Следующая программа содержит две функции: main() и myfunc() . Еще до выполнения этой программы (или чтения последующего описания) внимательно изучите ее текст и попытайтесь предугадать, что она должна отобразить на экране.

 

 

Программа работает следующим образом. Вызывается функция main() и выполняется ее первая cout ‑инструкция. Затем из функции main() вызывается функция myfunc() . Обратите внимание на то, как этот вызов реализуется в программе: указывается имя функции myfunc , за которым следуют пара круглых скобок и точка с запятой. Вызов любой функции представляет собой С++‑инструкцию и поэтому должен завершаться точкой с запятой. Затем функция myfunc() выполняет свою единственную cout ‑инструкцию и передает управление назад функции main() , причем той строке кода, которая расположена непосредственно за вызовом функции. Наконец, функция main() выполняет свою вторую cout ‑инструкцию, которая завершает всю программу. Итак, на экране мы должны увидеть такие результаты.

 

 

В этой программе необходимо рассмотреть следующую инструкцию.

 

 

Прототип объявляет функцию до ее первого использования.

Как отмечено в комментарии, это – прототип функции myfunc() . Хотя подробнее прототипы будут рассмотрена ниже, все же без кратких пояснений здесь не обойтись. Прототип функции объявляет функцию до ее определения. Прототип позволяет компилятору узнать тип значения, возвращаемого этой функцией, а также количество и тип парамeтров, которые она может иметь. Компилятору нужно знать эту информацию до первого вызова функции. Поэтому прототип располагается до функции main(). Единственной функцией, которая не требует прототипа, является main(), поскольку она встроена в язык C++.

Как видите, функция myfunc() не содержит инструкцию return . Ключевое слово void , которое предваряет как прототип, так и определение функции myfunc() , формально заявляет о том, что функция myfunc() не возвращает никакого значения. В C++ функции, не возвращающие значений, объявляются с использованием ключевого слова void .

 

Аргументы функций

 

Функции можно передать одно или несколько значений. Значение, передаваемое функции, называется аргументом . Несмотря на то что в программах, которые мы рассматривали до сих пор, ни одна из функций (ни main(), ни myfunc()) не принимала никаких значений, функции в C++ могут принимать один или несколько аргументов. Верхний предел числа принимаемых аргументов определяется конкретным компилятором. Согласно стандарту C++ он равен 256.

Аргументэто значение, передаваемое функции при вызове.

Рассмотрим короткую программу, которая для отображения абсолютного значения числа использует стандартную библиотечную (т.е. встроенную) функцию abs() . Эта функция принимает один аргумент, преобразует его в абсолютное значение и возвращает результат.

 

 

Здесь функции abs() в качестве аргумента передается число ‑10 . Функция abs() принимает этот аргумент при вызове и возвращает его абсолютное значение, которое в свою очередь передаётся инструкции cout для отображения на экране абсолютного значения числа ‑10 . Дело в том, что если функция является частью выражения, она автоматически вызывается для получения возвращаемого ею значения. В данном случае значение, возвращаемое функцией abs() , оказывается справа от оператора "<<" и поэтому законно отображается на экране.

Обратите также внимание на то, что рассматриваемая программа включает заголовок <cstdlib> . Этот заголовок необходим для обеспечения возможности вызова функции abs() . Каждый раз, когда вы используете библиотечную функцию, в программу необходимо включать соответствующий заголовок. Заголовок, помимо прочей информации, содержит прототип библиотечной функции.

Параметрэто определяемая функцией переменная, которая принимает передаваемый функции аргумент.

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

 

 

При каждом вызове функции mul() выполняется умножение значения, переданного параметру х , на значение, переданное параметру у . Однако помните, что х и у – это просто переменные, которые принимают значения, передаваемые при вызове функции.

Рассмотрим следующую короткую программу, которая демонстрирует использование функции mul() .

 

 

Эта программа выведет на экран числа 200 , 30 и 72 . При вызове функции mul() С++‑компилятор копирует значение каждого аргумента в соответствующий параметр. В данном случае при первом вызове функции mul() число 10 копируется в переменную х , а число 20 – в переменную у . При втором вызове 5 копируется в х , а 6 – в у . При третьем вызове 8 копируется в х , а 9 – в у .

Если вы никогда не работали с языком программирования, в котором разрешены параметризованные функции, описанный процесс может показаться несколько странным. Однако волноваться не стонт: по мере рассмотрения других С++‑программ принцип использования функций, их аргументов и параметров станет более понятным.

Узелок на память. Термин аргумент относится к значению, которое используется при вызове функции. Переменная, которая принимает этот аргумент, называется параметром. Функции, которые принимают аргументы, называются параметризованными функциями.

Если С++‑функции имеют два или больше аргументов, то они разделяются запятыми. В этой книге под термином список аргументов следует понимать аргументы, разделенные запятыми. Для рассмотренной выше функции mul() список аргументов выражен в виде x , у .

 


Дата добавления: 2018-09-22; просмотров: 268; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!