Основные конструкции языка Си

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

Рубрика Программирование, компьютеры и кибернетика
Вид курс лекций
Язык русский
Дата добавления 29.06.2016
Размер файла 165,3 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

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

- массив элементов заданного типа;

- указатель на объект заданного типа;

- функция, возвращающая значение заданного типа.

Массив - это упорядоченная последовательность переменных одного типа. Каждому элементу массива отводится одна ячейка памяти. Элементы одного массива занимают последовательно расположенные ячейки памяти. Все элементы имеют одно имя - имя массива и отличаются индексами - порядковыми номерами в массиве. Количество элементов в массиве называется его размером. Чтобы отвести в памяти нужное количество ячеек для размещения массива, надо заранее знать его размер. Резервирование памяти для массива выполняется на этапе компиляции программы.

6.1 Определение массива в Си/Си++

int a[100];//массив из 100 элементов целого типа

Операция sizeof(a) даст результат 400, т. е.100 элементов по 4 байта.

Элементы массива всегда нумеруются с 0.

0

1

2

…..

99

Чтобы обратиться к элементу массива, надо указать имя массива и номер элемента в массиве (индекс):

a[0] - индекс задается как константа,

a[55] - индекс задается как константа,

a[I] - индекс задается как переменная,

a[2*I] - индекс задается как выражение.

Элементы массива можно задавать при его определении:

int a[10]={1,2,3,4,5,6,7,8,9,10} ;

Операция sizeof(a) даст результат 40, т. е.10 элементов по 4 байта.

int a[10]={1,2,3,4,5};

Операция sizeof(a) даст результат 40, т. е.10 элементов по 4 байта. Если количество начальных значений меньше, чем объявленная длина массива, то начальные элементы массива получат только первые элементы.

int a[]={1,2,3,4,5};

Операция sizeof(a) даст результат 20, т. е.5 элементов по 4 байта. Длин массива вычисляется компилятором по количеству значений, перечисленных при инициализации.

6.2 Обработка одномерных массивов

При работе с массивами очень часто требуется одинаково обработать все элементы или часть элементов массива. Для этого организуется перебор массива.

Перебор элементов массива характеризуется:

- направлением перебора;

- количеством одновременно обрабатываемых элементов;

- характером изменения индексов.

По направлению перебора массивы обрабатывают :

- слева направо (от начала массива к его концу);

- справа налево (от конца массива к началу);

- от обоих концов к середине.

Индексы могут меняться

- линейно (с постоянным шагом);

- нелинейно (с переменным шагом).

6.2.1 Перебор массива по одному элементу

Элементы можно перебирать:

1) Слева направо с шагом 1, используя цикл с параметром

for(int I=0;I<n;I++){обработка a[I];}

2) Слева направо с шагом отличным от 1, используя цикл с параметром

for (int I=0;I<n;I+=step){обработка a[I];}

3) Справа налево с шагом 1, используя цикл с параметром

for(int I=n-1;I>=0;I--){обработка a[I];}

4) Справа налево с шагом отличным от 1, используя цикл с параметром

for (int I=n-1;I>=0;I-=step){обработка a[I];}

6.2.2 Формирование псевдодинамических массивов

При описании массива в программе надо обязательно указывать количество элементов массива для того, чтобы компилятор выделил под этот массив нужное количество памяти. Это не всегда бывает удобно, т. к. число элементов в массиве может меняться в зависимости от решаемой задачи. Динамические массивы реализуются с помощью указателей (см. далее).

Псевдодинамические массивы реализуются следующим образом:

1) при определении массива выделяется достаточно большое количество памяти:

const int MAX_SIZE=100;//именованная константа

int mas[MAX_SIZE];

2) пользователь вводит реальное количество элементов массива меньшее N.

int n;

cout<<”\nEnter the size of array<”<<MAX_SIZE<<”:”;cin>>n;

3) дальнейшая работа с массивом ограничивается заданной пользователем размерностью n.

0

1

2

3

n

MAX_SIZE

Т. о. используется только часть массива.

6.2.3 Использование датчика случайных чисел для формирования

массива

Датчик случайных чисел (ДСЧ) - это программа, которая формирует псевдослучайное число. Простейший ДСЧ работает следующим образом:

1) Берется большое число К и произвольное .

2) Формируются числа х1=дробная_часть(х0*К); х2=дробная_часть(х1*К); и т. д.

В результате получается последовательность чисел х0, х1, х2,. . . беспорядочно разбросанных по отрезку от 0 до 1. Их можно считать случайными, а точнее псевдослучайными. Реальные ДСЧ реализуют более сложную функцию f(x).

В Си++ есть функция

int rand() - возвращает псевдослучайное число из диапазона 0..RAND_MAX=32767, описание функции находится в файле <stdlib.h>.

Пример формирования и печати массива с помощью ДСЧ:

#include<iostream.h>

#include<stdlib.h>

void main()

{

int a[100];

int n;

cout<<”\nEnter the size of array:”;cin>>n;

for(int I=0;I<n;I++)

{a[I]=rand()%100-50;

cout<<a[I]<<” “;

}

}

В этой программе используется перебор массива по одному элементу слева направо с шагом 1.

Задача 1

Найти максимальный элемент массива.

#include<iostream.h>

#include<stdlib.h>

void main()

{

int a[100];

int n;

cout<<”\nEnter the size of array:”;cin>>n;

for(int I=0;I<n;I++)

{a[I]=rand()%100-50;

cout<<a[I]<<” “;

}

int max=a[0];

for(I=1;I<n;I++)

if (a[I]>max)max=a[I];

cout<<”\nMax=”<<max”;

}

В этой программе также используется перебор массива по одному элементу слева направо с шагом 1.

Задача 2

Найти сумму элементов массива с четными индексами.

#include<iostream.h>

#include<stdlib.h>

void main()

{

int a[100];

int n;

cout<<”\nEnter the size of array:”;cin>>n;

for(int I=0;I<n;I++)

{a[I]=rand()%100-50;

cout<<a[I]<<” “;

}

int Sum=0;

for(I=0;I<n;I+=2)

Sum+=a[I];//элементы с индексами 0, 2, 4… cout<<”\nSum=”<<Sum”;

}

Ввод массива

//Второй способ

for(I=0;I<n;I++)

if(I%2==0)Sum+=a[I]; ];//элементы с индексами 0, 2, 4…

cout<<”\nSum=”<<Sum”;

6.2.4 Перебор массива по два элемента

1) Элементы массива можно обрабатывать по два элемента, двигаясь с обеих сторон массива к его середине:

2) int I=0, J=N-1;

3) while( I<J)

{обработка a[I] и a[J];I++;J--;}

4) Элементы массива можно обрабатывать по два элемента, двигаясь от начала к концу с шагом 1(т. е. обрабатываются пары элементов a[1]и a[2], a[2]и a[3] и т. д.):

5) for (I=1;I<N;I++)

6) {обработка a[I] и a[I+1]}

7) Элементы массива можно обрабатывать по два элемента, двигаясь от начала к концу с шагом 2 (т. е. обрабатываются пары элементов a[1]и a[2], a[3]и a[4] и т. д.)

8) int I=1;

9) while (I<N-1 )

10) {обработка a[I] и a[I+1];

11) I+=2;}

6.3 Классы задач по обработке массивов

1) К задачам 1 класса относятся задачи, в которых выполняется однотипная обработка всех или указанных элементов массива.

2) К задачам 2 класса относятся задачи, в которых изменяется порядок следования элементов массива.

3) К задачам 3 класса относятся задачи, в которых выполняется обработка нескольких массивов или подмассивов одного массива. Массивы могут обрабатываться по одной схеме - синхронная обработка или по разным схемам - асинхронная обработка массивов.

4) К задачам 4 класса относятся задачи, в которых требуется отыскать первый элемент массива, совпадающий с заданным значением - поисковые задачи в массиве.

6.3.1 Задачи 1-ого класса

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

#include<iostream.h>

#include<stdlib.h>

void main()

{

int a[100];

int n;

cout<<”\nEnter the size of array:”;cin>>n;

for(int I=0;I<n;I++)

{a[I]=rand()%100-50;

cout<<a[I]<<” “;

}

int Sum=0;

for(I=0;I<n;I++)

Sum+=a[I];

Cout<<”Среднее арифметическое=”<<Sum/n”;

}

6.3.2 Задачи 2-ого класса

Обмен элементов внутри массива выполняется с использованием вспомогательной переменной:

int R=a[I];a[I]=a[J]; a[J]:=R; // обмен a[I] и a[J] элементов массива.

Пример1.

Перевернуть массив.

//формирование массива

for(int i=0,j=n-1;i<j;i++,j--)

{int r=a[i];

a[i]=a[j];

a[j]=r;}

//вывод массива

Пример 2.

Поменять местами пары элементов в массиве: 1и2, 3 и 4, 5 и 6 и т. д.

for(int i=0;i<n-1;i+=2)

{int r=a[i];

a[i]=a[i+1];

a[i+1]=r;}

Пример 3.

Циклически сдвинуть массив на к элементов влево (вправо).

int k,i,t,r;

cout<<"\nK=?";cin>>k;

for(t=0;t<k;t++)

{

r=a[0];

for(int i=0;i<n-1;i++)

a[i]=a[i+1];

a[n-1]=r;

}

6.3.3 Задачи 3-ого класса

При синхронной обработке массивов индексы при переборе массивов меняются одинаково.

Пример 1. Заданы два массива из n целых элементов. Получить массив c, где c[I]=a[I]+b[I].

For(int I=0;I<n;I++)c[I]=a[I]+b[I];

При асинхронной обработке массивов индекс каждого массива меняется по своей схеме.

Пример 2. В массиве целых чисел все отрицательные элементы перенести в начало массива.

int b[10];//вспомогательный массив

int i,j=0;

for(i=0;i<n;i++)

if(a[i]<0){b[j]=a[i];j++;}//переписываем из а в b все отрицательные элементы

for(i=0;i<n;i++)

if(a[i]>=0){b[j]=a[i];j++;}// переписываем из а в b все положительные элементы

for(i=0;i<n;i++) cout<<b[I]<<” “;

Пример3.

Удалить из массива все четные числа

int b[10];

int i,j=0;

for(i=0;i<n;i++)

if(a[i]%2!=0){b[j]=a[i];j++;}

for(i=0;i<j;i++) cout<<b[i]<<" ";

cout<<"\n";

6.3.4 Задачи 4-ого класса

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

- нужный элемент найден ;

- элемент не найден, но просмотр массива закончен.

Пример1. Найти первое вхождение элемента К в массив целых чисел.

int k;

cout<<"\nK=?";cin>>k;

int ok=0;//признак найден элемент или нет

int i,nom;

for(i=0;i<n;i++)

if(a[i]==k){ok=1;nom=i;break;}

if(ok==1)

cout<<"\nnom="<<nom;

else

cout<<"\nthere is no such element!";

6.4 Сортировка массивов

Сортировка - это процесс перегруппировки заданного множества объектов в некотором установленном порядке.

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

Простые методы подразделяются на три основные категории:

- сортировка методом простого включения;

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

- сортировка методом простого обмена;

6.4.1 Сортировка методом простого включения (вставки)

Элементы массива делятся на уже готовую последовательность и исходную. При каждом шаге, начиная с I=2, из исходной последовательности извлекается I-ый элемент и вставляется на нужное место готовой последовательности, затем I увеличивается на 1 и т. д.

44

55

12

42

94

18

готовая

исходная

В процессе поиска нужного места осуществляются пересылки элементов больше выбранного на одну позицию вправо, т. е. выбранный элемент сравнивают с очередным элементом отсортированной части, начиная с J:=I-1. Если выбранный элемент больше a[I], то его включают в отсортированную часть, в противном случае a[J] сдвигают на одну позицию, а выбранный элемент сравнивают со следующим элементом отсортированной последовательности. Процесс поиска подходящего места заканчивается при двух различных условиях:

- если найден элемент a[J]>a[I];

- достигнут левый конец готовой последовательности.

int i,j,x;

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

{

x=a[i];//запомнили элемент, который будем вставлять

j=i-1;

while(x<a[j]&&j>=0)//поиск подходящего места

{

a[j+1]=a[j];//сдвиг вправо

j--;

}

a[j+1]=x;//вставка элемента

}

6.4.2 Сортировка методом простого выбора

Выбирается минимальный элемент массива и меняется местами с первым элементом массива. Затем процесс повторяется с оставшимися элементами и т. д.

44

55

12

42

94

18

1

мин

int i,min,n_min,j;

for(i=0;i<n-1;i++)

{

min=a[i];n_min=i;//поиск минимального

for(j=i+1;j<n;j++)

if(a[j]<min){min=a[j];n_min=j;}

a[n_min]=a[i];//обмен

a[i]=min;

}

6.4.3 Сортировка методом простого обмена

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

44

55

12

42

94

18

for(int i=1;i<n;i++)

for(int j=n-1;j>=i;j--)

if(a[j]<a[j-1])

{int r=a[j];a[j]=a[j-1];a[j-1]=r;}

}

6.5 Поиск в отсортированном массиве

В отсортированном массиве используется дихотомический (бинарный) поиск. При последовательном поиске требуется в среднем n/2 сравнений, где n - количество элементов в массиве. При дихотомическом поиске требуется не более m сравнений, если n- m-ая степень 2, если n не является степенью 2, то n<k=2m.

Массив делится пополам S:=(L+R)/ 2+1 и определяется в какой части массива находится нужный элемент Х. Т .к. массив упорядочен, то если a[S]<X, то искомый элемент находится в правой части массива, иначе - находится в левой части. Выбранную часть массива снова надо разделить пополам и т. д., до тех пор, пока границы отрезка L и R не станут равны.

1

3

8

10

11

15

19

21

23

37

0

1

2

3

4

5

6

7

8

9

L S R

S=(L+R)/2=4

int b;

cout<<"\nB=?";cin>>b;

int l=0,r=n-1,s;

do

{

s=(l+r)/2;//средний элемент

if(a[s]<b)l=s+1;//перенести леую границу

else r=s;//перенести правую границу

}while(l!=r);

if(a[l]==b)return l;

else return -1;

7. Указатели

7.1 Понятии указателя

Указатели являются специальными объектами в программах на Си++. Указатели предназначены для хранения адресов памяти.

Пример: Когда компилятор обрабатывает оператор определения переменной, например, int i=10;, то в памяти выделяется участок памяти в соответствии с типом переменной (int=> 4байта) и записывает в этот участок указанное значение. Все обращения к этой переменной компилятор заменит на адрес области памяти, в которой хранится эта переменная.

а

Программист может определить собственные переменные для хранения адресов областей памяти. Такие переменные называются указателями. Указатель не является самостоятельным типом, он всегда связан с каким-то другим типом.

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

В простейшем случае объявление указателя имеет вид:

тип *имя;

Тип может быть любым, кроме ссылки.

Примеры:

int *i;

double *f, *ff;

char *c;

Размер указателя зависит от модели памяти. Можно определить указатель на указатель: int**a;

Указатель может быть константой или переменной, а также указывать на константу или переменную.

Примеры:

1. int i;//целая переменная

const int ci=1;//целая константа

int *pi; //указатель на целую переменную

const int *pci;//указатель на целую константу

Указатель можно сразу проинициализировать:

int *pi=&i; //указатель на целую переменную

const int *pci=&ci;;//указатель на целую константу

int*const cpi=&i;//указатель-константа на целую переменную

const int* const cpc=&ci;//указатель-константа на целую константу

Если модификатор const относится к указателю (т. е. находится между именем указателя и * ), то он запрещает изменение указателя, а если он находится слева от типа (т. е. слева от * ), то он запрещает изменение значения, на которое указывает указатель.

Для инициализации указателя существуют следующие способы:

1) Присваивание адреса существующего объекта:

1) с помощью операции получения адреса

int a=5;

int *p=&a; или int p(&a);

2) с помощью проинициализированного указателя

int *r=p;

3) адрес присваивается в явном виде

char*cp=(char*)0х В800 0000;

где 0х В800 0000 - шестнадцатеричная константа, (char*) - операция приведения типа.

4) присваивание пустого значения:

int*N=NULL;

int *R=0;

7.2 Динамические переменные

Все переменные, объявленные в программе размещаются в одной непрерывной области памяти, которую называют сегментом данных (64К). Такие переменные не меняют своего размера в ходе выполнения программы и называются статическими. Размера сегмента данных может быть недостаточно для размещения больших массивов информации. Выходом из этой ситуации является использование динамической памяти. Динамическая память - это память, выделяемая программе для ее работы за вычетом сегмента данных, стека, в котором размещаются локальные переменные подпрограмм и собственно тела программы.

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

Для создания динамических переменных используют операцию new, определенную в СИ++:

указатель = new имя_типа[инициализатор];

где инициализатор - выражение в круглых скобках.

Операция new позволяет выделить и сделать доступным участок динамической памяти, который соответствует заданному типу данных. Если задан инициализатор, то в этот участок будет занесено значение, указанное в инициализаторе.

int*x=new int(5);

Для удаления динамических переменных используется операция delete, определенная в СИ++:

delete указатель;

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

delete x;

В языке Си определены библиотечные функции для работы с динамической памятью, они находятся в библиотеке <stdlib.h>:

1) void*malloc(unsigned s) - возвращает указатель на начало области динамической памяти длиной s байт, при неудачном завершении возвращает NULL;

2) void*calloc(unsigned n, unsigned m) - возвращает указатель на начало области динамической для размещения n элементов длиной m байт каждый, при неудачном завершении возвращает NULL;

3) void*realloc(void *p,unsigned s) -изменяет размер блока ранее выделенной динамической до размера s байт, р - адрес начала изменяемого блока, при неудачном завершении возвращает NULL;

4) void *free(void *p) - освобождает ранее выделенный участок динамической памяти, р- адрес начала участка.

Пример:

int *u=(int*)malloc(sizeof(int)); // в функцию передается количество требуемой памяти в байтах, т. к. функция возвращает значение типа void*, то его необходимо преобразовать к типу указателя (int*).

free(u); //освобождение выделенной памяти

7.3 Операции с указателями

С указателями можно выполнять следующие операции:

1) разыменование (*);

2) присваивание;

3) арифметические операции (сложение с константой, вычитание,

4) инкремент ++, декремент --);

5) сравнение;

6) приведение типов.

1) Операция разыменования предназначена для получения значения переменной или константы, адрес которой хранится в указателе. Если указатель указывает на переменную, то это значение можно изменять, также используя операцию разыменования.

Примеры:

int a; //переменная типа int

int*pa=new int; //указатель и выделение памяти под динамическую переменную

*pa=10;//присвоили значение динамической переменной, на которую указывает указатель

a=*pa;//присвоили значение переменной а

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

2) Приведение типов

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

int a=123;

int*pi=&a;

char*pc=(char*)&a;

float *pf=(float*)&a;

printf("\n%x\t%i",pi,*pi);

printf("\n%x\t%c",pc,*pc);

printf("\n%x\t%f",pf,*pf);

При выполнении этой программы получатся следующие результаты:

66fd9c 123

66fd9c {

66fd9c 0.000000

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

В примере при инициализации указателя была использована операция приведения типов. При использовании в выражении указателей разных типов, явное преобразование требуется для всех типов, кроме void*. Указатель может неявно преобразовываться в значения типа bool, при этом ненулевой указатель преобразуется в true, а нулевой в false.

3) Арифметические операции применимы только к указателям одного типа.

- Инкремент увеличивает значение указателя на величину sizeof(тип).

Например:

char *pc;

int *pi;

float *pf;

. . . . .

pc++;//значение увеличится на 1

pi++;//значение увеличится на 4

pf++;//значение увеличится на 4

- Декремент уменьшает значение указателя на величину sizeof(тип).

- Разность двух указателей - это разность их значений, деленная на размер типа в байтах.

Например:

int a=123,b=456,c=789;

int*pi1=&a;

int *pi2=&b;

int*pi3=&c;

printf("\n%x",pi1-pi2);

printf("\n%x",pi1-pi3);

Результат

1

2

Суммирование двух указателей не допускается.

Можно суммировать указатель и константу:

pi3=pi3+2;

pi2=pi2+1;

printf("\n%x\t%d",pi1,*pi1);

printf("\n%x\t%d",pi2,*pi2);

printf("\n%x\t%d",pi3,*pi3);

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

66fd9c 123

66fd9c 123

66fd9c 123

При записи выражений с указателями требуется обращать внимание на приоритеты операций.

8. Ссылки

8.1 Понятие ссылки

Ссылка - это синоним имени объекта, указанного при инициализации ссылки.

Формат объявления ссылки

тип & имя =имя_объекта;

Примеры:

int x;// определение переменной

int& sx=x;// определение ссылки на переменную х

const char& CR='\n';//определение ссылки на константу

8.2 Правила работы со ссылками

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

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

3) Не существует указателей на ссылки, массивов ссылок и ссылок на ссылки.

4) Операция над ссылкой приводит к изменению величины на которую она ссылается

Ссылка не занимает дополнительного пространства в памяти, она является просто другим именем объекта.

Пример1:

#include <iostream.h>

void main()

{

int I=123;

int &si=I;

cout<<”\ni=”<<I<<” si=”<<si;

I=456;

cout<<”\ni=”<<I<<” si=”<<si;

I=0; cout<<”\ni=”<<I<<” si=”<<si;

}

Выведется

I=123 si=123

I=456 si=456

I=0 si=0

9. Указатели и массивы

9.1 Одномерные массивы и указатели

При определении массива ему выделяется память. После этого имя массива воспринимается как константный указатель того типа, к которому относятся элементы массива. Исключением является использовании операции sizeof (имя_массива) и операции &имя_массива.

Примеры:

int a[100];

int k=sizeof(a);// результатом будет 4*100=400 (байтов).

int n=sizeof(a)/sizeof(a[0]);//количество элементов массива

Результатом операции & является адрес нулевого элемента массива:

имя_массива==&имя_массива=&имя_массива[0]

Имя массива является указателем-константой, значением которой служит адрес первого элемента массива, следовательно, к нему применимы все правила адресной арифметики, связанной с указателями. Запись имя_массива[индекс] это выражение с двумя операндами: имя массива и индекс. Имя_массива - это указатель константа, а индекс определяет смещение от начала массива. Используя указатели, обращение по индексу можно записать следующим образом: *(имя_массива+индекс).

Пример:

for(int i=0;i<n;i++)//печать массива

cout<<*(a+i)<<" ";//к имени адресу массива добавляется константа i и полученное //значение разыменовывается

Так как имя массива является константным указателем, то его невозможно изменить, следовательно, запись *(а++) будет ошибочной, а *(а+1) - нет.

Указатели можно использовать и при определении массивов:

int a[100]={1,2,3,4,5,6,7,8,9,10};

int * na=a;//поставили указатель на уже определенный массив

int b=new int[100];//выделили в динамической памяти место под массив из 100 элементов

9.2 Многомерные массивы и указатели

Многомерный массив это массив, элементами которого служат массивы. Например, массив с описанием int a[4][5] - это массив из 4 указателей типа int*, которые содержат адреса одномерных массивов из 5 целых элементов (см. рис.).

int **a

Рис.

Инициализация многомерных массивов выполняется аналогично одномерным массивам. Примеры:

int a[3][4] = {{11,22,33,44},{55,66,77,88},{99,110,120,130}};//проинициализированы все //элементы массива

int b[3][4] = {{1},{2},{3}};//проинициализированы первые элементы каждой строки

int c[3][2]={1,2,3,4,5,6};//проинициализированы все элементы массива

Доступ к элементам многомерных массивов возможен и с помощью индексированных переменных и с помощью указателей:

a[1][1] - доступ с помощью индексированных переменных,

*(*(a+1)+1) - доступ к этому же элементу с помощью указателей (см. рис.).

9.3 Динамические массивы

Операция new при использовании с массивами имеет следующий формат:

new тип_массива

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

Примеры:

1. int *a=new int[100];//выделение динамической памяти размером 100*sizeof(int) байтов double *b=new double[10];// выделение динамической памяти размером 10*sizeof(double) байтов

2. long(*la)[4];//указатель на массив из 4 элементов типа long

lа=new[2][4];//выделение динамической памяти размером 2*4*sizeof(long) байтов

3. int**matr=(int**)new int[5][10];//еще один способ выделения памяти под двумерный //массив

4. int **matr;

matr=new int*[4];//выделяем память под массив указателей int* их n элементов

for(int I=0;I<4;I++)matr[I]=new int[6];//выделяем память под строки массива

Указатель на динамический массив затем используется при освобождении памяти с помощью операции delete.

Примеры:

delete[] a;//освобождает память, выделенную под массив, если а адресует его начало

delete[]b;

delete[] la;

for(I=0;I<4;I++)delete [] matr[I];//удаляем строки

delete [] matr;//удаляем массив указателей

Пример

Удалить из матрицы строку с номером K

#include <iostream.h>

#include <string.h>

#include <iostream.h>

#include <stdlib.h>

void main()

{

int n,m;//размерность матрицы

int i,j;

cout<<"\nEnter n";

cin>>n;//строки

cout<<"\nEnter m";

cin>>m;//столбцы

//выделение памяти

int **matr=new int* [n];// массив указателей на строки

for(i=0;i<n;i++)

matr[i]=new int [m];//память под элементы матрицы

//заполнение матрицы

for(i=0;i<n;i++)

for(j=0;j<m;j++)

matr[i][j]=rand()%10;//заполнение матрицы

//печать сформированной матрицы

for(i=0;i<n;i++)

{

for(j=0;j<m;j++)

cout<<matr[i][j]<<" ";

cout<<"\n";

}

//удаление строки с номером к

int k;

cout<<"\nEnter k";

cin>>k;

int**temp=new int*[n-1];//формирование новой матрицы

for(i=0;i<n;i++)

temp[i]=new int[m];

//заполнение новой матрицы

int t;

for(i=0,t=0;i<n;i++)

if(i!=k)

{

for(j=0;j<m;j++)

temp[t][j]=matr[i][j];

t++;

}

//удаление старой матрицы

for(i=0;i<n;i++)

delete matr[i];

delete[]matr;

n--;

//печать новой матрицы

for(i=0;i<n;i++)

{

for(j=0;j<m;j++)

cout<<temp[i][j]<<" ";

cout<<"\n";

}

}

10. Символьная информация и строки

Для символьных данных в Си++ введен тип char. Для представления символьной информации используются символы, символьные переменные и текстовые константы.

Примеры:

const char c='c'; //символ - занимает один байт, его значение не меняется

char a,b;//символьные переменные, занимают по одному байту, значения меняются

const char *s=“Пример строки\n” ;//текстовая константа

Строка в Си++ - это массив символов, заканчивающийся нуль-символом - `\0' (нуль-терминатором). По положению нуль-терминатора определяется фактическая длина строки. Количество элементов в таком массиве на 1 больше, чем изображение строки.

A

\0

A

“A”

строка (2байта)

`A'

символ (1байт)

Рис.2. Представление строки и символа

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

Пример

void main()

{

char s1[10]="string1";

int k=sizeof(s1);

cout<<s1<<"\t"<<k<<endl;

char s2[]="string2";

k=sizeof(s2);

cout<<s2<<"\t"<<k<<endl;

char s3[]={`s','t','r','i','n','g','3'}

k=sizeof(s3);

cout<<s3<<"\t"<<k<<endl;

char *s4="string4";//указатель на строку, ее нельзя изменить

k=sizeof(s4);

cout<<s4<<"\t"<<k<<endl;

}

Результаты:

string1 10 - выделено 10 байтов, в том числе под \0

string2 8 - выделено 8 байтов (7+1байт под \0)

string3 8 - выделено 8 байтов (7+1байт под \0)

string4 4 - размер указателя

Примеры:

char *s=”String5”; - выделяется 8 байтов для строки

char*ss; - описан указатель

ss=”String6”;//память не выделяется , поэтому программа может закончиться аварийно.

char *sss=new char[10];//выделяем динамическую память

strcpy(sss,”String7”);//копируем строку в память

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

int getchar(void) - осуществляет вод одного символа их входного потока, при этом она возвращает один байт информации (символ) в виде значения типа int. Это сделано для распознавания ситуации, когда при чтении будет достигнут конец файла.

int putchar (int c) - помещает в стандартный выходной поток символ c.

char* gets(char*s) - считывает строку s из стандартного потока до появления символа `\n', сам символ `\n' в строку не заносится.

int puts(const char* s) записывает строку в стандартный поток, добавляя в конец строки символ `\n', в случае удачного завершения возвращает значение больше или равное 0 и отрицательное значение (EOF=-1) в случае ошибки.

Примеры:

1. char s[20];

cin>>s;//ввод строки из стандартного потока

cout<<s;//вывод строки в стандартный поток

Результат работы программы:

При вводе строки “123 456 789”, чтение байтов осуществляется до первого пробела, т. е. в строку s занесется только первое слово строки “123/0”, следовательно, выведется: 123.

2. char s[20];

gets(s);//ввод строки из стандартного потока

puts(s);//вывод строки в стандартный поток

Результат работы программы:

При вводе строки “123 456 789”, чтение байтов осуществляется до символа `\n', т. е. в s занесется строка”123 456 789\n\0”, при выводе строки функция puts возвращает еще один символ `\n', следовательно, будет выведена строка “123 456 789\n\n”.

3. char s[20];

scanf(“%s”,s);//ввод строки из стандартного потока

printf(“%s”,s);//вывод строки в стандартный поток

Результат работы программы:

При вводе строки “123 456 789”, чтение байтов осуществляется до первого пробела, т. е. в строку s занесется только первое слово строки “123/0”, следовательно, выведется: 123. Т. к. s - имя массива, т. е. адрес его первого элемента, операция & в функции scanf не используется.

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

Прототип функции

Краткое описание

Примечание

unsigned strlen(const char*s);

Вычисляет длину строки s.

int strcmp(const char*s1, const char *s2);

Сравнивает строки s1 и s2.

Если s1<s2, то результат отрицательный, если s1==s2, то результат равен 0, если s2>s1 - результат положительный.

int strcnmp(const char*s1, const char *s2);

Сравнивает первые n символов строк s1 и s2.

Если s1<s2, то результат отрицательный, если s1==s2, то результат равен 0, если s2>s1 - результат положительный.

char*strcpy(char*s1, const char*s2);

Копирует символы строки s1 в строку s2.

char*strncpy(char*s1, const char*s2, int n);

Копирует n символов строки s1 в строку s2.

Конец строки отбрасывается или дополняется пробелами.

char*strcat(char*s1, const char*s2);

Приписывает строку s2 к строке s1

char*strncat(char*s1, const char*s2);

Приписывает первые n символов строки s2 к строке s1

char*strdup(const char*s);

Выделяет память и переносит в нее копию строки s

При выделении памяти используются функции

Пример1:

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

#include <stdio.h>

#include <string.h>

void main()

{

char s[250], //исходная строка

w[25], //слово

mas[10][25];//массив слов

puts(“\nвведите строку”);

gets(s);

int k=0,t=0,i,len,j;

len=strlen(s);

while(t<len)

{

for(j=0,i=t;s[i]!=' `;i++,j++)w[j]=s[i];//формируем слово до пробела

w[j]='/0';//формируем конец строки

strcpy(mas[k],w);//копируем слово в массив

k++;//увеличиваем счетчик слов

t=i+1;//переходим к следующему слову в исходной строке

}

strcpy(s,””);//очищаем исходную строку

for(t=0;t<k;t++)

if(mas[t][0]<'0'&&mas[t][0]>'9')//если первый символ не цифра

{

strcat(s,mas[t]);//копируем в строку слово

strcat(s,” “);//копируем в строку пробел

}

puts(s);//выводим результат

}

Пример2:

Сформировать динамический массив строк. Удалить из него строку с заданным номером.

#include <iostream.h>

#include <string.h>

void main()

{

int n;

cout<<"\nN=?";cin>>n;

char s[100];

char**matr=new char*[n];

for(int i=0;i<n;i++)

{

cout<<"\nS=?";

cin>>s;

matr[i]=new char[strlen(s)];

strcpy(matr[i],s);

}

for(i=0;i<n;i++)

{

cout<<matr[i];

cout<<"\n";

}

int k;

cout<<"\nK=?";

cin>>k;

if(k>=n){cout<<"There is not such string\n";return;}

char **temp=new char*[n-1];

int j=0;

for(i=0;i<n;i++)

if(i!=k)

{

temp[j]=new char[strlen(matr[i])];

strcpy(temp[j],matr[i]);

j++;

}

n--;

for(i=0;i<n;i++)

{

cout<<temp[i];

cout<<"\n";

}

}

11. Функции в Си++

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

Часто используемые функции можно помещать в библиотеки. Таким образом, создаются более простые в отладке и сопровождении программы.

11.1 Объявление и определение функций

Функция - это именованная последовательность описаний и операторов, выполняющая законченное действие, например, формирование массива, печать массива и т. д.

Функция, во-первых, является одним из производных типов СИ++, а ,во-вторых, минимальным исполняемым модулем программы.

Любая функция должна быть объявлена и определена.

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

Определение функции содержит, кроме объявления, тело функции, которое представляет собой последовательность описаний и операторов.

тип имя_функции([список_формальных_параметров])

{ тело_функции}

Тело_функции - это блок или составной оператор. Внутри функции нельзя определить другую функцию.

В теле функции должен быть оператор, который возвращает полученное значение функции в точку вызова. Он может иметь 2 формы:

1) return выражение;

2) return;

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

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

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

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

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

Пример:

Заданы координаты сторон треугольника. Если такой треугольник существует, то найти его площадь.

1. Математическая модель:

1) l=sqrt(pow(x1-x2,2)+pow(y1-y2,2));//длина стороны треугольника

2) p=(a+b+c)/2;

3) s=sqrt(p*(p-a)*(p-b)*(p-c));//формула Герона

4) проверка существования треугольника

5) (a+b>c&&a+c>b&&c+b>a)

2. Алгоритм:

1) Ввести координаты сторон треугольника (х1,у1),(х2,у2),(х3,у3);

2) Вычислить длины сторон ab, bc, ca;

3) Проверить существует ли треугольник с такими сторонами. Если да, то вычислить площадь и вывести результат.

4) Если нет, то вывести сообщение.

5) Если все координаты равны 0, то конец, иначе возврат на п.1.

#include <iostream.h>

#include <math.h>

double line(double x1,double y1,double x2,double y2)

{

//функция возвращает длину отрезка, заданного координатами x1,y1 и x2,y2

return sqrt(pow(x1-x2,2)+pow(y1-y2,2));

}

double square(double a, double b, double c)

{

//функция возвращает площадь треугольника, заданного длинами сторон а,b,c

double s, p=(a+b+c)/2;

return s=sqrt(p*(p-a)*(p-b)*(p-c));//формула Герона

}

bool triangle(double a, double b, double c)

{

//возвращает true, если треугольник существует

if(a+b>c&&a+c>b&&c+b>a) return true;

else return false;

}

void main()

{

double x1=1,y1,x2,y2,x3,y3;

double point1_2,point1_3,point2_3;

do

{

cout<<"\nEnter koordinats of triangle:";

cin>>x1>>y1>>x2>>y2>>x3>>y3;

point1_2=line(x1,y1,x2,y2);

point1_3=line(x1,y1,x3,y3);

point2_3=line(x2,y2,x3,y3);

if(triangle(point1_2,point1_3,point2_3)==true)

cout<<"S="<<square(point1_2,point2_3,point1_3)<<"\n";

else cout<<"\nTriagle doesnt exist";

}

while(!(x1==0&&y1==0&&x2==0&&y2==0&&x3==0&&y3==0));

}

11.2. Прототип функции

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

double line(double x1,double y1,double x2,double y2);

double square(double a, double b, double c);

bool triangle(double a, double b, double c);

double line(double ,double ,double ,double);

double square(double , double , double );

bool triangle(double , double , double );

Это прототипы функций, описанных выше.

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

Имя_файла - определяет заголовочный файл, содержащий прототипы группы стандартных для данного компилятора функций. Например, почти во всех программах мы использовали команду #include <iostream.h> для описания объектов потокового ввода-вывода и соответствующие им операции.

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

11.3.Параметры функции

Основным способом обмена информацией между вызываемой и вызывающей функциями является механизм параметров. Существует два способа передачи параметров в функцию: по адресу и по значению.

При передаче по значению выполняются следующие действия:

- вычисляются значения выражений, стоящие на месте фактических параметров;

- в стеке выделяется память под формальные параметры функции;

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

Пример:

double square(double a, double b, double c)

{

//функция возвращает площадь треугольника, заданного длинами сторон а,b,c

double s, p=(a+b+c)/2;

return s=sqrt(p*(p-a)*(p-b)*(p-c));//формула Герона

}

1) double s1=square(2.5,2,1);

2) double a=2.5,b=2,c=1;

double s2=square(a,b,c);

3) double x1=1,y1=1,x2=3,y2=2,x3=3,y3=1;

double s3=square(sqrt(pow(x1-x2,2)+pow(y1-y2,2)),//расстояние между 1и2

sqrt(pow(x1-x3,2)+pow(y1-y3,2)), //расстояние между 1 и 3

sqrt(pow(x3-x2,2)+pow(y3-y2,2)));//расстояние между 2 и3

Стек

A

2.5

B

2

C

1

S

P

P и S - локальные переменные.

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

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

Пример.

void Change(int a,int b)//передача по значению

{int r=a;a=b;b=r;}

int x=1,y=5;

Change(x,y);

A

1

5

B

5

1

r

1

cout<<”x=”<<x<<”y=”<<y;

выведется: x=1y=5

void Change(int *a,int *b)//передача по адресу

{int r=*a;*a=*b;*b=r;}

int x=1,y=5;

Change(&x,&y);

A

&x

5

B

&y

1

r

1

cout<<”x=”<<x<<”y=”<<y;

выведется: x=5y=1

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

void Change(int &a,int &b)

{int r=a;a=b;b=r;}

int x=1,y=5;

Change(x,y);

A

&x

5

B

&y

1

r

1

cout<<”x=”<<x<<”y=”<<y;

выведется: x=5y=1

Использование ссылок вместо указателей улучшает читаемость программы, т. к. не надо применять операцию разыменовывания. Использование ссылок вместо передачи по значению также более эффективно, т .к. не требует копирования параметров. Если требуется запретить изменение параметра внутри функции, используется модификатор const. Рекомендуется ставить const перед всеми параметрами, изменение которых в функции не предусмотрено (по заголовку будет понятно, какие параметры в ней будут изменяться, а какие нет).

11.4 Локальные и глобальные переменные

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

int*f()

{

int a;

. . . .

return&a;// НЕВЕРНО

}

Глобальные переменные - это переменные, описанные вне функций. Они видны во всех функциях, где нет локальных переменных с такими именами.

Пример:

int a,b;//глобальные переменные

void change()

{

int r;//локальная переменная

r=a;a=b;b=r;

}

void main()

{

cin>>a,b;

change();

cout<<”a=”<<a<<”b=”<<b;

}

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

11.5 Функции и массивы

11.5.1 Передача одномерных массивов как параметров функции

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

Пример1:

Удалить из массива все четные элементы

#include <iostream.h>

#include <stdlib.h>

int form(int a[100])

{

int n;

cout<<"\nEnter n";

cin>>n;

for(int i=0;i<n;i++)

a[i]=rand()%100;

return n;

}

void print(int a[100],int n)

{

for(int i=0;i<n;i++)

cout<<a[i]<<" ";

cout<<"\n";

}

void Dell(int a[100],int&n)

{

int j=0,i,b[100];

for(i=0;i<n;i++)

if(a[i]%2!=0)

{

b[j]=a[i];j++;

}

n=j;

for(i=0;i<n;i++)a[i]=b[i];

}

void main()

{

int a[100];

int n;

n=form(a);

print(a,n);

Dell(a,n);

print(a,n);

}

Пример 2

Удалить из массива все элементы, совпадающие с первым элементом, используя динамическое выделение памяти.

#include <iostream.h>

#include <stdlib.h>

int* form(int&n)

{

cout<<"\nEnter n";

cin>>n;

int*a=new int[n];//указатель на динамическую область памяти

for(int i=0;i<n;i++)

a[i]=rand()%100;

return a;

}

void print(int*a,int n)

{

for(int i=0;i<n;i++)

cout<<a[i]<<" ";

cout<<"\n";

}

int*Dell(int *a,int&n)

{

int k,j,i;

for(k=0,i=0;i<n;i++)

if(a[i]!=a[0])k++;

int*b;

b=new int [k];

for(j=0,i=0;i<n;i++)

if(a[i]!=a[0])

{

b[j]=a[i];j++;

}

n=k;

return b;

}

void main()

{

int *a;

int n;

a=form(n);

print(a,n);

a=Dell(a,n);

print(a,n);

}

11.5.2 Передача строк в качестве параметров функций

Строки при передаче в функции могут передаваться как одномерные массивы типа char или как указатели типа char*. В отличие от обычных массивов в функции не указывается длина строки, т. к. в конце строки есть признак конца строки /0.

Пример: Функция поиска заданного символа в строке

int find(char *s,char c)

{

for (int I=0;I<strlen(s);I++)

if(s[I]==c) return I;

return -1

}

С помощью этой функции подсчитаем количество гласных букв в строке.

void main()

{

char s[255];

gets(s)

char gl=”aouiey”;

for(int I=0,k=0;I<strlen(gl);I++)

if(find(s,gl[I])>0)k++;

printf(“%d”,k);

}

11.5.3 Передача многомерных массивов в функцию

При передаче многомерных массивов в функцию все размерности должны передаваться в качестве параметров. По определению многомерные массивы в Си и СИ++ не существуют. Если мы описываем массив с несколькими индексами, например, массив int mas[3][4], то это означает, что мы описали одномерный массив mas, элементами которого являются указатели на одномерные массивы int[4].

Пример: Транспонирование квадратной матрицы

Если определить заголовок функции:

void transp(int a[][],int n){…..} - то получится, что мы хотим передать в функцию массив с неизвестными размерами. По определению массив должен быть одномерным, и его элементы должны иметь одинаковую длину. При передаче массива ничего не сказано и о размере элементов, поэтому компилятор выдаст ошибку.

Самый простой вариант решения этой проблемы определить функцию следующим образом:

void transp(int a[][4],int n), тогда размер каждой строки будет 4, а размер массива указателей будет вычисляться.

#include<iostream.h>

const int N=4;//глобальная переменная

void transp(int a[][N],int n)

{

int r;

for(int I=0;I<n;I++)

for(int j=0;j<n;j++)

if(I<j)

{

r[a[I][j];a[I][j]=a[j][I];a[j][I]=r;

}

}

void main()

{

int mas[N][N];

for(int I=0;I<N;I++)

for(int j=0;j<Nlj++)

cin>>mas[I][j];

for(I=0;I<N;I++)

{

for(j=0;j<N;j++)

cout<<mas[I][j]

cout<<”\n”;

}

transp(N,mas);

for(I=0;I<N;I++)

{

for(j=0;j<N;j++)


Подобные документы

  • Основные этапы создания алгоритмов, представление в виде программы. Рассмотрение методов решения задач. Метод поэтапных уточнений. Различие между численными и логическими алгоритмами. Реализация цикла со счетчиком. Процесс разработки сложного алгоритма.

    презентация [1,3 M], добавлен 22.10.2013

  • Написание транслятора посредством языка Си, обрабатывающего конструкции integer, if Le then, записи (record), а также реализующего обработку new для выделения динамической памяти: разработка алгоритма реализации задачи, представление листинга программы.

    курсовая работа [171,7 K], добавлен 03.07.2011

  • Фаза "избавления" программы от ошибок. Задача обработки ошибок в коде программы. Ошибки с невозможностью автоматического восстановления, оператор отключения. Прекращение выполнения программы. Возврат недопустимого значения. Директивы РНР контроля ошибок.

    учебное пособие [62,3 K], добавлен 27.04.2009

  • Изучение понятия и свойств алгоритма. Определение сущности технологии Robson. Исполнитель, а также блок-схема алгоритма или его графическое представление, в котором он изображается в виде последовательности связанных между собой функциональных блоков.

    реферат [155,9 K], добавлен 19.10.2013

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

    курсовая работа [305,9 K], добавлен 03.07.2011

  • Функция записи в сжатое представление массива. Распечатка внутреннего представления матрицы. Результат работы программы при Xm=4. Построение графика зависимости T=F(Xm) по начальному значению времени выполнения алгоритма. Запись элементов в массив.

    лабораторная работа [471,8 K], добавлен 05.12.2015

  • Характеристика программирования с точки зрения процесса создания программы. Спецификация и определение требований к программе. Основные символы, используемые для представления алгоритма в виде блок-схемы. Особенности процесса поиска и устранения ошибок.

    лекция [234,9 K], добавлен 07.04.2011

  • Основные алгоритмические структуры. Запись алгоритма в словесной форме, в виде блок-схемы. Система команд исполнителя. Язык высокого уровня. Создание программы и её отладка. Интегрированные среды разработки: Integrated Development Environment, IDE.

    лекция [61,7 K], добавлен 09.10.2013

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

    курсовая работа [495,8 K], добавлен 09.06.2013

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

    реферат [192,2 K], добавлен 10.11.2014

  • Приемы и правила объектно-ориентированного программирования с использованием языка С++. Общие принципы разработки объектно-ориентированных программ. Основные конструкции языка С++. Разработка различных программ для Windows с использованием WIN32 API.

    учебное пособие [1,6 M], добавлен 28.12.2013

  • Разработка программы с использованием языка программирования Pascal для выполнения алгебраических действий с действительными числами без знака в шестнадцатеричной системе счисления. Описание хода выполнения, схема алгоритма, листинг программы, ее функции.

    реферат [687,5 K], добавлен 28.10.2011

  • Изучение теоретических основ разработки программы и правил выбора языка программирования. Рассмотрение основных задач по созданию сайта автоклуба. Основы разработки базы данных, создания web-дизайна, текстового наполнения сайта и его публикации.

    курсовая работа [687,9 K], добавлен 07.04.2014

  • Проведение сравнительного анализа языков программирования. Создание алгоритма и специфика составления математической модели программы "Механические часы, показывающие текущее время" в среде Microsoft Visual Studio 2010, на базе языка программирования С++.

    курсовая работа [408,9 K], добавлен 11.03.2013

  • Методика разработки и частичная реализация транслятора для языка "С" с использованием языка "С++", производящего разбиение на минимальные неделимые конструкции языка исходной цепочки символов основываясь на лексике языка. Анализ работы программы.

    курсовая работа [841,3 K], добавлен 19.03.2012

  • Элементы и переменные, используемые для составления записи в Паскале. Основные числовые типы языка Turbo Pascal. Составление блок-схемы приложения, программирование по ней программы для вычисления функции. Последовательность выполнения алгоритма.

    лабораторная работа [256,9 K], добавлен 10.11.2015

  • Словесное описание алгоритма программы. Открытие файла процедурой Rewrite, его проверка на наличие ошибок при открытии. Особенности построения диаграммы. Листинг программы, ее тестирование и отладка. Выполнение процедуры CloseFile при закрытии файла.

    контрольная работа [17,3 K], добавлен 11.06.2010

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

    курсовая работа [1,2 M], добавлен 19.02.2015

  • Разработка алгоритма, представление его в виде блок-схемы. Программа для табулирования функции. Ввод и вывод данных с рабочего листа MS Excel. Ввод данных через диалоговое окно, вывод результатов на рабочий лист MS Excel. Вычисление суммы членов ряда.

    контрольная работа [329,7 K], добавлен 16.10.2013

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

    контрольная работа [150,4 K], добавлен 03.05.2014

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.