2017-11-28 16 views
0

현재 출력에서 ​​오류가 발생하고 이유를 모르겠습니다. 왜 누군가가 나를 안내 할 수 있다면 그것은 크게 감사 할 것입니다. 두 다항식을 함께 추가 할 수 있지만 출력을 얻을 때 출력 연산자에서 공백을 제거한 후 세그멘테이션 오류가 발생합니다. 나는 이것이 왜 있는지 모른다. 나는 그것이 도움이된다면 나는 또한 codeblocks를 사용하고있다.폴리 출력 오류 연결 목록

MAIN.CPP

#include <iostream> 
#include "poly.h" 
using namespace std; 
int main() 
{ 

int x1[] = {1 , 0 , 3 , 4 , 5}; 
int x2[] = {3 , 2}; 

polynomial p1(x1 , 4); 
polynomial p2(x2 , 1); 
polynomial p3(5); 
polynomial p4; 
polynomial result; 

result = 6; 


cout << " p1 = " << p1 << endl ; 
cout << " p2 = " << p2 << endl ; 
cout << " p3 = " << p3 << endl ; 
cout << " p4 = " << p4 << endl ; 
cout << " result = " << result << endl << endl ; 

result = p1 + p2 ; 
cout << " p1 + p2 = " << result << endl ; 

poly.h

#include <iostream> 
using namespace std; 

class polynomial 
{ 

    struct node 
    { 
     int coefficient ; 
     node * link ; 
    }; 

public: 
polynomial(); 
polynomial(const polynomial&); 
polynomial(int* ,int); 
polynomial(int); 
~polynomial(); 


polynomial operator+(const polynomial&) const; 
polynomial operator+(int) const; 
const polynomial& operator=(const polynomial &); 
const polynomial& operator=(int); 

friend ostream& operator<<(ostream& outfile , const polynomial&); 
friend polynomial operator+(int ,const polynomial&); 

private: 
node* head; 
int degree; 
}; 

poly.cpp

#include <iostream> 
#include "poly.h" 
using namespace std; 

polynomial::polynomial() 
{ 
    head = new node; 
    head->coefficient = 0; 
    head->link = NULL; 
    degree = -1; 
}; 

polynomial::polynomial(const polynomial& copy) 
{ 
    if(this != &copy) 
    { 
     delete[] head; 
     head = copy.head; 
    } 
}; 

polynomial::polynomial(int * p, int degree) 
{ 
    this->degree = degree; 
    head = new node; 
    head->coefficient = p[0]; 
    head->link = NULL; 

    for(int x=1;x<degree;x++) 
    { 
     node* temp; 
     temp = new node; 
     temp->coefficient = p[x]; 
     temp->link = head; 
     head = temp; 
    } 

    node* temp; 
    temp = new node; 
    temp->coefficient = p[degree]; 
    temp->link = head; 
    head = temp; 
}; 

polynomial::polynomial(int s) 
{ 
    degree = 0; 
    head = new node; 
    head->coefficient = s; 
    head->link = NULL; 
}; 

polynomial::~polynomial() 
{ 
    node* temp = head; 
    node* current = head; 
    while(current != NULL) 
    { 
     current = current->link; 
     delete temp; 
     temp = current; 
     if (current == NULL || current == NULL) 
      break; 
    } 
}; 

polynomial polynomial::operator+(const polynomial& rhs) const 
{ 
    polynomial hold; 
    polynomial tempLhs; 
    polynomial tempRhs = rhs; 

    tempLhs.degree = degree; 
    tempRhs.degree = rhs.degree; 
    hold.degree; 
    int tempDegree; 

    tempLhs.head = new node; 
    tempRhs.head = new node; 
    hold.head = new node; 

    for(int x=0;x<tempDegree+1;x++) 
    { 
     node* temp; 
     temp = new node; 
     temp->coefficient = 0; 
     temp->link = hold.head; 
     hold.head = temp; 
    } 

    tempLhs.head = head; 
    tempRhs.head = rhs.head; 

    if(tempLhs.degree < tempRhs.degree) 
    { 
     tempDegree = tempLhs.degree; 
     hold.degree = tempDegree; 
     for(int x = (tempDegree-tempLhs.degree-1);x<tempDegree+1;x++) 
     { 
      node* temp; 
      temp = new node; 
      temp->coefficient = 0; 
      temp->link = tempLhs.head; 
      tempLhs.head = temp; 
     } 

    } 
    else if(tempLhs.degree > tempRhs.degree) 
    { 
     tempDegree = tempLhs.degree; 
     hold.degree = tempDegree; 
     for(int x = (tempDegree-tempRhs.degree-1);x<tempDegree+1;x++) 
     { 
      node* temp; 
      temp = new node; 
      temp->coefficient = 0; 
      temp->link = tempRhs.head; 
      tempRhs.head = temp; 
     } 
    } 
    else 
    { 
     tempDegree = tempRhs.degree = tempLhs.degree; 
     hold.degree = tempDegree; 
    } 


    node* lhsCurrent = tempLhs.head; 
    node* rhsCurrent = tempRhs.head; 
    int tempArr[tempDegree]; 

    while(lhsCurrent != NULL && rhsCurrent != NULL) 
    { 
     for(int x=tempDegree;x>-1;x--) 
     { 
      tempArr[x]= lhsCurrent->coefficient + rhsCurrent->coefficient; 
      lhsCurrent = lhsCurrent->link; 
      rhsCurrent = rhsCurrent->link; 
     } 
    } 

    polynomial use(tempArr, tempDegree); 
    return use; 
}; 

polynomial polynomial::operator+(int rhs) const 
{ 
    polynomial temp = *this; 

    return rhs+temp; 
}; 

const polynomial& polynomial::operator=(const polynomial& rhs) 
{ 
    cout << "doing = operator" << endl; 
    degree = rhs.degree; 

    if(this != &rhs) 
    { 
     delete[] head; 
     head = rhs.head; 
    } 

    return *this; 
}; 

const polynomial& polynomial::operator=(int rhs) 
{ 
    degree = 0; 
    head = new node; 
    head->coefficient = rhs; 
    head->link = NULL; 
}; 

ostream& operator<<(ostream& out, const polynomial& rhs) 
{ 
    out << "operator "; 

    polynomial::node* temp = new polynomial::node; 
    temp = rhs.head; 

    while(temp != NULL) 
    { 
     out << temp->coefficient << " "; 
     temp = temp->link; 
     if(temp == NULL) 
      break; 
    } 
    out << " "; 
}; 

출력이

p1 = 5 x ^4 + x ^2 + 5 x + 4 
p2 = 3 x + 2 
p3 = 5 
p4 = 0 
result = 6 
p1 + p2 = 5 x ^4 + x ^2 + 8 x + 6 
되어야

이 결과를 얻고 있지만 학위가 올바르게 표시되도록 서식을 지정해야하지만 추가적으로 올바르게 출력됩니다. 문제가되지 않는 출력 연산자를 조정해야합니다. 내가 poly.cpp의 마지막 줄에 두 번째

out << " "; 

하지 않고 프로그램을 실행할 때마다

오류가 발생합니다.

코드에서 삭제 될 때 < < 때 폴리 Cpppp의 마지막 줄을 일이 줄 215 이후에 세그먼트 오류가 있습니다.

+0

생성자에 대한 관련없는 참고 사항 : 하나에 대한 필요성을 알았지 만 ... 'if (this! = = & copy)'가 항상 발생합니다. 복사 생성자에서 새로운'다항식'을 만듭니다. 이것은 오래된 다항식의 주소를 가질 수있는 방법이 없다는 것을 의미합니다. 이것은'head'까지 확장됩니다. 이 객체는 아주 새롭고 아직'head'를 설정하지 않았기 때문에 당신은 아마도'삭제 '할 머리를 가질 수 없습니다. 'delete'는 자신이 소유하지 않은 데이터를 삭제하려고 시도하기 때문에 실제로 많은 시간이 걸릴 것입니다. – user4581301

+0

이 댓글은 약간 길었습니다. 죄송합니다. 마지막으로'head = copy.head; '는 복사 생성자의 기본 동작으로 돌아가므로 복사 생성자를 만드는 것을 무효로합니다. 복사 대상을 생각하지 않고 모든 멤버를 눈먼만큼 복사합니다. 이것은 노드를 복사하지 않으며, 헤드 노드에 포인터를 복사합니다. 이제 동일한 목록을 가리키는 두 개의 객체가 있습니다. 이것은 매우 나쁩니다. 하나의 사본을 수정하면 다른 사본이 수정됩니다. 한 장의 복사본을 삭제하면 다른 하나는 쓰레기 메모리를 가리키고 시간 소절이 생깁니다. – user4581301

+0

'operator = '에 대한주의 사항 : 일단 복사 생성자가 작동하면 이것을 훨씬 쉽게 구현할 수 있습니다. 매우 자세한 내용은 [복사 및 스왑 (copy-and-swap) 관용구 란 무엇입니까?] (https://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom)을 참조하십시오. 다시 말하지만 포인터를 할당하고 노드를 복사하지 않습니다. 그건 그렇고, 당신의 붐을 불러옵니다. 그래서 결국이 모든 것이 관련이없는 것은 아닙니다. 어쩌면 정식 답을 써야할까요? – user4581301

답변

0
result = p1 + p2 ; 

polynomial tempRhs = rhs; 

이 범위를 벗어나 이동 한 다음의 말에 죽을 것 자동 변수를 만들 수있는 복사 생성자를 호출 여기에 전체를 재현 너무 긴 operator+하지만

를 호출 기능. 복사 생성자를 살펴 보겠습니다.

polynomial::polynomial(const polynomial& copy) 
{ 
    if(this != &copy) 
    { 
     delete[] head; 
     head = copy.head; 
    } 
}; 

이것은 거의 완전히 잘못되었습니다. Asker가 자신이 필요로한다는 것을 깨닫기에 좋았지 만 도움이되지 않습니다. 문제를 해결해 드리겠습니다.

if(this != &copy) 

은 피하기 어렵습니다. 복사 생성자가 호출되어 polynomial에서 새로운 polynomial을 만듭니다. 당신은 자신을 복사하는 작업을해야하기 때문에 테스트 할만한 가치가 없을 것입니다.

delete[] head; 

head 그래서 delete[] 사용하는 잘못된 조작 또는 당신이 아직 도달하지 않은 다른 곳에서 이상한 버그를 가지고, 하나의 node해야한다. delete에는 단일 항목 delete을 사용합니다. delete에 항목의 배열, delete[]

다음을 사용하여,이 새로운 객체이며 head 아직 불필요하고 치명적인 모두이 만드는 아무것도 할당되지 않은 :이 프로그램은 아마 소유하지 않은 스토리지를 삭제하려고하고, 기억 장치 블록을 소유하고 있다면 다른 포인터는 메모리가 사라진 것을 발견하면 매우 불쾌한 놀라움을 얻고 있습니다.맹목적으로 복사되는 무슨 생각을 포기하지 않고 모든 멤버를 복사

head = copy.head; 

당신이 바로 다시 복사 생성자의 기본 동작을하기 때문에 복사 생성자를 만들기의 포인트를 패배. 이것은 노드를 복사하지 않고 headnode에 포인터를 복사하므로 두 개의 객체가 동일한 node을 가리키며 매우 나쁩니다. 하나의 사본을 수정하면 다른 사본이 수정됩니다. 한 장의 복사본을 삭제하면 다른 하나는 쓰레기 메모리를 가리키고 시간 소절이 생깁니다.

그래서

polynomial tempRhs = rhs; 

tempRhsrhs 다시 동일한 목록에 두 점을 받고. tempRhs은 범위 끝까지 도달하고 destoyed되며 node의 공유 목록을 가져옵니다. rhs이 나중에 파괴되면 node의 목록을 파괴하려고 시도합니다. 이는 아마도 Asker가보고있는 충돌 일 것입니다. 왜냐하면 무효 한 메모리에 액세스하여 rhs에 액세스 할 수있는 프로그램이 거의 없기 때문에 충돌이 발생하거나 완전히 이상하게 보일 것입니다.

는의가 복사 생성자

에게 추천 일을 해결하자 : 당신은, 기존의 polynomialnode의 반복 그 사본을 만들고, head에 복사본을 배치해야합니다. 연결된 목록 구현에 삽입 함수가 있으면이 함수를 사용하는 것이 가장 좋습니다. 이는

으로 연결됩니다. 권장 사항 2 : 연결된 목록 논리를 polynomial 논리와 분리하십시오. 두 가지 이유 : 1) 왜 다항식 클래스는 다항식 이상에 관한 것이 아닌가? 클래스가 적 으면 일반적으로 더 강력합니다. 2) 이렇게하면 별도로 테스트하고 디버깅 할 수 있습니다. 연결된 목록이 작동하는지 확인하면 smurf를 테스트 했으므로 polynomial에 연결된 목록 클래스의 인스턴스가 포함되어 있고 연결된 목록이 보급 된대로 작동하는지 신뢰합니다.

polynomial::polynomial(const polynomial& copy) 
{ 
    node * from = copy.head; // copying from 
    node ** to = &head; // pointer to where we want to copy to 
    while (from != nullptr) // keep going until end of list. You did mark 
          // the end of the list, didn't you? 
    { 
     *to = new node(*from); copy from into a new node and store it at to 
     to = &(*to)->next; // advance to 
     from = from.next; // advance from 
    } 
    *to = nullptr; // all done. Terminate list. 
    degree = copy.degree; // update the degree 
}; 

node ** to = &head;의 비밀 우리는 항목을 제거하는 것이 아니라, 논리 정확히 동일 Using pointers to remove item from singly-linked list를 읽어 해명합니다. 위에서 언급했듯이이를 수행하는 가장 좋은 방법은 연결 목록 클래스로 작성하고 polynomial을 다항식으로 유지하고 목록을 유지하는 것입니다.

괜찮 았어! 지금 polynomial을 복사 할 수 있습니다! 다 했어, 그렇지?

틀린.

우리에게 권장 사항이 있습니다. 3 : 테스트간에 코드를 많이 쓰지 마십시오. 기껏해야 함수를 작성하십시오. 그런 다음 함수에 의존하는 코드를 작성하기 전에 함수가 확실하게 작동 할 때까지 함수를 테스트하십시오. 버그가있는 동안 더 많은 코드를 작성하지 마십시오. 버그는 서로를 먹고 서로 감추고 있습니다. 벌레가 나쁘다. 너는 어떤 것도 원하지 않지만, 특히 너는 하나 이상을 원하지 않는다.

polynomial operator+(const polynomial&) const; 

값으로 돌아갑니다. 그것이해야합니다. 하지만

result = p1 + p2 ; 

는 할당 연산자를 호출, 그래서 지금 우리는 operator=를 해결 가야 해요. 복사 생성자와 같은 핵심 문제를 가지고 있으며 복사 및 스왑 익셉션을 적용하여 수정할 수 있기 때문에 빨리 건너 뛸 것입니다.What is the copy-and-swap idiom? 1500 번 상향 조정 된 것을 다시 설명하려고하는 것은 의미가 없으므로 링크를 클릭하여 읽고 구현하십시오.

우리가 열심히 탐구해온 것은 The Rule of Three.입니다. 이제 규칙 3이 올바르게 구현되어 코드의 다른 버그를 해결할 수 있습니다. 내가 어디에 있느냐가 늦었 어. 그래서 여기서 멈추고있어.