Описание структуры хранения данных

Факультет вычислительной математики и кибернетики

ОТЧЕТ

по лабораторной работе № 4

«Аналитические преобразования полиномов

от нескольких переменных»

Выполнил: студент группы 8210

__________________Баранов А.М. Проверил:

__________________Сидоров С.В.

Нижний Новгород

2011 г.

Оглавление

Аннотация. 3

Введение. 3

Постановка задачи. 3

Руководство пользователя. 4

Руководство программиста. 6

Описание структуры хранения данных. 6

Описание программы.. 7

Описание алгоритма. 7

Заключение. 10

Литература. 11

Приложение (исходный код программы) 12

Аннотация

В данной работе рассматриваются вопросы реализации некоторых базовых аналитических преобразований и операций над полиномами от нескольких переменных.

Для хранения полиномов используются однонаправленные динамические списки.

Введение

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

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

Постановка задачи

Лабораторная работа предполагает программную реализацию системы аналитических преобразований полиномов от трех переменных. Требуется реализовать следующие операции в аналитическом представлении исходных данных и результатов:

· ввод полиномов;

· вывод полиномов;

· удаление полиномов;

· приведение полиномов

· сложение полиномов;

· Вычитание полиномов;

· Производная от полинома;

· Умножение полиномов

Например, пусть имеется два полинома: P(x,y,z)=x7y2z+3x2z-6y2-3z9 и Q(x,y,z)=-7x2z+6y2+5. В результате выполнения операции сложения должен быть получен полином R(x,y,z)=x7y2z-4x2z-3z9+5.

Программа должна обеспечивать диалоговый интерфейс с пользователем обеспечивающий ввод исходных данных из заранее подготовленного файла с заданным именем.

Руководство пользователя

После запуска исполняемого файла программы вы увидите главное окно программы (рис. 1).

Описание структуры хранения данных - student2.ru

Рис. 1. Главное окно программы.

Основные операции.

Операция сложения/вычитания/умножения полиномов:

· Выбирается пункт меню 1/2/4;

· Вводится имя файла с первым полиномом;

· Выводится исходный неприведенный полином;

· Выводится приведенный полином;

· Вводится имя файла со вторым полиномом;

· Выводится исходный неприведенный полином;

· Выводится приведенный полином;

· Выводится результат в приведенном виде.

Описание структуры хранения данных - student2.ru

Рис. 2. Выполнение операции сложения.

Описание структуры хранения данных - student2.ru

Рис.3. Результат операции вычитания.

Описание структуры хранения данных - student2.ru

Рис.4. Результат операции умножения.

Операция вычисления производной:

· Выбирается пункт меню 3;

· Вводится имя файла с полиномом;

· Выводится исходный неприведенный полином;

· Выводится приведенный полином;

· Выводится результат в приведенном виде.

Описание структуры хранения данных - student2.ru

Рис.5.Результат вычисления производной.

Руководство программиста

Описание структуры хранения данных

При манипуляции разреженными полиномами эффективной структурой хранения являются списки.

В качестве структуры хранения данных полинома был выбран однонаправленный динамический список. Каждый узел содержит два элемента содержащие атрибуты монома

elem - коэфффициент монома

pol – свертка монома

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

· фиксируется старшинство переменных.

· Будем считать, что x - самая старшая переменная, затем следует y, затем z.

· Для каждого монома определим его "свернутую степень" (индекс).

· Для монома xAyBzC+n. индекс равен A*1000+B*100+C*10+n (по условию задачи A, B и C не выше 9).

· Старшим считается моном с большей свернутой степенью.

Свертка монома служит в дальнейшем ключом для идентификации монома

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

Для хранения промежуточного результата синтаксического разбора исходной строки используется массив Mpars

unsigned int Mpars[500];

node *Bfirst, *Blast ;

node *BRes; //Указатель на найденное звено списка.

node *Afirst, *Alast ;

node *ARes; //Указатель на найденное звено списка.

struct node {

int elem;

unsigned int pol;

node *next;

};

Для хранения полинома класс Spisok

class Spisok

{

private:

int N_monom;

public:

Spisok() {phead = new (node); (*phead).next=NULL;} //Конструктор.

~Spisok() { delete phead; } //Деструктор.

void Initial(node **first, node **last);

int Empty(node *first);

void Add(node **last,int elem, unsigned int pol);

void Show(node *first);

int Poisk_Eqv (node *first,unsigned int pol,node **last);

int Poisk_Less (node *first,int el,node **last);

void Izm (node *Res, int el,unsigned int pol);

void DelAll(node *first, node **last);

void AddLess (node **Res, int el,unsigned int pol);

int Next (node *first,int el,node **last);

void Del1 ();

};

Описание программы

Программа использует класс Spisok

class Spisok

{

private:

node *phead; //указатель на начало списка .

node *pend;

node *cursosr;

node *Res; //указатель на найденное звено .

int N_monom;

public:

Spisok() {phead = new (node); (*phead).next=NULL;} //конструктор

~Spisok() { delete phead; } //деструктор.

void Initial(node **first, node **last);

int Empty(node *first);

void Add(node **last,int elem, unsigned int pol);

void Show(node *first);

int Poisk_Eqv (node *first,unsigned int pol,node **last);

int Poisk_Less (node *first,int el,node **last);

void Izm (node *Res, int el,unsigned int pol);

void DelAll(node *first, node **last);

void AddLess (node **Res, int el,unsigned int pol);

int Next (node *first,int el,node **last);

void Del1 ();

};

Описание алгоритма

Работа программы начинается с вывода основного меню. Для начала работы выбирается пункт

"1.Операции"

При этом осуществляется запрос имени файла, где хранится описание полинома.

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

P='x7y2z1+3x2z1-6y2-3z9 '

Q='-7x2z1+6y2+5'

Коэффициенты мономов имеют целочисленный тип. При вводе полинома производится синтаксический разбор строки и приведение монома к стандартному виду – коэффициент со знаком и свертка.

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

Рекомендуемая форма печати полинома состоит в представлении полинома в виде текстовой строки с формульным выражением, описывающим полином. Например, полином P(x,y,z) из контрольного примера может быть представлен как строка:

P(x,y,z)='x7y2z1-4x2z1-3x9+5'

Реализация алгоритмов обработки полиномов организуется путем следующих шагов

1. Производится считывание исходной строки полинома с stdin ()

2. Выполняется анализ исходной строки на наличие запрещенных символов

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

4. Если свернутые степени мономов совпадают, то осуществляется приведение подобных членов: к коэффициенту монома полинома P прибавляется коэффициент монома полинома Q. Если при этом сумма коэффициентов оказывается равной нулю, то соответствующий моном полинома P исключается из списка.

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

· Сложение и вычитание

· Умножение

· Взятие производной. Для сложения полиномов P и Q производится одновременный обход обоих списков, начиная с головных звеньев, по правилу слияния упорядоченных массивов. Сумма формируется на месте первого слагаемого (P). При этом, если свернутая степень текущего монома полинома Q больше свернутой степени текущего монома полинома P, то копия монома полинома Q вставляется в полином P; в полиноме Q осуществляется переход на следующее звено. Если свернутая степень текущего монома полинома P больше свернутой степени текущего монома полинома Q, то в полиноме P осуществляется переход на следующее звено. Если свернутые степени текущих мономов полиномов P и Q совпадают, то осуществляется приведение подобных членов: к коэффициенту монома полинома P прибавляется коэффициент монома полинома Q. Если при этом сумма коэффициентов оказывается равной нулю, то соответствующий моном полинома P исключается из списка. В обоих списках осуществляется переход к следующему звену. Для реализации операций вставки и удаления звеньев в односвязных списках необходимы указатели как текущего, так и предыдущего звеньев.

· Удаление полинома. При удалении полинома предлагается немедленно возвращать освободившуюся память в кучу. В этом случае не образуется мусор из освободившихся звеньев. При удалении полинома осуществляется обход списка аналогично предыдущей операции, и каждое звено возвращается в кучу процедурой Dispose(q).

Заключение

Таким образом, все задачи, поставленные во введении, с успехом достигнуты, а именно: была реализована структура хранения список для прикладной задачи произведение операций над полиномами от трех переменных: сложение, вычитание, умножение полиномов, вычисление производной. Были получены необходимые навыки практического использования и реализации структуры список.

Литература

1. Топп У., Форд У. Структуры данных в C++: Пер. с англ. – М.: ЗАО «Издательство БИНОМ», 1999. – 816 с.: ил.

2. Шилдт Г. Полный справочник по C++ :Пер. с англ. – М.: изд. Вильямс, 2007. – 800 с.

3. Гергель В.П., Курс лекций по предмету «Языки программирования».

Приложение (исходный код программы)

Stdafx.h

#ifndef ST_REAL_H

#define ST_REAL_H

#pragma once

#include <stdlib.h >

#include <conio.h>

#include <stdarg.h>

#include <math.h>

#include <windows.h>

#include <process.h>

#include <string.h>

#include <stdio.h>

#include <fstream> // средства для управляемой пользователем обработки файлов.

#include <iostream> // объекты cin, cout, cerr и clog,

#include <iomanip> // управления форматируемым вводом/выводом с помощью параметризованных манипуляторов потока.

using namespace std;

using namespace System;

using std::cin;

using std::cout;

int parse();

void inttoname(int nom,unsigned int pol,char buffer[]);

int Svernut(char s[]);

void AntiPars(int Anom,unsigned int Mpars[]);

void CreatSpis(int Anom);

int getfile();

struct node {

int elem;

unsigned int pol;

node *next;

};

void Proizvodnay(node *first);

class Spisok

{

private:

node *phead; //указатель на начало списка .

node *pend;

node *cursosr;

node *Res; //указатель на найденное звено .

int N_monom;

public:

Spisok() {phead = new (node); (*phead).next=NULL;} //конструктор

~Spisok() { delete phead; } //деструктор.

void Initial(node **first, node **last);

int Empty(node *first);

void Add(node **last,int elem, unsigned int pol);

void Show(node *first);

int Poisk_Eqv (node *first,unsigned int pol,node **last);

int Poisk_Less (node *first,int el,node **last);

void Izm (node *Res, int el,unsigned int pol);

void DelAll(node *first, node **last);

void AddLess (node **Res, int el,unsigned int pol);

int Next (node *first,int el,node **last);

void Del1 ();

};

#endif

Spis06.cpp

#include "stdafx.h"

Spisok A,B;

unsigned int Mpars[500];

//unsigned int Mpars1[500];

node *Bfirst, *Blast ;

node *BRes; //Указатель на найденное звено списка.

node *Afirst, *Alast ;

node *ARes; //Указатель на найденное звено списка.

void Spisok::Del1 ()

//Удаление звена, на которое указывает ссылка Res.

{

node *q,*q1,*q2;

//Определяем местоположение следующего за удаляемым элемента.

q = (*ARes).next;

if (q!=NULL)//Если удаляемое звено не является последним

{

(*ARes).elem = (*q).elem;

(*ARes).pol = (*q).pol;

(*ARes).next = (*q).next; // "Переписываем" следующий элемент в удаляемый

delete q;

}

else

{

q1 = Afirst;

q2 = (*q1).next;

while (q2!=ARes)

{

q1 = q2;

q2 = (*q2).next;

}

(*q1).next = NULL;

q2 = NULL;

delete ARes;

}

}

void Spisok::Initial(node **first, node **last)

{

*first=new node;

(*first)->next=NULL;

*last=*first;

N_monom=0;

}

int Spisok::Empty(node *first)

{

if (first->next==NULL)

return 1;

else

return 0;

}

void Spisok::Add(node **last,int elem,unsigned int pol)

{

node *tmp=new node;

tmp->elem=elem;

tmp->pol=pol;

tmp->next=NULL;

(*last)->next=tmp;

*last=tmp;

N_monom++;

}

void Spisok::Izm (node *Res, int el,unsigned int pol)

// изменение содержимого найденого звена на el

{

// cout << endl<<"izmres="<< Res->elem<< Res->pol;

cout << endl;

Res->elem = el;

Res->pol = pol;

// (*Res).pol = pol;

}

void Spisok::DelAll(node *first, node **last)

{

node *tmp;

while(first->next!=NULL)

{

tmp=first->next;

first->next=tmp->next;

delete tmp;

}

*last=first;

}

void Spisok::Show(node *first)

{

node *tmp=first->next;

cout <<endl;

while(tmp!=NULL)

{

cout << tmp->elem << " "<< tmp->pol << ", ";

tmp=tmp->next;

}

cout <<endl;

}

int Spisok::Poisk_Eqv (node *first,unsigned int pol,node **last)

//Поиск звена с элементом равным el в списке, заданном указателем

// *first. В случае успешного поиска в Res заносится 1 а в last находится адрес

//звена списка, содержащего элемент el, в случае неуспеха

//в Res помещается 0.

{

unsigned int r;

int rez=0;

node *tmp=first->next;

while(tmp!=NULL)

{

r=tmp->pol ;

if(pol==r)

{

// cout << r << " ";

rez=1;

break;

}

tmp=tmp->next;

}

*last=tmp;

return(rez);

}

int Spisok::Poisk_Less (node *first,int sv,node **last)

//Поиск звена с элементом меньше el в списке, заданном указателем

// *first. В случае успешного поиска в Res заносится 1 а в last находится адрес

//звена списка, содержащего элемент меньше el, в случае неуспеха

//в Res помещается 0.

{

int rez=0;

int r;

node *tmp=first->next;

while(tmp!=NULL)

{

r=tmp->pol ;

if(sv>r)

{

/// cout << r << " ";

rez=1;

break;

}

tmp=tmp->next;

}

*last=tmp;

return(rez);

}

void Spisok::AddLess (node **Res, int el,unsigned int pol)

//Включение звена с информационным полем el

//перед звеном, на которое указывает *Res.

{

node *q;

// формируем новое звено и перекидываем в него содержимое

q = new (node);

(*q).elem = (**Res).elem;

(*q).pol = (**Res).pol;

(*q).next = (**Res).next;

// заменяем значения в старом звене

(**Res).elem = el;

(**Res).pol = pol;

(**Res).next = q;

N_monom++;

}

int Spisok::Next (node *first,int el,node **last)

//Поиск звена с элементом el в списке, заданном указателем

//phead. В случае успешного поиска в Res находится адрес

//звена списка, содержащего элемент el, в случае неуспеха

//в Res помещается NULL.

{

int r;

node *tmp=first->next;

if (tmp==NULL) return (1);

r=tmp->elem ;

*last=tmp;

return(0);

}

void Show(node *first)

{

node *tmp=first->next;

int el;

unsigned int pol;

char buf[256];

while(tmp!=NULL)

{

el =tmp->elem;

pol =tmp->pol;

inttoname(el ,pol, buf);

tmp=tmp->next;

}

}

void CreatSpisA(int Anom)

{

int dig=0;

unsigned int sv=0;

int dig0=0;

for(int i=0;i<(Anom/2);i++)

{

dig0=0;

dig=Mpars[i*2];// результаты разбора

sv=Mpars[i*2+1];

A.Poisk_Eqv (Afirst, sv,&ARes);

if(ARes!=NULL)

{

dig0=ARes->elem; // такой уже есть- складываем коэффициенты и не добавляем

dig0=dig0+dig;

/// cout << endl<<"poisk pol = "<< ARes->pol<< endl;

if(dig0!=0)

{

A.Izm (ARes, dig0, sv); // складываем коэффициенты и не добавляем

continue;

}

if(dig0==0) // не добавляем и удаляем

{

A.Del1 ();

continue;

}

}

if( A.Poisk_Less (Afirst, sv,&ARes)== 1) {

A.AddLess (&ARes, dig, sv);

}

else {

A.Add(&Alast,dig,sv);

}

}

cout << endl<<"== Приведенный полином A" << endl;

Show(Afirst);

}

void CreatSpisB(int Anom)

{

int dig=0;

unsigned int sv=0;

int dig0=0;

for(int i=0;i<(Anom/2);i++)

{

dig0=0;

dig=Mpars[i*2];// результаты разбора

sv=Mpars[i*2+1];

B.Poisk_Eqv (Bfirst, sv,&BRes);

if(BRes!=NULL)

{

dig0=BRes->elem; // такой уже есть- складываем коэффициенты и не добавляем

dig0=dig0+dig;

if(dig0!=0)

{

B.Izm (BRes, dig0, sv); // складываем коэффициенты и не добавляем

continue;

}

if(dig0==0) // не добавляем и удаляем

{

B.Del1 ();

continue;

}

}

if( B.Poisk_Less (Bfirst, sv,&BRes)== 1) {

B.AddLess (&BRes, dig, sv);

}

else {

B.Add(&Blast,dig,sv);

}

}

cout << endl<<"== Приведенный полином B" << endl;

Show(Bfirst);

}

void Proizvodnay(node *first)

{

node *tmp=first->next;

int el;

unsigned int pol;

char buf[256];

int x,y,z,i;

cout <<endl;

while(tmp!=NULL)

{

el =tmp->elem;

pol =tmp->pol;

x=pol/1000;

y=(pol%1000)/100;

z=((pol%1000)%100)/10;

if(x>1)

{

el=el*x;

x=x-1;

}

pol=x*1000+y*100+z*10;

if(x!=0) B.Add(&Blast,el,pol);

// поскольку исходный полином приведен добавляем все подряд

tmp=tmp->next;

}

cout<<endl<< "производная"<<endl;

Show(Bfirst);

}

void Proizvodnay1(node *Afirst,node *Bfirst,int Anom)

{

node *Atmp=Afirst->next;

int el=5;

int el1;

int rel;

unsigned int pol, pol1, rpol;

char buf[256];

int x,y,z,i;

int x1,y1,z1;

int rx,ry,rz;

int dig=0;

int imonom=0;

unsigned int MMult[500];

int Mi=0;

Mi=0;

imonom=0;

while(Atmp!=NULL)

{

node *Btmp=Bfirst->next;

el =Atmp->elem;

pol =Atmp->pol;

x=pol/1000;

y=(pol%1000)/100;

z=((pol%1000)%100)/10;

// умножаем коэфиициент на степень x

pol=pol*x;

y=0;

z=0;

if (x>1 ) x=x-1;

// вычитаем из степени x

// формируем свертку

pol=x*1000+y*100+z*10;

if(x!=0) B.Add(&Blast,el,pol);

// поскольку исходный полином приведен добавляем все подряд

Atmp=Atmp->next;

} // конец цикла по первому полиному

AntiPars( imonom, Mpars);

// нормализуем результат

cout << endl << "Результат "<< endl;

Show(Bfirst); // антипарсер для полинома

getch();

cout<<endl<< "производная"<<endl;

Show(Bfirst);

}

void Mult(node *Afirst,node *Bfirst,int Anom)

{

node *Atmp=Afirst->next;

int el=5;

int el1;

int rel;

unsigned int pol, pol1, rpol;

char buf[256];

int x,y,z,i;

int x1,y1,z1;

int rx,ry,rz;

int dig=0;

int imonom=0;

unsigned int MMult[500];

int Mi=0;

Mi=0;

imonom=0;

while(Atmp!=NULL)

{

node *Btmp=Bfirst->next;

el =Atmp->elem;

pol =Atmp->pol;

x=pol/1000;

y=(pol%1000)/100;

z=((pol%1000)%100)/10;

while(Btmp!=NULL)

{

el1 =Btmp->elem;

pol =Btmp->pol;

x1=pol/1000;

y1=(pol%1000)/100;

z1=((pol%1000)%100)/10;

// перемножаем элементы

rel=el*el1;

// складывавем степени при x y z

rx=x+x1;

ry=y+y1;

rz=z+z1;

// записываем коэффициент и формируем свертку

Mpars[imonom]=rel;// запоминаем результаты разбора

Mpars[imonom+1]=rx*1000+ry*100+rz*10;

imonom=imonom+2;

Btmp=Btmp->next;

} // конец цикла по второму полиному

Atmp=Atmp->next;

} // конец цикла по первому полиному

AntiPars( imonom, Mpars);

// нормализуем результат

A.DelAll(Afirst,&Alast); // чистим список

CreatSpisA(imonom); //создаем список из массива с доп проверками

cout << endl << "Результат "<< endl;

Show(Afirst); // антипарсер для полинома

getch();

}

int main()

{

A.Initial(&Afirst,&Alast);

B.Initial(&Bfirst,&Blast);

char otv;

int nom;

unsigned int svertka;

char buf[300];

int dig;

int Anom=0;

unsigned int sv;

FILE *in;

do

{

cout // << endl << "1. Отладка" << endl

// << "2. Разбор и свертка полинома" << endl

//<< "3. Развертка и вывод полинома" << endl

///<< "4. Создание списка мономов" << endl

//<< "5. Прогон " << endl

//<< "6. Сдвиг полинома" << endl

<< "1. Операция" << endl

//<< "8. " << endl

//<< "9. " << endl

<< "0. Выход" << endl;

cout << '>';

cin >> otv;

switch(otv)

{

case '88': //+++ отладка

break;

case '2': //

//Anom= getfile(); break;

case '3'://+++

// AntiPars(Anom,Mpars); // разворачиваем полином из буфера

break;

case '4'://+++

// CreatSpis(Anom); //создаем список из массива с доп проверками

break;

case '5'://+++

//Show(Afirst); // антипарсер для полинома

break;

case '6'://+++ // сдвиг полинома

break;

case '1'://+++ операция

cout<<endl<< "--1-сложить";

cout<<endl<< "--2-вычесть";

cout<<endl<< "--3-производная";

cout<<endl<< "--4-умножить"<< endl;

cin >> otv;

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

if(otv=='1') //сложить

{

A.DelAll(Afirst,&Alast); // чистим список

Anom= getfile();

CreatSpisA(Anom); //создаем список из массива с доп проверками

B.DelAll(Bfirst,&Blast); // чистим список

Anom= getfile();

CreatSpisB(Anom); //создаем список из массива с доп проверками

CreatSpisA(Anom); //добавляем в список из массива с доп проверками

getch();

}

if(otv=='2') //вычесть

{

A.DelAll(Afirst,&Alast); // чистим список

Anom= getfile();

CreatSpisA(Anom); //создаем список из массива с доп проверками

B.DelAll(Bfirst,&Blast); // чистим список

Anom= getfile();

CreatSpisB(Anom); //создаем список из массива с доп проверками

AntiPars(Anom, Mpars);

// меняем знак

for(int i=0;i<Anom/2;i++)

{

Mpars[i*2]=(Mpars[i*2])*(-1);// результаты разбора

//dig=Mpars[i*2];

//sv=Mpars[i*2+1];

//inttoname(dig ,sv, buf);

}

AntiPars(Anom, Mpars);

CreatSpisA(Anom); //добавляем в список из массива с доп проверками

getch();

}

if(otv=='3') //призводная нужен только один операнд

{

A.DelAll(Afirst,&Alast); // чистим список

Anom= getfile();

CreatSpisA(Anom); //создаем список из массива с доп проверками

B.DelAll(Bfirst,&Blast); // чистим список

Proizvodnay1(Afirst,Bfirst, Anom);

_getch();

}

if(otv=='4') //умножить

{

A.DelAll(Afirst,&Alast); // чистим список

Anom= getfile();

CreatSpisA(Anom); //создаем список из массива с доп проверками

B.DelAll(Bfirst,&Blast); // чистим список

Anom= getfile();

CreatSpisB(Anom); //создаем список из массива с доп проверками

Mult(Afirst,Bfirst,Anom);

_getch();

}

break;

case '0':// Выход

A.DelAll(Afirst,&Alast);

break;

default:

cout << endl << "Ошибка" << endl;

break;

}

}while(otv!='0');

}

Pars6.cpp

#include "stdafx.h"

extern unsigned int Mpars[500];

void AntiPars(int Anom, unsigned int Mpars[])

// разворачивание полинома

// печать полинома из массива в форме xyz

{

int i=0;

int dig;

unsigned int sv;

char buf[256];

printf("\n");

for(int i=0;i<Anom/2;i++)

{

dig=Mpars[i*2];// результаты разбора

sv=Mpars[i*2+1];

inttoname(dig ,sv, buf);

}

printf("\n");

}

void inttoname(int elem ,unsigned int pol,char buffer[])

//разворачивание монома

// вход коэффициент. свертка монома. буфер - строка развернутого монома

{

int j=0;

int x,y,z,i;

i=pol%1000;

x=pol/1000;

y=(pol%1000)/100;

z=((pol%1000)%100)/10;

j = sprintf( buffer," "); // C4996

if(elem!=1) j += sprintf( buffer+j,"%+d",elem); // C4996

if(elem==1) j += sprintf( buffer+j,"+"); // C4996

if(elem==-1) j += sprintf( buffer+j,"-"); // C4996

if(x>1) j += sprintf( buffer+j,"x%d",x); // C4996

if(y>1) j += sprintf( buffer+j,"y%d",y); // C4996

if(z>1) j += sprintf( buffer+j,"z%d",z); // C4996

if(x==1) j += sprintf( buffer+j,"x"); // C4996

if(y==1) j += sprintf( buffer+j,"y"); // C4996

if(z==1) j += sprintf( buffer+j,"z"); // C4996

printf("%s",buffer);

}

int getfile()

{

FILE *in;

char name[200];

char buf[300];

int inom=0;

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

cin >> name;

// printf("\n %s \n",name);

if( (in = fopen( name, "r" )) == NULL ) // C4996

{

printf( "\n Файл не открыт %s\n",name );

_getch();

exit(0);

}

else

{

// printf( "\n Файл открыт %s\n",name );

fgets(buf,200,in);

fclose(in);

inom= Svernut (buf);

}

return(inom);

}

//============================================================

/*

фиксируется старшинство переменных.

Будем считать, что x - самая старшая переменная, затем следует y, затем z.

Для каждого монома определим его "свернутую степень" (индекс).

Для монома xAyBzC+n. индекс равен A*1000+B*100+C*10+n (по условию задачи A, B и C не выше 9).

Старшим считается моном с большей свернутой степенью.

Например, x3y старше xy7z6, так как 310 больше 176.

Например, пусть имеется два полинома:

P(x,y,z)=x7y2z+3x2z-6y2-3z9 и

Q(x,y,z)=-7x2z+6y2+5.

В результате выполнения операции сложения должен быть получен полином R(x,y,z)=x7y2z-4x2z-3z9+5.

вход - исходная строка

выход - свернутый полином в Mpars

выход - количество мономов

*/

int Svernut(char buf[])

{

// int x,y,z;

int i,j,k,l;

char c;

unsigned int sv=0; // 0 to 4,294,967,295

//char buf[128];

char nom[50];

char monom[50];

int pr=0; // признак начала числа

int dig=0;

int imonom=0;

i=0;

cout << endl<< "==Исходный полином: "<< endl ;

cout << buf ;

for(;;)

{

j=0;

if(i>strlen(buf)) break;

c=buf[i];

if(isdigit(c))

{

monom[j]='+';

j++;

}

if(pr==0)

{

if(c=='+'|| c=='-')

{

monom[j]=c;

j++;

i++;

pr=1;

}

if(isdigit(c))

{

monom[j]='+';

j++;

pr=1;

}

} //конец первого монома

for(;;)

{

pr=0;

monom[j]=0x00;

c=buf[i];

if(i>strlen(buf)) break;

if(c=='+'|| c=='-') break;

monom[j]=c;

j++;

i++;

monom[j]=0x00;

} //моном

// разделяем моном на коэффициент и степени

k=0;

for(;;)

{

if(k>=j) break;

c=monom[k];

if(c=='x'|| c=='y'|| c=='z') break;

nom[k]=c;

k++;

}

nom[k]=0x00;

// printf("\n nom=%s",nom); // нашли коффициент

// ищем свертку

for(;;)

{

if(k>=j) break;

c=monom[k];

l=1;

if(k+1<j) // есть что-то дальше

{

if(isdigit( monom[k+1]))

{

l=monom[k+1]-'0';

}

}

if(c=='x')

{

sv=sv+l*1000;

if (l>1 ) k++; // пропускаем степень

}

if(c=='y')

{

sv=sv+l*100;

if (l>1 ) k++; // пропускаем степень

}

if(c=='z')

{

sv=sv+l*10;

if (l>1 ) k++; // пропускаем степень

}

k++;

}

nom[k]=0x00;

dig=atoi(nom);

if(strlen(nom)==1) // это для мономов без коэффициента

{

if(nom[0]=='-') dig=-1;

if(nom[0]=='+' )dig=1;

}

if(dig==0) dig=1;

///printf("\n Коэффициент монома=%s %d",nom ,dig); // нашли коффициент strtoi

if(sv==0) sv=1; // это завершающее число

///printf("\n Свертка монома sv=%d",sv); // нашли свертку

Mpars[imonom]=dig;// запоминаем результаты разбора

Mpars[imonom+1]=sv;

imonom=imonom+2;

sv=0; // пошли наследующий моном

j=0;

} // конец буфера

return(imonom);// количество мономов

}

Наши рекомендации