Schoolwork/자료구조와 C++프로그래밍

[C++] 5주차 과제4

FATKITTY 2020. 8. 5. 11:30
반응형

다항식을 입력출력계산하는 프로그램을 구현한다

다항식은 객체(class)로 생성해야 하며, 다항식 연산을 위하여 연산자 오버로딩 기능을 이용한다. 

  • 다항식 a, b, c를 입력받아 문제에 주어진 연산을 수행한다.(다양한 입력 예를 테스트하는 것을 추천함)
  • 다항식 입력은 (계수, 지수) 표현 형태를 이용한다.
  • 다항식의 출력 형식은 첨부파일과 같은 형식을 따른다. 
  • 첨부파일의 프로그램 코드를 실행한다.

입력물: 다항식 a, b, c, 정수 x

출력물: 첨부파일의 프로그램 코드를 실행한 결과물(출력 결과물).

 

* 연산자 오버로딩을 구현해야함.

* 프로그램 내용 외에 다른 내용이 출력된다면 감점이 될 수 있으니 유의바람.

 

과제4-다항식

입력은 0~9까지로 음수 예외처리는 하지 않으셔도 됩니다.

과제4 확인필수

Code

#include <iostream>
#include <cmath>

using namespace std;

class Polynomial;  // 전방선언

class Term {  // (계수,지수)
	friend Polynomial;
	friend istream& operator>>(istream& in, Polynomial& p);  // 다항식의 입력. 연산자 오버로딩
	friend ostream& operator<<(ostream& out, Polynomial& p);  // 다항식의 출력. 연산자 오버로딩
private:
	int coef;  // 계수 0~9
	int exp;  // 지수 0~9, 음수 입력시 처음으로
};

class Polynomial {
private:
	Term* termArray;  // nonzero term들의 배열
	int capacity;  // termArray의 최대크기
	int terms;  // nonzero term의 수

public:
	Polynomial();  // 생성자. 다항식 p(x) = 0을 반환
	//~Polynomial();
	friend istream& operator>>(istream& in, Polynomial& p);  // 다항식의 입력. 연산자 오버로딩
	friend ostream& operator<<(ostream& out, Polynomial& p);  // 다항식의 출력. 연산자 오버로딩
	void NewTerm(const int theCoeff, const int theExp);  // 새로운 항을 termArray에 끝에 첨가
	Polynomial operator+(Polynomial& B);  // *this와 B(x)를 더한 결과 반환, 연산자 오버로딩
	Polynomial operator*(Polynomial& B);  // *this와 B(x)를 곱한 결과 반환, 연산자 오버로딩
	Polynomial sMultPoly(int single_Coef, int single_Exp);  // 다항식의 단항 곱셈
	void sortPoly();  // 지수의 내림차순으로 출력 - 선택정렬
	int evalPoly(int x);  // *this에 x를 대입해서 계산한 결과 반환
	int polyterms() { return terms; }
};

Polynomial::Polynomial() : capacity(1), terms(0)
{
	// capacity = 1, terms = 0 으로 초기화
	termArray = new Term[capacity];
}

void Polynomial::NewTerm(const int theCoeff, const int theExp)
{
	if (terms == capacity)  // termArray가 꽉 차면 두배로 확장
	{
		capacity *= 2;
		Term* temp = new Term[capacity];  // 새로운 배열
		copy(termArray, termArray + terms, temp);  // 기존 termArray에 있던 내용을 새로 확장된 termArray로 옮겨줌
		delete[] termArray;  // 그 전 메모리 반환
		termArray = temp;
	}
	// termArray의 크기에 문제 없으면, 배열 끝에 값들 첨가
	termArray[terms].coef = theCoeff;
	termArray[terms++].exp = theExp;
}

istream& operator>>(istream& in, Polynomial& p)  // 6. >> 오버로딩
{
	string poly;
	int coef = 0;
	int exp = 0;
	int count = 1;

	poly.clear();  // string poly 초기화
	in >> poly;  // (계수,지수)(계수,지수)...꼴의 입력을 통째로 string으로 받아옴

	if (poly[0] == '.') exit(0);  // 1. . 종료

	for (int i = 0; i < poly.length(); i++)  // 계수, 지수는 0~9 정수
	{
		if (isdigit(poly[i])) {  // isdigit : 문자가 숫자 0~9 사이에 속하는지 검사하는 함수
			// isdigit 성립하면서 count가 홀수면 그것은 계수, 짝수면 지수
			if (count % 2 == 1) coef = poly[i] - '0';  // char 데이터형을 int로 변환하기 위해 -'0'
			if (count % 2 == 0) {
				exp = poly[i] - '0';
				
				// 이미 입력한 항들 중, 현재 입력된 항과 지수가 같은 항이 존재하는지 확인
				int sameornot = -1;
				for (int check_exp = 0; check_exp < p.polyterms() ; check_exp++) {
					if (exp == p.termArray[check_exp].exp) sameornot = check_exp;
				}

				if ((sameornot == -1) && coef != 0) p.NewTerm(coef, exp);  // 없다면 NewTerm으로 새로 추가 (단, 계수가 0이 아닐 때)
				else p.termArray[sameornot].coef += coef;  // 같은 항이 존재한다면 거기에 계수만 더해줌
			}
			count++;
		}
	}

	return in;
}

void Polynomial::sortPoly()  // 지수 내림차순 선택정렬
{
	for (int i = 0; i < terms; i++)
	{
		int j = i;
		for (int k = i + 1; k < terms; k++) {
			if (termArray[k].exp > termArray[j].exp) j = k;
		}
		swap(termArray[i].exp, termArray[j].exp);
		swap(termArray[i].coef, termArray[j].coef);  // 지수가 swap됨에 따라 계수도 같이 swap 해준다.
	}
}

ostream& operator<<(ostream& out, Polynomial& p)  // 6. << 오버로딩
{
	p.sortPoly();  // 지수의 내림차순으로 먼저 정렬

	// 계수, x^ or x or none, 지수, +연산자 순으로 차례대로 출력
	for (int i = 0; i < p.terms; i++) 
	{
		if (p.termArray[i].coef > 1) out << p.termArray[i].coef;  // possible coef 1~9 중 1보다 큰 계수만 출력
		if ((p.termArray[i].coef == 1) && (p.termArray[i].exp == 0)) out << p.termArray[i].coef;  // 상수항이 1일 때의 예외처리
		if (p.termArray[i].exp > 1) out << "x^";  // 지수가 2 이상이어야 x^num 꼴로 출력
		if (p.termArray[i].exp == 1) out << "x";  // 지수가 1일땐 x만 출력
		if (p.termArray[i].exp > 1) out << p.termArray[i].exp;  // 지수가 2 이상일 때만 지수 따로 출력
		if (i != p.terms - 1) out << " + ";  // 계수가 1~9(양수)니까 +만 출력 (종료시까지, 마지막 항 뒤에 + 출력 되지 않도록 주의)
	}
	out << endl;

	return out;
}

Polynomial Polynomial::operator+(Polynomial& B)  // 5. + 오버로딩
{
	Polynomial AddResult;  // 계산 결과 저장
	int aPos = 0, bPos = 0;  // 각 A,B 에서 계산할 항

	while ((aPos < terms) && (bPos < B.terms))  // A,B 지수가 같은 경우
	{
		if (termArray[aPos].exp == B.termArray[bPos].exp)
		{
			int t = termArray[aPos].coef + B.termArray[bPos].coef;  // 계수 더한 결과, 0이면 버림
			if (t) AddResult.NewTerm(t, termArray[aPos].exp);
			aPos++; bPos++;
		}
		
		else if (termArray[aPos].exp < B.termArray[bPos].exp)  // A 지수가 더 큰 경우
		{
			AddResult.NewTerm(B.termArray[bPos].coef, B.termArray[bPos].exp);
			bPos++;
		}

		else  // B 지수가 더 큰 경우
		{
			AddResult.NewTerm(termArray[aPos].coef, termArray[aPos].exp);
			aPos++;
		}
	}

	for (; aPos < terms; aPos++)  // B의 항 다 쓰고 A에 항들이 남은 경우
		AddResult.NewTerm(termArray[aPos].coef, termArray[aPos].exp);

	for (; bPos < B.terms; bPos++)  // A의 항 다 쓰고 B에 항들이 남은 경우
		AddResult.NewTerm(B.termArray[bPos].coef, B.termArray[bPos].exp);

	return AddResult;
}

Polynomial Polynomial::sMultPoly(int single_Coef, int single_Exp)  // 2. sMultPoly(c,e)
{
	Polynomial sMultResult;  // 계산 결과 저장
	int pos;

	// 기준이 되는 다항식의 각 항에, 입력된 단항식의 계수를 곱하고, 지수는 더해준다.
	for (pos = 0; pos < terms; pos++)
	{
		int smult_coef = termArray[pos].coef * single_Coef;
		int smult_exp = termArray[pos].exp + single_Exp;
		int place = -1;  // 새로운 항을 저장할 인덱스

		for (int i = 0; i < sMultResult.terms; i++) {
			if (sMultResult.termArray[i].exp == smult_exp) place = i;  // 같은 지수인 인덱스가 있다면 place에 저장
		}

		if (place == -1) sMultResult.NewTerm(smult_coef, smult_exp);  // 같은 지수인 인덱스가 없다면 끝에 새로 추가
		else sMultResult.termArray[place].coef += smult_coef;  // 같은 지수인 인덱스 있으면 계수끼리만 더해준다.
	}

	return sMultResult;
}

Polynomial Polynomial::operator*(Polynomial& B)  // 4. * 오버로딩
{
	Polynomial tempMult;  // sMultPoly이 return하는 polynomial 임시로 저장
	Polynomial MultResult;  // 계산 결과 저장
	int pos = 0;  // B에 곱해줄 A의 항

	// B(x)에 A(x)의 단항식을 차례대로 곱한다. 그 곱셈 결과들을 다 더해준다.
	for (pos = 0; pos < terms; pos++)
	{
		tempMult = B.sMultPoly(termArray[pos].coef, termArray[pos].exp);
		MultResult = MultResult + tempMult;
	}

	return MultResult;
}

int Polynomial::evalPoly(int x)  // 3. evalPoly(c)
{
	int eval = 0;

	for (int i = 0; i < terms; i++) 
	{
		eval += termArray[i].coef * pow(x, termArray[i].exp);
	}

	return eval;
}

int main()
{
	cout << "다항식 A,B,C 와 x 값을 입력하세요 >> ";
	while (1) {
		Polynomial a, b, c, d, t;  // a,b,c 다항식 읽고 생성, t=a*b, d=t+c
		int x;  // 다항식의 x에 대입할 값
		cin >> a;
		cin >> b;
		cin >> c;
		cout << "A(x) = " << a;
		cout << "B(x) = " << b;
		cout << "C(x) = " << c;
		t = a * b;
		d = t + c;
		cout << "T(x) = " << t;
		cout << "D(x) = " << d;
		cin >> x;
		cout << "x = " << x << " --> " << d.evalPoly(x) << '\n' << endl;
		cout << "다항식 A,B,C 와 x 값을 입력하세요 >> ";
	}

	return 0;
}

실행결과

 

점수 10/10

 

 

  ❤와 댓글은 큰 힘이 됩니다. 감사합니다 :-)  

반응형

'Schoolwork > 자료구조와 C++프로그래밍' 카테고리의 다른 글

[C++] 9주차 과제6  (0) 2020.08.05
[C++] 7주차 과제5  (0) 2020.08.05
[C++] 3주차 과제3  (0) 2020.08.05
[C++] 2주차 과제2  (0) 2020.08.05
[C++] 1주차 과제1  (0) 2020.08.05