分段故障 - 多项式

时间:2015-01-30 17:46:18

标签: c++ templates dictionary segmentation-fault fault

我使用`std :: map。

制作了一个基本程序来操作多项式

这是源代码

polynome.hpp

#ifndef POLYNOME_HPP
#define POLYNOME_HPP

using namespace std;


template<typename T> 
string to_string( const T & Value ) 
{ 
//Utiliser un flux de sortie pour créer la chaîne 
ostringstream oss; 
//Ecrire la valeur dans le flux
oss << Value; 
//Renvoyer une string 
return oss.str(); 
} 

template <typename T>
class Polynome
{
public:
    //Constructeurs et destructeur
    Polynome();
    Polynome(const Polynome &);
    Polynome(T (tab[]), unsigned int);
    Polynome(map<unsigned int, T>&);
    ~Polynome(){}
    //Méthodes d'accès
    unsigned int GetOrder() const {return ItsOrder;}
    map<unsigned int, T> GetPoly() const {return ItsPolynome;}
    void SetOrder(unsigned int order) { ItsOrder=order;}
    void SetPoly(map<unsigned int, T> poly){ItsPolynome=poly;}
    //Surcharge d'opérateur
    T & operator[](unsigned int);
    T operator[](unsigned int) const;
    Polynome operator+(const Polynome &);
    Polynome operator-(const Polynome &);
    Polynome operator*(const Polynome &);
    Polynome& operator=(const Polynome &);
    template <typename U>
    friend ostream& operator<<(ostream&, Polynome<U>&);
    //Autres méthodes
    void Deriv();
    T Eval(const Polynome &, T);

private:
    //Données membres
    map<unsigned int,T> ItsPolynome;
    unsigned int ItsOrder;
 };

 //Constructeur par défaut
 template <typename T>
 Polynome<T>::Polynome(): ItsOrder(0)
 {
 map<unsigned int, T> m;
 m[0]=0;
 ItsPolynome=m;;
 }

 //Constructeur de copie
 template <typename T>
 Polynome<T>::Polynome(const Polynome<T> & rhs)
 {
   map<unsigned int, T> m;
   m[0]=0;
   ItsPolynome=m;
   map<unsigned int, T> a=rhs.GetPoly();
   for(typename map<unsigned int, T>::const_iterator ii=a.begin();ii!=a.end(); ++ii)
{
    ItsPolynome[ii->first] = ii->second;
}

ItsOrder=rhs.GetOrder();
}

//Constructeur à partir d'un tableau contenant les coefficients
template <typename T>
Polynome<T>::Polynome(T (tab)[],unsigned int size)
{
map<unsigned int, T> m;
m[0]=0;
ItsOrder=0;
ItsPolynome=m;
for(unsigned int i=0;i<size;i++)
{
    ItsPolynome[i]=tab[i];
}
ItsOrder=size-1;
}

//Constructeur qui prend une map(tableau associatif) en paramètre
template <typename T>
Polynome<T>::Polynome(map<unsigned int, T> & a)
{
ItsPolynome=a;
unsigned int b=0;
for(typename map<unsigned int, T>::const_iterator ii=a.begin();ii!=a.end(); ++ii)
{
    if((ii->first)>b)
    {
        b=ii->first;
    }
}
ItsOrder=b;
}

//Opérateur d'indexation  non constant
template <typename T>
T & Polynome<T>::operator[](unsigned int n)
{
if(ItsPolynome.count(n))
{
    return ItsPolynome[n];
}
else
{
    return 0;
}
}

//Opérateur d'indexation constant
template <typename T>
T Polynome<T>::operator[](unsigned int n) const
{
if(ItsPolynome.count(n))
{
    return ItsPolynome[n];
}
else
{
    return 0;
}
}

//Surcharge de l'opérateur +
template <typename T>
Polynome<T> Polynome<T>::operator+(const Polynome<T> & rhs)
{
map<unsigned int, T> polyrhs=rhs.GetPoly();
/*On définit l'ordre du nouveau polynôme obtenu. */
if(ItsOrder<rhs.GetOrder())
{
    ItsOrder=rhs.GetOrder();
}
/* On additionne enfin les deux polynômes pour obtenir une map pour le polynôme obtenu suite à l'addition. */
for(typename map<unsigned int, T>::const_iterator ii=polyrhs.begin();ii!=polyrhs.end(); ++ii)
{
    ItsPolynome[ii->first]+=polyrhs[ii->first];
}
}

//Surcharge de l'opérateur - (analogue à la surcharge de l'opérateur +)
template <typename T>
Polynome<T> Polynome<T>::operator-(const Polynome<T> & rhs)
{
map<unsigned int, T> polyrhs=rhs.GetPoly();
/*On définit l'ordre du nouveau polynôme obtenu. */
if(ItsOrder<rhs.GetOrder())
{
    ItsOrder=rhs.GetOrder();
}
/* On additionne enfin les deux polynômes pour obtenir une map pour le polynôme obtenu suite à l'addition. */
for(typename map<unsigned int, T>::const_iterator ii=polyrhs.begin();ii!=polyrhs.end(); ++ii)
{
    ItsPolynome[ii->first]-=polyrhs[ii->first];
}
}

//Surcharge de l'opérateur *
template <typename T>
Polynome<T> Polynome<T>::operator*(const Polynome<T> & rhs)
{
map<unsigned int, T> polyrhs=rhs.GetPoly();
/*On définit l'ordre du nouveau polynôme obtenu. */
ItsOrder=ItsOrder+rhs.GetOrder();
/* On additionne enfin les deux polynômes pour obtenir une map pour le polynôme obtenu suite à l'addition. */
for(int i=0;i<=ItsOrder;i++)
{
    for(int j=0; j<=i;j++)
    {
        ItsPolynome[i]+=ItsPolynome[j]*polyrhs[i-j];
    }
    }
    }

    //Surcharge de l'opérateur de flux
    template <typename T>
    ostream& operator<<(ostream& stream, Polynome<T>& p)
   {
    string a="", b="", c="";
    map<unsigned int, T> poly=p.GetPoly();
    for(typename map<unsigned int, T>::const_iterator ii=poly.begin();ii!=poly.end(); ++ii)
    {
    b=to_string(ii->second);
    c=to_string(ii->first);
    a+="+"+b+"x^"+c;
        }
    stream<<a;

    return stream;
    }

    //Surcharge de l'opérateur d'affectation
    template <typename T>
    Polynome<T>& Polynome<T>::operator=(const Polynome<T> & rhs)
    {
if(this==&rhs)
{
    return *this;
}
ItsOrder=rhs.GetOrder();
ItsPolynome=rhs.GetPoly();
return *this;
}

//Méthode permettant de dériver le polynôme
template <typename T>
void Polynome<T>::Deriv()
{
//On définit l'ordre du polynôme dérivé
if(ItsOrder==0)
{
    ItsOrder=0;
}
else
{
    ItsOrder--;
}
//On définit les coefficients du polynôme dérivé (On prend chaque a*x^n un a un, et la dérivation le transforme en a*n*x^(n-1) )
for(typename map<unsigned int, T>::const_iterator ii=ItsPolynome.begin();ii!=ItsPolynome.end(); ++ii)
{
    if((ii->first)!=0)
    {
        ItsPolynome[ii->first-1]=(ii->second)*(ii->first);
        ItsPolynome[ii->first]=0;
    }
  }
  }

  //Méthode permettant d'évaluer le polynôme en un point x
  template <typename T>
  T Polynome<T>::Eval(const Polynome<T> & p, T x)
  {
T a=0;
map<unsigned int, T> poly=p.GetPoly();
for(typename map<unsigned int, T>::const_iterator ii=poly.begin();ii!=poly.end(); ++ii)
{
    a+=(ii->second)*(pow(x,ii->first));
}
return a;
 }

 #endif

的main.cpp

#include <iostream>
#include <string>
#include <cstring>
#include <sstream> 
#include <cmath>
#include <map>
#include "polynome.hpp"

using namespace std;

int main()
{
double tab[3]={1.0,1.0,1.0};
map<unsigned int, double> m;
m[0]=1;
m[1]=1;
m[2]=1;
Polynome<double> p(m);
Polynome<double> q(tab,3);
Polynome<double> r;

cout<<p<<endl;
cout<<q<<endl;

r=p+q;

cout<<r<<endl;

return 0;
 }

 /*Le programme a été écrit sur gedit, et compilé sous gcc avec le warning  Weffc++ */

此程序编译,但有以下警告

In file included from main.cpp:7:0:
polynome.hpp: In instantiation of ‘Polynome<T>::Polynome(std::map<unsigned int, T>&) [with T = double]’:
main.cpp:18:22:   required from here
polynome.hpp:94:1: warning: ‘Polynome<double>::ItsPolynome’ should be initialized in the member initialization list [-Weffc++]
 Polynome<T>::Polynome(map<unsigned int, T> & a)
 ^
polynome.hpp:94:1: warning: ‘Polynome<double>::ItsOrder’ should be initialized in the member initialization list [-Weffc++]
polynome.hpp: In instantiation of ‘Polynome<T>::Polynome(T*, unsigned int) [with T = double]’:
main.cpp:19:26:   required from here
polynome.hpp:79:1: warning: ‘Polynome<double>::ItsPolynome’ should be initialized in the member initialization list [-Weffc++]
 Polynome<T>::Polynome(T (tab)[],unsigned int size)
 ^
polynome.hpp:79:1: warning: ‘Polynome<double>::ItsOrder’ should be initialized in the member initialization list [-Weffc++]
polynome.hpp: In instantiation of ‘Polynome<T>::Polynome() [with T = double]’:
main.cpp:20:19:   required from here
polynome.hpp:54:1: warning: ‘Polynome<double>::ItsPolynome’ should be initialized in the member initialization list [-Weffc++]
 Polynome<T>::Polynome(): ItsOrder(0)
 ^

,结果是:

“+ 1X ^ 0 + 1×^ 1 + 1×2 ^

+ 1X ^ 0 + 1×^ 1 + 1×2 ^

Erreur de segmentation(核心倾销) “

所以,我想了解,在我的程序中,在添加方法中有什么问题,因为我认为这个问题就在这里。

非常感谢您阅读此内容。 ;)

PS:对不起我的英文,我是法国人。 并对不起代码的介绍。 如果你愿意,我会引用评论,如果你愿意,我可以这样做。 ;)

: - )

3 个答案:

答案 0 :(得分:2)

我立即看到的明显错误是您没有从需要返回值的函数返回值。

例如,查看您的operator+功能:

template <typename T>
Polynome<T> Polynome<T>::operator+(const Polynome<T> & rhs)
{
    map<unsigned int, T> polyrhs = rhs.GetPoly();
    if (ItsOrder<rhs.GetOrder())
    {
        ItsOrder = rhs.GetOrder();
    }
    for (typename map<unsigned int, T>::const_iterator ii = polyrhs.begin(); ii != polyrhs.end(); ++ii)
    {
        ItsPolynome[ii->first] += polyrhs[ii->first];
    }
  // <-- Where is the return value?
}

您不会返回值。不返回值是未定义的行为。该函数应该返回一个Polymer<T>对象,但你没有这样做。

您对其他重载运算符犯了同样的错误,因此您还需要更改它们。某些运算符(例如+)应该const到他们执行的对象上。您需要按值返回精心设计的对象;不要修改现有对象:

//Surcharge de l'opérateur +
template <typename T>
Polynome<T> Polynome<T>::operator+(const Polynome<T> & rhs) const
{
    Polynome<T> res = *this; // make copy of this object

    res.ItsOrder = std::max(res.ItsOrder, rhs.ItsOrder);
    for(auto const& term : rhs.ItsPolynome)
        res.ItsPolynome[term.first] += term.second;
    return res; // return crafted object by-value.
}

答案 1 :(得分:1)

您需要返回operator+()的值。这同样适用于operator-()operator*()

出了什么问题?

您已定义所有这些运算符以覆盖当前对象,因此p+q会修改p而不是保持pq不变并产生结果。由于您没有返回值,因此完全未定义赋值运算符可以复制的内容。因此,段错误。

还有什么问题?

如果您返回*this,代码会编译但不会按预期工作!对于简单表达式r=p+q,它将使用p的内容覆盖p+q,并将p的新值复制到rr符合您的预期,但您希望p更改吗?您的代码根本无法完成更复杂的操作。假设你写了一个像r = (p+q)*(p-q)这样的表达式;您的代码会产生未定义的行为,具体取决于编译器评估表达式的顺序!

解决问题的建议

查看有关运营商实施的 this guideline article

与此同时,这里有一个适用的改编版本:

template <typename T>
Polynome<T> Polynome<T>::operator+(const Polynome<T> & rhs)
{
    Polynome<T> t=*this ; // temporary polynom to return 
    if (t.ItsOrder<rhs.GetOrder())  
        t.ItsOrder = rhs.GetOrder();  // take the max
    for (auto ii = rhs.ItsPolynome.begin(); ii != rhs.ItsPolynome.end(); ++ii)
        t.ItsPolynome[ii->first] += ii->second;
    return t ;
}

答案 2 :(得分:0)

问题在于你的operator +函数 - 你说它返回Polynome<T>但是没有return语句。

在for循环之后添加:return *this,它应该可以正常工作。