Статические переменные и функции — КиберПедия 

Индивидуальные и групповые автопоилки: для животных. Схемы и конструкции...

История создания датчика движения: Первый прибор для обнаружения движения был изобретен немецким физиком Генрихом Герцем...

Статические переменные и функции

2018-01-28 205
Статические переменные и функции 0.00 из 5.00 0 оценок
Заказать работу

Функции и пе­ременные, для которых указан класс памяти static, видимы лишь от точки описания до конца файла. Если пользователь не указал начального зна­чения, то все статические переменные, как и внешние, инициируются значением нуль. Инициирование струк­турных статических переменных выполняется по тем же правилам, что и внешних. Если статическая переменная описана внутри фун­к­ции, то первый раз она инициируется при входе в блок функции. Значение переменной сохра­няет­ся от одного вызова функции до другого. Таким образом, статические переменные можно использовать для хра­не­ния значений внутри функции на протяжении времени работы программы, при­чем такие переменные будут невидимы вне файла, где они опреде­ляют­ся.

Внешние переменные

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

Операции

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

К арифметическим операциям относятся: сложение (+), вычитание (-), деление (/), умножение (*) и оста­ток от деления (%). Остаток не опре­де­лен для ве­щественных переменных. Целочисленные сложение и вычитание выпол­няются без учета переполнения.

Операция поразрядного сдвига целого числа E влево или вправо на E2 разрядов имеет вид соответственно: E<<E2 или E>>E2.

Операции отношения

В языке определены следующие операции отношения: ра­вен­ство (==, два знака равества), неравенство (!=), меньше (<), меньше или равно (<=), больше (>), больше или равно (>=).

Все перечисленные операции вырабатывают результат типа int (в числовых выражениях) или bool (в логических выражениях). Если данное отношение между операндами истин­но, то значение этого целого - единица (true), а если отноше­ние ложно, то нуль (false).

Все операции типа «больше - меньше» имеют равный прио­ритет, причем он выше, чем приоритет операций == и!=. Приоритет операции присваивания ниже приоритета всех операций отношения. Для задания правильного порядка вы­числений используются скобки.

 

Логические операции

Допускаютсяследующие логические операции: && (И), || (Или, две верти­каль­ные черточки),! (отрицание, восклицательный знак).

Аргументами логических операций могут быть любые числа, вклю­чая задаваемые аргументами типа char или логические переменные (bool). Ре­зультат логической операции аналогичен результату операции срав­нения. Вообще все числовые значения, отличные от ну­ля, интерпре­тируются как истина.

Логические операции имеют самый низкий приоритет.

Внимание! Вычисление выражений, содержащих логические опера­ции, производится слева напра­во и прекращается (усека­ется), как только удаст­ся определить резуль­тат, т.е. остальные проверки, не влияющие на ко­нечный результат, не производятся.

Для целочисленных переменных существуют операции поразрядного И (&), ИЛИ (^), исключающего ИЛИ (|, вертикальная черта), отрицания (~, тильда).

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

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

Пример: а = (b = c) * d; // в начале вычисляется b = c, далее a=b*d.

Пример использования многократного при­сваивания: a=b=c=d=e=0.

Операции a+=b, a-=b, a*=b и a/=b являются укороченной фор­мой записи, соответственно: а = а + b; а = а - b; a= а* b; а = а/b.

Префиксные и постфиксные операции «++» (два плюса) и «–» (два минуса) исполь­зуют для уве­ли­че­ния (инкремент) и уменьшения (декре­мент) на единицу значения пере­мен­ной до использования переменной в выражении, если операция указана пе­ред именем переменной; если операция указана после имени перемен­ной, то после использования пере­мен­ной соответственно.

Если тип левой части присваивания отличается от типа правой части, то тип правой части приводится к типу левой.

Пример вычисления выражения и вывода его значения (50):

int main(int argc, char **argv) { int a,b,c=3,d=4,f=3,g,h=5,z=6,i;

a=z+(b=c*d*f +(g= h +(i=3))); printf (“%d\n”, a); getch(); return 0; }

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

Операция «запятая» применяется для связывания меж­ду собой выражений. Список выражений, разделенный запя­тыми, трактуется как единое выражение и вычисляется слева направо.

Операторы

Блоки и составные операторы

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

1.2.10.2. Оператор возврата из функции ‑ return

return [<выражение>];

Оператор предназначен для выход из функции со значением указан­ного выражения. Если выражение отсутствует, то в объявлении функции это указывается параметром void перед именем функции.

 

1.2.10.3. Условный оператор ‑ if

if ( <условие> ) <оператор-1 >[ else <оператор-2>]

Если условие истинно, то выполня­ется <оператор-1>, в противном случае - <оператор-2>. Синтаксис предписывает, что else всегда относится к ближайшему оператору if.

Пример вложенногооператораif:

int main(int argc, char **argv) { int i = 4, j = 6, k = 8; if (i < k) if (i > j)

printf («оператор 1\n»); else printf («оператор 2\n»);getch(); return 0; }

1.2.10.4. Условная операция ‑?

< результат >= (< условие >)? < выражение-1>: < выражение-2 >

Если условие истинно, то результату присваивается значение <выражение-1>, иначе ‑ < выражение-1>.

Пример: main () { int i = 6, j = 4; int result = (i < j)? i: j; }

 

1.2.10.5. Оператор выбора варианта ‑ switch

switch (< выражение >)

{case <константное выражение_1>: <операторы> [ < break; > ]

...

case <константное выражение_n >: <операторы> [ < break; > ]

[ default: <операторы>]

}

После вычисления выражения в заголовке оператора его результат последовательно сравнивается с констант­ными выражениями, начиная с самого верхнего, пока не будет установлено их соответствие. Тогда вы­пол­няют­ся операторы внутри соответствующего case, управление пе­рехо­дит на следующее константное выражение, и проверки продолжаются. Именно поэтому в конце каждой последова­тельности операторов должен присутствовать оператор break. После выполнения последовательности операторов внутри одной ветки case, завершающейся оператором break, происходит выход из оператора switch. Обычно оператор switch исполь­зуется тогда, когда программист хочет, чтобы была выполнена только од­на последователь­ность операторов из нескольких возможных. Каждая последовательность операторов может содер­жать нуль или бо­лее от­дельных операторов. Фигурные скобки в этом случае не требуются.

Если ветка, называемая default (умолчание) есть, то пос­ле­до­ва­тель­ность опе­раторов, стоящая непосредственно за словом de­fault и дво­е­­­точием, выполняется только тогда, когда сравнение ни с од­ним из стоя­щих выше константных выражений не ис­тинно.

1.2.10.6. Оператор безусловного перехода ‑ goto

Оператор goto используется для передачи управления внутри функции от одного оператора к другому. Синтаксис оператора такой:

goto < идентификатор >. Управление передается безусловно на оператор, помеченный указанным идентификатором.

Пример: goto backend;... backend: x+= 3;...

Рекомендуется минимизировать число операторов goto и не вхо­дить извне внутрь бло­ка операторов if, else, switch или операто­ров цикла.

1.2.10.7. Цикл с предусловием ‑ while

while (<условие>) <оператор>.

Проверка условия про­изводится перед выполнением тела цикла. Если результат вычисления условного выражения ‑ истина, то выпол­няется оператор (или группа операторов). Перед входом в цикл while в первый раз обычно инициализируют одну или несколько переменных для то­го, чтобы условное выражение имело какое-либо значение. Оператор или группа операто­ров, составляющих тело цикла, должны, как правило, из­­менять значения одной или нескольких переменных, входя­щих в ус­лов­ное выражение, с тем, чтобы в конце концов выражение обратилось в нуль, и цикл завершился. Оператор continue передает управ­ле­ния на начало следующего повторения цикла. Цикл while завершается, если условие ста­ло ложным или в теле цикла встретился оператор break или return.

Пример программы поиска элемента в массиве:

int main(int argc, char **argv) // основная функция

{ int scores[100];extern int search(int data[ ],int size,int key);// объявл.функции

int i; for (i = 0; i < 100; i++) scores [ i ] = i; // заполнение массива

printf(«\nИндекс числа 107 в массиве = %d\n»,search (scores, 100, 107));

getch(); return 0;

} // конец основной функции

int search (int data [],int size,int key) // функция поиска элемента массива

{ int index = 0; while (index < size && data [ index ]!= key) index++;

return (data [index]==key)?index: -1; }

1.2.10.8. Цикл с постусловием ‑ do while

В цикле do while проверка условия осуществляется после выпол­нения тела цикла. Синтаксис цикла: do <оператор> while (<условие>);

Оператор continue передает управление на начало следующего пов­то­рения цикла. Цикл прекращает выполняться, когда условие становится ложным или внутри цикла встретился оператор break или return.

Пример функции сравнения двух строк (str1, str2):

int main(int argc, char **argv) // основная функция

{ extern int compare (char str1 [ ], char str2 [ ]); char str1 [ 80 ], str2 [ 80 ];

printf («\nВведите первую строку: «); scanf(«%s», str1); // ввод строки 1

printf («\nВведите вторую строку: «); scanf («%s», str2); // ввод строки 2

if (compare (str1,str2)< 0) printf («\nПервая строка меньше второй «);

else if (compare (str1,str2)==0) printf («\n\nПервая строка равна второй»);

else printf («\n\nПервая строка больше второй»); getch();

} // конец основной функции

int length (char str [ ]) // функция вычисления длины строки

{ int index=0; while (str [index++]!= 0); return -index; }

int compare (char str1 [ ], char str2 [ ]) // функция сравнения строк

{ extern int length(char str[ ]); int len1 = length(str1); int len2=length(str2);

int index=-1; int minlength=(len1<len2)?len1:len2; // длина короткой строки

do index++; while (index < minlength && str1[index] ==str2[index]);

if (len1== len2 && str1[index] == str2[index]) return 0; // строки равны

if (str1[index]==str2[index] &&len1 < len2)return -1; // строка 1 < строки 2

if (str1[index]==str2[index] &&len2 > len1) return 1; // строка 1 > строки 2

if (str1[index ]<str2[index]) return -1; else return 1; // строка 1 > строки 2

}

1.2.10.9. Итерационный цикл ‑ For

for ( [<выражение-1>]; [<выражение-2>]; [< выражение-3>] ) <оператор>

Формально правила выполнения этого оператора можно описать так:

1. Если первое выражение присутствует, то оно вычисляется.

2. Вычисляется второе выражение (если оно присутству­ет). Если вы­ра­­ба­ты­вается значение 0 (false), то цикл пре­кращается, в противном случае цикл будет продолжен.

3. Исполняется тело цикла (<оператор>).

4. Вычисляется третье выражение (если оно присутствует).

5. Переход к пункту 2.

Появление в любом месте тела цикла оператора continue или break при­во­дит к переходу к шагу 4 или к выходу из цикла соответственно.

Пример программы подсчета суммы ряда 1+1/2+1/3+1/4+...1/1000:

int main(int argc, char **argv) {

float s, i; for (s=0,i=1;i<=1000; s+=1/i++); printf («\n%20.8f», s); getch(); }

Пример программы подсчета среднего числа массива чисел 1,2,..,100:

# define size 100 // макроподстановка размерности массива - 100

int main(int argc, char **argv) { // основная функция

int data [size]; extern float average (int a[ ], int s); int i;

for (i=0; i<size; i++) data [i]= i; // заполнение массива числами от 0 до 99

printf(«\nСреднее значение массива data=%f\n»,average(data,size));getch(); }

float average(int a [ ], int s) // функция подсчета среднего числа массива

{ float sum = 0.0; int i; for (i = 0; i < s; i++) sum += a [ i ]; return sum / s; }

Пример программы вычисление максимальных и минимальных зна­чений элементов массива случайных чисел:

# define size 100 // макроподстановка size=100 ‑ размерность массива

int main(int argc, char **argv) { // основная функция

float scores [size]; // объявление массива из ста вещественных чисел

float max(float data[ ],int s), min(float data[ ],int s); // объявление функций

int i; randomize(); // включение счетчика случайных чисел

for (i =0; i < size; i++) scores[ i ]= rand(); // заполнение массива случ.чисел

printf («\nМаксимальное значение = %f», max(scores, size));

printf («\nМинимальное значение = %f\n», min(scores, size)); getch(); } float max(float data [ ], int s) { // функция поиска максимального числа

float maximum = data [ 0 ]; int i; for(i=1;i <s; i++)

if (data[i]>maximum) maximum=data[i]; return maximum; }

float min(float data [ ], int s) { // функция поиска минимального числа

float minimum = data [0]; int i; for (i = 1; i < s; i++)

if (data [1] < minimum) minimum = data [i]; return minimum; }

Пример программы сортировки «методом пузырька» массива из десяти случайных чисел. В основной функции в массив data заносится size (десять) вещественных чисел, затем вызывается функция сортировки bubble_sort, после чего от­сортированный массив распечатывается.

На первом проходе алгоритма сортировки все элементы массива, начиная с последнего, сравниваются попарно, и если элемент а[j] оказы­вает­ся меньше, чем элемент а[j-l], то элементы меняются мес­тами. После завершения первого прохода наименьший элемент массива будет помещен в a[0]. На втором проходе выполняются те же действия, однако про­ход заканчивается на элементе a[1]. После второго прохода второй по значе­нию элемент будет в a[1] и т.д. Название «метод пузырька» дано алго­рит­му потому, что при каждом просмотре наименьшие элементы как бы мед­ленно всплывают «наверх», подобно пузырьку воздуха в воде.

# define size 10 // макроподстановка size=10 ‑ размерность массива

int main(int argc, char **argv) { // основная функция

float data [size]; // объявление массива

extern void bubble_sort(float a[ ], int s); // объявление функции сортировки

int index; randomize(); // включение счетчика случайных чисел

for (index=0;index<size;index++) data[index]=rand(); // заполнение массива

bubble_sort (data, size); // обращение к функции сортировки массива

for (index=0;index<size; index++)// цикл вывода отсортированного массива

printf(«\ndata [ %d ] = %f», index, data [ index ]); getch(); }

void bubble_sort(float a [ ], int s) { // функция сортировки массива

int i, j; float temp; // объявление переменных

for (i=0;i<s-1;i++) // внешний цикл

for(j=s-1;j>1;j--) // внутренний цикл

if (a[j]<a[j-1]) {temp=a[j]; a[j]=a[j-1];a[j-1]=temp;} }

 

Пустой оператор

Пустой оператор представляется символом «;», перед которым нет вы­ра­жения. Пустой оператор используют там, где синтаксис языка тре­бует присутствия в данном месте программы оператора, однако по логике прог­раммы оператор должен отсутство­вать.

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

 

Указатели

Указатель - это адрес памяти. Значение указателя сообщает, где раз­­ме­щен объект, но не говорит о самом объекте. Пере­мен­­ная типа ука­за­­тель описывается так: <тип> * <переменная-указатель>. Данная запись означает, что переменная-указатель является указателем на любую переменную указанного типа.

Символ операции « (звез­дочка) используется для задания указателя на объект.

Пример: int *х; // указатель на любую переменную типа int. Указатель на тип void совместим с любым указателем.

Пример: void *х; int *y; // допустимо присваивание: y = x.

Двумя наиболее важными операциями, связанными с указателями, являются операция обращения по адресу (разадре­сации) и операция опре­де­ления адреса. Операция обращения по адресу (*) служит для прис­ваива­ния или счи­тывания значения переменной, размещенной по адресу «переменная‑ ука­затель» (*ptr_var = value).

Пример. Предложение *х=16 означает, что по адресу, зада­ваемому в х, помещается значение 16.

Операция определения адреса возвращает адрес памяти своего опе­ранда. Операндом должна быть переменная. Операция определения ад­реса выполняется следующим образом:

<указатель-переменная> = & <переменная>;

Пример. Запись a=*&b равносильна записи a=b.

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

Если переменная, например, ptr определена как указатель на струк­ту­ру, то для дос­тупа к полю структуры (field); можно ис­пользовать опера­цию -> в виде: ptr->field, которая эквивалентна выражению (*ptr).field.

Существует четыре способа задать переменной-указателю начальное значение:

• описать указатель вне любой функции или снабдить его предписанием static. Начальным значением явля­ется нулевой адрес памяти ‑ 0;

• присвоить указателю адрес переменной;

• присвоить указателю значение другого указателя;

• использовать операторы распределения памяти new и delete.

Операция динамического выделения памяти имеет вид:

<указатель-переменная> = new [ < имя переменной>] [<тип переменной>];

Операция возвращает нулевое значение, если не может выделить па­мять.

Операция освобождения выделенной памяти имеет вид:

delete <указатель-переменная>.

Примеры:

ptr=new int [3];// выделение памяти для массива из трех элементов типа int

ptrf=new float[3][5];// выделение памяти для массива 3 на 5 чисел типа float

ptrstack=new stack; //выделение памяти для структуры (записи) stack

delete ptrstack; // освобождается память выделенная ранее по адресу ptrstack

Пример динамического формирования и вывода стека

int main(int argc, char **argv) { // создание и вывод стека из чисел 1,2,3,4,5

struct stack { int inf; stack* next;}; // объявление структуры (записи) stack

stack *top=0,*kon,*del; //объявление переменных-указателей на запись stack

for (int i=1;i<=5;i++) // цикл формирования стека из пяти записей

{ kon=new stack; // выделение памяти для новой записи

kon->next=top; kon->inf=i; //запоминание адреса предыдущей записи

top=kon; // запоминание адреса последней записи (вершины стека)

} // конец цикла формирования стека

kon=top; // установка адреса вершины стека (последней записи стека)

while (kon!=0) // цикл вывода записей стека на экран (cout <<)

{cout<<kon->inf<<endl;del=kon;kon=kon->next;delete del;} //вывод 5,4,3,2,1

getch(); return 0; } // задержка и завершение работы функции

 


Поделиться с друзьями:

Биохимия спиртового брожения: Основу технологии получения пива составляет спиртовое брожение, - при котором сахар превращается...

Архитектура электронного правительства: Единая архитектура – это методологический подход при создании системы управления государства, который строится...

Археология об основании Рима: Новые раскопки проясняют и такой острый дискуссионный вопрос, как дата самого возникновения Рима...

Историки об Елизавете Петровне: Елизавета попала между двумя встречными культурными течениями, воспитывалась среди новых европейских веяний и преданий...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.089 с.