Лекция 1. Основы алгоритмизации и программирования на Си (1153708), страница 6
Текст из файла (страница 6)
Заголовочный файл <conio.h> подключается, чтобыможно было использовать функцию _getch(). Эта функция считываетсимвол с клавиатуры без его отображения на экране. В наших примерах она нужна, чтобы задержать консольный экран до нажатия произвольной клавиши и посмотреть результаты.2. Русские буквы неправильно выводятся в консольный экран. Ихнеобходимо заменить латинскими. В наших примерах они используются, чтобы содержание поясняющих фраз было лучше понятно русскоязычному читателю.30началоВвод a,b,cd b 2 4acнетдаd>0b2adx2 2ax1 b d2ab dx2 2ax1 Вывод: “действ.и мнимая частикорней”,x1,x2Вывод:“действкорни”,x1,x2конецРис.7. Блок-схема алгоритма решения квадратного уравнения31началоПример 2. СоставитьВвод a,b,p,nДаa<bНетv=ai=1in &&vbдаВыво дi,vv=v-bv=v*(1+p/100)i=i+1конецРис.8.
Блок-схемапримера 232программу решенияследующей задачи.Наначалопервого из рассматриваемых месяцеввклад клиента вбанке был равен aруб. В течение каждогоследующегомесяца со счетаснимается b руб.; вконце каждого месяца на остатоквклада начисляетсяр%. Вывести величинувкладананачало 1, 2,...n месяца.Исходныеданные: a, b, p - вещественные переменные, n - целаяпеременная.Выходныеданные: i - номермесяца, v - величина вклада на началомесяца.Блок-схема алгоритма приведенана рис. 8.#include <stdio.h>#include <conio.h>void main()/*вычисление величины вклада в банке*/{float a,b,v,p; int n,i;printf("Введите a, b, p, n\n");scanf("%f%f%f%d",&a,&b,&p,&n);if (a<b)printf("вклад меньше тpебуемой суммы\n");else{ printf("месяцвеличина вклада\n");v=a;i=1;while ((i<=n) && (v>=b)){printf("%2d%e\n",i,v);v=v-b;v=v*(1+p/100);i=i+1;}}_getch();}1.5.
Массивы и указатели1.5.1. Понятие массива.Основные правила работы с массивами в СиДо сих пор мы рассматривали только простые переменные, т. е.переменные, занимающие одну ячейку памяти. Значение этой переменной представляет собой единое целое, не разделяется на компоненты. Существуют сложные переменные, состоящие из несколькихкомпонент (и, соответственно, занимающих несколько ячеек памяти).Примером сложной переменной (иногда говорят о переменной сложной структуры или сложного типа) является массив.Массив - это сложная переменная, состоящая из конечного числаупорядоченных компонент, имеющих одно имя, одинаковый тип и расположенных в последовательных ячейках памяти компьютера.В программировании массивы применяются очень часто, так какмногие задачи связаны с обработкой информации, представляющей33собой конечное множество однотипных данных. Например, массивыоценок в студенческой ведомости, массивы выплат сотрудникам некоторого предприятия, массивы фамилий, имен и отчеств сотрудников, ит.
д.Упорядоченность компонент массива означает, что они пронумерованы. "Достать" компоненту можно указав ее номер (индекс) илиномера, потому что у одной компоненты может быть несколько номеров; например, оценка в сводной ведомости успеваемости студентовхарактеризуется двумя номерами - номером студента и номеромпредмета. В Си принято индексы указывать в квадратных скобках.Количество индексов у элементов массива называется размерностью массива. Массив размерности 1 называется также одномерным, размерности 2 - двумерным, и т. д.
Двумерные массивы такженазываются матрицами.Количество значений какого-либо индекса называется размероммассива по данному индексу, а общее количество элементов массива- размером массива или его длиной. Легко видеть, что размер массиваравен произведению его размеров по всем индексам.В Си элементы массивов нумеруются, начиная с нуля. Так, одномерный массив а из двадцати элементов имеет элементыа[0], a[2],...,a[19]. Элементы двумерного массива (матрицы) b с размерами 3 и 5 можно представить в виде таблицы из 3 строк и 5 столбцов. Принято считать, что первый индекс является номером строки, авторой - номером столбца таблицы:b[0][0] b[0][1] ...
b[0][4]b[1][0] b[1][1] ... b[1][4]b[2][0] b[2][1] ... b[2][4]При описании массивов необходимо указать размеры всех егоиндексов. Описание массива имеет вид:тип имя [размер1] [размер2]...[размерN];В квадратных скобках указывается размерi - размер по i-му индексу, обязательно целая положительная константа, иначе компилятор не сможет распределить память под массив.Например,float a[20]; int b[3][5];34Случаи, когда размер первого индекса (и только первого) можноне указывать, будут рассмотрены ниже.Двумерные массивы располагаются в памяти по строкам, многомерные - так, что чаще меняются правые индексы.В программах на Си в качестве индекса элемента массива можноиспользовать любое целочисленное выражение при условии, что егозначение не выходит за объявленные при описании границы. Элементмассива (его также называют переменной с индексами) можно использовать в выражениях точно так же, как простую переменную такого жетипа.
Ввод и вывод массивов происходит поэлементно, т. е. для ихпрограммирования необходимо организовывать циклы.1.5.2. Примеры программ с массивами.Пример 1. Дан массив а из 20 элементов. Вычислить сумму положительных и количество неположительных элементов массива.Исходные данные. а – заданный массивВыходные данные. s - сумма положительных элементов массива,k – количество неположительных элементов.Промежуточные переменные.
i – счетчик элементов массива.Алгоритм состоит из ввода исходных данных, цикла, в которомнакапливаются s и k (цикл управляется переменной i, которая изменяется от 0 до 19) и вывода результатов. Перед циклом накапливаемымпеременным присваиваются начальные значения. Основной частьютела цикла является ветвление. Блок-схема алгоритма приведена нарис. 9. Далее приведена Си-программа.35началоВвод a[i],i=0,…19s=0; k=0i=0i<20данетдаa[i]>0k=k+1s=s+a[i]i=i+1Вывод s,kконецРис.9. Блок-схема программы с массивами36#include<stdio.h>#include <math.h>void main(){float a[20],s; int k,i;printf("Введите массив из 20 элементов\n");/* Далее цикл для поэлементного ввода массива*/for (i=0; i<20; i++)scanf("%f", &a[i]);/*Далее алгоритм по блок-схеме*/s=0; k=0;for (i=0; i<20; i++)if (a[i]>0)s=s+a[i];elsek=k+1;printf(" s=%f k=%d",s,k );}1.5.3.
Инициализация массивовПри описании элементы массивов можно инициализировать, т. е.задавать им начальные значения. Эти значения записываются в фигурных скобках через запятую и присваиваются элементам массивапоследовательно в порядке их нумерации. Значений не может бытьбольше, чем объявлено элементов массива. Если значений меньше,чем элементов в массиве, то оставшиеся элементы считаются неинициализированными9.Список инициализирующих значений можно использовать дляопределения размера массива по первому индексу. Поясним это напримерах.Одномерные массивыПусть число элементов массива задано явно.
Например,сhar a[10]={'A', 'B', 'C', 'D'};в результате a[0] имеет значение 'A', a[1] - 'B', a[2] - 'C', a[3] - 'D',остальные элементы массива не инициализированы.Пусть число элементов массива явно не задано:9Локальные переменные считаются неопределенными, статические переменные при описании автоматически обнуляются - см.пп. 1.2.5 и 2.4.37сhar a[ ]={'A', 'B', 'C', 'D'};С помощью такой инструкции описан и инициализирован массивиз четырех элементов.Двумерные массивыПрисваивание перечисленных значений происходит по строкам(в соответствии с расположением массивов в памяти компьютера).Пример: int m[2][3]={0,1,2,5,6,7};Эта инструкция объявляет и присваивает начальные значения0 1 2 матрице m .
Можно не указывать число строк, тогда оно5 6 7 будет определено по числу начальных значений, т. е. инструкцияint m[ ][3]={0,1,2,5,6,7};приведет к такому же результату.Значения, соответствующие одной строке, могут быть заключеныво внутренние фигурные скобки; это может быть полезно, если стороки инициализируются не полностью. Так, инструкцияint m[ ][3]={{0},{1,2}};объявляет матрицу m размером 2*3 и частично инициализирует ее.0m , незаполненные элементы не инициализированы:1 2 неопределены, если m - локальная переменная, и равны нулю, еслиглобальная.Таким образом, при объявлении массива количество его элементов должно быть задано или явным указанием в квадратных скобкахили количеством значений при инициализации.
Исключение из этогоправила составляют массивы-аргументы функций (см. п.2.2.1).1.5.4. Указатели в Си10Указатель - это специальная переменная, которая содержит адрес другой переменной.Работа с указателями и динамической памятью обычно относится к области системного программирования. В Си указатели активно10Этот и следующий параграфы отражают специфику языка Си.Они могут быть пропущены при первом чтении лекции.38используются даже в простых инструкциях языка. По-видимому, этоявляется следствием того, что Си разрабатывался как язык системного программирования. В п.1.3.3 уже показано использование указателей в функции ввода scanf().В следующем параграфе мы рассмотримприменение указателей для работы с массивами.
Этот параграфпредваряет его и посвящен правилам работы с указателями в Си.Основные операции для работы с указателями (см., также таблицу 3):* - взятие содержимого по адресу (*i - содержимое переменной с адресом i)& - взятие адреса (&a - адрес переменной а).При описании указателя задается тип значения, на которое онуказывает. Описание имеет вид:тип *имя_указателя;Можно интерпретировать смысл этой конструкции так:: объявляется переменная, содержимое которой имеет данный тип.Пример: int *i, j, *pointj;j -переменная целого типа; i, pointj - указатели на значения целого типа.При описании указателей возможна их инициализация.
Пример:int v1, *pointv1=&v1, *p=(int*)200;Здесь указателю pointv1 задается начальное значение, равноеадресу переменной v1, а указателю р - значение константы 200, приведенное к типу int*, т. е. адрес двухсотой от начала рассматриваемойобласти памяти ячейки типа int.Как данные любого типа, указатели могут быть переменными иликонстантами. Указателями-константами, например, являются адресапеременных, имена массивов, явные константы (например, (int*)200), атакже константа NULL (нулевой или несуществующий адрес).При работе с указателями-константами надо помнить следующее:*нельзя брать содержимое от константы без приведения типа; запись *200 является некорректной в отличие от *(int*)200*нельзя брать адрес константы (например, некорректна запись &200), в Си адрес константы считается недоступным;39*нельзя определять адрес выражения.Размер памяти, отводимой под указатель, зависит от модели памяти.