Элементарные средства программирования 


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



ЗНАЕТЕ ЛИ ВЫ?

Элементарные средства программирования



Деление операторов языка Си на группы.

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

директивы препроцессора

void main()

{ определения_объектов;

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

}

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

Каждый исполняемый оператор определяет действия программы на очередном шаге ее выполнения. У оператора (в отличие от выражения) нет значения. По характеру действий различают два типа операторов: операторы преобразования данных и операторы управления работой программы.

Наиболее типичные операторы преобразования данных - операторы присваивания и произвольные выражения, завершенные символом "точка с запятой”:

i++; /*Арифметическое выражение - оператор*/

x*=i; /*Оператор составного присваивания*/

i=x-4*i; /*Оператор простого присваивания*/

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

имя функции (список_фактических параметров);

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

Операторы управления работой программы называют управляющими конструкциями программы. К ним относятся:

• составные операторы;

• операторы выбора;

• операторы циклов;

• операторы перехода.

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

{

n++;

summa+=(float)n)

}

а этот фрагмент - блок:

{

int n=0;

n++;

summa+=(float)n;

}

Наиболее часто блок употребляется в качестве тела функции.

Операторы выбора - это условный оператор (if) и переключатель (switch).

Операторы циклов в языке Си трех видов - с предусловием (while), с постусловием (do) и параметрический (for).

Операторы перехода выполняют безусловную передачу управления: goto (безусловный переход), continue (завершение текущей итерации цикла), break (выход из цикла или переключателя), return (возврат из функции).

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

Условный оператор имеет сокращенную форму:

if (выражение_условие) оператор;

где в качестве выражения_условия могут использоваться: арифметическое выражение, отношение и логическое выражение. Оператор, включенный в условный, выполняется только в случае истинности (т.е. при ненулевом значении) выраж-ния_условия. Пример:

if (х < 0 && х > -10) х=-х:

Кроме сокращенной формы, имеется еще и полная форма условного оператора:

if (выражение_условие)

оператор _1;

else

оператор _2;

Здесь в случае истинности выражения-условия выполняется только оператор_1, при нулевом значении выражения-условия выполняется только оператор_2. Например:

if (x > 0)

b =х;

Else

b=-х;

Оператор в сокращенном варианте оператора if, и оператор_1 и оператор 2 в полном операторе if могут быть как отдельными, так и составными операторами.

Например, при решении алгебраического уравнения 2-й степени ax2+bx+c=0 действительные корни имеются только в случае, если дискриминант (b2~4ас) неотрицателен. Следующий фрагмент программы иллюстрирует использование условного оператора при определении действительных корней х1, х2 квадратного уравнения:

...............

d=b*b - 4*а*с; /* d - дискриминант */

if (d>=0.0)

{

xl=(-b+sqrt(d))/2/a;

х2=(-b-sqrt(d))/2/а;

printf("\n Корни: xl=%e, x2=%e", xl, х2);

}

Else

printf("\n Действительные корни отсутствуют.");

Во фрагменте предполагается, что переменные d, b, a, xl, х2 - вещественные (типа float либо double). До приведенных операторов переменные а, b, с получили конкретные значения, для которых выполняются вычисления. В условном операторе после if находится составной оператор, после else - только один оператор - вызов функции printf(). При вычислении корней используется библиотечная функция sqrt() из стандартной библиотеки компилятора. Ее прототип находится в заголовочном файле math.h.

Метки и пустой оператор. Метка - это идентификатор, помещаемый слева от оператора и отделенный от него двоеточием ":". Например,

СОН: Х+=-8;

Чтобы можно было поставить метку в любом месте программы (или задать пустое тело цикла), в язык Си введен пустой оператор, изображаемый только одним символом ";". Таким образом, можно записать такой помеченный пустой оператор:

МЕТКА:;

Оператор перехода. Оператор безусловного перехода имеет

следующий вид:

goto идентификатор;

где идентификатор - одна из меток программы. Например: goto СОН; или goto МЕТКА;

Ввод данных. Для ввода данных с клавиатуры ЭВМ в программе будем использовать функцию (описана в заголовочном файле stdio.h):

scanf {форматная_строка, список_аргументов);

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

И форматная строка, и список аргументов для функции scanf() обязательны. Форматную строку для функции scanf() будем формировать из спецификаций преобразования вида:

% * ширина_поля модификатор спецификатор

Среди элементов спецификации преобразования обязательны только % и спецификатор. Для ввода числовых данных используются спецификаторы:

d - для целых десятичных чисел (тип int);

u - для целых десятичных чисел без знака (тип unsigned int);

f -для вещественных чисел (тип float);

е - для вещественных чисел (тип float).

Ширина_поля - целое положительное число, позволяющее определить, какое количество байтов (символов) из входного потока соответствует вводимому значению.

В качестве модификаторов используются символы:

h - для ввода значений типа short int (hd);

l - для ввода значений типа long int (ld) или double (lf, le);

L - для ввода значений типа long double (Lf, Le).

В отличие от функции printf() аргументами для функции scanf() могут быть только адреса объектов программы, в частном случае - адреса ее переменных. Не расшифровывая понятие адреса (адресам и указателям будут рассмотрены позже), напомним, что в языке Си имеется специальная унарная операция & получения адреса объекта:

& имя_обьекта

Выражение для получения адреса переменной будет таким:

& имя_переменной

Итак, для обозначения адреса перед именем переменной записывают символ &. Если name - имя переменной, то &name -ее адрес.

Например, для ввода с клавиатуры значений переменных n, z, х можно записать оператор:

scanf ("%d%f%f",&n,&z,&x);

В данном примере спецификации преобразования в форматной строке не содержат сведений о размерах полей и точностях вводимых значений. Это разрешено и очень удобно при вводе данных, диапазон значений которых определен не строго. Если переменная n описана как целая, z и х - как вещественные типа float, то после чтения с клавиатуры последовательности символов 18 18 -0.431 переменная n получит значение 18, z — значение 18.0, х-значение -0.431.

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

Пример: Вычисление объема цилиндра.

/*Вычисление объема прямого цилиндра*/

#include <stdio.h>

void main()

{

double h, r, v;

const float PI = 3.14159;

/*h - высота цилиндра, r -радиус цилиндра*/

/*v - объем цилиндра, PI - число "пи" */

printf("\n Радиус цилиндра r= ");

scanf("%lf", &r);

printf("Высота цилиндра h= ");;

scanf("%lf”, &h);

v = h * PI * r * r;

printf("Объем цилиндра: %10.4f",v):

}

В тексте программы несколько особенностей. Определена константа PI, т.е. со значением 3.14159 связано имя PI, которое до конца выполнения программы будет именовать только это значение.

Перед каждым вводом помещены вызовы функции printf(), выводящей на экран запрос-подсказку, вслед за которой на экране отображается набираемое на клавиатуре вводимое значение. Функция scanf() считывает только это значение, как только будет нажата клавиша "Ввод" (Enter), что воспринимается как признак конца строки ввода. Поэтому очередной вызов функции printf() выводит данные на следующую строку. Обратите внимание на спецификации преобразования %lf Если бы переменные h и r имели тип float, то в форматных строках функций scanf() нужно было бы применять спецификации %f или %е. Текст на экране при выполнении программы может быть таким:

радиус цилиндра r= 2.0

высота цилиндра h= 4.0

Объем цилиндра: 50.2654

Здесь пользователь ввел 2.0 для г и 4.0 для h. Другой вариант:

радиус цилиндра r= 4.0

высота цилиндра h= 2.0

Объем цилиндра: 100.5309

Еще раз обратите внимание на использование в функции scanf() не имен переменных, а их адресов &r, &h.

Сумма членов ряда Фибоначчи. Ряд Фибоначчи определен, если известны первые два его члена f1, f2, так как очередной член fi =fi-1 + fi-2 для r>2. Необходимо вычислить сумму заданного количества (k) первых членов ряда Фибоначчи, если известны первые два: р = F1 и r = F2. Следующая программа решает эту задачу:

/*Вычисление суммы членов ряда Фибоначчи*/

#include <stdio.h>

void main()

{

int k,i;/*к-число членов; i-номер члена */

float s,p,r,f; /* s - искомая сумма */

/*Члены: р -первый; r - второй; f- i-й*/

Ml: printf("\n Введите число членов ряда k=");

scanf ("%d",&k);

if(k > 2) goto M2;

printf("\n Ошибка! k должно быть > 2!");

goto Ml;

M2: printf("\n Первый член ряда р=");

scanf("%f",&p);

printf("\n Второй член ряда r=");

scanf("%fn,&r);

i = 3;

s = p + r;

M: f = p + r;

s = s + f;

p = r;

r = f;

i = i + 1;

if (i <= k) goto M;

printf("\n Сумма членов ряда: %10.3f", s);

}

Обратите внимание на строки, где выполняется проверка введенного значения k. Программа может правильно работать только при к>2, поэтому только в этом случае выполняется переход к метке М2. В противном случае печатается сообщение об ошибке, и после перехода к метке Ml запрашивается новое значение k.

Особенность и недостаток программы состоят в том, что она никогда не закончит вычислений, если не ввести допустимого значения к>2.

Операторы цикла

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

Цикл while (цикл с предусловием) имеет вид:

while (выражение_условие)

тело_цикла

В качестве выражения_условия чаще всего используется отношение или логическое выражение. Если оно истинно, т.е. не равно 0, то тело цикла выполняется до тех пор, пока выражение_условие не станет ложным.

Проверка истинности выражения осуществляется до каждого выполнения тела цикла. Таким образом, для заведомо ложного выраж-ния_условия тело цикла не выполнится ни разу. Выражение _условие может быть и арифметическим выражением. В этом случае цикл выполняется, пока значение выражения_условия не равно 0.

Цикл do (цикл с постусловием) имеет вид:

do

тел_ цикла

while (выражение_условие)\

Выражени_условие логическое или арифметическое, как и в цикле while. В цикле do тело цикла всегда выполняется по крайней мере один раз. После каждого выполнения тела цикла проверяется истинность выражения_условия (на равенство 0), и если оно ложно (т.е. равно 0), то цикл заканчивается. В противном случае тело цикла выполняется вновь.

Цикл for (называемый параметрическим) имеет вид:

for (выражение_1; выражение_условие; выражение_3)

тело_цикла

Первое и третье выражения в операторе for могут состоять из нескольких выражений, разделенных запятыми. Выражение_1 определяет действия, выполняемые до начала цикла, т.е. задает начальные условия для цикла; чаще всего это выражение присваивания. Выражение_условие - обычно логическое или арифметическое. Оно определяет условия окончания или продолжения цикла. Если оно истинно (т.е. не равно 0), то выполняется тело цикла, а затем вычисляется выражение _3. Выражение_3 обычно задает необходимые для следующей итерации изменения параметров или любых переменных тела цикла. После выполнения выражения_3 вычисляется истинность выражения_условия, и все повторяется... Таким образом, выражение_1 вычисляется только один раз, а выражение_условие и выражение_3 вычисляются после каждого выполнения тела цикла. Цикл продолжается до тех пор, пока не станет ложным выражение_условие. Любое из трех, любые два или все три выражения в операторе for могут отсутствовать, но разделяющие их символы ";" должны присутствовать всегда. Если отсутствует выражение_усповие, то считается, что оно истинно и нужны специальные средства для выхода из цикла.

Схемы организации циклов while, do и for даны на рисуке.

Проиллюстрируем особенности трех типов цикла на примере вычисления приближенного значения

для заданного значения х. Вычисления будем продолжать до тех пор, пока очередной член ряда остается больше заданной точности. Обозначим точность через eps, результат - b, очередной член ряда - г, номер члена ряда - i. Для получения i-ro члена ряда нужно (i-l)-йt член умножить на х и разделить на i, что позволяет исключить операцию возведения в степень и явное вычисление факториала. Опустив определения переменных, операторы ввода и проверки исходных данных, а также вывода результатов, запишем три фрагмента программ.

/* Цикл с предусловием */

i = 2;

b = 1.0;

r = х;

while(r > eps || r < -eps)

b=b+r; r=r*x/i;

i++;

}

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

/* Цикл с постусловием */

i=1;

b=0.0;

r=1.0;

do {

b-b+r;

r=r*x/i;

i++;

}

while(r >= eps || r <= -eps);

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

/* Параметрический цикл */

i=2;

d=1.0;

 
 

r=х;

for(; r > eps | | r < -eps;)

{

b=b+r;

r=r*x/i;

i=i+1;

}

Условие окончания параметрического цикла такое же, как и в цикле while.

Все три цикла записаны по возможности одинаково, чтобы подчеркнуть сходство циклов. Однако в данном примере цикл for имеет существенные преимущества. В заголовок цикла (в качестве выражения_1) можно ввести инициализацию всех переменных:

for (i=2, b=l.0, r=х; r>eps || r<-eps;)

{

b=b+r;

r=r*x/i;

i=i+1;

}

В выражение_З можно включать операцию изменения счетчика членов ряда:

for(i=2, b=1.0, r=x; r>eps || r<-eps; i++)

{

b=b+r;

r=r*x/i;

}

Можно еще более усложнить заголовок, перенеся в него все исполнимые операторы тела цикла:

for (i=2, b=1.0, r=x; r>eps || r<-eps;

b+=r, r*=x/i, i++);

В данном случае тело цикла - пустой оператор. Для сокращения выражения_3 в нем использованы составные операции присваивания и операция ++.

Оператор break. Этот оператор прекращает выполнение оператора цикла и передает управление следующему за ним (за циклом) оператору.

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

{

операторы

if (условие) break;

операторы

}

Пример:

while(1)

{

printf ("\n Введите значение n=”);

scanf("%d",&n);

if(n > 0) break;

printf ("\n ошибка! n должно быть >0!\n”);

}

Оператор continue. Еще одну возможность влиять на выполнение операторов тела цикла обеспечивает оператор перехода к следующей итерации цикла continue. Оператор continue противоположен по действию оператору break. Он позволяет в любой точке тела цикла прервать текущую итерацию и перейти к проверке условий продолжения цикла, определенных в предложениях for или while. В соответствии с результатами проверки выполнение цикла либо заканчивается, либо начинается новая итерация. Оператор continue удобен, когда от итерации к итерации изменяется последовательность выполняемых операторов тела цикла, т.е. когда тело цикла содержит ветвления. Рассмотрим пример.

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

#include <stdio.h>

/* Сумма положительных чисел */

void main()

{

double s,x;/*x - очередное число, s - сумма*/

int k; /*k - количество положительных */

printf("\nВведите последовательность чисел"

" с 0 в конце:\n");

for(х=1.0, s=0.0, k=0; x!> 0.0;)

{

scanf("%lf",&x);

if(х <= 0.0) continue;

k++;s+=x;

}

printf("\n Cyммa=%f,

количество положительных=%<d" rs,k);

}

Результат выполнения программы:

Введите последовательность чисел с 0 в конце:

б -3.0 14.0 -5 -4 10 0.0

Сумма=30.000000, количество положительных=3

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

Проверка на четность:

вариант 1:

"a&1" дает истину, когда число нечетное.

Пример проверки четности:

if (a&1) printf("Число нечетно");

else printf("Число четно");

вариант 2

#include <stdio.h>

void main()

{int i, s,a[100];

s=0;

printf("\nvvedi massiv\n");

for(i=1;i<=10;i++)

{

scanf("%d",&a[i]);

printf("\na=%d",a[i]);

if (a[i]%2==0) /*для четных*/

/* if (a[i]%2) для нечетных*/

/*if (a[i]%2!=0) для нечетных*/

{s+=a[i]; printf("\ns=%d",s);}

}

printf("\ns=%d",s);

}

 



Поделиться:


Последнее изменение этой страницы: 2017-02-10; просмотров: 185; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.149.234.141 (0.122 с.)