Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Sb98333

.pdf
Скачиваний:
9
Добавлен:
13.02.2021
Размер:
371.01 Кб
Скачать

МИНОБРНАУКИ РОССИИ

–––––––——————————–––––––

Санкт-Петербургский государственный электротехнический университет «ЛЭТИ» им. В.И. Ульянова (Ленина)

————————————————————

Г.В.РАЗУМОВСКИЙ И.А.ХАХАЕВ

ОСНОВЫ ПРОГРАММИРОВАНИЯ НА ЯЗЫКЕ СИ

Учебно-методическое пособие

Санкт-Петербург Издательство СПбГЭТУ «ЛЭТИ»

2019

УДК 004.43(07) ББК 9 973.2-018.197

Р 17

Разумовский Г. В. Хахаев И. А.

Основы программирования на языке Си: учеб.-метод. пособие. СПб.: Издво СПбГЭТУ «ЛЭТИ», 2019. 32 с.

ISBN 978-5-7629-2524-2

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

Предназначено для студентов бакалавриата направления 09.03.01 «Информатика и вычислительная техника».

Рецензенты: кафедра «Информационные и вычислительные системы» ФГОУ ВО ПГУПС (д. т. н., проф. А.Д. Хомоненко); д .т. н., проф.

В.В. Езерский (СПб ГУАП).

УДК 004.43(07) ББК 9 973.2-018.197

Утверждено

редакционно-издательским советом университета в качестве учебно-методического пособия

ISBN 978-5-7629-2524-2

© СПбГЭТУ «ЛЭТИ» 2019

варианта локализации

ВВЕДЕНИЕ

Практические занятия являются одним из элементов учебного процесса, связанного с изучением языка программирования С (Си). На них студенты знакомятся с конструкциями языка и отлаживают программы в соответствии с указанным заданием. Занятия разбиты на темы, каждая из которых посвящена изучению одного понятия или конструкции языка Си. В описании каждой темы содержатся краткие сведения об элементах языка Си, примеры их использования и задания для написания программ. При составлении заданий частично использованы задачи из сборника задач Д. М. Златопольского [1].

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

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

Для написания и отладки программы студенты на своих компьютерах могут использовать любые операционные системы, редакторы и среды разработки. Однако для совместимости с программным обеспечением компьютерного класса рекомендуется использовать свободно распространяемую среду разработки Code::Blocks. Она может быть установлена с сайта www.codeblocks.org/download/. Версия для Windows, не требующая установки (-mingw-nosetup), распаковывается

вспециально созданную папку, а ее запуск обеспечивается файлом CbLauncher. Для упрощения работы с Code::Blocks можно в меню Панели инструментов отключить (снять «галочки») для всех панелей инструментов, кроме трех: Главная, Compiler и CodeCompletion. Далее в пункте главного меню Настройки в диалоге Компилятор... на вкладке Флаги компилятора следует включить два режима –

Создать отладочную информацию и Enable all common compiler warnings

(обязательно). Если предполагается вывод русского текста в консоль Code::Blocks, то необходимо при первом запуске программы в окне cb_console_runner в диалоге свойств установить шрифт LucidaConsole. Кроме того, в программе надо подключить заголовочный файл описания локализаций директивой препроцессора #include <locale.h> и в самом начале программы вызвать функцию установки

setlocale(LC_ALL,"russian").

ТЕМА 1. СТРУКТУРА ПРОГРАММЫ И ТИПЫ ДАННЫХ

Простейшая программа на языке Си состоит из набора директив препроцессора и определения главной функции main(). Наиболее часто используемой препроцессорной директивой является #include <name>, которая включает в текст программы заголовочный файл с именем name. Например, директивы #include <math.h> и #include <stdio.h> позволят использовать стандартные математические функции (квадратный корень, абсолютное значение, тригонометрические функции, возведение в степень и т.д.) и функции ввода-вывода без их определения в программе.

Точкой входа в программу является функция main(), которой передает управление операционная система компьютера. Ее описание имеет следующий вид

int main()

{

/* тело функции */ return 0;

}

Перед именем функции указывается тип возвращаемого значения (int), а в конце тела функции оператор return, в котором записывается это значение. Данная функция возвращает значение 0, что означает корректное завершение программы. Все ненулевые значения интерпретируются операционной системой как результат ошибочного завершения программы.

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

float.h.

Описание тела функции осуществляется в следующем порядке:

блок описания локальных переменных с указанием их типов и идентификаторов;

блок инициализации (присваивания начальных значений) переменных;

блок операторов (действий с переменными).

Для хорошей читаемости и понимания программы необходимо придерживаться стандарта оформления кода. Образцом оформления программ при выполнении заданий может стать набор соглашений, описанных в пособии А. В. Столя-

4

рова [2]. Далее приведен текст программы, в которой используются библиотечные функции ввода–вывода и математические функции.

#include <stdio.h> #include <math.h> #include <locale.h> int main()

{

setlocale(LC_ALL,"russian"); int n;

double q,pi,e; char c,b;

puts ("Введите символ: "); /* Вывод строки */ b=getchar();/* Ввод символа */

putchar(b); /* Вывод символа */

puts("Введите значения: целое, вещественное, символ"); /* Форматированный ввод и вывод данных */

scanf("%i %lf %c", &n, &q, &c); printf("Результаты обработки: %i %lf\n", c, n*q); pi=4*atan(1);

e=exp(1); printf("%lf\n", pi); printf("%lf\n", e); return 0;

}

В этой программе для ввода символа с клавиатуры и вывода его на экран используются соответственно функции getchar() и putchar(). Первая функция требует после выбора символа на клавиатуре нажатия клавиши Enter. Для вывода текста используется функция puts(). Ее аргументом является строка, заключенная в двойные кавычки (").

Форматированный ввод и вывод данных обеспечивают функции scanf() и printf(). Их параметрами являются управляющая строка, заключенная в двойные кавычки, и список вводимых или выводимых аргументов. Управляющая строка содержит спецификации форматов и используется для установления количества и типов аргументов. Каждая спецификация формата начинается со знака % и включает в себя код преобразования и управляющие символы. В рассматриваемом примере функция scanf() служит для ввода трех значений. В управляющей строке указываются, какие данные читаются, а в аргументах – куда они сохраняются. Первое значение является целым десятичным числом (спецификатор i) и записывается в переменную n, второе значение является числом с плавающей точкой двойной точности (спецификатор lf) и записывается в переменную q и третье значение является символом (спецификатор с) и записывается в переменную с. Элементы входного потока должны быть разделены пробелами, символами табуляции или разделителями строк. Такие символы, как запятая, точка с запятой и т.п. не распознаются в качестве разделителей. Аргументы функции scanf() должны быть адресами переменных. Для

5

этого перед именем переменной, в которую заносится значение, записывается символ &. Функция scanf() возвращает число, равное количеству аргументов, для которых успешно присвоены значения.

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

Форматированный вывод описывается по тем же правилам. Функция printf() использует управляющую строку, чтобы определить, сколько всего аргументов и каковы их типы. Аргументами могут быть переменные, константы, выражения, вызовы функций. Кроме спецификаторов формата в управляющую строку непосредственно может быть записан выводимый текст (в нашем примере Результаты обработки) и управляющие символы. Одним из таких символов является \n (переход на новую строку). Более подробную информацию о всех возможностях описания форматированного ввода–вывода можно найти в [3].

Использование математических функций в программе проиллюстрировано вычислением числа pi с помощью тригонометрической функции arctg (в библиотеке Си она имеет имя atan) и экспоненты (exp).

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

В Code::Blocks компиляция, сборка и запуск осуществляются при помощи кнопок в панели инструментов или с помощью соответствующих пунктов меню Сборка. Для сборки и запуска можно использовать также «горячие клавиши» CTRL+F9 (сборка без запуска) или F9 (сборка и запуск).

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

Задания по теме.

1. Минимальные и максимальные значения для чисел различных типов определены в заголовочных файлах limits.h и float.h. Используя корректные спецификаторы форматов для printf() и справочные сведения об этих заголо-

6

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

2.Проверить результат работы функции putchar(), если вместо одного символа при вводе с помощью getchar() набрать несколько букв или цифр.

3.Проверить поведение программы, если для переменной, получаемой с помощью getchar(), указан тип int, а не char.

4.Проверить вывод при инициализации аргумента функции putchar() значениями ´\74´ (восьмеричный код символа), 74 (десятичный код символа) и ´\x74´ (шестнадцатеричный код символа).

5.Размер памяти (в байтах), требуемой для любого типа данных или пере-

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

6.Проверить результат чтения переменной как символа, а вывода – как целого числа (использовать scanf() и printf()). Составить таблицу результатов для гласных букв английского языка.

7.Продумать способ и написать программу проверки «машинного нуля» при использовании различных математических и тригонометрических операций. Проверить программу для различных вариантов вещественных чисел

(float, double, longdouble).

8. Написать программу, которая считывает три произвольных вещественных числа и выводит их в поля шириной восемь позиций с тремя знаками после десятичной точки.

ТЕМА 2. УСЛОВНЫЙ ОПЕРАТОР И ОПЕРАТОР ВЫБОРА

Условный оператор (оператор ветвления) обеспечивает выполнение определенных действий при выполнении некоторых условий. При выполнении условия выполняется один набор действий, в противном случае – другой набор действий. Каждый набор действий может быть пустым (действия могут отсутствовать). Различные варианты использования условного оператора (if()) показаны ниже на примере решения задачи определения возможности пронести коробку (ящик) с размерами A × B × C см в дверь размерами M × N см (размеры задаются в сантиметрах).

#include <stdio.h> #include <locale.h> int main()

{

setlocale(LC_ALL,"russian");

7

int a,b,c; /* размеры ящика: ширина, высота, длина */ int m,n; /* размеры двери: ширина, высота */

int vnum; /* количество корректных значений */ int key; /* флаг */

int smax,smin; /* наибольший и наименьший размер двери */ key=0;

printf("Введите размеры ящика в см (a, b, c) через пробел: "); vnum=scanf("%d %d %d",&a,&b,&c);

key=vnum;

printf("Введите размеры двери в см (m, n) через пробел: "); vnum=scanf("%d %d",&m,&n);

key=key+vnum;

if(key==5) /* проверка правильности форматов ввода данных */

{

if(m>n) /* определение какой размер двери является наибольшим */

{

smax=m; /* ширина двери больше высоты*/ smin=n;

}

else if(m<n)

{

smax=n; /* ширина двери меньше высоты*/ smin=m;

}

else smax=smin=m; /* ширина и высота двери одинаковы*/ key=0;

if((a<smax)&&(b<smax)) key=1; /* стороны a и b меньше максимального размера */

if((b<smax)&&(c<smax)) key=1; /* стороны b и c меньше максимального размера */

if((a<smax)&&(c<smax)) key=1; /* стороны a и c меньше максимального размера */

if((a<smin)||(b<smin)||(c<smin)) key=key+1; /* одна из сторон меньше минимального размера */

if(key>1) puts("Удачно"); else puts("Неудачно...");

}

else puts("Ошибка при вводе данных! Попробуйте еще раз."); return 0;

}

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

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

8

должны быть меньше максимального размера двери и хотя бы один любой размер ящика должен быть меньше минимального размера двери.

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

Вусловиях могут выполняться одновременно несколько проверок, связанных логическими операциями «И» и «ИЛИ», а также использоваться знаки отношений: проверка на равенство == (два символа =), проверка на неравенство !=, меньше <, больше >, меньше или равно <=, больше или равно >= . Символы

&&означают логическую операцию «И», символы || – логическую операцию «ИЛИ», скобки обеспечивают правильный порядок действий.

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

При большом количестве проверок, а также для организации простейших меню при работе с программами, используется оператор выбора (множественного выбора) switch. Он сравнивает по порядку указанное значение с несколькими константами и выполняет блок операторов, где произошло совпадение.

Пример использования этого оператора:

#include <stdio.h> int main()

{

char ch;

puts("There are some options:"); puts("1 - to get help"); puts("2 - to run program");

puts("3 - to run alternate program"); puts("q - to exit program"); printf("Enter option: "); ch=getchar();

switch(ch)

{

case 0x31:

puts("Information about program"); break;

case 0x32:

puts("Program running...."); break;

case 0x33:

puts("Alternate program running..."); break;

case 0x71:

puts("Program finished!"); break;

default:

9

puts("Incorrect input! Please try again.");

}

return 0;

}

В данном примере проверяется, нажата ли одна из заданных клавиш. Эта проверка осуществляется по коду символа на клавише, указанному в кодировочной таблице ASCII. Если одна из таких клавиш нажата, появляется соответствующее сообщение. Команда break обеспечивает прекращение обработки ветви для оператора switch. Если не использовать break, то будут проверяться все последующие ветви. Операторы, следующие за меткой default, выполняются, когда не найдено ни одного совпадения.

Задания по теме.

1. Разработать алгоритм и программу решения квадратного уравнения (только вещественные корни) с проверкой на нулевое значение первого коэффициента. Для возведения в степень использовать функцию pow(), описанную в

math.h.

2.Разработать алгоритм и программу для решения задачи: Дано двухзначное число. Определить, входит ли в него цифра 5.

3.Разработать алгоритм и программу для решения задачи: Дано двухзначное число. Определить, входит ли в него произвольная заданная цифра.

4.Разработать алгоритм и программу для решения задачи: Траектория сна-

ряда, вылетающего из орудия под углом α с начальной скоростью v0, определя-

ется уравнениями x=v0·t·cos(α), y=v0·t·sin(α)-9.81·t2/2. Определить попадет ли снаряд в цель размером h, находящуюся в плоскости его полета на расстоянии R

ивысоте H.

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

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

7.Разработать алгоритм и программу для решения задачи: Даны вещественные положительные числа a, b, c, d. Выяснить, можно ли прямоугольник со сторонами a, b поместить в прямоугольник со сторонами c, d так, чтобы стороны одного прямоугольника были параллельны или перпендикулярны сторонам другого прямоугольника.

8.Разработать алгоритм и программу для решения задачи: Две прямые на

плоскости заданы значениями коэффициентов a1, b1, c1 и a2, b2, c2 (уравнение

10

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]