Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
СИ++(лекции).doc
Скачиваний:
23
Добавлен:
27.03.2015
Размер:
551.42 Кб
Скачать

3. Добавление новых элементов в проект

Если необходимо расположить вводимые функции в отдельном файле рекомендуется прототипы функций располагать в отдельном головном файле, а тела функций в файле с тем же именем с расширением cpp. Для того, чтобы добавить файл к проекту необхрдимо в разделе Project выбрать пункт Add New Item (рис. 6) и в открывшемся окне выбрать в окне Categories пункт Code, а в окне Templates тот тип файла, который хотим добаыить (или головной фай с расширение h или файл с расширение cpp). Окно диалога представлено на рис.7. В файле с расширением cpp следует расположить те функции, прототипы которых указаны в головном файле с тем же именем.. В листинге программы, представленном ниже, приведен пример функции вычисления полинома вида , причем функции вычисления полинома и печать результата вынесены в отдельный файл.

Листинг 4.

// stdafx.h : include file for standard system include files,

// or project specific include files that are used frequently, but

// are changed infrequently

//

#pragma once

#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers

#include <stdio.h>

#include <tchar.h>

#include"f.h"

#include <iostream>

using namespace std;

// TODO: reference additional headers your program requires here

Файл f.h

int f1(int x,int n);

void f2(int x);

Файл f.cpp

#include "stdafx.h"

#include "f.h"

int f1(int x,int n)

{

int y=1;

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

{y=y*x+i;

}

return y;

}

void f2(int x)

{

cout<<"f2: "<<x<<'\n';

}

// mulfil.cpp : Defines the entry point for the console application.

//

#include "stdafx.h"

int _tmain(int argc, _TCHAR* argv[])

{

int x,n,y;

cout<<" Input x and n ";

cin>>x>>n;

y=f1(x,n);

f2(y);

cin.get();

cin.get();

return 0;

}

Глава 3. Операторы языка СИ++

Глава 4. Адреса, указатели, массивы, память

1. Указатели и адреса объектов

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

Указатели делятся на два вида – указатели на объекты и указатели на функции. Это разделение обусловлено отличиями в свойствах и правил использования. Например, указатели на функции не допускают применение к ним арифметических операций, а указатели объектов разрешено использовать в некоторых арифметических выражениях.

2. Указатели на функции

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

Тип_возращаемого_результата (*имя_указателя)(спецификация_параметров)

Например, int(*funreplace)(char); - определение указателяfunreplaceна функцию с параметромcharи возвращающую значениеint. Первые круглые скобки очень важны, так как если их опустить, то компилятор воспримет это как прототип функции, возвращающей указатель наint, В качестве простейшей иллюстрации приведем программу с указателем на функцию.

// stdafx.h

#pragma once

#define WIN32_LEAN_AND_MEAN

#include <stdio.h>

#include <tchar.h>

#include <iostream>

using namespace std;

// funk_ukazatel.cpp :

#include "stdafx.h"

int max(int *x,int n);

int min(int *x,int n);

int _tmain(int argc, _TCHAR* argv[])

{

int n,*y,i;

int(*ptr)(int*,int);

cout<<"Input n ";

cin>>n;

y=new int[n];

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

{

cout<<"Input x("<<i+1<<")=";

cin>>y[i];

}

ptr=max;

cout<<(*ptr)(y,n)<<'\n';

ptr=min;

cout<<(*ptr)(y,n)<<'\n';

cin.get();

cin.get();

return 0;

}

int max(int *x,int n)

{

int maxx,i;

maxx=x[0];

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

if(x[i]>maxx) maxx=x[i];

return maxx;

}

int min(int *x,int n)

{

int minx,i;

minx=x[0];

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

if(x[i]<minx) minx=x[i];

return minx;

}

В программе указателю ptrпоследовательно присваиваются имена функцийmaxиmin.Форма вызова функции с помощью указателя осуществляется следующим образом

(*имя_указателя)(список_фактических_параметров);

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

typedef float (*PTF)(float);

typedef char* (*PTC)(char);

typedef void (*PTFFUNC)(PTF,int,float); Здесь PTF – имя типа “указатель на функцию с параметрами типа float, возвращающую значение типа float”. PTC– имя типа “указатель на функцию с параметром типаchar, возвращающую указатель на тип char”.PTFFUNC– имя типа “указатель на функцию, возвращающее пустое значение (типvoid)”. Параметрами для этой функции служат: PTF- указатель на функциюfloat имя(float), выражение типаintи выражениеfloat. В определении имени типаPTFFUNC вошел только что определенный типPTF.

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

// stdafx.h

#pragma once

#define WIN32_LEAN_AND_MEAN

#include <stdio.h>

#include <tchar.h>

#include <iostream>

using namespace std;

// funk_ukazatel.cpp

#include "stdafx.h"

void act1(char* name);

void act2(char* name);

void act3(char* name);

void act4(char* name);

void act5(char* name);

typedef void(*MENU)(char*);//Определение типа указатель на функцию с именем MENU

MENU MenuAct[5]={act1,act2,act3,act4,act5};//Инициализация адресов пунктов меню

int _tmain(int argc, _TCHAR* argv[])

{

int number;//Номер выбранного пункта

char FileName[15];//Строка для имени файла

setlocale(LC_CTYPE,"russian");

cout<<"\n 1 - создание файла";

cout<<"\n 2 - уничтожение файла";

cout<<"\n 3 - чтение файла";

cout<<"\n 4 - модификация файла";

cout<<"\n 5 - выход из программы";

while(1)//Бесконечный цикл

{

while(1)//Цикл продолжается до введения правильного номера

{

cout<<"\n\nВведите номер пункта меню ";

cin>>number;

if(number>=1&&number<=5)break;

cout<<"\nОшибка в номере пункта меню!";

}

if(number!=5)

{

cout<<"\nВведите имя файла ";

cin>>FileName;

}

(*MenuAct[number-1])(FileName);

}

return 0;

}

void act1(char*name)

{

cout<<"\nДействия по созданию файла ";

setlocale(LC_CTYPE,".866");

cout<<name;

setlocale(LC_CTYPE,"russian");

}

void act2(char*name)

{

cout<<"\nДействия по уничтожению файла ";

setlocale(LC_CTYPE,".866");

cout<<name;

setlocale(LC_CTYPE,"russian");

}

void act3(char*name)

{

cout<<"\nДействия по чтению из файла ";

setlocale(LC_CTYPE,".866");

cout<<name;

setlocale(LC_CTYPE,"russian");

}

void act4(char*name)

{

cout<<"\nДействия по модификации файла ";

setlocale(LC_CTYPE,".866");

cout<<name;

setlocale(LC_CTYPE,"russian");

}

void act5(char*name)

{

cout<<"\nДействия по закрытию файла ";

cin.get();

cin.get();

exit(0);

}

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

// stdafx.h

#pragma once

#define WIN32_LEAN_AND_MEAN

#include <stdio.h>

#include <tchar.h>

#include<conio.h>

#include"Funcija.h"

#include<math.h>

#include<iostream>

using namespace std;

//Funcija.h

#include"stdafx.h"

double f(double x);//Подинтегральная функция

//Функция вычисления нитеграла методом трапеций,

double integ(double(*g)(double ),double a, double b,double e);

//Fucija.cpp

#include"stdafx.h"

double f(double x)

{

return x*x;

}

double integ(double(*g)(double ),double a, double b,double e)

{

double i0,i1,r,x=a,h;

int n=1,i;

i0=(b-a)*g((b-a)/2);//Значение интеграла при n=1

do

{

n=n*2;

h=(b-a)/n;

x=a+h/2;

for(i=1,i1=0;i<=n;i++,x+=h)

{

i1+=g(x)*h;

}

//i1- значение нитеграла при разбиении 2n

r=fabs(i0-i1);//погрешность

i0=i1;

}while(r>=e);

return i0;

}

// func.cpp

#include "stdafx.h"

int _tmain(int argc, _TCHAR* argv[])

{

double a,b,e,i;

setlocale(LC_CTYPE,"russian");

cout<<"Введите границы a b и точность e ";

cin>>a>>b>>e;

i=integ(f,a,b,e);

cout<<"int="<<i<<'\n';

getch();

return 0;

}