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

Для Symbian 11.04.2019
Для Symbian

Как вставить математические формулы на сайт?

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

Если же вы постоянно используете математические формулы на своем сайте, то я рекомендую вам использовать MathJax - специальную библиотеку JavaScript, которая отображает математические обозначения в веб-браузерах с использованием разметки MathML, LaTeX или ASCIIMathML.

Есть два способа, как начать использовать MathJax: (1) при помощи простого кода можно быстро подключить к вашему сайту скрипт MathJax, который будет в нужный момент автоматически подгружаться с удаленного сервера (список серверов ); (2) закачать скрипт MathJax с удаленного сервера на свой сервер и подключить ко всем страницам своего сайта. Второй способ - более более сложный и долгий - позволит ускорить загрузку страниц вашего сайта, и если родительский сервер MathJax по каким-то причинам станет временно недоступен, это никак не повлияет на ваш собственный сайт. Несмотря на эти преимущества, я выбрал первый способ, как более простой, быстрый и не требующий технических навыков. Следуйте моему примеру, и уже через 5 минут вы сможете использовать все возможности MathJax на своем сайте.

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

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

Подключить MathJax проще всего в Blogger или WordPress: в панели управления сайтом добавьте виджет, предназначенный для вставки стороннего кода JavaScript, скопируйте в него первый или второй вариант кода загрузки, представленного выше, и разместите виджет поближе к началу шаблона (кстати, это вовсе не обязательно, поскольку скрипт MathJax загружается асинхронно). Вот и все. Теперь изучите синтаксис разметки MathML, LaTeX и ASCIIMathML, и вы готовы вставлять математические формулы на веб-страницы своего сайта.

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

Итеративный алгоритм построения губки Менгера достаточно простой: исходный куб со стороной 1 делится плоскостями, параллельными его граням, на 27 равных кубов. Из него удаляются один центральный куб и 6 прилежащих к нему по граням кубов. Получается множество, состоящее из 20 оставшихся меньших кубов. Поступая так же с каждым из этих кубов, получим множество, состоящее уже из 400 меньших кубов. Продолжая этот процесс бесконечно, получим губку Менгера.

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

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

Определение 2. Прямая называется асимптотой графика функции, если расстояние от переменной точки М графика функции до этой прямой стремится к нулю при неограниченном удалении точки М от начала координат по какой-либо ветви графика функции.

Различают три вида асимптот: вертикальные, горизонтальные и наклонные.

Вертикальные асимптоты

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

Из определения следует, что прямая x = a является вертикальной асимптотой графика функции f (x ) , если выполняется хотя бы одно из условий:

При этом функция f (x ) может быть вообще не определена соответственно при x a и x a .

Замечание:

Пример 1. График функции y =lnx имеет вертикальную асимптоту x = 0 (т.е. совпадающую с осью Oy ) на границе области определения, так как предел функции при стремлении икса к нулю справа равен минус бесконечности:

(рис. сверху).

самостоятельно, а затем посмотреть решения

Пример 2. Найти асимптоты графика функции .

Пример 3. Найти асимптоты графика функции

Горизонтальные асимптоты

Если (предел функции при стремлении аргумента к плюс или минус бесконечности равен некоторому значению b ), то y = b горизонтальная асимптота кривой y = f (x ) (правая при иксе, стремящимся к плюс бесконечности, левая при иксе, стремящимся к минус бесконечности, и двусторонняя, если пределы при стремлении икса к плюс или минус бесконечности равны).

Пример 5. График функции

при a > 1 имеет левую горизонтальную асимпототу y = 0 (т.е. совпадающую с осью Ox ), так как предел функции при стремлении "икса" к минус бесконечности равен нулю:

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

Наклонные асимптоты

Вертикальные и горизонтальные асимптоты, которые мы рассмотрели выше, параллельны осям координат, поэтому для их построения нам требовалось лишь определённое число - точка на оси абсцисс или ординат, через которую проходит асимптота. Для наклонной асимптоты необходимо больше - угловой коэффициент k , который показывает угол наклона прямой, и свободный член b , который показывает, насколько прямая находится выше или ниже начала координат. Не успевшие забыть аналитическую геометрию, а из неё - уравнения прямой, заметят, что для наклонной асимптоты находят уравнение прямой с угловым коэффициентом . Существование наклонной асимптоты определяется следующей теоремой, на основании которой и находят названные только что коэффициенты.

Теорема. Для того, чтобы кривая y = f (x ) имела асимптоту y = kx + b , необходимо и достаточно, чтобы существовали конечные пределы k и b рассматриваемой функции при стремлении переменной x к плюс бесконечности и минус бесконечности:

(1)

(2)

Найденные таким образом числа k и b и являются коэффициентами наклонной асимптоты.

В первом случае (при стремлении икса к плюс бесконечности) получается правая наклонная асимптота, во втором (при стремлении икса к минус бесконечности) – левая. Правая наклонная асимптота изображена на рис. снизу.

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

При совпадении пределов при иксе, стремящемся к плюс бесконечности и к минус бесконечности прямая y = kx + b является двусторонней асимптотой кривой.

Если хотя бы один из пределов, определяющих асимптоту y = kx + b , не существует, то график функции не имеет наклонной асимптоты (но может иметь вертикальную).

Нетрудно видеть, что горизонтальная асимптота y = b является частным случаем наклонной y = kx + b при k = 0 .

Поэтому если в каком-либо направлении кривая имеет горизонтальную асимптоту, то в этом направлении нет наклонной, и наоборот.

Пример 6. Найти асимптоты графика функции

Решение. Функция определена на всей числовой прямой, кроме x = 0 , т.е.

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

Следовательно, x = 0 – вертикальная асимптота графика данной функции.

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

Выясним наличие наклонной асимптоты:

Получили конечные пределы k = 2 и b = 0 . Прямая y = 2x является двусторонней наклонной асимптотой графика данной функции (рис. внутри примера).

Пример 7. Найти асимптоты графика функции

Решение. Функция имеет одну точку разрыва x = −1 . Вычислим односторонние пределы и определим вид разрыва:

Заключение: x = −1 - точка разрыва второго рода, поэтому прямая x = −1 является вертикальной асимптотой графика данной функции.

Ищем наклонные асимптоты. Так как данная функция - дробно-рациональная, пределы при и при будут совпадать. Таким образом, находим коэффициенты для подстановки в уравнение прямой - наклонной асимптоты:

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

y = −3x + 5 .

На рисунке график функции обозначен бордовым цветом, а асимптоты - чёрным.

Пример 8. Найти асимптоты графика функции

Решение. Так как данная функция непрерывна, её график не имеет вертикальных асимптот. Ищем наклонные асимптоты:

.

Таким образом, график данной функции имеет асимптоту y = 0 при и не имеет асиптоты при .

Пример 9. Найти асимптоты графика функции

Решение. Сначала ищем вертикальные асимптоты. Для этого найдём область определения функции. Функция определена, когда выполняется неравенство и при этом . Знак переменной x совпадает со знаком . Поэтому рассмотрим эквивалентное неравенство . Из этого получаем область определения функции: . Вертикальная асимптота может быть только на границе области определения функции. Но x = 0 не может быть вертикальной асимптотой, так как функция определена при x = 0 .

Рассмотрим правосторонний предел при (левосторонний предел не существует):

.

Точка x = 2 - точка разрыва второго рода, поэтому прямая x = 2 - вертикальная асимптота графика данной функции.

Ищем наклонные асимптоты:

Итак, y = x + 1 - наклонная асимптота графика данной функции при . Ищем наклонную асимптоту при :

Итак, y = −x − 1 - наклонная асимптота при .

Пример 10. Найти асимптоты графика функции

Решение. Функция имеет область определения . Так как вертикальная асимптота графика этой функции может быть только на границе области определения, найдём односторонние пределы функции при .

Асимптотой графика функции y = f(x) называется прямая, обладающая тем свойством, что расстояние от точки (х, f(x)) до этой прямой стремится к нулю при неограниченном удалении точки графика от начала координат.

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

Нахождение асимптот графика основано на следующих трех теоремах.

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

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

Теорема о горизонтальной асимптоте. Пусть функция у = f(х) определена при достаточно больших х и существует конечный предел функции . Тогда прямая у = b есть горизонтальная асимптота графика функции.

Замечание. Если конечен только один из пределов , то функция имеет соответственно левостороннюю либо правостороннюю горизонтальную асимптоту.

В том случае, если , функция может иметь наклонную асимптоту.

Теорема о наклонной асимптоте. Пусть функция у = f(х) определена при достаточно больших х и существуют конечные пределы . Тогда прямая y = kx + b является наклонной асимптотой графика функции.

Без доказательства.

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

Исследование функций и построение их графиков обычно включает следующие этапы:

1. Найти область определения функции.

2. Исследовать функцию на четность-нечетность.

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

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

5. Найти экстремумы и интервалы монотонности функции.

6. Найти интервалы выпуклости функции и точки перегиба.

7. Найти точки пересечения с осями координат и, возможно, некоторые дополнительные точки, уточняющие график.

Дифференциал функции

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

Применим это теорему к дифференцируемой функции: .


Таким образом, приращение функции Dу состоит из двух слагаемых: 1) линейного относительно Dх, т.е. f `(x)Dх; 2) нелинейного относительно Dх, т.е. a(Dx)Dх. При этом, так как , это второе слагаемое представляет собой бесконечно малую более высокого порядка, чем Dх (при стремлении Dх к нулю оно стремится к нулю еще быстрее).

Дифференциалом функции называется главная, линейная относительно Dх часть приращения функции, равная произведению производной на приращение независимой переменной dy = f `(x)Dх.

Найдем дифференциал функции у = х.

Так как dy = f `(x)Dх = x`Dх = Dх, то dx = Dх, т.е. дифференциал независимой переменной равен приращению этой переменной.

Поэтому формулу для дифференциала функции можно записать в виде dy = f `(x)dх. Именно поэтому одно из обозначений производной представляет собой дробь dy/dх.

Геометрический смысл дифференциала проиллюстрирован
рисунком 3.11. Возьмем на графике функции y = f(x) произвольную точку М(х, у). Дадим аргументу х приращение Dх. Тогда функция y = f(x) получит приращение Dy = f(x + Dх) - f(x). Проведем касательную к графику функции в точке М, которая образует угол a с положительным направлением оси абсцисс, т.е. f `(x) = tg a. Из прямоугольного треугольника MKN
KN = MN*tg a = Dх*tg a = f `(x)Dх = dy.

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

Свойства дифференциала в основном аналогичны свойствам производной:

3. d(u ± v) = du ± dv.

4. d(uv) = v du + u dv.

5. d(u/v) = (v du - u dv)/v 2 .

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

Из определения дифференциала для функции y = f(x) дифференциал dy = f `(x)dх. Если эта функция y является сложной, т.е. y = f(u), где u = j(х), то y = f и f `(x) = f `(u)*u`. Тогда dy = f `(u)*u`dх. Но для функции
u = j(х) дифференциал du = u`dх. Отсюда dy = f `(u)*du.

Сравнивая между собой равенства dy = f `(x)dх и dy = f `(u)*du, убедимся, что формула дифференциала не изменяется, если вместо функции от независимой переменной х рассматривать функцию от зависимой переменной u. Это свойство дифференциала и получило название инвариантности (т.е. неизменности) формы (или формулы) дифференциала.

Однако в этих двух формулах все же есть различие: в первой из них дифференциал независимой переменной равен приращению этой переменной, т.е. dx = Dx, а во в торой дифференциал функции du есть лишь линейная часть приращения этой функции Du и только при малых Dх du » Du.

Кафедра: Автоматика и Информационные Технологии ОСНОВЫ С

Введение

Глава 1. Основы языка Си

1.1. Алфавит

1.2. Основные конструкции Си

1.3. Ввод-вывод.

1.3.1. Вывод

1.4. Базовые типы данных языка Си

1.4.1. Идентификаторы.

1.4.2. Типизированные константы

1.4.3. Переменные

1.4.3.1. Целые типы

1.4.3.2. Вещественные типы

1.4.3.3. Символьные типы

1.4.4. Тип данных строка

1.4.5. Структуры

1.4.5.1. Массивы

1.4.5.2. Записи

1.4.6 Область видимости и время жизни переменных

1.5. Основные операторы

1.6. Препроцессор

1.7. Программы. Функции

1.8. Указатели

1.9. Указатели и функции

1.10. Файлы

1.11. Дополнительные функции Си

1.11.1. Функции преобразования

Функции преобразования символьных строк: atoi(), atof(). 37с.

1.11.3. Функции, работающие со строками

1.12. Особенности программирования на языке Си

1.12.1. Модули. Многомодульное программирование

1.12.2 . Модели памяти

1.12.3 . Программирование в DOS и Windows

1.12.4 . Использование языка ассемблера в программах на Си

Глава 2. Примеры использования языка Си

2.1. Сортировка

2.2. Рекурсивные алгоритмы

2.3. Задача "Ханойские башни"

Глава 3. Основы С++

3.1. Отличия С++ от Си

3.2. Объектно-ориентированное программирование в С++

3.2.1. Классы

3.2.2. Перегрузка функций

3.2.3. Конструкторы

3.2.4. Деструкторы

3.2.5. Конструкторы с параметрами

3.2.6. Введение в наследование

3.2.7. Виртуальные функции

3.2.8. Указатели на объекты

Глава 4. Основы программирования на языке С++Builder

4.1. Характеристика С++Builder

4.2. Компоненты VCL. Свойства. События. Методы

4.2.1. Типы компонент

4.2.2. Иерархия классов VCL

4.3. Структура файлов в С++Builder

4.4. Визуальные компоненты(VCL)

4.5. Программы, управление событиями, исключения

4.6. Стратегия отладки Windows-программ

4.7. Использование компонент VCL в разработке программ

4.8. Графические компоненты.

4.9. Мультимедиа

4.10. Спрайтовая графика

4.11. Объектная технология OLE2

4.12. Библиотеки DLL.

4.13. Разработка визуальных компонент

4.14. Введение в программирование CGI

3.15. Программирование баз данных.

3.16. Пакеты

Заключение

Литература

Приложение N1


Введение

В 1804 году французский изобретатель Жозеф Мари Жаккар создал "программно-управляемый" ткацкий станок. Для управления станком использовались перфокарты, соединенные друг с другом в виде ленты. Деревянные шпильки "читающего устройства" станка по расположению отверстий в перфокарте определяли, какие нити следует поднять, а какие опустить для получения нужного узора.

В 1890 году в США изобретателем Германом Холлеритом разработана электромеханическая счетная машина - табулятор, управляемая перфокартами, была использована для составления таблиц с результатами переписи населения США. Основанная Холлеритом фирма по производству табуляторов впоследствии превратилась в корпорацию International Business Machines (IBM).

В 1936 году двадцатипятилетний студент Кембриджского университета англичанин Алан Тьюринг опубликовал статью "О вычислимых числах", в которой рассматривалось гипотетическое устройство ("машина Тьюринга"), пригодное для решения любой разрешимой математической или логической задачи, - прообраз программируемого компьютера.

В1941 году немецкий инженер Конрад Цузе построил действующий компьютер Z3, в котором использовалась двоичная система счисления. Программы записывались на перфоленте.

В 1945 году в высшем техническом училище Пенсильванского университета (США) физик Джон Мочли и инженер Проспер Экерт построили полностью электронную машину "Эниак". Для задания программы было необходимо вручную установить тысячи переключателей и воткнуть сотни штекеров в гнезда контактной панели.

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

21 июня 1948 года в Манчестерском университете (Великобритания) на машине "Марк-1" выполнена первая в мире хранимая в памяти машины программа - поиск наибольшего сомножителя заданного числа.

В 1949 году под руководством Мориса Уилкса создан компьютер "Эдсак". Проектировщики "Эдсака" ввели систему мнемонических обозначений, где каждая машинная команда представлялась одной заглавной буквой, и автоматизировали настройку подпрограмм на определенное место в памяти. Морис Уилкс назвал мнемоническую схему и библиотеку подпрограмм собирающей системой (assembly system) - отсюда слово "ассемблер".

В 1949 году в Филадельфии (США) под руководством Джона Мочли создан "Краткий код" - первый примитивный интерпретатор языка программирования.

В 1951 году в фирме Remington Rand американская программистка Грейс Хоппер разработала первую транслирующую программу. Хоппер назвала ее компилятором (compiler - компоновщик).

В 1957 году на 20-м этаже штаб-квартиры фирмы IBM на Мэдисон-авеню в Нью-Йорке родился язык Фортран (FORmula TRANslation - трансляция формул). Группой разработчиков руководил 30-летний математик Джон Бэкус. Фортран - первый из "настоящих" языков высокого уровня.

В 1972 году 31-летний специалист по системному программированию из фирмы Bell Labs Деннис Ритчи разработал язык программирования Си.

В 1984 году французский математик и саксофонист Филип Кан основывает фирму Borland International.

Первоначально Си был разработан как язык для программирования в операционной системе Unix.

Вскоре он стал распространяться для программистов-практиков. В конце 70-х были разработаны трансляторы Си для МикроЭВМ для операционной системой СР/M.

После появления IBM PC стали появляться и компиляторы Си (для этого компьютера их сейчас более 20).

В 1983 г. Американский Институт Стандартов (ANSI) сформировал Технический Комитет X3J11, для создания стандарта языка Си. Появившийся на рынке язык Си++ корпорации Borland подчиняется большинству требований стандарта.

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

Среди множества достоинств языка Си нужно отметить основные:


Универсальность (используется почти на всех существующих ЭВМ);

Компактность и универсальность кода;

Быстрота выполнения программ;

Гибкость языка;

Высокую структурированность.


Глава 1. Основы языка Си

1.1. Алфавит

Алфавит языка состоит из следующих символов:

Заглавные и строчные латинские буквы A-Z, a-z и символ подчеркивания. Цифр от 0 до 9. Специальных символов + - * / = >

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

Программа на Cи++ представляет собой последовательность ACSII-символов, представляющих собой ее исходный текст.

1.2. Основные конструкции Си

Рассмотрим простую программу печати на экране фразы "Привет от ЭВМ"

// программа

printf("Привет от ЭВМ ");

Рассмотрим структуру программы

Cи– программа
# Директивы препроцессора
Main
Операторы
Функция 1()
Операторы
Функция n ()
Операторы
Описания
Присваивания
Функции
Управления
Пустые

Команда #include подключает файл stdio.h к нашей программе. В файле содержится сведения о функциях ввода-вывода.

Файл с именем stdio.h содержит информацию о вводе-выводе.

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

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

После символов // стоят комментарии (для одной строки), (комментариями также называются символы, стоящие между /* и */).

Фигурные скобки {} отмечают начало и конец тела программы или функции. Они также применяются для объединения нескольких операторов программы в блок.

В строке printf ("Привет от ЭВМ ") содержится стандартная функция печати Си. Строка символов, заключенная в скобки (аргумент), является информацией, передаваемой функции printf() из нашей главной функции main(). Когда выполнение функции будет завершено, управление вернется обратно в исходную программу. Символ - обозначает перевод строки на новую строку после печати.

Рассмотрим следующий пример - написать программу перевода метров в сантиметры.

printf(" В %d М содержится %d cm ", I,J);

В данной программе определены две целочисленные переменные I и J.

Введена функция scanf("%d",&I); которая позволяет вводить десятичное число с клавиатуры и значение присвоить переменной I, далее по команде J=100*I; идет вычисление4.

Следующая строка printf(" В %d М содержится %d cm ", I,J); печатает фразу. На место первого %d (d- целая переменная) ставится значение I, на место второго %d ставится значение J.

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

Рассмотрим еще пример. Напишем функцию и вызовем ее из нашей программы.

printf("Вы меня вызывали? ");

printf("Я вызываю функцию supervisor. ");

printf("Да. Посмотрите, кто из студентов спит и разбудите их. ");

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

Я вызываю функцию supervisor.

Вы меня вызывали?

Да. Посмотрите, кто из студентов спит, и разбудите их.

1.3 Ввод-вывод Для решения задачи в какой-либо проблемной области необходимо написать программу, в которой должны быть команды, позволяющие: - выделять место для хранения данных;

Вводить исходные данных;

Обрабатывать исходные данные по алгоритму;

Выводить выходные данные.

Си содержит функции, необходимые для выполнения этих действий. Все функции будем рассматривать на примерах и начнем с функций ввода-вывода.

1.3.1. Вывод

Вывод осуществляется на экран, принтер, винчестер (гибкие диски), порт. Рассмотрим функции вывода на экран.

Функция printf предназначена для этой цели. Формат: printf([,аргумент1],...).

Формат - это строка в двойных кавычках, которая выводится на экран. Перед выводом printf заменяет все объекты в строке в соответствии со спецификациями аргумента. Например, printf(" В %d М содержится %d cm ", I,J); %d в строке формата - это спецификация аргумента.

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

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

- %d целое число;

- %u целое число без знака;

- %ld длинное целое число;

- %p значение указателя;

- %f число с плавающей точкой;

- %e число с плавающей точкой в экспоненциальной форме;

- %c cимвол;

- %s строка;

- %x целое в шестнадцатеричном формате.

Можно задать ширину поля, например %6d -поле шириной 6.

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

Для формата вещественных чисел можно указать дробную часть, например %8.4f - поле шириной 8, десятичная часть 4.

В конце форматной строки можно поставить знаки:

перевод строки;.

f (перевод формата или очистка экрана)

(табуляция)

xhhh (вставка символа c кодом ASCII hhh, где hhh содержит от 1 до 3 16-ричных цифр)

Для вывода можно использовать функции: puts и putchar.

Функция puts выводит строку на экран. Например:

puts("Привет, студент");

Функция putchar выводит на экран один символ.

1.3.2 Ввод

Ввод в Си в основном осуществляется с клавиатуры, из файла и порта.

Функция scanf аналогична printf. Ее формат: scanf([,аргумент1],...). В scanf используются те же спецификаторы формата, что и у функции printf. Необходимо отметить, что scanf имеет одну особенность: аргументы, следующие за строкой формата, должны быть адресами, а не значениями (это не распространяется на символьные переменные). Ранее в примерах мы видели, что при вводе целого числа записывалась функция следующим образом:

scanf("%d", &a);

& -операция адреса, которая передает scanf адреса.

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

scanf ("%d, %d", &a, &b);

Теперь можно вводить, например 23,56.

Имеются сложности с вводом строки символов из нескольких слов - введутся только данные до первого пробела. Для решения этой проблемы существует функция gets.

printf("Как вас зовут: ");

printf ("Привет, %s ", name);

Функция gets читает все, что набирается до тех пор, пока не нажат Ввод.

В С++ ввод-вывод может осуществляться не только с помощью функций, но и с помощью операций. Операция вывода >.

Формат вывода на экран:cout

Формат ввода с клавиатуры:cin

При использовании операций ввода-вывода необходимо включить в программу файл iostream.h.

Возможен ввод-вывод нескольких величин (через пробел).


1.4 Базовые типы данных Языка Си

1.4.1 Идентификаторы

Имена, которые присваиваются константам, типам данных, переменным и функциям называются идентификаторами. В Си следующие правила создания идентификаторов: должны начинаться с буквы (a...z,A...Z) или с подчеркивания (_), остальная часть идентификатора должна состоять из букв, подчеркиваний и/или цифр(0...9).

1.4.2 Типизированные константы

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

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

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

Константы представляются в виде целого десятичного, восьмиричного или шестнадцатиричного числа.

Описание констант начинается с ключевого слова const, далее тип и значение, например const int Nalog=2.

1.4.3 Переменные

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


1.4.3.1 Целые типы

Целые числа представляются целыми типами. Целый тип - это обобщенный тип, представление которого зависит от операционной системы и типа процессора.

Рассмотрим основные типы целых чисел:

Рассмотрим простой пример.

const int Nalog= 2;

Symma = Stavka * Nalog;

printf("Symma naloga = %d ",Symma);

В примере объявлены одна константа и две переменные целого типа.

1.4.3.2 Вещественные типы

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

В C++ существуют следующие основные типы вещественных чисел:

Рассмотрим следующий пример.

const float Nalog= 0.7;

Symma = Stavka * Nalog;

printf("Symma naloga = %8.4f ",Symma);

В данном примере вещественный тип представлен переменной Symma.

1.4.3.3 Символьные типы

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

Рассмотрим пример:

printf("A= %c B= %c ",A,B);

printf("C= %c ",C);

В данном примере переменной A присвоено значение ‘D^, переменной B значение ‘!^, а переменной С присвоено значение символа ‘*^.

1.4.4 Тип данных строка

Для представления строки символов в Си используют массивы типа char.

Рассмотрим пример.

char A; /* длина может быть до 256 символов */

strcpy(A,"IBM PC Pentium");

strcpy(B,"Windows 95");

strcpy(C,""); /* очистка переменной */ printf("A= %s ",A);

printf("B= %s ",B);

printf("C= %s ",C);

В данном примере представлены три строки символов A, B, C.

По команде, например, strcpy (A,"IBM PC Pentium"); в строку A помещается текст IBM PC Pentium.

Кроме рассмотренного примера, для определения строк можно использовать указатель на символы. Пример:

msg = "Привет, студент";

Звездочка перед msg означает, что msg является указателем на символ - т.е. msg может хранить адрес символа. Однако, при этом память для размещения символов не выделяется.

Команда msg = "Привет, студент " присваивает начальный адрес этой строки - (адрес символа П) переменной msg. Команда puts(msg) печатает символы до тех пор, пока она не встретит нулевой символ, обозначающий конец строки..

1.4.5 Структуры

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

1.4.5.1 Массивы

Именованная совокупность однородных данных называется массивом. Каждый элемент массива хранится в отдельной области памяти и имеет собственный номер (начиная с нуля).

Рассмотрим пример.

B = 10; B = 20; B = 30;

printf("B= %d ",B);

printf("B= %d ",B);

printf("B= %d ",B);

printf("B= %d ",B);

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

Существуют многомерные массивы, например:

Массив A -двумерный массив (состоит из четырех строк и трех столбцов):

Массив A - четырехмерный массив.

Рассмотрим пример работы с двумерным массивом.

B = 1.2; B = 1.3;

printf("B= %4.2f B= %4.2f B= %4.2f ", B,B,B);

printf("B= %4.2f B= %4.2f B= %4.2f ", B,B,B);

1.4.5.2 Записи

В отличие от массивов запись позволяет хранить данные различных типов. Запись начинается после ключевого слова struct. Рассмотрим пример - в записи хранится информация о студентах: фамилия, год рождения, номер группы.

typedef struct A {

strcpy(B.Fio,"Ivanow G.I."); B.God = 1977;

printf("Fio = %s ",B.Fio);

printf("God = %d ",B.God);

В рассмотренном примере запись имеет следующую структуру:

struct A { /* A имя записи} */

char Fio; /* 1 поле записи */

int God; /* 2 поле записи */

С помощью ключа typedef структурам дается имя.

Пример можно переписать следующим образом.

typedef struct {

strcpy(B.Fio,"Ivanow G.I.");

printf("Fio = %s ",B.Fio);

printf("God = %d ",B.God);

printf("Gruppa = %d ",B.Gruppa);

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

typedef struct A {

WGruppa.God = 1977;

WGruppa.Gruppa = 384;

WGruppa.God = 1978;

WGruppa.Gruppa = 384;

printf("Fio2 = %s ",WGruppa.Fio);

printf("God2 = %d ",WGruppa.God);

printf("Gruppa2 = %d ",WGruppa.Gruppa);

Первоначально мы определили структуру A, а затем использовали ее при объявлении структуры WGruppa, как массива состоящего из 12 записей структуры B.

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

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

typedef struct Adress {

char Street_Nd_Kw; };

typedef struct A {

Adress D_addr; };

strcpy(WGruppa.Fio,"Ivanow G.I.");

WGruppa.God = 1977;

WGruppa.Gruppa = 384;

strcpy(WGruppa.D_addr.City,"Shadrinsk"); strcpy(WGruppa.D_addr.Street_Nd_Kw,"Lenina 10 kw.1");

strcpy(WGruppa.Fio,"Petrow R.G.");

WGruppa.God = 1978;

WGruppa.Gruppa = 384;

strcpy(WGruppa.D_addr.City,"Kataisk"); strcpy(WGruppa.D_addr.Street_Nd_Kw,"Akulowa 1 kw.2");

printf("Fio1 = %s ",WGruppa.Fio);

printf("God1 = %d ",WGruppa.God);

printf("Gruppa1 = %d ",WGruppa.Gruppa);

printf("City= %s ",WGruppa.D_addr.City);

printf("Fio2 = %s ",WGruppa.Fio);

printf("God2 = %d ",WGruppa.God);

printf("Gruppa2 = %d ",WGruppa.Gruppa);

printf("City= %s ",WGruppa.D_addr.City);

printf("Street= %s ",WGruppa.D_addr.Street_Nd_Kw);

1.4.6 Область видимости и время жизни переменных

По области видимости переменные в Си можно разделить на три группы:

1.Переменная, определенная во всех модулях (файлах) программы. Такая переменная определяется при помощи ключевого слова extern. Эта переменная будет видна во всех точках программы. Такая переменная является глобальной для всей программы.

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

3.Переменная определенная в данной функции. Эта переменная может быть использована только в пределах данной функции. Такую переменную мы будем называть локальной.

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

1.Переменные живущие в течении работы программы.

2.Переменные уничтожающиеся после выхода из функции.

Глобальные переменные относятся к первому типу по времени жизни. Локальные переменные уничтожаются по выходу из функции. В том случае, когда мы хотим сделать локальную переменную долгоживущей используется слово static. Локальные переменные имеющие такой тип живут начиная с момента первого вызова функции и до конца работы программы. Однако в смысле видимости эти переменные остаются локальными. Запись static int i=0; Означает, что переменная инициализируется нулем при первом входе в функцию, но при последующих входах в функцию ее значение сохраняется в зависимости от тех действий, которые над ней были произведены.

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

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

1.5 Основные операторы

Операция присваивания.

Самой общей операцией является присваивание, например, с= a/b. В Си присваивание обозначается знаком равенства=, при этом значение справа от знака равенства присваивается переменной слева. Возможно, применять также последовательные присваивания, например: с = a = b.

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

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

1.Бинарные: сложение(+), вычитание(-), умножение(*), деление(/), целочисленное деление(%) (для типа int получение остатка).

2.Унарные: унарный плюс (+), унарный минус (-), адресация (&), косвенная адресация (*), определение размера памяти типа (sizeof).

3.Логические: и (&&), или (!!), не (!=).

4.Отношения:

a)равно (==), не равно(!>);

б) меньше чем (), меньше или равно (=);

5.Приращения (++) и уменьшения (--). Например, i++ обозначает, что i=i+1, а i-- обозначает i=i-1.

6.Побитовые операции - позволяют производить операции над битами.

7.Комбинированные операции. В Турбо-Си существуют сокращения при написании выражений, содержащих многочисленные операции:

a = a + b; сокращается до a += b;

a = a - b; сокращается до a -= b;

a = a * b; сокращается до a *= b;

a = a / b; сокращается до a /= b;

a = a % b; сокращается до a %= b;

8.Адресные операции:

1. Операция определения адреса (&) 2. Операция обращения по адресу (*).

Операция & возвращает адрес данной переменной; если Х является переменной типа int, то &Х является адресом (расположения в памяти) этой переменной. С другой стороны, если msg является указателем на тип char, то *msg является символом, на который указывает msg. Рассмотрим пример:

msg = "Привет ";

printf(" X = %d &X = %p ",X,&X);

printf("*msg = %c msg = %p ", *msg, msg);

При печати в первой функции печатается два значения: значение X 7 и адрес X (назначаемый компилятором). Во второй функции также печатается два значения: символ, на который указывает msg (П), и значение msg, которое является адресом этого символа (также назначен компилятором).

Старшинство операций в Си соответствует старшинству операций в математике.

Оператор запятая.

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

(X = Y, Y = getch())

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

Операторы управления.

Оператор If... дает возможность в зависимости от условия выполнять ту или иную ветвь программы. Синтаксис оператора следующий:

If условие выражение1 else выражение2;

Условие должно давать результат в виде логического значения истинности или ложности. Выражение1 будет выполняться если условие истинно. Выражение2 будет выполняться если условие ложно.

Существует сокращенный вариант оператора:

If условие выражение1

Пример. Определить, является ли введенное число днем недели, т.е. входит ли число в диапазон от 1 до 7.

printf("Error %d ",A);

else printf("OK %d ",A);

Выражение условия (A 7) будет давать TRUE, если выполняется A 7 - в этом случае выполняется ветка printf("Error ",A);, иначе ветка printf("OK ",A);.

Существует другой вариант записи оператора If ... Пример:

y=(t>0)? t*10: t-10; /* if t>0 y=t*10 else y=t-10;*/

printf("OK %d ",y);

В данном варианте вид оператора показан в комментариях.

Оператор switch... case используется в случае, когда необходимо анализировать переменную и в зависимости от ее значения производить те или иные действия. Рассмотрим пример. С клавиатуры вводятся буквы латинского алфавиты. В зависимости от буквы произвести те или иные действия.

case "c": printf(" smoll %c ",A); break; /* выход из блока */

case "G": printf(" big %c ",A);

default: printf("Error %c ",A);

В данном примере если введен символ с, то выполняется printf(" smoll %c ",A);, если вводится заглавные буквы F или G, то выполняется printf(" big %c ",A);, если не один из рассмотренных символов не вводится, то выполняется printf("Error %c ",A);.

Для повторения некоторого множества команд несколько раз можно использовать оператор do... while. Рассмотрим пример.

printf("Zifra? ");

printf("Error %d ",A);

} while (!(A == 9));

printf("OK %d ",A);

С клавиатуры вводится число. Выполняется оператор printf("Error %d ",A);. Далее идет анализ - равно число 9 или нет, если не равно, снова выполняется тело цикла:

printf("Zifra? ");

printf("Error %d ",A).

Если число равно 9, то выполняется оператор printf("OK %d ",A); и работа цикла заканчивается.

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

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

Оператор while... в отличие от do... while вначале анализирует условие, а затем выполняет тело цикла.

printf("Zifra? ");

printf("Error %d ",A);

printf("OK %d ",A);

В данном примере инициализирована переменная A:=0;. Это сделано, потому что вначале идет анализ равна она 9 или нет. Если не равна, то выполняется тело цикла. Смысл рассматриваемого оператора заключается в следующем:

«Пока истинно условие выполняй тело цикла».

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

printf("Zifra %d ",A);

В этом примере A хранит состояние счетчика цикла. Первоначально A:=1. Выполняется оператор printf("Zifra %d ",A). Далее значение A увеличивается на единицу. Идет анализ A

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

for (A = 5; A >= 1; A--) /* A-- означает A=A-1 */

printf("Zifra %d ",A);

Существует множество модификаций оператора for..., например:

Пустой оператор - для временной задержки:

; /* пустой оператор */

Использование различного шага:

Изменение переменных:

Рассмотрим пример, в котором инициализируются две переменные и каждая из которых, изменяется после итерации цикла:

Оператор goto позволяет передавать управление на любую строку программы. Для этой цели используется метка. Пример.

label_1:/* метка */ printf("? ");

if (A != "y") goto label_1; }

Для прерывания цикла по некоторому условию можно использовать оператор break. Пример.

i (A == "y") break;

Для прерывания итерации цикла и перехода к следующей итерации используется оператор Continue. Пример.

if (A == "y") continue;

printf("Работает %c ",A);

Для прерывания программы также используются операторы return() и exit().

1.6. Препроцессор

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

Директива #define.

Директива #define может появляться в любом месте программы, а даваемое ею определение имеет силу от места до конца программы.

#define OTWET TRI*TRI

#define OT printf("ОТВЕТ равен %d. ",OTWET)

#define jd cin >>C;

После выполнения программы получится:

ОТВЕТ равен 9

В первой строке программы TRI - это макроопределение и оно равно 3, где 3 - строка замещения.

Во второй строке макроопределение OTWET имеет строку замещения TRI*TRI и т.д. Каждая строка состоит из трех частей. Первой стоит директива #define, далее идет макроопределение. Макроопределение не должно содержать внутри себя пробелы. И, наконец, идет строка (называемая "строкой замещения"), которую представляет макроопределение. Когда препроцессор находит в программе одно из макроопределений, он заменяет его строкой замещения. Этот процесс прохождения от макроопределения до заключительной строки замещения называется "макрорасширением".

Директива #include.

Когда препроцессор "распознает" директиву #include, он ищет следующее за ней имя файла и включает его в текущую программу. Директива бывает в двух видах:

#include имя файла в угловых скобках

#include "my.h" имя файла в двойных кавычках

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

Директивы: #undef, #ifdef, #else, #endif

Эти директивы позволяют приостановить действие более ранних определений.

Директива #undef отменяет самое последнее определение поименованного макроопределения.

#undef TRI /* TRI теперь не определен */

#define F 10 /* F переопределен как 10 */

#undef F /* F снова равен 5 */

#undef F /* F теперь не определен */

Рассмотрим еще пример.

#include "otw.h" /* выполнится, если OTW определен */

#include "w.h" /* выполнится, если OTW не определен */

Директива ifdef сообщает, что если последующий идентификатор OTW определяется препроцессором, то выполняются все последующие директивы вплоть до первого появления #else или #endif. Когда в программе есть #else, то программа от #else до #endif будет выполняться, если идентификатор не определен.

1.7 Программы. Функции

Как мы рассматривали раньше, программа на Си имеет корневой сегмент, начинающийся с директив препроцессора и ключевого слова main.

Часто используемые участки программы выделяются в функции. Каждая функция также начинается с директив препроцессора и имени и скобок { }.

Рассмотрим пример программы рисования лестницы.

printf("|----| ");

printf("|----| ");

printf("|----| ");

А теперь напишем эту программу с использованием функции Lestniza.

printf("|----| ");

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

Lestniza(int B)/* B - формальный аргумент */

printf("|----| ");

Lestniza(3); /* 3 -фактический аргумент */

В данной функции B является формальным аргументом (конечная величина оператора for to). Для присвоение ей конкретного значения используется фактический аргумент, который передается функции при ее вызове в основной программе.

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

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

float Kwadrat(float A)

printf("Kwadrat = %8.2f ",Kwadrat(B));

Как видно из примера - имя функции Kwadrat - она вычисляет квадрат числа. В строке printf("Kwadrat = %8.2f ",Kwadrat(B)); эта функция вызывается - на вход подается значение (введенное число), а в результате получаем результат - квадрат числа, который возвращается в программу по команде return.

Рассмотрим еще один вариант работы с функцией, возвращающей значение без команды return.

Kwadrat(float A, float *B)

printf("Kwadrat = %8.2f ",D);

1.8. Указатели

Указатель - это переменная, содержащая адрес данных, а не их значение. Указатель используется:

1.Для связи независимых структур друг с другом.

2.Для динамического распределения памяти.

3.Для доступа к различным элементам структуры.

Рассмотрим следующую программу:

printf("Прямое значение Z: %d ", Z);

printf("Значение Z, полученное через указатель: %d ",*Y);

printf(" Адрес Z через получение адреса: %p ",&Z);

printf("Адрес Z через указатель: %p ", Y);

В данном примере Y указатель на целую переменную и содержит ее адрес. В свою очередь & позволяет получить адрес по которому размещено значение переменной Z. В этой программе:

Адрес переменной Z присваивается Y;

Целое значение 100 присваивается Z;

Оператор &, позволяет получить адрес,

по которому размещено значение Z.

Результат работы программы:

Прямое значение Z: 100

Значение Z, полученное через указатель: 100

Адрес Z через получение адреса: 85B3:0FDC

Адрес Z через указатель: 85B3:0FDC

Указатели также используются для оптимального распределения памяти.

Рассмотрим пример указателя на число типа char.

char *str; /* указатель на символьную переменную */

str = (char *)malloc(10);

strcpy(str, "Hello");

printf("String is %s ", str);

Вначале по команде char *str; создан тип str, который является указателем на переменную типа char(* обозначает "указатель"). По команде str = (char *)malloc(10); выделяем 10 байт памяти под переменную str(типа строка). По команде strcpy(str, "Hello"); осуществляется - "записать в область памяти, на которую указывает str, строку символов "Hello". По команде printf("String is %s ", str); осуществляется "напечатать на экране то, на что указывает str. Команда free(str); освобождает память, на которую указывает str.

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

}; /* конец записи */

struct Student *A;

if ((A =(Student *) malloc(sizeof(Student))) == NULL)

printf("Нет памяти ");

strcpy(A.Fio, "Ivanov");

printf("Fio1 %s Gruppa %d ", A.Fio, A.Gruppa);

strcpy(A.Fio, "Petrow");

printf("Fio2 %s Gruppa %d ", A.Fio, A.Gruppa);

Указатель также может использоваться для получения косвенного указателя на структуру.

Пусть poit является указателем на структуру и что elem элемент, определенный структурным шаблоном. Тогда point->elem определяет элемент, на который выполняется ссылка. Рассмотрим предыдущий пример.

struct Student { /* запись Student */

char Fio; /* поле записи Fio */

int Gruppa; /* поле записи Gruppa */

}; /* конец записи */

Сейчас к полям структуры мы можем обращаться несколькими способами. Эквивалентные обращения:

Student.Gruppa=236;

poin->Gruppa=236;

Отметим одну важную особенность указателей в Си. Транслятор автоматически учитывает тип указателя в арифметических действиях над ним. Например если i есть указатель на целую (т.е. двухбайтную) переменную, то действие типа i++ означает, что указатель получает приращение не один, а два байта, т.е. будет указывать на следующую переменную или элемент массива. По этой причине указатель можно использовать вместо индексов массива. Например если A - указатель на массив целого типа, то вместо A[i] можно писать *(A+i). Более того, использование указателей вместо индексов позволяет компилятору создавать более компактный и быстрый код.

1.9 Указатели и функции

Указатели также можно использовать в качестве формальных параметров функции. Рассмотрим пример.

Функция swap (обмен) объявляет два формальных параметра x и y, как указатели на данные типа int. Это означает, что функция swap работает с адресами целых переменных (а не с их значениями). Поэтому будут обработаны данные, адреса которых переданы функции во время обращения к ней. Функция main(), вызывает swap.

swap(int *x, int *y)

wr = *x; *x = *y; *y =wr;

printf("Было: i=%d, j=%d ",i,j);

printf("Стало: i =%d, j=%d ",i,j);

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

Таким образом, рассмотрены основные элементы языка Си.

1.10 Файлы

Файл - это совокупность данных, записанных на каком-либо носителе. Файл можно создать, записать в него данные, стереть данный, обновить данные, дополнить данными. Ввод-вывод в файл осуществляется с помощью методов прямого или последовательного доступа.

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

Ввод-вывода буферизован. Это означает, что программа пишет и читает в буфер; обмен данными между буфером и файлом происходит в случае, если буфер полон, или произошло закрытие файла, или перед выходом из программы.

printf("Исходный файл ");

printf("Выходной файл ");

if ((in = fopen(n1, "rt"))== NULL)

printf("Не могу открыть исходный файл "); return 1;

if ((out = fopen(n2, "wt"))== NULL)

printf("Не могу открыть выходной файл "); return 1;

while (!feof(in))

fputc(fgetc(in), out);

Строка FILE *in, *out; определяет указатель на два файла. Имя файла м.б. любым- в нашем случае in - исходный файл, out - выходной.

В следующей строке char n1, n2; определяем две переменные n1 и n2 для хранения имен файлов. Следующие четыре строки позволяют ввести имена входного и выходного файла и присвоить эти имена переменным n1 и n2. Прежде чем начать работать с файлом он должен быть открыт. Для этого существует функция fopen() в которой первый параметр содержит имя файла, а второй - вид работы, например "rt"– читать файл.

Команда in = fopen(n1, "rt" вызовет открытие файла, запомненного в переменной n1 на чтение, и в программе будет возвращен указатель in на этот файл, которым (указателем) мы и будем пользоваться при чтении символов из файла. Если файл не существует, то значение fp будет NULL, произойдет выполнение fprintf(stderr, "Не могу открыть выходной файл "); return 1; и программа завершит работу.

Аналогично работает функция out = fopen(n2, "wt", только теперь out - выходной файл, а вид работы "wt" -запись в файл).

По этой команде создается файл под именем, записанным в переменной n2.

Чтение из файла осуществляется вызовом fgetc(in). Читается один символ из файла, связанного с указателем in.

По команде fputc(fgetc(in), out); считанный символ записывается в файл out. Для чтения информации из всего файла используется конструкция while (!feof(in))

fputc(fgetc(in), out);.

Функция feof(in) возвращает величину, отличную от нуля, если находится в конечной позиции, и ноль - в противном случае. Пока не встретится ноль, данные из исходного файла читаются и записываются в выходной.

Закрытие файла происходит при вызове функции fclose(). Если при этом файл был открыт на запись, происходит вывод содержимого буфера, связанного с этим файлом. Связь между указателем и файлом разрывается.

Аналогично функция fgetc(string,n,fp) читает из файла, связанного с fp, строку и помещает ее в string. Символы читаются, пока не будет получен символ " ", или пока не исчерпается файл, или пока не будет прочитано (n-1) символов.

Режим прямого доступа более гибок, т.к. позволяет обращаться напрямую к любой записи файла. Минимальной записью для файла прямого доступа является байт. Ниже будет рассмотрен случай файла прямого доступа с записью равной байту. Такие файлы называются двоичными. Файлы прямого доступа незаменимы при написании программ, которые должны работать с большими объемами информации, хранящимися на внешних устройствах. В основе обработке СУБД лежат файлы прямого доступа.

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

1). Каждая запись в файле прямого доступа имеет свой номер. Записи нумерются от 0 до N-1, где N - количество записей в файле. Для двоичного файла N совпадает с длиной файла в байтах. Для открытого файла одна из записей является текущей - говорят, что указатель установлен на данную запись. Перемещать указатель можно при помощи функции lseek.

2). При открытии (или создания файла) указатель автоматически помещается на начало (запись 0). При выполнении операций чтения или записи указатель автоматически перемещается за последнюю считанную (записанную запись) запись.

3). Изменить размер файла (увеличить или урезать) можно при помощи функции chsize. При увеличении размера файла к нему добавляются записи, заполненные кодами 0.

Ниже представлена программа, демонстрирующая работу с файлами.

int h; /*дескриптор создаваемого файла*/

char * s="Эта строка будет помещена в файл";

char buf; /*буфер для чтения из файла*/

Fmode=O_BINARY; /*работаем с двоичными файлами*/

if((h=creat("proba.txt",S_IREAD |S_IWRITE))==-1) /*создать файл*/

printf("Не удалось открыть файл! ");

write(h,s,strlen(s)); /*записать в файл строку s*/

lseek(h,4,SEEK_SET); /*четвертый байт от начала файла*/

buf=0; /*отмечаем конец строки*/

close(h); /*закрыть файл*/

printf("%s ",buf); /*печать считанной строки*/

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

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

2. При удачном открытии файла ему отводится дескриптор (уникальное число), по которому затем можно к файлу обращаться.

3. Наконец не забывайте, что строка только тогда станет строкой, когда в конце стоит код

Основы и тонкости языка программирования C++. Практические задания и тесты. Хотите научиться программировать? Тогда вы по адресу. Неважно, имеете ли вы опыт в программировании или нет, эти уроки помогут вам начать создавать, компилировать и отлаживать программы на языке C++ в разных средах разработки: Visual Studio, Code::Blocks, Xcode, Eclipse и других IDE. Множество примеров и подробных разъяснений. Отлично подойдут как для новичков (чайников), так и для более продвинутых. Объясняется всё с нуля и до самых деталей. Эти уроки (200+) дадут вам хорошую базу/фундамент в понимании программирования не только на С++, но и на других языках. И это абсолютно бесплатно!

От вас нужно только желание, желание учиться. Всё остальное вы найдёте здесь .

За репост +20 к карме и моя благодарность!

Глава №0. Введение. Начало работы Глава №1. Основы C++ Глава №2. Переменные и основные типы данных в C++ Глава №3. Операторы в C++ Глава №4. Область видимости и другие типы переменных в C++

Рекомендуем почитать

Наверх