Версия:
Аннотация
Что есть программирование. Откуда что берется.
Цель: Научится писать простейшие программы, которые могут вводить числа в консоли, выполнять арифметические действия, в частности, над введенными числами, сохранять промежуточный результат в переменные и выводить что-то в консоль, например, результат вычисления.
Внимание! Данная заметка является предварительной!
Раньше каждое устройство делалось с нуля... С увеличением количества входов увеличивалось в размерах само устройство. С точки зрения пользователя и раньше существовали по отдельности: калькулятор, портативный музыкальный проигрыватель, портативный (по размеру как крупный сотовый телефон) телевизор, устройство спутниковой навигации GPS и тому подобное. Сейчас за счет унификации узлов их эквивалент обеспечивается одним устройством – сотовым телефоном.
Как вычислить 2*3+5*7 на калькуляторе? Нужна память, а именно – сначала вычисляем 2*3 и сохраняем в памяти. Далее вычисляем 5*7, а потом прибавляем к этой величине сохраненное в памяти. Без памяти это выражение не вычислить.
Упражнение: придумайте арифметическое выражение, для вычисления которого потребуется две ячейки памяти.
Существует парадигма функционального программирования. Мы же фактически рассматриваем императивное программирование. В данном подходе необходимо указать последовательность действий, приводящих к достижению цели. Как следствие, необходима память для хранения промежуточных результатов.
Работающая программа – это программа, которая как-то о себе дала знать: чем-то мигнула, что-то включила или выключила и тому подобное. В противном случае отсутствовал бы смысл в запуске программы. Так, если она что-то и вычислила и уж тем более вычислила правильно, то пока она это не «покажет» пользователю, бессмысленно говорить о работе программы.
Первая программа В связи с выше описанным, простейшая программа – это программа, которая что-то выводит на «экран», а точнее в консоль. Поэтому традиционно программировать начинают со следующего примера программы:
Отмечу, что числа, расположенные слева от текста, не являются частью программы, а необходимы для удобства пояснения её устройства. Так, всюду далее при необходимости будет даваться ссылка на номера соответствующих строчек. Иногда возможно применение сокращения «стр.».
Пробелы, форматирование текста, в частности, отступы не влияют на работоспособность программы. Тем не менее, в случае нарушения принятого форматирования текста программы оная не будет зачтена.
Строчки 1-6 являются комментарием к программе. Они применяются для пояснения происходящего в программе человеку, читающего код твоей программы. Смысл комментария строчки 3 заключается в том, что текст комментария начинается с двойного символа косая черта («//») и не обязательно с начала строки (см. строчка 17).
Простейший вывод в консоль Написать программу на чистом Си, которая бы чего-то выводила, например, на экран невозможно. Необходим вспомогательный код, который обеспечивает связь программы с "реальным миром"(с операционной системой). Базовый набор такого рода вспомогательного кода находится в библиотеке stdio.h, название которой расшифровывается как standard input/output, т.е. стандартный ввод/вывод. Данная библиотека содержит вспомогательный код, отвечающий за ввод данных (например, чисел) в программу и вывод из программы текста, численного результата (тех же чисел). В частности, в строчке 17 вызывается вспомогательный код printf , который обеспечивает печать в консоль строчки указанной в соответствующих кавычках, например, как в "Hello world!".
Помимо ввода и вывода, при написании программ необходимо вызвать функции, которые в принципе можно написать самому, но на это может уйти много времени и, главное, усилий, что может привести к её провалу. В таких случаях также прибегают к вспомогательному коду из различных библиотек, например, для вычисления тригонометрических функций. Последнее означает, что в программах чуть посложнее строчек на подобии 8ой становится все больше и больше.
Блок действий Любая программа начинает свою работу с «блока» кода под названием main. Отмечу, что именно такие именные блоки кода (как в обсуждаемой программе) в языке Си называются функциями, так как в общем случае такие блоки имеют входные аргументы, которые указываются в скобках, и возвращают некий результат работы, где возвращаемый тип указывается перед названием функции. В общем случае данное обсуждение является предметом отдельной заметки.
В простейшем случае (как в рассматриваемой программе), функция состоит только из списка подряд идущих действий (в нашей первой программе см. строчки 17 и 20). Подчеркну, что каждое из действий в Си завершается точкой с запятой (;). При этом блок кода (состоит из списка действий) сам по себе не является действием, поэтому и не завершается этим символом.
Результат выполнения программы (в данном случае, единственной функции main) заключается в выполнении перечисленных действий в теле блока (см. стр. 16–22 ). Завершением (выходом из) функции считается выполнение действия return (по сути, возврат из функции её значения), которое возвращает вычисленное значения функции, т.е., в данном случае, результат выполненной работы.
В сложных функциях (т.е. речь идет не от sin, cos и тому подобное) принято возвращать отрицательное число в случае ошибки и неотрицательное число в случае успеха. Бывает, что величина самого значение характеризует дополнительную информацию. Например, объем успешно обработанных данных или причину возникновения ошибки. Ноль () возвращается в случае успеха, но без каких либо подробностей.
Контрольные упражнения Упражнение. Запусти указанную программу. Поиграйся с выводимым текстом. Размножь строчку 17, поизменяй текст, находящийся в кавычках.
Упражнение. Что произойдет, если убрать комбинацию «\n»? Что произойдет, если добавить «\n», «\t» или «\r» внутри/в конце текстовой строчки?
Выводить просто текст не интересно, тем более, что он фактически в точности повторяет то, что написано в самой программе. Нужно заставить компьютер «поработать», ведь именно в этом заключается его основной смысл. Например, сделать то, что человеку не всегда просто: выполнить некоторые арифметические вычисления.
Тип числа С точки зрения компьютера (точнее, процессора входящего в его состав) числа бывают целыми и вещественными. Указанные типы чисел преследуют разные цели: целые для счетчиков, т.е. целочисленного подсчета чего либо, например, степень многочлена, а вещественные для численных вычислений, т.е., в согласии с предыдущем, поиск корней многочлена.
Последнее оказало влияние и на язык Си, так, в нем вещественные числа имеют десятичную точку (именно точку, а не запятую, язык Си же не русифицирован): например,
и тому подобное, а целые – не имеют оную: например,
и так далее. Как будет ясно из ниже написанного, крайне важно отмеченные типы чисел не путать.
Над указанными числами доступны (встроены в сам язык Си, т.е. являются его частью) как минимум следующие стандартные арифметические операции: +, -, * и /. Сразу отмечу, что в отличии других языков программирования, в СИ отсутствует встроенная операция возведению числа в степень.
Если тип хотя бы одного из операндов (у каждой операции их два) – вещественное число, то второе преобразуется в вещественное. Последнее крайне важно, так как смысл отмеченных вычислительных операций зависит от типа операндов, при этом, численный результат может существенно различаться. Так, для вещественных чисел вычислительные операции +, -, * и / действуют в соответствие с общепринятыми математическими законами, а для целых имеется своя специфика.
В текущих заметках для обозначения операции вычисления выражения (т.е. приведения его к числовому значению) будет использоваться символ . Подчеркну, что данная операция не имеет отношение к языку Си. Она будет использоваться исключительно для пояснения сути происходящего в программе, а именно – для рассмотрения внутреннего устройства программы. В виду последнего, для следующей программы будет уместно прояснить, что , ровно как это и сделано в строчке 8 самого текста программы.
Вывод чисел в консоль Приведем пример программы, которая выводит (печатает) числа в консоль:
Печать вещественных чисел осуществляется комбинацией символов %f (см. 9), где %f от слова float (плавающая точка). Причем, число фактически вставляется в то место, где и находится эта самая комбинация символов (%f). Поясню, что при выполнении действия строчки 9, сначала вычисляется значение выражения , а уже потом вычисленное значение () вместе с самой строчкой («"Value %d\n"») передается в функцию printf, т.е. передается её управление, что приводит к печать указанной информации в консоли.
В выражениях вместо чисел можно использовать и математически функции (берущиеся, например, из библиотеки math.h, для этого нам и нужна строчка 3). Например, в выражении (см. строчку 13), сначала будет вычислено значение , далее оно будет подставлено в и вычислено ( квадратный корень из числа ), а потом и оно будет использовано (подставлено) в самом выражении. Система далее продолжит приводить выражение к числу (как в точности как в математике) ровно как и в прошлом (см. строчку 9) варианте. Такой способ вызова вспомогательного кода (функций) называется вызов по значению, т.е. сначала вычисляются значения всех аргументов функции, а уже потом к ним производится применение вспомогательного кода (вызов функции).
Вещественные числа Другие функции указаны в комментарии под строчкой 4. Отмечу, что, во-первых, все указанные функции выполняют действия над вещественными числами, т.е. и аргументы и возвращаемое значение имеет вещественный тип. Во-вторых, функции acos, atan и тому подобные являются обратными соответственно к функциям cos, tan, и, в-третьех, у всех тригонометрических функций (sin, asin, cos, tan и тому подобных) угол измеряется в радианах.
Функция возводит число в степень , т.е. . log, ln.
Целые числа При вычислениях с целыми числами имеется определенная тонкость, а именно – хоть первые 3 операции действуют ровно также как и для вещественных – в соответствие с ожиданием – (точнее они производятся в соответствующем кольце вычетов), последняя имеет особенность. Так, деление выполняется в целочисленной арифметике, т.е., например, , а . Для целых чисел доступно также и крайне важная и отличительная операция % – деление с остатком. Приведем примеры для прояснения сути:
В конце концов отметим, что печать целых чисел осуществляется комбинацией %d (см. строчку 17), где %d от слова decimal (число).
Контрольные упражнения Упражнение 1. Поиграйся с вещественным арифметическим выражением, а именно – замени выражение , используемое в программе, на собственное.
Упражнение 2. Поиграйся с целочисленным арифметическим выражением. Убедись в правильном понимании операции взятия остатка (%).
Упражнение 3. Воспользуйся отмеченными ранее математическими функциями. Вычисли длину гипотенузы, зная катет и угол.
Упражнение 4. Какую ошибку выдаст компилятор, если перепутать %d с %f и наоборот? Запомни выводимую ошибку на будущее.
Обсудим конструкцию языка Си, соответствующую памяти (как это было в примере с калькулятором). В языке Си памяти соответствует понятие переменной, причем, именной, дабы можно было указывать, о какой именно переменной идет речь. В отличии от некоторых других языков программирования, в Си перед тем как переменную можно будет использовать её нужно сначала создать (объявить). Замечу, что с точки зрения компьютера/процессора имен нет, есть адреса/индексы в памяти. Имена у ячеек памяти появляются благодаря языкам программирования.
Создание переменных Начнем с переменных по своему типу соответствующих обсуждаемым ранее вещественным и целым числам. Вещественным числам соответствует тип double (или float, имеющих меньший диапазон/точность), а целым – тип int.
Переменная объявляется (создается, т.е. выделяется память) следующей конструкцией (фрагмент кода):
После создания переменной её можно использовать, а именно – главное, что для переменных вводится операция присвоения, т.е. сохранение некой величины в переменную, и неявная операция считывания/извлечения значения из переменной. Для присвоения в языке Си используется операция .
Отмечу, что первоначального значения переменные не имеют. В конкретных реализациях (т.е. в компиляторе) обычно содержат мусор(произвольное числовое значение, но могут и 0). На конкретное значение рассчитывать не стоит. При вычислениях нарушение последнего может привести к странным итоговым значениям, а то и к принудительному (иначе, странному) завершению программы операционной системой.
Присвоение Для присвоения используется конструкция:
На любом шаге программы в переменную можно сохранить новое значение. Следовательно, в отличии от выкладок из математики, механики и др., бессмысленно говорить о значении переменной без указания номера шага хода выполнения программы. В принципе, можно построить график из значений переменных, где по вертикали значение, а по горизонтали номер шага. Забегая вперед можно уточнить, что в таком случае также нужно указывать и вычислительный блок, о котором идет речь. Просто в данной программе он пока один. Но подобные графики почти никогда явно не строятся.
Извлечение значения Если переменная используется в математическом выражении, то при вычислении используется значение ранее сохраненное в этой переменной. При применении оператора присвоение (), сначала вычисляется значение правой части, а потом результат присваивается левой. Поэтому одна и та же переменная может фигурировать и справа и с лева от оператора . При применении переменных в выражениях справа от оператора присвоения производится только извлечение самих значений.
Ввод Помимо вывода программа должна уметь вводить данные, т.е. в нашем случае числа. В противном случае, результат работы программы фактически неизменяемый и поэтому неинтересен. Более того, иначе результат можно было бы подтасовать...
Как выполнить ввод, а фактически – как присвоить значение переменной уже после запуска программы? Делается это посредством функции scanf:
Символ амперсант (&) перед переменной обязателен. Пока пускай это будет как элемент магии. Обращаю внимание на отличие от функции printf – комбинация «%d» используется как и ранее для целых чисел, а вот для вещественных теперь уже – «%lf».
Вывод Вывод можно делать достаточно сложным. Частично это уже было показано ранее. В частности, одним вызовом функции printf можно вывести не только значение больше одной переменной, но и ещё и сопутствующий текст. Следующий код показывает эквивалентность.
Первый аргумент функции printf – текстовая строка – называется форматной. Она указывает, какой текст необходимо вывести. Символ процент (%) является экскейпным, т.е. он не выводится на печать. Вместо этого он указывает на дополнительное действие, а именно – сюда нужно вставить значение соответствующей переменной из списка аргументов (после форматной строки). Последовательно идущие процентные комбинации символов заменяются на значения в соответствие с их порядком в списке аргументов.
Контрольные упражнения Упражнение. Напиши программу, которая по известной формуле что-либо считает, а именно – программа приветствует пользователя, запрашивает необходимые числа, вводит числа, выполняет некие вычисления и выводит результат.
Выжимка По итогам данной заметки теперь ты имеешь/знаешь как:
Эталонная программа Приведем в согласии с данной заметкой фрагмент эталонной программы: