Партнерка на США и Канаду по недвижимости, выплаты в крипто
- 30% recurring commission
- Выплаты в USDT
- Вывод каждую неделю
- Комиссия до 5 лет за каждого referral
sin (x) - sin x; cos (x) – cos x ; tan(x) - tg х ; log (x) - ln x; log10(x) – lg x; exp(x) - показательная функция ex ; sqrt (x)- корень квадратный от х; роw(x, y) – x в степени y; abs(x)- модуль x.; acos(x) – arccos x; asin(x) – arcsin x; atan(x)- arctg x; sinh(x)- sh x; cosh (x) – ch x; tanh(x)-th x.
Для тригонометрических функций аргумент х измеряется в радианах и имеет тип double, как и значения функций.
Пример программы линейной структуры:
Вычислить площадь и стороны прямоугольного треугольника, если известны гипотенуза c и угол x. Для вычислений воспользуемся формулами :
a=c• sin x; b=c• cos x; S=ab;
Программа вычислений имеет вид:
// вычисление сторон и площади треугольника
#include <stdio. h> //заголовочный файл для организации ввода-вывода
#include <math. h> //заголовочный файл математических функций
main() //главная функция
{float a, b,c, x, S; //описание переменных вещественного типа
printf (“\n Введите гипотенузу и угол треугольника ”);
scanf (“%f%f “,&c,&x); // ввод значений вещественного типа
a=c*sin(x);
b=c*cos(x);
S=a*b;
printf (“\n Результаты: a=%7.2f b=%7.2f S=%7.2f “,a, b, S);
return 0;
}
Комментарий в программе не влияет на компиляцию программы, а служит для разъяснения действий основных блоков текста и программы в целом. Однострочный комментарий действует от двух символов // до конца строки. Многострочный комментарий заключается в пары символов /* и */.
Вторая строка программы #include <stdio. h> является директивой компилятора для включения заголовочного файла stdio. h для доступа к средствам ввода-вывода (связи с внешними устройствами), отсутствующими в самом языке Си. Третья строка - #include<math. h> является директивой компилятора для включения заголовочного файла math. h, обеспечивающего выполнение математических функций.
Программа на языке Си состоит из ряда функций, из которых функция main (главная) является обязательной и служит точкой входа в программу. В круглые скобки заключаются параметры функции, причем наличие круглых скобок обязательно, если даже список параметров пуст. В фигурные скобки заключаются составной оператор (несколько операторов). Для придания тексту программы наглядности открывающая и соответствующая ей закрывающая фигурные скобки печатаются на одном уровне, а заключенный между ними текст сдвигается на 1-2 символа вправо, вложенный блок также сдвигается вправо и т. д. Образуется иерархия вложенных блоков, придающая программе на Си характерный вид.
В программе описаны переменные a, b, c, х, S вещественного типа (float). В отличие от других языков в Си учитывается регистр при определении имени переменной, т. е. s и S – разные переменные. Функции printf и scanf доступны при подключении заголовочного файла stdio. h и служат для вывода на экран и ввода с клавиатуры соответственно. Управляющие символы \n в функции printf служат для перевода на новую строку. Символ & в функции scanf указывает на адрес вводимой переменной. Ввод и вывод переменных вещественного типа производится в формате f. Признаком форматного вывода в функции printf является %. При выводе между знаком процента и форматной переменной f можно включить общую ширину поля вывода и число позиций после десятичной точки. Оператор return 0; служит для выхода из функции main, 0 является признаком успешного окончания программы. Завершает текст программы закрывающая фигурная скобка, означающая конец функции main.
8. Понятие о препроцессоре языка Си
Препроцессором называется составная часть компилятора, которая производит обработку исходного текста программы перед ее трансляцией. Управление работой препроцессора осуществляется с помощью специальных директив. Все директивы препроцессора начинаются со знака #.
Ранее была рассмотрена директива include. Вместо нее в исходный текст программы препроцессор вставляет содержимое файла, указанного в директиве.
Так, по директиве #include <stdio. h> в текст программы вставляет содержимое файла stdio. h, находящегося в специальном системном каталоге, а только потом происходит трансляция.
Если в директиве #include имя файла заключено в кавычки, то вставляемый файл вначале ищется по правилам, предусмотренным MSDOS, а только потом в специальном системном каталоге. Например, по директиве препроцессора #include "func. h" будет осуществлена вставка текста из файла func. h, находящегося в текущем каталоге текущего диска.
Директива #define используется для назначения символических имен различным строкам текста. Например, директива:
#define PI 3.14159
осуществляет назначение имени PI строки 3.14159. В дальнейшем, вместо 3.14159 в программе можно использовать имя PI. Вместо него перед трансляцией программы препроцессор подставит соответствующую строку.
В принципе строка может быть сколь угодно сложной, например:
#define TITLE printf("-------sin(x)-------cos(x)-------");
Однако использовать такие конструкции не рекомендуется ввиду сложности отыскания ошибок.
9. Операторы языка Си и приемы программирования
Оператор (statement - предложение) - блок, используемый при создании программы. Программа всегда представляет собой последовательность операторов ( предложений ).
Признаком конца оператора в простейшем случае является ";". Одиночная ";" является пустым оператором. Как было отмечено выше, точка с запятой поставленная в конце выражения превращает его в оператор.
Кроме простого оператора в языке Си вводится понятие составного оператора, который представляет собой несколько операторов, заключенных в фигурные скобки:
составной_оператор = "{" оператор { оператор } "}"
Пример:
{ a = b + c; scanf( "%lf", &t ); }
Составной оператор рассматриваются компилятором как одиночный оператор и может быть использован в любом месте, где допускается использование одиночного оператора.
Все операторы языка Си, кроме оператора-выражения начинаются с ключевых слов. Например, описания начинаются с int, double и т. д.
Ключевые слова являются зарезервированными, т. е. их нельзя использовать для обозначения объектов программ. Имена стандартных функций не являются зарезервированными.
9.1. Оператор цикла while
Оператор цикла while предназначен для реализации циклических алгоритмов и имеет следующую форму записи
"while" "(" выражение ")" оператор
Пример :
while( a < 18 ) a = a+2;
При выполнении оператора цикла while вначале вычисляется выражение. Если оно не равно 0, то выполняется оператор. Далее снова вычисляется выражение и если оно не равно 0, то снова выполняется оператор. Такие циклические действия продолжаются до тех пор, пока выражение отлично от 0. Отсюда и название цикла while ( пока ). Как только выражение станет равным 0 цикл прекращает выполнятся и управление передается на следующий за циклом оператор.
Циклически выполняемый оператор обычно называют телом цикла. Если в теле цикла необходимо разместить не один, а несколько операторов, то в этом случае используют составной оператор.
Все операторы тела цикла должны быть записаны с отступом, обычно в три пробела.
Рассмотрим пример программы, которая выводит на экран таблицу функций sin(x) и cos(x):
#include <math. h>
#include <stdio. h>
void main( void )
{
double x = 0;
while( x < 3.0 )
{
printf( "%6.3lf %9.6lf %9.6lf\n",x, sin(x), cos(x) );
x += 0.2;
}
}
Если после while( x < 3.0 ) ошибочно поставить точку с запятой, то никаких сообщений об ошибках выдано не будет, но цикл станет бесконечным. Действительно, в этом случае тело цикла будет пустым оператором ";", переменная x не будет меняться, следовательно, результат выражения x < 3.0 всегда будет отличен от нуля.
В теле правильно организованного цикла обязательно должны содержатся операции, влияющие на выражение в заголовке цикла так, чтобы цикл рано или поздно завершился.
9.2. Условный оператор и условная операция
Условный оператор предназначен для выбора одного из двух альтернативных действий и имеет следующую форму записи:
условный_оператор =
"if" "("выражение")" оператор_1 ["else" оператор_2]
Пример:
if ( a ) c = b+1; else c = b - 1;
if ( a > b ) k = sin( x ); else k = x + x;
При выполнении условного оператора вначале вычисляется <выражение>. Если его значение не равно нулю, то выполняется <оператор_1>, а <оператор_2> пропускается. Если значение выражения равно нулю, то выполняется <оператор_2>, а <оператор_1> пропускается.
При наличии вложенных операторов if следует иметь в виду, что ключевое слово else всегда относится к ближайшему if, как показано в следующем примере:
if( b > a )

if( c < d ) k= sin(x);
else t = cos(x);
else c = tan( x );
Для того чтобы избежать ошибок рекомендуется использовать операторные скобки
if( b < a )
{
if( c < d ) k = sin( x );
else t = cos( x );
}
else c = tan( x );
Особенно это важно если у вложенного оператора if отсутствует else, т. е
if( b > a )
if( c < d ) k = sin( x );
else c = tan( x ); /* else относится к
вложенному if */
if( b > a )
{
if( c < d ) k = sin( x );
}
else
c = tan( x ); /* else относится к первому if */
Если в качестве <оператора_1> или <оператора_2> используется группа операторов, то ее записывают как составной оператор, заключая ее в операторные скобки "{" и "}".
Для того, чтобы сделать программу более понятной, рекомендуется операторы записывать в следующих формах:
1) короткие операторы:
if( a > b ) k = sin( x ); else k = x*x;
if( a > b ) k = sin( x );
else k = x*x;
2) группы коротких операторов:
if( a > b ) { ... } else {... }
if( a > b ) { ... }
else { ... }
или
if( ... )
{ ..... }
else
{ ..... }
3) длинные группы операторов:
if(... )
{
.
.
.
}
else
{
.
.
.
}
4) множественный выбор:
if ( a == 6 ) { ... }
else if ( a == 8 ) { ... }
else if ( a == 15 ) { ... }
else if ( a > 20 && a < 28 ) { ... }
else { ... }
В некоторых случаях вместо оператора if удобно использовать условную операцию?:, которая позволяет сократить запись программ и число используемых переменных.
условное_операция = выр_0 "?" выр_1 ":" выр_2
Значение условной операции равно <выр_1>, если <выр_0> не равно 0 и <выр_2> в противном случае. Например, следующий оператор
if ( x>a ) f = sin( x-a ); else f = sin(x);
можно заменить условной операцией, и сразу вычислить f:
f = sin( x>a? x-a : x );
Очевидно, в последнем случае получился более короткий код, поскольку обращений к переменной f и функции sin вдвое меньше.
9.3. Запись алгоритмов с помощью диаграмм Несси - Шнейдермана (структограмм )
Язык Си является достаточно развитым для того, чтобы вообще обойтись без каких-либо особых способов записи алгоритмов.
Однако для тех, кто только начинает программировать, может понадобится более наглядное средство иллюстрации алгоритмов.
Раньше для таких целей широко использовались так называемые блок-схемы. Однако их применение очень легко может привести к появлению программ с неоправданно сложной структурой, в которой трудно разобраться.
Для описания логики работы программ вместо блок-схем можно использовать диаграммы Несси - Шнейдермана, которые отличаются тем, что пригодны для описания только структуированных программ (состоящих из базовых логических структур).
Рассмотрим базовые логические структуры и их представление в виде структограмм.
Процесс - один или несколько операторов, выполнение которых происходит последовательно. Изображается в виде прямоугольника, управление в который передается сверху, а выходит из него снизу:
![]() |
Проверка условия - управление передается в один из нижних процессов:
![]() |
Цикл - пока. Процесс повторяется несколько раз пока истинно условие.
9.4.
![]() |
Некоторые приемы программирования
Рассмотрим некоторые типовые приемы программирования и использования рассмотренных выше операторов.
Для подсчета различных объектов, получающихся в процессе работы программы используют счетчики, которые представляют собой переменные целого типа, меняющие свои значения в процессе выполнения счета. Использование счетчика покажем на примере
программы, которая подсчитывает количество отрицательных значений функции sin( x ) для x меняющегося от xn до xk с шагом h.
Вначале запишем алгоритм с помощью диаграммы Несси-Шнейдермана.
![]() |
Теперь можно рассмотреть программу на языке Си :
#include <math. h>
#include <stdio. h>
/* использование счетчика */
void main( void )
{
double xn, xk, h, x;
int Count; /* счетчик */
printf( "Введите xn, xk, h \n" );
scanf( "%lf%lf%lf", &xn, &xk, &h );
x = xn;
Count = 0; /* инициализация счетчика */
while( x <= xk )
{
if( sin(x) < 0 ) Count++; /* выполнение счета */
x += h;
}
printf( "Число отрицательных синусов = %d\n", Count);
}
Довольно часто в программах приходится вычислять суммы и произведения. При нахождении суммы надо выделить переменную для ее хранения, обнулить ее, затем циклически добавлять к ней очередное значение. Найдем сумму отрицательных значений функции sin(x) для x меняющегося от xn до xk с шагом h. Следующая программа решает эту задачу:
#include <math. h>
#include <stdio. h>
/* нахождение суммы отрицательных значений синуса */
void main( void )
{
double xn, xk, h, x, sum;
printf( "Введите xn, xk, h \n" );
scanf( "%lf%lf%lf", &xn, &xk, &h );
x = xn;
sum = 0; /* обнуление суммы */
while( x <= xk )
{
if( sin(x)<0 ) sum += sin(x); /* вычисление суммы */
x += h;
}
printf( "Сумма = %lf\n", sum);
}
Для повышения эффективности программы можно описать еще одну переменную, например sinus и изменить оператор вычисления суммы:
if( ( sinus = sin(x) ) < 0 ) sum += sinus;
В этом случае экономится время за счет однократного вычисления синуса.
Для вычисления произведения необходимо выделить переменную для его хранения, занести в эту переменную единицу и в цикле домножать ее на очередное значение.
Во многих сложных алгоритмах требуется запоминать факты наступления различных событий, связанных с процессом выполнения программы. Для этих целей используются флаги, которые представляют собой переменные целого типа, принимающие определенные значения в зависимости от этих событий. Простейший пример использования флагов иллюстрирует фрагмент программы, моделирующий работу оператора if с помощью оператора while. Иными словами, показывается, что при реализации программ можно вообще обойтись без оператора if. Действительно, рассмотрим следующий оператор if:
if( a > b ) k = sin(x); else k = x * x;
Очевидно, такие же действия будет выполнять группа операторов, использующая флаг и приведенная ниже:
fl = 1; /* флаг */
while ( a > b && fl ) { k = sin(x); fl = 0; }
while ( fl ) { k = x * x; fl = 0; }
В данном случае флаг сигнализирует о выборе одной из альтернатив оператора if.
Следующая программа устанавливает факт наличия отрицательных значений sin(x) для x меняющегося от xn до xk c шагом h :
#include <math. h>
#include <stdio. h>
/* использование флагов */
void main( void )
{
double xn, xk, h, x;
int minus; /* флаг */
printf( "Введите xn, xk, h \n" );
scanf( "%lf%lf%lf", &xn, &xk, &h );
x = xn;
minus = 0; /* предполагается, что нет не одного
отрицательного значения */
while( x <= xk )
{
if( sin(x) < 0 ) minus = 1;
x += h;
}
if( minus ) printf( "Имеются отрицательные значения\n" );
else printf( "Все синусы положительные\n" );
}
В данной программе флаг устанавливается в 1, как только появляется отрицательный синус.
9.5. Оператор прерывания цикла
Предыдущая программа имеет существенный недостаток: перебираются все значения синуса, хотя цикл можно остановить, когда появится первое отрицательное значение. Этот недостаток можно исправить, как показано в следующем фрагменте:
x = xn;
minus = 0;
while( x < xk && !minus )
{
...
}
В языке Си есть специальный оператор для прерывания цикла. Это оператор "break;". Выполнение его в программе немедленно прерывает цикл, в котором он находится и управление передается на следующий за циклом оператор. Используя оператор break, цикл предыдущей программы можно переписать в виде:
x = xn;
minus = 0;
while( x < xn )
{
if( sin(x) < 0 ) { minus = 1; break; }
x += h;
}
9.6. Оператор продолжения цикла
Оператор "continue;" вызывает переход к следующей итерации цикла, т. е. к очередной проверке условия. Естественно, все операторы тела цикла, находящиеся между continue и концом тела цикла пропускаются:

while( ... )
{
...
if(...) continue;
... /* операторы пропускаются */
}
Операторы break и continue позволяют избавиться от необходимости применения оператора goto, поэтому последний в этом методическом пособии не рассматривается.
9.7. Пример организации простейшего меню
Современный стиль программирования предписывает использовать в программах различного рода меню, которые предоставляют пользователю возможность выбора одного из предложенных действий. Следующая программа вычисляет sin(x), cos(x), tan(x) в зависимости от выбора пользователя:
#include <math. h>
#include <stdio. h>
/* Организация простейшего меню */
void main ( void )
{
int loop; /* Флаг, который сигнализирует о конце работы */
int choice; /* Текущий выбор пункта меню */
double fun, x; /* Значения функции и аргумента */
printf( "\nВведите аргумент x=" );
scanf( "%lf", &x );
loop=1;
while ( loop )
{
printf ( "\n Введите номер функции:\n" );
printf ( "1. sin(x)\n2. cos(x)\n" );
printf ( "3. tan(x)\n4. Конец работы\n" );
scanf ( "%d", &choice );
if (choice==1) fun=sin(x);
else if (choice==2) fun=cos(x);
else if (choice==3) fun=tan(x);
else if (choice==4) { loop=0; continue; }
else { printf( "Неверный выбор\n" ); continue; }
printf( "Значение функции %lf\n", fun );
}
}
Данная программа выводит на экран дисплея список возможных действий. Пользователь должен выбрать нужное, введя его номер.
Для управления выходом из цикла и организации конца работы программы используется флаг loop.
9.8. Множественный выбор. Оператор переключения
В предыдущей программе осуществлялся так называемый "множественный выбор", когда в зависимости от значения некоторой переменной целого типа выбиралось одно из нескольких действий.
Для осуществления подобных операций в языке Си существует специальный оператор "switch" - переключатель. Используя этот оператор, вместо вложенных "if" в предыдущей программе можно записать следующую конструкцию:
switch ( choice )
{
case 1 : fun=sin(x); break;
case 2 : fun=cos(x); break;
case 3 : fun=tan(x); break;
case 4 : loop=0; break;
default: printf( "Неверный выбор\n" ); break;
}
Здесь ключевое слово "case" (случай) указывает на то, что следующая константа является значением переменной choice, для которого выполняются соответствующие действия.
Оператор "break;" осуществляет выход из оператора "switch", а не из цикла. Именно поэтому для выхода из цикла пришлось использовать специальный флаг loop.
Ключевое слово "default" ( умолчание ) означает, что следом записаны действия, выполняющиеся, если значение choice не совпадет ни с одной из констант, указанных за "case".
Оператор switch в общем виде выглядит так:
оператор_переключения =
"switch" "(" выражение ")"
"{"
"case" константа ":" { оператор }
"case" константа ":" { оператор }
[ "default" ":" { оператор } ]
"}"
В качестве выражения можно использовать любое выражение, имеющее символьный или целый тип. Константы тоже должны быть символьного или целого типа, например case 4 , case 'A'.
Допускается использовать несколько констант для пометки одной группы операторов, например
case 2 :
case 4 :
case 8 : f = sin(x); break;
Если группа операторов не завершается оператором break, то будут выполняться все последующие операторы независимо от наличия case с константами до ближайшего break или другого оператора, прерывающего естественную последовательность действий. Иными словами ключевое слово case с константой надо рассматривать как метку для передачи управления. Так, в следующем операторе
switch( ch )
{
case 'A' :
case 'B' : x++;
case 'C' :
case 'D' : f = sin(x); break;
case 'E' : f = cos(x); break;
}
будет вычислено f=sin(x+1), при ch равном 'A' или 'B'; f=sin(x), при ch равном 'C' или 'D'; f=cos(x), при ch равном 'E'.
При использовании оператора switch необходимо внимательно следить за правильностью написания ключевого слова default и за тем, чтобы между ключевым словом case и числовой константой обязательно имелся пробел. В противном случае, эти конструкции будут приняты за правильно записанные метки для оператора goto, и компилятор не выдаст никакой диагностики.
9.9. Оператор цикла do-while.
Оператор цикла do-while предназначен для реализации циклических алгоритмов и имеет следующую форму записи
цикл_do-while =
"do" оператор "while" "("выражение")" ";"
Оператор выполняется циклически до тех пор, пока выражение отлично от нуля. В отличие от оператора while, тело оператора do-while выполняется хотя бы один раз до первого вычисления условия.
Работу оператора do-while проиллюстрируем на примере программы, которая определяет корень уравнения x-cos(sin(x))=0 методом итераций, который заключается в циклическом вычислении очередного приближения x_new по предыдущему приближению x_old, согласно выражению x_new=cos(sin(x_old)), вытекающему из исходного уравнения. Процесс итерации заканчивается тогда, когда x_new станет равен x_old. Программа, реализующая этот алгоритм, приведена ниже.
#include <stdio. h>
#include <math. h>
/* Решение уравнения x-cos(sin(x))=0 */
void main (void)
{
double x_new=0.9, x_old, eps=0.0001;
do
{
x_old = x_new;
x_new = cos(sin(x_old));
} while ( fabs( x_new - x_old ) > eps );
printf ( "x=%lf", x_new );
}
Сравнение двух вещественных чисел осуществляется с использованием точности eps. Это необходимо потому, что из-за погрешностей округления прямая проверка на равенство двух вещественных чисел скорее всего даст в результате 0 (ложь).
9.10. Перечисления. Работа с клавиатурой IBM PC
Перечисления используются для задания символических имен константам целого типа.
перечисление =
"enum" [ имя_перечисления ]
"{"
имя_конст [ "=" конст_выр ]
{ "," имя_конст [ "=" конст_выр ] }
"};"
Здесь имя_перечисления - любое символическое имя; имя_конст - символическое имя, назначаемое константе; конст_выр - константное выражение, то есть такое, которое не содержит переменных и функций и может быть определено на этапе компиляции.
Если константное выражение отсутствует, то имени назначается значение предыдущего выражения, увеличенное на единицу. Если отсутствует выражение, соответствующее первому имени константы, то ему назначается значение 0. Например:
enum DAYS { MON=1, TUE, WED, THU, FRI, SAT, SUN };
enum MONTH { JAN=1, FEB, MAR, APR, MAY, JUN,
JUL, AUG, SEP, OCT, NOV, DEC };
В дальнейшем в программе эти имена можно использовать вместо целых констант. Например, DEC вместо 12, THU вместо 4 и т. д.
Рассмотрим использование перечислений для организации удобной работы с клавиатурой IBM PC.
В библиотеке conio имеется функция, осуществляющая ввод одиночного символа (точнее его кода) без отображения его на экране дисплея. Она имеет следующий прототип:
int getch( void );
При обращении к этой функции выполнение программы приостанавливается до нажатия на клавишу. После нажатия на клавишу код соответствующего символа возвращается в виде целого числа.
Некоторым клавишам клавиатуры не соответствует ни один символ из кодовой таблицы. При нажатии на подобные клавиши getch() вначале возвращает нулевое значение. Если при этом обратиться к функции повторно, то она возвратит условный номер клавиши на клавиатуре, так называемый скэн-код. Это свойство используется в функции GetCh() для расширения возможностей getch(). Функция GetCh() будет возвращать коды символов в обычных случаях. При нажатии специальной клавиши GetCh() возвратит скэн-код, увеличенный на 256 (0x100) или на 512 (0x200), в зависимости от того, была ли нажата клавиша Shift или нет. Текст функции GetCh() приводится ниже.
#include <conio. h>
#include <bios. h>
/* Ввод одиночного символа с клавиатуры */
int GetCh( void )
{
int ch;
if( ( ch = getch() ) == 0 )
ch = getch() | ( bioskey(2) & 3 ? 0x200 : 0x100 );
return ch;
}
Здесь, выражение bioskey(2) & 3 осуществляет проверку нажатия клавиши Shift и отлично от нуля, если последняя нажата.
Прототип функции GetCh() и коды специальных клавиш перечисления KeyboardCodes, получаемых с помощью этой функции, следует поместить в файл, например, keyboard. h и в дальнейшей использовать не числовые значения кодов, а только символические имена. Фрагмент перечисления KeyboardCodes приведен ниже:
enum KeyboardCodes
{
kbF1 = 315, kbF2, kbF3, kbF4, ..., kbF10,
kbShiftF1 = 596, kbShiftF2, kbShiftF3, ..., kbShiftF10,
kbCtrlF1 = 350, kbCtrlF2, kbCtrlF3, ..., kbCtrlF10,
kbAltF1 = 360, kbAltF2, kbAltF3, ..., kbAltF10,
kbAlt1 = 376, kbAlt2, kbAlt3, ..., kbAlt0,
kbAltQ = 272, kbAltW, kbAltE, ..., kbAltP,
kbAltA = 286, kbAltS, kbAltD, ..., kbAltL,
kbAltZ = 300, kbAltX, kbAltC, ..., kbAltM,
kbCtrlA = 1, kbCtrlB, kbCtrlC, ..., kbCtrlZ,
kbUp = 328, kbDown = 336, kbTab = 9,
kbCtrlUp = 397, kbCtrlDown = 401, kbCtrlTab = 404,
kbAltUp = 408, kbAltDown = 416, kbAltTab = 421,
kbShiftUp = 584, kbShiftDown = 592, kbShiftTab = 527,
kbRight = 333, kbLeft = 331, kbEsc = 27,
kbCtrlRight = 372, kbCtrlLeft = 371,
kbAltRight = 413, kbAltLeft = 411, kbAltEsc = 257,
kbShiftRight = 589, kbShiftLeft = 587,
kbPgUp = 329, kbPgDn = 337, kbIns = 338,
kbCtrlPgUp = 388, kbCtrlPgDn = 374, kbCtrlIns = 513,
kbAltPgUp = 409, kbAltPgDn = 417, kbAltIns = 418,
kbShiftPgUp = 585, kbShiftPgDn = 593, kbShiftIns = 594,
kbHome = 327, kbEnd = 335, kbDel = 339,
kbCtrlHome = 375, kbCtrlEnd = 373, kbCtrlDel = 515,
kbAltHome = 407, kbAltEnd = 415, kbAltDel = 419,
kbShiftHome = 583, kbShiftEnd = 591, kbShiftDel = 595,
kbEnter = 13, kbBackspace = 8,
kbCtrlEnter = 10, kbCtrlBackspace = 127,
kbAltEnter = 284, kbAltBackspace = 270
};
Предложенная методика работы с клавиатурой IBM PC не требует никаких изменений исходных текстов программ, использующих функцию GetCh(), в случае изменения аппаратных средств.
9.11. Пример организации светового меню
Меню современных программ, как правило, представляет собой набор строк по которому перемещается светлый прямоугольник - световое окно. Для написания программ с подобным меню необходимо уметь выводить в нужное место экрана информацию разными цветами.
Экран IBM PC имеет 25 строк и 80 позиций. Нумерация строк и позиций начинается с 1. Первая строка находится вверху, первая позиция слева. Все необходимые функции работы с экраном IBM PC имеются в библиотеке компилятора, их прототипы находятся в файле conio. h. Рассмотрим некоторые из этих функций:
void clrscr( void ); - осуществляет стирание экрана;
void gotoxy( int x, int y ); - перемещает курсор в позицию x строки y;
void cprintf( char *format, ... ); - выполняет то же самое, что и printf, но выводит информацию, используя установленный цвет фона и цвет символа;
void textcolor( int color ); - установка цвета символа с кодом color;
void textbackground( int color ); - установка цвета фона с кодом color;
Последние функции не изменяют цвет уже выведенных символов. Их влияние распространяется на все последующие выводы с помощью функции cprintf.
При установке цвета допускается использовать шестнадцать цветов символа с кодами 0...15, и восемь цветов фона с кодами 0...7. Для удобства работы с цветами в conio. h определены мнемонические имена для цветов:
enum COLORS {
/* цвета для символов и фона */
BLACK /* черный */, BLUE /* синий */,
GREEN /* зеленый */, CYAN /* салатовый */,
RED /* красный */, MAGENTA /* малиновый */,
BROWN /* коричневый */, LIGHTGRAY /* светло-серый */,
/* цвета только для символов */
DARKGRAY /*темно-серый */, LIGHTBLUE /* ярко-синий */,
LIGHTGREEN /*ярко-зеленый*/, LIGHTCYAN /*ярко-салатовый*/,
LIGHTRED /*ярко-красный*/, LIGHTMAGENTA /*ярко-малиновый*/,
YELLOW /* желтый */, WHITE /* белый */ };
Приведенная ниже программа вычисляет функции sin(x), cos(x) и tan(x) в зависимости от выбора пользователя. Выбор осуществляется с помощью светового меню. Движение светового окна организуется путем перерисовки пункта меню другим цветом фона. Основной цикл этой программы управляет изменением переменной choice, в которой хранится текущий выбор пользователя.
#include <stdio. h>
#include <math. h>
#include <conio. h>
#include "keyboard. h"
#define N 4
#define ROW 10
#define COL 35
#define TEXT_C WHITE
#define TEXT_BG BLACK
#define CHOICE_BG LIGHTGRAY
void out_str( int num, int bg_color );
/* Организация светового меню */
void main ( void )
{
int loop; /* Флаг конца работы */
int choice; /* Текущий выбор пункта меню */
int old_choice; /* Старый выбор пункта меню */
double fun, x; /* Значения функции и аргумента */
int i;
textbackground( TEXT_BG ); textcolor( TEXT_C );
clrscr(); gotoxy( COL, ROW-1 );
cprintf( "Аргумент x=" ); scanf( "%lf", &x );
/* Начальный вывод всех пунктов меню */
i=1; while( i <= N ) { out_str( i, TEXT_BG ); i++; }
loop = 1; choice = 1; old_choice = 2;
while ( loop )
{
out_str( old_choice, TEXT_BG );
out_str( choice, CHOICE_BG );
old_choice = choice;
switch( GetCh() )
{
case kbUp :
if ( choice>1 ) choice--; else choice = N; break;
case kbDown :
if ( choice<N ) choice++; else choice = 1; break;
case kbEnter :
switch ( choice )
{
case 1 : fun=sin(x); break;
case 2 : fun=cos(x); break;
case 3 : fun=tan(x); break;
case 4 : loop=0; continue;
}
textbackground( TEXT_BG ); gotoxy( COL-5, ROW+6 );
cprintf( "Значение функции %lf\n", fun );
}
}
}
/* Функция вывода строки меню с указанным цветом фона */
void out_str( int num, int bg_color )
{
textbackground( bg_color ); gotoxy( COL, ROW+num );
switch( num )
{
case 1: cprintf( "1. sin(x) " ); break;
case 2: cprintf( "2. cos(x) " ); break;
case 3: cprintf( "3. tan(x) " ); break;
case 4: cprintf( "4. Конец работы" ); break;
}
}
На аналогичных принципах могут быть построены более сложные диалоговые программы, имеющие разнообразные вертикальные, горизонтальные, вложенные и выпадающие меню, управляемые световым окном.
9. Массивы. Адресная арифметика языка Си
Массив - это совокупность элементов данных одного и того же типа, объединенных общим именем и расположенных в непрерывной области памяти ЭВМ так, что к каждому элементу массива можно получить доступ, зная его порядковый номер или индекс.
9.1. Описание массива
Описание массива производится с помощью обычного оператора описания, при этом за именем массива в квадратных скобках должна быть записана целая положительная константа или константное выражение, равное размеру этого массива, то есть максимально возможному числу элементов. Например:
int a[100], ab[2*40];
double c[200], speed[100];
char name[20];
Имя массива без квадратных скобок за ним имеет значение, равное адресу первого элемента этого массива.
Имя массива с квадратными скобками, в которых записано индексное выражение целого типа, обозначает значение соответствующего элемента массива. В языке Си нумерация элементов массива начинается с нуля, то есть для массива d из пяти элементов допустимы следующие обозначения:
d[0], d[1], d[2], d[3], d[4].
Индексированные переменные могут использоваться в любых выражениях в тех местах, где допускается применение переменных соответствующих типов.
При работе с индексированными переменными необходимо внимательно следить за тем, чтобы индексы не вышли из допустимого диапазона, определяемого описаниями массивов. Дело в том, что компилятор не проверяет факт выхода индексов за границы массива, а при ошибочном занесении данных за пределы массива может запортиться нужная информация и, скорее всего, компьютер зависнет.
9.2. Ввод-вывод массива
Язык Си не имеет встроенных средств для ввода-вывода массива целиком, поэтому массив вводят и выводят поэлементно с помощью циклов, как, например, в следующей программе:
#include <stdio. h>
void main(void)
{
double a[100]; int n, i;
printf("Введите количество чисел n = ");
scanf("%d", &n);
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 |






