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

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

№ 6.2

floatGetFuguresS(void** ppFigures, intcount)

{

floatS = 0;

for(inti = 0; i < count; i++)

{

void* p = ppFigures[i];

Figures kind = *((Figures*)p);

switch(kind)

{

caseFCyrcle:

S += pow((float)((Cyrcle*)p)->Rad,2)*3.14;

break;

caseFRectangle:

S += ((Rect*)p)->width*((Rect*)p)->len;

break;

caseFTriangle:

{

Triangle* t = (Triangle*)p;

floatpper = (t->side_a+t->side_b+t->side_c)/2;

// ɩɥɨɳɚɞɶ ɬɪɟɭɝɨɥɶɧɢɤɚ

S+= sqrtf(pper*(pper - t->side_a)

*(pper - t->side_b)

*(pper - t->side_c));

break;

}

default:

printf("Error in ɋalculation of Square!!! \n");

return0;

}

}

returnS;

}

№7.1.

Время жизни переменных программы определяется классом памяти. В языке Си принято различать статические (static), автоматические (auto) и динамические данные.

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

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

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

Модификаторы типов

За исключением типа void, основные типы данных могут иметь различные модификаторы. Модификаторы используются для более точного управления ситуацией. Ниже приведен список модификаторов:
signed
unsigned
short

Модификаторы signed, unsigned, long и short могут применяться к целочисленным типам. К символам можно применять signed и unsigned, long может применяться к типу double. Таблица показывает все допустимые комбинации стандарта ANSI С для 16-битных типов данных вместе с размером типа в битах и границами применения в Borland С++.

Тип Длина в битах Диапазон
char 8 от-128 до 127
unsigned char 8 от 0 до 255
signed char 8 от-128 до 127
int 16 от-32768 до 32767
unsigned int 16 от 0 до 65535
signed int 16 от -32768 до 32767
short int 16 от -32768 до 32767
unsigned short int 16 от 0 до 65535
signed short int 16 от -32768 до 32767
long int 32 от -2147483648 до 2147483647
unsigned long int 32 от 0 до 4294967295
signed long int. 32 от -2147483648 до 2147483647
float 32 от 3.4е-38 до 3.4е+38
double 64 от 1.7е-308 до 1.7e+308
long double 80 от 3.4е-4932 до 1.1e+4932

№ 7.2.

voidRemoveFigures(void** ppFigs, intcount)

{

intcounter = 0;

void* p = ppFigs[counter];

while(p != NULL)

{

Figures kind = *((Figures*)p);

switch(kind)

{

caseFCyrcle:

free((Cyrcle*)p);

printf("Cyrcle was removed. \n");

break;

caseFRectangle:

free( (Rect*)p);

printf("Rect was removed. \n");

break;

caseFTriangle:

free( (Triangle*)p);

printf("Triangle was removed. \n");

break;

default:

printf("Error in RemoveFigures!!! \n");

return;

}

ppFigs[counter] = NULL;

counter++;

if(counter == count)

return;

p = ppFigs[counter];

}

}

 

RemoveFigures(ppFigArray, realCount);

_CrtDumpMemoryLeaks();

return0;

}

№8.1.

Оператор if-else выражает процесс принятия альтернативных решений. Его формальный синтаксис таков:

i f (выражение)

оператор1

else

оператор2

Часть, начинающаяся со слова else, необязательна. Вначале вычисляется

выражение; если оно истинно (т.е. имеет ненулевое значение), то выполняется оператор!.

Если оно ложно (т.е. имеет нулевое значение) и присутствует блок else, то выполняется

оператор2. Поскольку в операторе if всего-навсего анализируется числовое значение

выражения, можно несколько упростить отдельные конструкции. Самый очевидный пример —

упрощение следующей конструкции:

if {выражение != 0)

Более краткая форма выглядит так:

if {выражение)

 

№8.2.

Реализация метода ввода фигур AddFigures представлено ниже:

// Метод для общего ввода фигур

intAddFigures(void** ppFigs)

{

intcounter = 0;

boolquit = false;

while(!quit)

{

if(counter > 3)

returncounter;

Основы создания программ в Си Page 26 of 37 printf("Enter Figure Kind: \n");

printf("1 - Cyrcle;\n");

printf("2 - Rectangle;\n");

printf("3 - Triangle;\n");

printf("e - Exit.\n\n");

intkey = getch();

switch(key)

{

case '1':

{ // блок для автоматической переменнойc

Cyrcle* c = CreateCyrcle();

if(c != NULL) // проверка что объект был создан

{

ppFigs[counter] = c;

counter++;

}

break;

}

case '2':

{ // блок для автоматической переменнойr

Rect* r = CreateRect();

if(r != NULL) // проверка что объект был создан

{

ppFigs[counter] = r; // добавление указателя на объект в массив

counter++;

}

break;

}

case '3':

{

Triangle* t = CreateTriangle();

if(t != NULL) // проверка что объект был создан

{

ppFigs[counter] = t;

counter++;

}

break;

}

case 'e':

case 'E':

printf("%d figures were created.\n\n", counter);

Основы создания программ в Си Page 27 of 37 returncounter;

break;

default:

printf("Enter correct number. Try again of Exit.\n");

}

}

printf("%d figures were created", counter);

returncounter;

}

№ 9.1

Цикл for

Если мы знаем точное количество действий (итераций) цикла, то можем использовать цикл for. Синтаксис его выглядит примерно так:

for (действие до начала цикла; условие продолжения цикла; действия в конце каждой итерации цикла) { инструкция цикла; инструкция цикла 2; инструкция цикла N;}

Итерацией цикла называется один проход этого цикла

Существует частный случай этой записи, который мы сегодня и разберем:

for (счетчик = значение; счетчик < значение; шаг цикла) { тело цикла;}

№9.2

#include "stdafx.h"

void ArrPrint(double *, int);
void Sort(double *, int);
void main()
{
double mas[10] = {4, 54, 5, -4, 87, 31, 6, 12, 1, 7}; // инициализируем массив
printf("Vvedenniy massiv \n");
ArrPrint(mas, 10);
printf("\nOtsortirovanniy massiv \n");
Sort(mas, 10);
ArrPrint(mas, 10);
printf("\n");
}

void ArrPrint(double *mas, int size)
{
for (int i = 0; i < size; i++)
printf("%.2lf ", mas[i]);
}

void Sort(double *mas, int size) // Функция сортировки массива
{
double temp;
for (int i = 0; i < size - 1; i++)
for (int k = 0; k < size - 1; k++)
if (mas[k] > mas[k + 1])
{
temp = mas[k];
mas[k] = mas[k + 1];
mas[k + 1] = temp;
}
}

 

№10.1

Цикл while

Когда мы не знаем, сколько итераций должен произвести цикл, нам понадобится цикл while или do...while. Синтаксис цикла while в C++ выглядит следующим образом.

while (Условие) { Тело цикла;}

Данный цикл будет выполняться, пока условие, указанное в круглых скобках является истиной. Решим ту же задачу с помощью цикла while. Хотя здесь мы точно знаем, сколько итераций должен выполнить цикл, очень часто бывают ситуации, когда это значение неизвестно.

Ниже приведен исходный код программы, считающей сумму всех целых чисел от 1 до 1000.

#include <iostream>using namespace std; int main(){ setlocale(0, ""); int i = 0; // инициализируем счетчик цикла. int sum = 0; // инициализируем счетчик суммы. while (i < 1000) { i++; sum += i; } cout << "Сумма чисел от 1 до 1000 = " << sum << endl; return 0;}

Цикл do while

Цикл do while очень похож на цикл while. Единственное их различие в том, что при выполнении цикла do while один проход цикла будет выполнен независимо от условия. Решение задачи на поиск суммы чисел от 1 до 1000, с применением цикла do while.

#include <iostream>using namespace std; int main (){ setlocale(0, ""); int i = 0; // инициализируем счетчик цикла. int sum = 0; // инициализируем счетчик суммы. do {// выполняем цикл. i++; sum += i; } while (i < 1000); // пока выполняется условие. cout << "Сумма чисел от 1 до 1000 = " << sum << endl; return 0;}

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

№10.2

К>struct DISTANCEК>{К> int least, greatest;К> double distance;К>}; К>DISTANCE Distance(const double* data, int length)К>{К> DISTANCE d;К> ...К> return d;К>}

 

 

№11.1

switch-case — это замена длинной if-else конструкции. Синтаксис:

1 2 3 4 5 6 7 8 9 10 11 12 switch ( <переменная> ) { case значение1: Выполнить если <переменная> == значение1 break; case значение2: Выполнить если <переменная> == значение2 break; ... default: выполнить, если ни один вариант не подошел break; }

№11.2

floatGetFuguresS(void** ppFigures, intcount)

{ // рсчитываемая площадь

floatS = 0;

// цикл обхода заданного числа элементов массива

for(inti = 0; i < count; i++)

{

void* p = ppFigures[i]; // указатель на объект фигуры

// получаем тип фигуры из указателя на объект

Figures kind = *((Figures*)p);

switch(kind)

{

caseFCyrcle:

S += pow((float)((Cyrcle*)p)->Rad,2)*3.14;

break;

caseFRectangle:

S += ((Rect*)p)->width*((Rect*)p)->len;

break;

caseFTriangle:

{

Triangle* t = (Triangle*)p;

// полупериметр

floatpper = (t->side_a+t->side_b+t->side_c)/2;

// площадь треугольника

S+= sqrtf(pper*(pper - t->side_a)

*(pper - t->side_b)

*(pper - t->side_c));

break;

}

default:

// случай ошибки в данных

printf("Error in С alculation of Square!!! \n");

return0;

}

}

returnS;

}

№12.1

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

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

Наиболее типичным блоком кода, в котором объявляются локальные переменные, является функция. Например, рассмотрим две функции:

void func1 (void)

{

int x;

x= 10;

)

void func2(void)

{

int x;

x = -199;

Целочисленная переменная x объявляется дважды: один раз в func1() и другой раз в func2(). х в func1() не имеет отношения к х в func2(), поскольку каждая х известна только в блоке, где произошло объявление переменной.

№12.2

Макросы - это препроцессорные "функции" , т.е. лексемы, созданные с помощью директивы #define, которые принимают параметры подобно функциям. После директивы #define указывается имя макроса, за которым в скобках (без пробелов) параметры, отделенные запятыми и определение макроса, отделенное пробелом.

Например:

#define ADD(x,y) x = x + y

если после этого написать:

int a=2;int b=3;ADD(a,b);cout

то получим:

a=5 b=3

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

#define MACRO1(x) x * x#define MACRO2(x) ( x ) * ( x )int a =2;int b=3;cout

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

#include "stdio.h"#include <stdio.h>

 

№13.1

Массивы и указатели

Массивы и указатели довольно тесно связаны между собой. Имя массива можно разыменовывать, как указатель. В свою очередь, указатель можно индексировать, как массив, если это имеет смысл. Поэтому мы рассматриваем массивы и указатели в одном разделе.

Массивы

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

int myArray[8];

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

int iArray[8] = {7, 4, 3, 5, 0, 1, 2, 6);

Обращение к отдельным элементам массива производится путем указания индекса элемента в квадратных скобках, например:

myArray[3] = 11;

myArray[i] = iArray[7-i];

Индекс должен быть целым выражением, значение которого не выходит за пределы допустимого диапазона. Поскольку индексация массивов начинается в С всегда с нуля (т. е. первый элемент имеет индекс 0), то, если массив состоит из N элементов, индекс может принимать значения от О до N-1.

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

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

№13.2

Условная компиляция

Условные конструкции препроцессора позволяют компилировать или пропускать часть программы в зависимсти от выполнения некоторого условия. Условие может принимать одну из описываемых ниже форм. #if константное_выражение Проверяется значение выражения, составленного из констант и если оно не равно нулю, компилируется (включается) последующий текст. #ifdef идентификатор Последующий тест компилируется, если "идентификатор" уже был опредеоен для препроцессора в команде #define. #ifndef идентификатор Последующий текст компилируется, если "идентификатор" в данный момент не определен. Конструкция #undef идентификатор исключает "идентификатор" из списка определенных для препроцессора имен. За любой из трех условных команд может следовать произвольное число строк текста, содержащих, возможно, команду вида #else и заканчивающихся #endif. Если проверяемое условие справедливо, то строки между #else и #endif игнорируются. Если же проверяемое условие не выполняется, то игнорируются все строки между проверкой и командой #else, а если ее нет, то командой #endif. Приведенная на примере 6.7 программа иллюстрирует применение некоторых из рассмотренных выше команд, обеспечивающих условную компиляцию. Пример 6.7
#define SIZE 16 #include stdio.h main() { char c='A'; #ifdef SIZE int x=123; printf("x=%d\n",x); #else static char x[SIZE]=" информатика "; printf("x=%s\n",x); #endif printf("%c\n",c); }

№18.2

Последовательности символов, начинающиеся с обратной косой черты, называютуправляющими, или escape-последовательностями.

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

Изображение Шестнадцатеричный код Наименование
\a 7 Звуковой сигнал
\b 8 Возврат на шаг
\f С Перевод страницы (формата)
\n А Перевод строки
\r D Возврат каретки
\t 9 Горизонтальная табуляция
\v В Вертикальная табуляция
\\ Обратная косая черта
\’ 27 Апостроф
22 Кавычка
\? 3F Вопросительный знак
\0ddd Восьмеричный код символа
\0xddd ddd Шестнадцатеричный код символа

Вообще, символ обратной косой черты используется для представления: