- •Глава 1. Основные понятия.
- •Общие сведения о программах, лексемах и алфавите
- •Процесс создания программы
- •Основные типы.
- •Основные типы данных
- •Глава 2. Создание консольных приложений в среде VisualStudio
- •1. Создание проекта
- •2. Начальный состав проекта
- •3. Добавление новых элементов в проект
- •Глава 4. Адреса, указатели, массивы, память
- •1. Указатели и адреса объектов
- •2. Указатели на функции
- •3. Ссылки
- •Глава 5. Структуры и объединения
- •1. Структура как тип и совокупность данных
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;
}