Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
UMKD_S__programm.doc
Скачиваний:
3
Добавлен:
01.07.2025
Размер:
1 Мб
Скачать
☆

Функцияға функциянын атына беру.

Шығару функциясын таблицалық мағына деп атап print_tabl, алдымен интерфейсті анықтап алу қажет.Таблицаны шығару үшін,функциямызға диопозон мен аргумент мағыналық өзгерту қадамын білу керек, тағы қандай функцияны табуымыз қажет? Барлығы ма? Жоқ,толық емес: функциянын қатарлар санын дұрыс анықтау,сондықтан print_tabl функциясын шақырушы параметрлер тізімін дәлірек қосу қажет. Print_tabl функциясын ешбір мағына қайтармайды,сондықтан атынын алдынан Void көрсету керек.

Функцияға қалай функциянын атын беру қажет? Дәл солай,кез келген өлшем: параметр тізімінде параметр атынан бұрын типін көрсету керек.Осы мезетке дейін біз стандартты типтін өлшемін функцияға беріп отырдық,ал енді біз өзіндік типті табу қажет.Функция типі қайтару мағынасымен оның типі арқылы табу және оның типтік параметрі. Функцияға былай көрінеді:

Double (*fun)(double, double);

Мында fun көрсеткіші арқылы функция сипатталады,double типі,ол екі аргумент алу және сол типтін мағынасын қайтару.

Жиі кездеседі, егер сипаттау типі күрделі болса,

кілттік сөзі арқылы программаға синонимін жақсарту мақсаты ретінде береді.

Typedef double (*p fun )(doudle,doudle);

P fun типі бұл операторда беріледі.

Стандартты типтермен айнымалыларды сипаттағанда қолдануға болады.Сонымен таблица, функция басында болу қажет.

Void print_tadl(p fun,double xn ,double xk, double dx,double eps);

Енді программа мәтінін жазамыз.минималды диогностикалық қателерін байланыстыру (максималді қажетті саны интерациянын функциясынан көп болса, аяқтайды. 0 қайтарып, ал шақырушы программа бұл мәнді шығарады):

#include<stdio.h>

#include<math.h>

#pragma hdrstop

//---------------------------------------------------------------------------

#pragma argsused

int main(int argc, char* argv[])

{

typedef double(*Pfun)(const double,const double);

void print_tabl(Pfun fun,const double Xn,const doubl Xk, const doubl dx,

const doublе eps);

double cosh(const double x,const double eps);

int main() {

double Xn,Xk,dx,eps;

printf("Enter Xn,Xk,dx,eps\n");

scanf ("%lf%lf%lf%lf",&Xn,&Xk,&dx,&eps);

print_tabl(cosh,Xn,Xk,dx,eps);

return 0;

}

void print_tabl(Pfun fun,const double Xn ,const double Xk,const double dx,

const double eps) {

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

printf("| X | Y | \n");

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

for (double x=Xn; x<=Xk;x+=dX);

printf(" |%9.2lf | %14.6g |\n ",x,fun (x,eps));

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

}

double cosh (const double x,const double eps){

const int MaxIter=500;

double ch=1,y=ch;

for (int n=o; fabs(ch)>eps; n++) {

ch*=x*x/(2*n+1)/(2*n+2);

y+=ch;

if(n>MaxIter) return 0;

}

return y; }

return 0;

}

//---------------------------------------------------------------------------

Print_tabl функциясы кез келген функциялық таблицанын мағынасын шығару үшін, double типі екі аргумент қабылдаушы және сол типтін мағынасын қайтарушы. Көріп тұрғандай,біз структуралық программаны өте жоғары деңгейге жеткізіп, екі логикалық бөлікке бөлдік. Функцияны табу және таблицаны шығару. Басты программада тек қана шыққан мәнді енгізу берілген және шақыру функциясы.

8-дәріс. Структуралар

Құрылым(структура)

Ә

Студент

Фамилия

курс

группа

факультет

ртүрлі типті деректерді бір типке біріктіреді.Құрылым типі деректер қорын және ақпараттық жүйелерді құрғанда қолданылады.Студенттер тізімін жасауда әрбір студент үшін бірнеше деректерді бірден жазу керек болады:

Осы структураның элементтері (фамилия, курс, группа, факультет) өрістер болып табылады. Әрбір өрісіне тип және ат сәйкестендіріледі.

Структуралық типті жазу форматы:

struct аты

{ тип_1 өріс1;

тип_2 өріс2;

...............

тип_n өрісn

};

Осы типтіің айнымалыларын сипаттау кәдімгідей

Тип_аты айнымалы_аты;

немесе тип сипатталғаннан кейін соңына жалғастырып жазуға да болады.

struct аты

{ тип_1 өріс1;

тип_2 өріс2;

...............

тип_n өрісn

} Айнымалы_аты1,..., айнымалы_атыn;

Жоғарыдағы деректер үшін құрылым сипаттау:

struct student

{ char fam[30];

int kurs;

char grup;

char fac[15];

};

student atud1,stud2;

немесе тіркеп, жалғастырып жазсақ:

struct student

{ char fam[30];

int kurs;

char grup;

char fac[15];

}stud1,stud2,*pst;

Құрылымның элементтеріне қатынау үшін келесі форматты пайдаланады:

айнымалы_аты. өріс_аты;

Мысалы, stud1.fam;

stud2.kurs;

Сипаттау барысында мән беріп кетуге болады:

student atud1={“Ахметов”, 3, “ИС-21”, “математика”};

Құрылымға көрсеткіш анықталғаннан кейін, меншіктеу орындалса,

Pst=&stud1;

Онда оның элементтеріне үш әдіспен қатынауға болады:

stud1.fam немесе(*pst).fam немесе pst fam

Класс-элементері типтелген деректер мен оларды өңдейтін функцияларды біріктіретін құрылымды (структураланған) тип.

Полиморфизм әртүрлі аргументтер мен операндтарға, сонымен бірге әртүрлі типтерге бірдей атпен функцияларды қолдану. Оны С++ те

# include <iostream.h>

# include <conio.h>

# include <math.h>

struct Frac

{int P;

int Q ;

} ;Frac F;

class Drob{

Frac A;

public:

void Vvod(void);

int NOD(void);

void Sokr(void);

void Stepen(int N);

void Print(void);

};

void Drob::Vvod(void)

{cout <<"Chislitel?"; cin >>A.P;

cout<< "Znaminatel?"; cin>>A.Q;

}

int Drob::NOD(void)

{ int M,N;

M=abs(A.P); N=A.Q;

while (M!=N)

{ if (M>N)

if (M%N!=0) M=M%N; else M=N;

else if (N%M!=0) N=N%M; else N=M;

}

return M;

}

void Drob::Sokr(void)

{int X;

X=NOD();

if (A.P!=0)

{A.P=A.P/X; A.Q=A.Q/X;}

else A.Q=1 ;

}

void Drob::Stepen(int N)

{ int i;

F.P=F.Q=1;

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

{F.P*=A.P; F.Q*=A.Q;}

}

void Drob::Print(void)

{cout<<"\n"<<A.P<<"/"<<A.Q<<"\n";}

void main(void)

{ Drob Y;

cout<<"Vvodite drob!"<<"\n";

Y.Vvod();

Y.Sokr();

cout<<"drob posle cokraschenj:"<<"\n";

Y.Print();

Y.Stepen(2);

cout<<"drob vozvedenie v kvadrat:"<<"\n";

cout<<F.P<<"/"<<F.Q<<"\n";

getch();

return;

}

C++ көрсеткіштер арқылы структураға қатынауға болады.

Структураға көрсеткіштің хабарлануында ешқандай өзгеріс жоқ, тек оған қатынауда өзіндік ерекшелігі бар.

Inv-type *inv_pointer;

Мұндағы Inv-type структуралық тип, ал inv_pointer көрсеткіш.

Структуралық айнымалы адресін табу үшін оның алдына «&» белгісін қоямыз.

Мысалы

struct bal {

float balance;

char name[80];

}person;

bal *p; структураға көрсеткіш хабарлау.

p=&person;

инструксиясы орындалғанда person структуралық айнымалының адресі р көрсеткішіне жазылады. Ал структура элементтеріне қатынас

стрелка арқылы жасалады

p->balance;

Cтруктураны функцияға параметр ретінде беру.

#pragma hdrstop

#include <iostream.h>

#include <conio.h>

using namespace std;

//---------------------------------------------------------------------------

struct sample{

int a;

char ch;

};

void f1(sample parm);

#pragma argsused

int main(int argc, char* argv[])

{

struct sample arg;

arg.a=1000;

arg.ch='X';

f1(arg);

getch();

return 0;

}

void f1(sample parm)

{

cout << parm.a <<"\n";

cout <<parm.ch << "\n";

}

//---------------------------------------------------------------------------

9-дәріс Жолдар. Жолдарды функцияға ауыстыру

Тексттік файлдың әр жолында қанша сан бар екендігін анықтайтын программа жаз. Әр жолдың ұзындығы 100 символдан аспайды.

Бұл есепті екіге бөлуге болады: файлдан деректерді енгізу және анализ. Әр жол үшін тексеру бөлек орындалады,сондықтан функция түрінде бір жолда сандарды іздеу және санау дұрыс болады. Функцияға кірерде жол берсек,шыққанда осы жолдағы сандардың жалпы санын аламыз.

Жолдарды функцияға ауыстырудың массивке ауыстырудан айырмашылығы бөлек параметрмен жолдың өлшемін бермей-ақ ,функция ішінде жолдың соңын ноль-символ арқылы анықтауға болады.

#include<fstream.h>

#include<ctype.h>

int num_num(const*str);

int main( ){

ifstream fin(“test.txt”,ios::in | ios::nocreate);

if(fin!){cout<<”net faila test.txt”<<endl: return 0);

const int len=101;

int i=1;

char str[len];

while(fin.getline(str.len)) {

cout<<”v stroke”<< i <<”soderzhitsj”<<num_num(str)<<”chisel”<<endl;

i++;

}

return 0;

}

int num_num(const char*str){

int cout = 0;

while(*str) {

if(isdigit(*str) && ! isdigit(*(str+1)) && *(str+1) !=’_’) cout++;

str++; }

return cout;

}

num_num функциясынлағы сандардың көбеюі әр сан аяқталғаннан кейін болады немесе басқаша айтсақ саннан кейін сан да, нукте де тұрмаса. Цикл ноль-символға жеткенте тоқтайды.

Структура массивінде іздеу жүргізу

І. Шығатын мәліметтер, нәтижелер және көлем аралығы

Шығатын мәліметтер. Қызметкерлер базасы текстік файлда орналасқан. Біріншіден, жедел жадыда бірмезгілде файлдың барлық ақпаратын сақтаймыз ба,әлдебір жолға буферді қолдануға болады ма екенін шешіп алу керек. Егер қызметкер туралы мәлімет бір ретсұралса, екінші таңдауда тоқтауға болар еді, бірақ база бойынша іздеу бірақ рет

Есептің шарты бойынша файлдағы жолдардың максималдық саны шектеулі, сол себепті оларды сақтау үшін 100 элементтері бар массивті бөліп беруге болады. Массивтің әрбір элементінде бір қызметкер туралы мағлұмат болады. Бұл мағлұматтар «разнородные» болғандықтан, оларды структура ретінде ұйымдастыру оңай болады.

Шарт бойынша осы программаға ізделуші қызметкерлердің фамилиясы енгізілуі керек. Фамилияларды сақтау үшін базадағыдай ұзындығы бар символдар жолын сипаттайық.

Нәтижелер. Программаның жұмыс істеу нәтижесінде экранға массивтен керек элементтерді шығару керек. Сонымен қатар, табылған қызметкерлердің жалақысының орташасын табу керек. Ол үшін нақты типті айнымалы керек.

Көлем аралығы.Орташа жалақыны табу үшін мағлұмат берілетін қызметкерлердің санын есептеу қажет. Ол үшін бүтін типті айнымалы енгіземіз. Кіретін файлдардың форматын сипаттау үшін атаулы тұрақтыларды қолданамыз.

ІІ. Есепті шешудің алгоритмі:

  1. Файлдан массивке қызметкерлер туралы мағлұматтарды енгізу

  2. Қызметкерлер туралы мәліметтерді енгізу үшін цикл құру:

А) клавиатурадан фамилияларды енгізу

В) массивтен қызметкерлерді іздеуді ұйымдастыру

С) суммарлық жалақыны арттыру және қызметкерлер санын арттыру

Д) қызметкер туралы мәліметті немесе оның жоқтығы туралы жауап беру

3. Орташа жалақыны есептеу

Циклдан шығу үшін фамилияның орнына end сөзін қолданамыз.Енді осы программаны жақынырақ қарастырайық.

//---------------------------------------------------------------------------

#include <fstream.h>

#include <string.h>

#include <stdlib.h>

//#include <windows.h>

#pragma hdrstop

//---------------------------------------------------------------------------

#pragma argsused

int main(int argc, char* argv[]) //0

{

const int l_name=30, l_year=5, l_pay=10,l_buf=l_name+ l_year+l_pay; //1

struct Man{ //2

int birth_year;

char name[l_name+1];

float pay;

};

const int l_dbase=100;

Man dbase[l_dbase]; //3

char buf [l_buf+1]; //4

char name [l_name+1]; //5

ifstream fin("dbase.txt", ios::in | ios::nocreate); //6

if (!fin) {cout <<"Owibka otcrytiya faila"; return 1;}

int i=0;

while (fin.getline (buf,l_buf)){ //7

if (i>=l_dbase) { cout <<"sliwkom dlinnyi fail"; return 1;}

strncpy (dbase[i].name,buf,l_name);

dbase[i].name[l_name]='\0';

dbase[i]. birth_year=atoi (&buf[l_name]);

dbase[i].pay = atof (&buf[l_name+l_year]) ;

i++;

}

int n_record=i, n_man=0; //8

float mean_pay=0;

while (true){ //9

cout <<"vvedite familiyu ili slovo end: "; cin >>name;

// OemToChar (name, name); //10

if (strcmp (name, "end")==0) break; //11

bool not_found=true; //12

for (i=0; i<n_record; i++) { //13

if (strstr(dbase[i].name,name)) //14

if (dbase[i].name[strlen(name)]==' '){ //15

strcpy (name, dbase [i].name);

// CharToOem(name,name); //16

cout <,name<< dbase [i].birth_year <<' '<<dbase[i].pay << endl;

n_man++; mean_pay+= dbase[i].pay;

not_found=false;

}

}

if (not_found) cout <<"Takogo sotrudnika net"<< endl;

}

if (n_man>0) cout << "Srednii oklad:"<< mean_pay/n_man<<endl; //17

return 0;

}

//---------------------------------------------------------------------------

1 операторда кіруші файлдардың форматы, яғни жазудың әрбір жолының (файлдың жолдары) ұзындығы сақталатын атаулы тұрақтылар берілген. Бұндай жақын келу программаларға өзгерістер енгізуге қолайлы. Файлдың әрбір жолы оқылатын буфердің ұзындығы көрсетілген жолдардың ұзындықтарының қосындысы ретінде есептелінеді.

  1. операторда бір қызметкер туралы мағлұмат сақталатын Man структурасы анықталады. Фамилия орналасатын жолдың ұзындығы ноль-символдың аяқталуымен берілген. 3 операторда барлық базаны сақтау үшін dbase структурасының массиві анықталады. Оның да көлемі атаулы тұрақтымен беріледі. 4 және 5 операторларда аралық айнымалылар беріледі: buf буфері - файлдан жолды енгізу үшін және name жолы - ізделінгелі қызметкердің фамилиясы.

6 операторда dbase.txt файлының оқуға ашылуы жүргізіледі. Бұл файл да текстік программа тұратын каталогта деп тұжырымдалады, әйтпесе толық жолды көрсетуге тура келер еді. Кіруші файлды, есептің шартына байланысты, кез-келген текстік редакторда программаның бірінші қосылуына дейін форматпен сәйкестендіріп жасаған жөн. Тестілеуге арналған файл бірнеше жолдан тұруы керек, сонымен қатар бір фамилия екінші бір фамилияның бөлігі болып келуі мүмкін жағдайды да қарастыру керек (Мысалы, Иванов және Ивановский).

7цикл файлдан buf жолына жолдық оқуды және кезекті dbase массивінің элементін толтыруды орындайды. i счетчигі массивтің бірінші бос элементінің индексін сақтайды. Структураның өрісін қалыптастыру үшін жолдардың көшірмесін жасау функциясы strncpy қолданылады, жолдан бүтін atoi санына құрайды және жолдан нақты atof санына жаңартамыз. Циклдың әрбір қайталанылуында жолдар санының массив ұзындығынан аспауына тексеру төмендегідей жүргізіледі жүргізіледі:

While (fin.getline(buf, l_buf)&& i< L_dbase){

……………………………………..

I++;

}

If (i>=l_dbase) {cout <<” Слишком длинный файл”; return 1;}

8 операторда 2 айнымалы анықталады: n_record барлық қызметкерлер туралы жазулардың санын сақтау үшін және n_man – мәлімет берілетін қызметкерлердің санын санау үшін, mean_pay айнымалысын нөлдетуді де ұмытпау керек, себебікелесі циклде оған жалақылардың суммасы жазылады. Қызметкерлерді фамилия бойынша іздеу циклы шексіз (9) мәжбүрленген шығумен (11) ұйымдастырылған.

12 операторда айнымалы-флаг not_found анықталады. Оның қызметі циклдың соңында ол дұрыс аяқталды ма, соны білу үшін пайдалынылады. Жазылуы төмендегідей:

If (not_found) cout <<”Такого сотрудника нет”<<endl;

13 операторда структуралардың массивін көру ұйымдастырылады (тек енгізу кезінде толып қалған элементтер көрсетіледі). 14 операторда strstr функциясының көмегімен name базвсының өрісінде ізделініп отырған әріптердің тізбегі бар ма, әлде жоқ па екені анықталады, ал 15 операторда фамилиядан кейін бос орын бар ма екені тексеріледі (егер бос орын болмаса, ізделініп жатқан фамилия басқа фамилияның бір бөлігі екендігі және бұл жолдың бізге керегі жоқ).

Егер сіз dbase.txt файлын NotePad ytvtct WordPad (ANSI кодтауы ) редакторында жазсаңыз, программа орысша әріптермен жұмыс істемейді. Мұндай жағдайда OemToChar() функциясын пайдаланамыз, ASCII кодтауындағы символдарды ANSI кодтауына ауыстырады (name айнымалысы). Сонымен қатар тексті консольді терезеге дұрыс шығару үшін кері жұмыс CharToOem функциясы арқылы жасалынады. Осы функцияларды қолдану үшін программа басында <windows.h> сөзі жазылып кеткені дұрыс.

Программаны талдауды жалғастырайық. Біз алгоритмнің сөйлем ішінде құрылғанында тоқталдық, яғни фамилия мәліметтер қорындағы жазудың бірінші позициясынан басталады.

17 операторда n_man айнымалысының тексерілу себебі, егер қолданушы бір де бір базадағы фамилиямен сәйкес келетін фамилия енгізбесе, 0-ге бөлу болмау үшін қолданылады. Латын алфавитінің символдарына арналған tolower (c) және toupper (c) функциялары бар. Егербазада бір фамилиялы бірнеше адам болса, программа олардың барлығы туралы мәлімет шығарады. Енді жаңағы прграмманы библиотекалық енгізу-шығару функциялары арқылы жазып көрейік:

//---------------------------------------------------------------------------

#include <stdio.h>

#include <string.h>

//#include <windows.h> //0

#pragma hdrstop

//---------------------------------------------------------------------------

#pragma argsused

int main(int argc, char* argv[])

{

const int l_name=30; //1

struct Man{

int birth_year;

char name[l_name+1];

float pay;

};

const int l_dbase=100;

Man dbase[l_dbase];

char name[l_name+1];

FILE*fin;

if ((fin=fopen("dbase.txt","r"))==NULL)

{puts ("Owibka otcrytiya faila\n"); return 1;}

int i=0;

while (!feof(fin)){

fgets(dbase[i].name, l_name, fin);

fscanf (fin, "%i%f\n", &dbase[i].birth_year, &dbase[i].pay); //2

i++;

if (i>=l_dbase) { puts ("sliwkom dlinnyi fail\n"); return 1;}

}

int n_record=i, n_man=0;

float mean_pay=0;

while (true){

puts ("vvedite familiyu ili Enter dlya okon4aniya: ");

gets(name);

if (strlen(name)==0) break; //3

// OemToChar (name, name); //4

bool not_found=true;

for (i=0; i<n_record; i++) {

if (strstr(dbase[i].name,name))

if (dbase[i].name[strlen(name)]==' '){

strcpy (name, dbase [i].name);

// CharToOem(name,name); //5

printf ("%30s%5i%10.2f\n", name,dbase[i].birth_year,dbase[i].pay );

n_man++; mean_pay+= dbase[i].pay; //6

not_found=false;

}

}

if (not_found) puts ("Takogo sotrudnika net\n") ;

}

if (n_man>0)printf( "Srednii oklad: %10.2f\n", mean_pay/n_man);

return 0;

}

//---------------------------------------------------------------------------

Біз сұрауға енгізу циклынан шығуды оңайраттық, тек Enter басса болды (оператор 3). Қызметкерлер туралы міліметті шығару үшін біз prinf (оператор 6) функциясын қолданамыз. Көріп отырғандарыңыздай, кей кездері ескі жақсы функциялар программаны оңай және көрнекі қылуы мүмкін!

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]