- •Первый семестр
- •1) Цикл с предусловием
- •2) Цикл с постусловием
- •Преобразование типа переменной в программе
- •Continue
- •Вычислить сумму произведений элементов
- •Найти максимальную из построчных сумм
- •Умножение матриц
- •Void create(int**X, int n)
- •Void show(int**X, int n)
- •Void mult ( int **X, int**y, int**z)
- •Void add ( int **X, int**y, int**z)
- •Исходные данные
- •За приближенное значение интеграла принимается такое, при котором .
- •Strcpy()
- •Strncpy()
- •Strcat()
- •Strcmp()
- •Strclen()
- •Int** create(ifstream &f , int n )
- •Int** subtr (int** X, int**y, int n)
- •Int** mult (int** X, int**y, int n)
Умножение матриц
С=A*B
# include <iostream.h>
const int n=3;
void main()
{
int a[n] [n], b[n] [n], c[n] [n];
int i, j, k;
//Ввод массива с клавиатуры
cout<<”enter array a:”<<endl;
for (i=0; i<n; i++)
for (j=0; j<n; j++)
cin>>a[i][j];
//Вывод массива на экран
cout<<”array a:”<<endl;
for (i=0; i<n; i++)
{
for (j=0; j<n; j++) cout<<a[i][j]<<’ ‘;
cout<<endl;
}
//Ввод массива с клавиатуры
cout<<”enter array b”<<endl;
for (i=0; i<n; i++)
for (j=0; j<n; j++)
cin>>b[i][j];
//Вывод массива b на экран
cout<<”array b:”<<endl;
for (i=0; i<n; i++)
{
for (j=0; j<n; j++) cout<<b[i][j]<<’ ’;
cout<<endl;
}
for (i=0; i<n; i++)
for (j=0; j<n; j++)
{
c[i][j]=0;
for (k=0; k<n; k++)
c[i][j]=c[i][j]+a[i][k]*b[k][j];
}
//Вывод массива на экран
cout<<”array c:”<<endl;
for (i=0; i<n; i++)
{
for (j=0; j<n; j++)
cout<<c[i][j]<<’ ’;
cout<<endl;
}
}
Лекция
Указатели.
Указатель – это объект, который содержит некоторый адрес памяти. Этот адрес обозначает местоположение в памяти другого объекта, такого как переменная. Если x содержит адрес переменной y, то о переменной x говорят, что она «указывает» на y.
Формат объявления переменной-указателя таков:
Тип *имя переменной.
Использование символа * перед именем переменной в инструкции объявления превращает эту переменную в указатель.
int *x;
x – укзатель на int.
Операторы, используемые с указателями.
С указателями используются два оператора ”*” и “&”.
Оператор “&”- унарный. Он возвращает адрес памяти, по которому расположен операнд.
int *ptr;
ptr= &total;
В переменную ptr помещается адрес переменной total.
Второй оперантор работы с указателями (“*”) служит дополнением к первому (“&”). Это также унарный оператор , но он обращается к значению переменной , расположенной по адресу , заданному его операндом. Другими словами, он ссылается на значение переменной , адресуемой заданным указателем. Если перменная ptr содержит адрес перменной total , то при выполнении инструкции
val=*ptr;
будет присвоено значение переменной total, на которую указывает переменная ptr.
Все байты в памяти нумеруются. Номер байта - адрес.
int х=5 – инициализация переменной
int *p- объявление указателя;
p- указатель( адрес)
p=&x- взятие адреса
*p=10 – изменение х через указатель
*-операция разыменования (косвенное присвоение)
Ссылки.
В языке C ссылок нет. С точки зрения реализации, ссылка — это, по сути, указатель, который жестко привязан к области памяти, на которую он указывает, и который автоматически разыменовывается, когда мы обращаемся по имени ссылки
int y=10;
int & x=y;
cout<<”x= “<<x<<endl;// x=10
* конкретные адреса переменных могут быть другими */
int a;
//переменная с именем "a" типа int размещена по адресу 0xbfd86d6c
int &ra = a;
/* задано альтернативное имя (ra) для переменной по адресу 0xbfd86d6
символ "&" используемый для уже созданного объекта является операцией взятия адреса
(и эта операция не есть ссылка), то есть &a тут означает получить адрес переменной к которому привязано имя "a" */
cout << &a << '\n' << &ra << '\n';
В stdout будет записано:
0xbfd86d6c 0xbfd86d6c
То есть оба имени "a" и "ra" привязаны к одному и тому же адресу.
Ссылки нельзя объявлять без привязки к переменной (то есть не инициализировав при объявлении). После объявления ссылки её невозможно привязать к другой переменной.
Важно отличать ссылки от оператора взятия адреса & (address of). Оператор взятия адреса используется для уже созданного объекта с целью получить его адрес (то есть адрес области памяти, где хранятся значения), а ссылка это только задание альтернативного имени объекта (с точки зрения программиста, а не реализации). Например:
int a; //переменная типа int размещена по адресу 0xbfd86d6c с именем "a"
int b = 3;
/* создан указатель с именем "p" по адресу 0xbf971c4c, значение этого указателя адрес объекта с именем "a" - 0xbfd86d6c (это значение можно будет менять)
*/
int *p = &a;
p = &b; //присваиваем указателю новое значение
Пример 1
# include <iostream.h>
void main()
{
int x=10;
int *p;
cout<<”x=”<<x<< endl; // 10
p=&x;
cout<<”p=”<<p<<endl;
//p=0X0012FF7C –адрес ячейки памяти, содержащей int x
*p=20;
cout<<”*p=”<<*p<<endl; //20
cout<<”x=”<<x<< endl; // 20
int & r=x; //& r-ссылка
r=50;
cout<<”r=”<<r<<endl; // 50
cout<<”x=”<<x<< endl; // 50
x=20;
cout<<”r=”<<r<<endl; // 20
cout<<”*p=”<<*p<<endl; //20
}
*Примечание
Ссылка -2ое имя Х, r работает как указатель, автоматически разыменовывается. Память под r не выделяется
Пример 2
# include <iostream.h>
void main()
{
int a[3]={1.2.3};
cout<<” array a:<<endl;
cout<<a[0]<<’ ‘ <<a[1]<<’ ‘ <<a[2]<<endl; // 1_2_3
cout<<”address a:”<<a<<’ ‘<<a+1<<’ ‘<<a+2<<endl ;
// address a: 0x0012FF68 0x0012FF6C 0x0012FF70
//Косвенное изменение массива
int *q=a; //q указатель на int
cout<<”q=”<<q<<’ ’<<q+1<<’ ’<<q+2<<endl;
// q= 0x0012FF68 0x0012FF6C 0x0012FF70
cout<<”*q=”<<*q<<’ ’<<*(q+1)<<’ ’<<*(q+2)<<endl;
//*q=1 2 3
*q=904; *(q+1)=905; *(q+2)=906;
cout<<” array a:”<<endl;
cout<<a[0]<<’ ‘ <<a[1]<<’ ‘<<a[2]<<endl;
// 904 905 906
a[0]=1;
a[1]=2;
a[2]=3;
cout<<” *q= ”<<*q<<’ ’<<*(q+1)<<’ ’<<*(q+2)<<endl ;
//*q=1 2 3
}
Функции
Основы использования функций.
Функции – этьо подпрограммы , которые содержат одну или несколько инструкций. Функции называются строительными блоками С++, поскольку программа в С++ , как правило, представляет собой коллекцию функций.
Общий формат С++ функций
Все С++ функции имеют общий формат
Тип_возвращаемого значения имя (список _параметров)
{
// тело функции
}
С помощью элемента тип_возвращаемого_значения указывается тип значения возвращаемого функцией. Это может быть любой тип , за исключением массива. Если функция не возвращает никакого значения , необходимо указать тип void.
В качестве имени можно использовать любой допустимый идентификатор, который еще не был задействован в программе.
После имени функции в круглых скобках указывается список параметров, который представляет собой список пар ( состоящих из типа данных и имени ), разделенных запятыми.
Параметры – это по сути переменные, которые получают значения аргументов, передаваемых функции при вызове.
Если функции не имеют параметров, то круглые скобки остаются пустыми.
В фигурные скобки заключено тело функции. Тело функции составляют С++-инструкции, которые определяют действие функции. Функция завершается ( и управление передается вызывающей процедуре) при достижении закрывающейся скобки или инструкции return
Создание функции.
#include<iostream>
using namespace std;
void myfunc();// прототип функции myfunc()
void main()
{
cout<<”В функции main().”<<endl;
myfunc();
cout<<”Снова в функции main().”<<endl;
}
// Определение функции myfunc()
void myfunc()
{
cout<<”В функции myfunc().”<<endl;
}
Использользование аргументов
Функции можно передать одно или несколько значений. Значение передаваемое функции называется аргументом. Таким образом, аргументы представляют собой средсьво передачи инициализации в функцию.
При создании функции, которая принимает одно или несколько аргументов, необходимо объявить переменные, которые получат значения этих аргументов. Эти переменные называются параметрами функции.
#include<iostream>
using namespace std;
void box(int length, int width, int height);// прототип функции
void main()
{
box(7,20,4);
box(50,3,2);
box(8,6,9);
}
// Определение функции box()
void box(int length, int width, int height)
{
cout<<” Объем параллелепипеда равен ”<< lengtht* width* height <<endl;
}
Использользование инструкции return
В предыдущих примерах возврат из функции к инициатору ее вызова происходил при обнаружении фигурной скобки. Однако это приемлимо не для всех функций.
Возврат значений.
Использование функции в выражениях
Правила действия областей видимости функций.
Локальная область видимости
Локальные переменные можно объявлять внутри любого блока.
Сокрытие имен
Параметры функции
Глобальная область видимости
Передача указателей и массивов в качестве аргументов функций
Передача функции указателя
Передача функции массива
Передача функциям строк
Возвращение функциями указателей
Оформление функции в С++
Тип имя функции (список формальных параметров);
Типы функции
int
double
char
void (не возвращает значений)
Функция - именованный набор операторов.
Если р1 и р2 функции, и р1 вызывает р2, то р2 должна быть описана раньше р1.
Если тело функции идет после main() , то перед main() должен стоять прототип функции.
Пример 1
Функция плюс
# include <iostream.h>
void plus (int,int,int); // прототип функции plus, параметры переданы по значению
void plus1 (int,int,int&); // прототип функции plus1, последний параметр передан по ссылке
int plus2(int, int) //результат функции число типа int
void main()
{
int a=4; int b=5; int c=10;
cout<<”plus()”<<endl;
plus(a,b,c);
cout<<”c=”<<c<<endl; //9
plus1(a,b,c);
cout<<”c=”<<c<<endl; //10
int c2=plus2(a,b);
cout<<”c2=”<<c2<<endl; //9
// Возможен вариант
cout<<”plus2()=”<<plus2(a,b)<<endl; //9
}
void plus (int x, int y, int z)
{
cout<<”x=”<<x<< endl; //4
cout<<”y=”<<y<< endl; // 5
cout<<”z=”<<z<< endl; // 10
z=x+y;
cout<<”z=”<<z<< endl; // 9
}
void plus1 (int x, int y, int &z)
{
cout<<”x=”<<x<< endl; //4
cout<<”y=”<<y<< endl; // 5
cout<<”z=”<<z<< endl; // 10
z=x+y;
cout<<”z=”<<z<< endl; // 9
}
int plus2 (int x, int y)
{
cout<<”x=”<<x<< endl; //4
cout<<”y=”<<y<< endl; // 5
cout<<”x+y”<<x+y<< endl; // 9
return x+y;
}
Примечание
При вызове функций plus2() на месте аргументов могут быть любые выражения данного типа.
plus2(a+b*c,2*c);
plus2(5,7);
Передача массивов функции.
Пример 2.
# include <iostream.h>
const int n=10;
void create ( int x[], int k);
//возможный вариант void vvod ( int x[n])
void show ( int x[], int k);
int max (int x[], int k);
void main()
{
int a[n];
create(a,n);
show ( a, n);
cout<< “max(a,n)= ”<<max(a,n)<<endl;;
}
void create ( int x[], int k)
{
int i;
for (i=0; i<k; i++)
{
cout<<”x[“<<i<<”]=”;
cin>>x[i];}
}
}
void show ( int x[], int k)
{
int i;
for (i=0; i<k; i++)
cout<<x[i]<<”_”;
}
int max(int x[], int k)
{
int i;
int m;
m=a[0];
for (i=0; i<k; i++)
if (m<x[i]) m=x[i];
return m;
}
Лекция №9
Динамические массивы
Задание статического массива
const int n=10;
int a[n];
Задание динамического массива
int n;
cout<< “Enter n:”;
cin>>n;
int*b //указатель на первый элемент массива
b= new int[n];
delete [] b - после работы программы необходимо освободить память «кучи» от b.
В параметрах функций динамический массив задается так же, как и статический
void vvod ( int x[], int n);
Или
void vvod ( int *x, int n);
void vvod ( int x[n])
Примечание
int*p;
p=new int;
*p=10; (косвенная динамическая память)
delete p ; (возврат памяти)
Задание двумерного динамического массива
Память выделяется в 2 этапа: сначала под строку указателей на столбцы, а затем в цикле под каждый столбец.
int colstr; colstb;
cout<< “Enter colstr:”;
cin>> colstr;
cout<< “Enter colstb:”;
cin>> colstb;
int **b;
b=new int*[colstr];
for (int i<0;i<colstr;i++)
b[i]=new int[colstb];
Соответственно, необходимо delete[][]b;
В параметрах функций
void create ( int **x, int n, int m);
void show( int **x, int n, int m);
Задача 1.
Даны два двумерных массива A и B (квадратные матрицы).
Матрица С= A* B, если в А существует строка простых чисел. В противном случае С= A+ B
# include <iostream.h>
# include <math.h>
void create ( int **, int);
void show( int **, int);
bool prime (int);
bool EA( int **, int);
void mult ( int **, int**, int**);
void add ( int **, int**, int**);
void main()
{
int n;
cout<<”enter size=”;
cin>>n;
int **a, **b, **c;
a= new int*[n];
int i;
for (i<0;i<n;i++)
a[i]=new int[n];
b= new int*[n];
for (i<0;i<n;i++)
b[i]=new int[n];
c= new int*[n];
for (i<0;i<n;i++)
c[i]=new int[n];
create(a,n);
create(b,n);
if (EA(a,n)) mult(a,b,c);
else add(a,b,c);
cout<<”array c:”<<endl;
show(c,n);
delete[][]a;
delete[][]b;
delete[][]c;
}
