Описание структуры хранения данных
Факультет вычислительной математики и кибернетики
ОТЧЕТ
по лабораторной работе № 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).
Рис. 1. Главное окно программы.
Основные операции.
Операция сложения/вычитания/умножения полиномов:
· Выбирается пункт меню 1/2/4;
· Вводится имя файла с первым полиномом;
· Выводится исходный неприведенный полином;
· Выводится приведенный полином;
· Вводится имя файла со вторым полиномом;
· Выводится исходный неприведенный полином;
· Выводится приведенный полином;
· Выводится результат в приведенном виде.
Рис. 2. Выполнение операции сложения.
Рис.3. Результат операции вычитания.
Рис.4. Результат операции умножения.
Операция вычисления производной:
· Выбирается пункт меню 3;
· Вводится имя файла с полиномом;
· Выводится исходный неприведенный полином;
· Выводится приведенный полином;
· Выводится результат в приведенном виде.
Рис.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);// количество мономов
}