This is a project for my object oriented programming class. I need to introduce the followings: overloading + to sum two polynomials, overloading * to multiply a polynomial with a scalar or to multiply it with another polynomial, overloading [] to return coeficient on a specific position, method for adding , deleting a coeficient and evaluating polynom in a certain point (f(x)).
1.Everything is working besides the destructor. The destructor that should be used (delete [] coef) of Polynomial will break (Heap Coruption) if i use cout << A + B and i do not know why.
What i use right now is a workaround but it will not delete coef[0]. That's the point where it breaks. If you can help me somehow i will be gratefull. Can you understand what caused it?
2.I need to have one more overloaded operator, " / ". It should make division between two polynomials and I do not know how to implement it. I tried to search for it but i couldn't understand any algorithm. Any advice or algorithm explanation would be great, because i really do not know from where to start and i need to finish it until tommorrow morning.
3.If you have any advice on coding or efficienty will also be great ( project requirement: do not use STL ).
Thank you!
Polynomial.h:
#pragma once
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
using std::ostream;
using std::istream;
class Polynomial
{
unsigned int deg;
double *coef;
public:
Polynomial() : deg(1), coef(new double[1]) {}
Polynomial(double [], int);
Polynomial(Polynomial&);
Polynomial& operator = (const Polynomial&);
~Polynomial();
friend ostream &operator <<(ostream&, const Polynomial&);
friend istream &operator >>(istream&, Polynomial&);
Polynomial operator + (const Polynomial) ;
double operator[] (unsigned int) const;
Polynomial operator * (int) const;
Polynomial operator * (const Polynomial obj) const;
unsigned int getDeg() { return this->deg; };
double eval(int);
void addCoef(double, int);
void delCoef(int);
};
inline Polynomial::Polynomial(double coefficients[], int number) : deg(number), coef(new double[number])
{
for (int i = 0; i < deg; i++) {
coef[i] = coefficients[i];
}
}
inline Polynomial::Polynomial(Polynomial &ob) {
this->deg = ob.deg;
this->coef = new double[deg];
for (int i = 0; i <= deg; i++)
{
this->coef[i] = ob.coef[i];
}
}
inline Polynomial::~Polynomial() {
for (int i = this->deg; i > 0; i--)
this->delCoef(i);
this->coef[0] = 0; //If i write it like this delete [] coef; it breaks.
this->deg = 0; //with HeapCoruption detected
}
Polynomial.cpp:
Polynomial& Polynomial::operator = (const Polynomial& obj)
{
if (this != &obj) //Testing to avoid situations like A = A;
{
this->deg = obj.deg;
for (int i = 0; i <= obj.deg; i++)
this->coef[i] = obj.coef[i];
}
return *this;
}
istream& operator >> (istream& in, Polynomial& obj)
{
in >> obj.deg;
cout << endl;
obj.coef = new double[obj.deg];
for (int i = 0; i <= obj.deg; i++)
{
in >> obj.coef[i];
}
return in;
}
ostream& operator << (ostream& out, const Polynomial& obj)
{
out << obj.deg << endl;
for (int i = 0; i <= obj.deg; i++)
{
if (obj.coef[i] != 0)
{
if (obj.coef[i] < 0)
out << '(' << obj.coef[i] << ')';
else
out << obj.coef[i];
if (i > 1)
out << "*x^" << i;
if (i == 1)
out << "*x";
if (i != obj.deg)
out << " + ";
}
}
out << endl <<endl;
return out;
}
Polynomial Polynomial::operator+ (const Polynomial obj)
{
Polynomial aux;
if (obj.deg >= deg)
{
aux.deg = obj.deg;
aux.coef = new double[obj.deg];
for (int i = 0; i <= deg; i++)
aux.coef[i] = obj.coef[i] + coef[i];
for (int i = deg + 1; i <= obj.deg; i++)
aux.coef[i] = obj.coef[i];
}
else // obj.deg < this->deg
{
aux.deg = deg;
aux.coef = new double[deg];
for (int i = 0; i <= obj.deg; i++)
{
aux.coef[i] = obj.coef[i] + coef[i];
}
for (int i = obj.deg + 1; i <= deg; i++)
{
aux.coef[i] = coef[i];
}
}
return aux;
}
double Polynomial::operator[] (unsigned int pos) const
{
if (pos > this->deg) {
throw std::out_of_range("Index bigger than polynomial length");
}
return this->coef[pos];
}
Polynomial Polynomial::operator * (const int scalar) const
{
Polynomial aux;
aux.deg = this->deg;
aux.coef = new double[aux.deg];
for (int i = 0; i <= aux.deg; i++)
aux.coef[i] = this->coef[i] * scalar;
return aux;
}
Polynomial Polynomial::operator * (const Polynomial obj) const
{
Polynomial aux;
aux.deg = obj.deg + this->deg;
aux.coef = new double[aux.getDeg()];
for (int i = 0; i <= aux.getDeg(); i++)
aux.addCoef(0, i);
for (int i = 0; i <= this->deg; i++)
for (int j = 0; j <= obj.deg; j++)
aux.coef[i+j] += (this->coef[i]) * obj.coef[j];
return aux;
}
double Polynomial::eval(int x) {
double sum = 0;
for (int i = 0; i <= this->deg; i++)
{
if (i == 0)
sum += this->coef[0];
else
{
int aux = i;
int xaux = x;
aux--;
while (aux != 0)
{
xaux *= x;
aux--;
}
sum += this->coef[i] * xaux;
}
}
return sum;
}
void Polynomial::addCoef(double NewCoef, int pos)
{
if (pos < 0)
return;
if (pos > this->deg)
{
double *newCoef = new double[pos];
for (int i = 0; i <= this->deg; i++)
newCoef[i] = this->coef[i];
for (int i = this->deg + 1; i < pos; i++)
newCoef[i] = 0;
newCoef[pos] = NewCoef;
this->coef = newCoef;
this->deg = pos;
return;
}
else
{
this->coef[pos] = NewCoef;
}
}
void Polynomial::delCoef(int pos)
{
if (pos > this->deg || pos < 0 )
return;
if (pos == this->deg)
{
this->coef[pos] = 0;
int degNoua = pos - 1;
while (this->coef[pos] == 0 && pos != 0)
pos--;
if (pos == 0 && this->coef[pos] == 0)
{
delete this->coef;
this->deg = 0;
}
else
{
this->deg = pos;
double *aux = new double[pos];
for (int i = 0; i <= pos; i++)
aux[i] = this->coef[i];
this->coef = aux;
}
}
else
{
this->coef[pos] = 0;
}
}
Related
My code is here
//RSA.cpp
#include <iostream>
#include <cstring>
#include <ctime>
#include <random>
#include <vector>
#include <string>
#include "BigNum.hpp"
using namespace std;
BigNum mygcd(BigNum a, BigNum b)
{
while(a != b)
{
if(a>b)
{
a = a - b;
}
else
{
b = b - a;
}
}
return a;
}
BigNum prime(int n)
{
vector<BigNum> ans;
ans.push_back(BigNum(2));
ans.push_back(BigNum(3));
for (int i = 0; i < n; i++)
{
BigNum addend = 1;
for (auto j : ans)
{
addend = addend * j;
}
ans.push_back(addend + 1);
}
return ans[ans.size() - 1];
}
BigNum exgcd(BigNum a, BigNum b, BigNum &x, BigNum &y)
{
if (b == 0)
{
x = 1, y = 0;
return a;
}
BigNum g = exgcd(b, a - (a / b) * b, x, y);
BigNum t;
t = x;
x = y;
y = t - a / b * y;
return g;
}
BigNum niyuan(BigNum a, BigNum b)
{
BigNum x, y;
BigNum aa = exgcd(a, b, x, y);
return (x + b) - ((x + b) / b) * b;
}
vector<BigNum> yinshu(BigNum n)
{
vector<BigNum> ans;
int a = 2;
while (n / 2 > a)
{
if (n % a == 0)
{
ans.push_back(a);
}
a++;
}
return ans;
}
vector<int> ToBit(BigNum obj){
vector<int> r;
while (obj != 0){
r.push_back( (obj - (obj / 2) * 2 == 0) ? 0 : 1 );
obj = obj / 2;
}
return r;
}
BigNum jiami(BigNum e, int i, BigNum n)
{
BigNum addend = i;
BigNum result = 1;
vector<int>bitE = ToBit(e);
int now = 0;
while (now != bitE.size())
{
if (bitE[now])
{
result = addend * result;
result = result - (result / n) * n;
}
addend = addend * addend;
now = now + 1;
}
return result;
}
BigNum jiemi(BigNum d, BigNum i, BigNum n)
{
BigNum addend = i;
BigNum result = 1;
vector<int>bitD = ToBit(d);
int now = 0;
while (now != bitD.size())
{
if (bitD[now])
{
result = addend * result;
result = result - (result / n) * n;
}
addend = addend * addend;
now = now + 1;
}
return result;
}
int main()
{
srand(time(0));
BigNum p = prime(rand() % 20 + 1);
srand(time(0));
BigNum q = prime(rand() % 20 + 1);
BigNum N = p * q;
BigNum r = (p - 1) * (q - 1);
sss:
srand(time(0));
BigNum e = random() + 2;
if (mygcd(e, r) - BigNum(1) > 0)
goto sss;
vector<BigNum> yinshus = yinshu(r);
BigNum d = BigNum(niyuan(e, r));
cout << "Alice send(" << N << ',' << e << ")to Bob" << endl;
cout << "Please input your massage:";
string m;
cin >> m;
vector<int> message;
for (auto i : m)
{
message.push_back((int)i);
}
vector<BigNum> miwen;
for (auto i : message)
{
miwen.push_back(jiami(e, i, N));
}
cout << "coded text:";
for (auto i : miwen)
{
cout << i << " ";
}
vector<BigNum> minwen;
for (auto i : miwen)
{
minwen.push_back(jiemi(d, i, N));
}
cout << "明文:";
for (auto i : minwen)
{
cout << i << " ";
}
cout << endl;
}
I used a self-defined data structure called BigNum in order to store some large integers without them overflowing.
//BigNum.hpp
#include <iostream>
#include <cstring>
#include <string>
#include <iomanip>
#include <algorithm>
using namespace std;
#define MAXN 9999
#define MAXSIZE 10
#define DLEN 4
class BigNum
{
private:
int a[999];
int len;
public:
BigNum()
{
len = 1;
memset(a, 0, sizeof(a));
}
BigNum(const int);
BigNum(const char *);
BigNum(const BigNum &);
BigNum &operator=(const BigNum &);
friend istream &operator>>(istream &, BigNum &);
friend ostream &operator<<(ostream &, BigNum &);
BigNum operator+(const BigNum &) const;
BigNum operator-(const BigNum &) const;
BigNum operator*(const BigNum &) const;
BigNum operator/(const int &) const;
BigNum operator/(const BigNum &) const;
BigNum operator^(const int &) const;
int operator%(const int &) const;
bool operator>(const BigNum &T) const;
bool operator>(const int &t) const;
bool operator<(const BigNum &) const;
bool operator<=(const BigNum &) const;
bool operator>=(const BigNum &) const;
bool operator==(const BigNum &) const;
bool operator!=(const BigNum &) const;
void print();
};
BigNum::BigNum(const int b)
{
int c, d = b;
len = 0;
memset(a, 0, sizeof(a));
while (d > MAXN)
{
c = d - (d / (MAXN + 1)) * (MAXN + 1);
d = d / (MAXN + 1);
a[len++] = c;
}
a[len++] = d;
}
BigNum::BigNum(const char *s)
{
int t, k, index, l, i;
memset(a, 0, sizeof(a));
l = strlen(s);
len = l / DLEN;
if (l % DLEN)
len++;
index = 0;
for (i = l - 1; i >= 0; i -= DLEN)
{
t = 0;
k = i - DLEN + 1;
if (k < 0)
k = 0;
for (int j = k; j <= i; j++)
t = t * 10 + s[j] - '0';
a[index++] = t;
}
}
BigNum::BigNum(const BigNum &T) : len(T.len)
{
int i;
memset(a, 0, sizeof(a));
for (i = 0; i < len; i++)
a[i] = T.a[i];
}
BigNum &BigNum::operator=(const BigNum &n)
{
int i;
len = n.len;
memset(a, 0, sizeof(a));
for (i = 0; i < len; i++)
a[i] = n.a[i];
return *this;
}
istream &operator>>(istream &in, BigNum &b)
{
char ch[MAXSIZE * 4];
int i = -1;
in >> ch;
int l = strlen(ch);
int count = 0, sum = 0;
for (i = l - 1; i >= 0;)
{
sum = 0;
int t = 1;
for (int j = 0; j < 4 && i >= 0; j++, i--, t *= 10)
{
sum += (ch[i] - '0') * t;
}
b.a[count] = sum;
count++;
}
b.len = count++;
return in;
}
ostream &operator<<(ostream &out, BigNum &b)
{
int i;
cout << b.a[b.len - 1];
for (i = b.len - 2; i >= 0; i--)
{
cout.width(DLEN);
cout.fill('0');
cout << b.a[i];
}
return out;
}
BigNum BigNum::operator+(const BigNum &T) const
{
BigNum t(*this);
int i, big;
big = T.len > len ? T.len : len;
for (i = 0; i < big; i++)
{
t.a[i] += T.a[i];
if (t.a[i] > MAXN)
{
t.a[i + 1]++;
t.a[i] -= MAXN + 1;
}
}
if (t.a[big] != 0)
t.len = big + 1;
else
t.len = big;
return t;
}
BigNum BigNum::operator-(const BigNum &T) const
{
int i, j, big;
bool flag;
BigNum t1, t2;
if (*this > T)
{
t1 = *this;
t2 = T;
flag = 0;
}
else
{
t1 = T;
t2 = *this;
flag = 1;
}
big = t1.len;
for (i = 0; i < big; i++)
{
if (t1.a[i] < t2.a[i])
{
j = i + 1;
while (t1.a[j] == 0)
j++;
t1.a[j--]--;
while (j > i)
t1.a[j--] += MAXN;
t1.a[i] += MAXN + 1 - t2.a[i];
}
else
t1.a[i] -= t2.a[i];
}
t1.len = big;
while (t1.a[t1.len - 1] == 0 && t1.len > 1)
{
t1.len--;
big--;
}
if (flag)
t1.a[big - 1] = 0 - t1.a[big - 1];
return t1;
}
BigNum BigNum::operator*(const BigNum &T) const
{
BigNum ret;
int i, j, up;
int temp, temp1;
for (i = 0; i < len; i++)
{
up = 0;
for (j = 0; j < T.len; j++)
{
temp = a[i] * T.a[j] + ret.a[i + j] + up;
if (temp > MAXN)
{
temp1 = temp - temp / (MAXN + 1) * (MAXN + 1);
up = temp / (MAXN + 1);
ret.a[i + j] = temp1;
}
else
{
up = 0;
ret.a[i + j] = temp;
}
}
if (up != 0)
ret.a[i + j] = up;
}
ret.len = i + j;
while (ret.a[ret.len - 1] == 0 && ret.len > 1)
ret.len--;
return ret;
}
BigNum BigNum::operator/(const int &b) const
{
BigNum ret;
int i, down = 0;
for (i = len - 1; i >= 0; i--)
{
ret.a[i] = (a[i] + down * (MAXN + 1)) / b;
down = a[i] + down * (MAXN + 1) - ret.a[i] * b;
}
ret.len = len;
while (ret.a[ret.len - 1] == 0 && ret.len > 1)
ret.len--;
return ret;
}
int BigNum::operator%(const int &b) const
{
int i, d = 0;
for (i = len - 1; i >= 0; i--)
{
d = ((d * (MAXN + 1)) % b + a[i]) % b;
}
return d;
}
BigNum BigNum::operator^(const int &n) const
{
BigNum t, ret(1);
int i;
if (n < 0)
exit(-1);
if (n == 0)
return 1;
if (n == 1)
return *this;
int m = n;
while (m > 1)
{
t = *this;
for (i = 1; i << 1 <= m; i <<= 1)
{
t = t * t;
}
m -= i;
ret = ret * t;
if (m == 1)
ret = ret * (*this);
}
return ret;
}
bool BigNum::operator>(const BigNum &T) const
{
int ln;
if (len > T.len)
return true;
else if (len == T.len)
{
ln = len - 1;
while (a[ln] == T.a[ln] && ln >= 0)
ln--;
if (ln >= 0 && a[ln] > T.a[ln])
return true;
else
return false;
}
else
return false;
}
bool BigNum::operator>(const int &t) const
{
BigNum b(t);
return *this > b;
}
void BigNum::print()
{
int i;
cout << a[len - 1];
for (i = len - 2; i >= 0; i--)
{
cout.width(DLEN);
cout.fill('0');
cout << a[i];
}
cout << endl;
}
bool BigNum::operator<(const BigNum &obj) const
{
for (int i = 0; i < len; i++)
{
if (a[i] < obj.a[i])
return true;
if (a[i] > obj.a[i])
return false;
}
return false;
}
bool BigNum::operator<=(const BigNum &obj) const
{
for (int i = 0; i < len; i++)
{
if (a[i] < obj.a[i])
return true;
if (a[i] > obj.a[i])
return false;
}
return true;
}
bool BigNum::operator>=(const BigNum &obj) const
{
for (int i = 0; i < len; i++)
{
if (a[i] > obj.a[i])
return true;
if (a[i] < obj.a[i])
return false;
}
return true;
}
bool BigNum::operator==(const BigNum &obj) const
{
for (int i = 0; i < len; i++)
{
if (a[i] != obj.a[i])
return false;
}
return true;
}
bool BigNum::operator!=(const BigNum &obj) const
{
for (int i = 0; i < len; i++)
{
if (a[i] != obj.a[i])
return true;
}
return false;
}
BigNum BigNum::operator/(const BigNum &op2) const
{
BigNum temp(*this);
if (op2 == 0)
{
cout << "ERROR!!";
for (int i = 0; i < len; i++)
temp.a[i] = 0;
}
else if (*this < op2)
{
for (int i = 0; i < len; i++)
temp.a[i] = 0;
}
else if (*this == op2)
{
temp.a[len - 1] = 1;
}
else if (op2 == 1)
{
temp = *this;
}
else if (op2 == 2)
{
int from = 0;
for (int i = 0; i < len; i++)
{
if (temp.a[i] != 0)
{
from = i;
break;
}
}
int carry = 0;
for (int i = from; i < len; i++)
{
if (temp.a[i] & 1)
{
if (carry == 1)
temp.a[i] = (temp.a[i] + 10) / 2;
else
temp.a[i] = temp.a[i] / 2;
carry = 1;
}
else
{
if (carry == 1)
temp.a[i] = (temp.a[i] + 10) / 2;
else
temp.a[i] = temp.a[i] / 2;
carry = 0;
}
}
}
else
{
BigNum begin(1), end("500000000000000000000000000000"); // 500000000000000000000000000000
while (begin < end)
{
BigNum mid = (begin + end) / 2;
BigNum res = mid * op2;
if (res == 0 || res >= *this)
end = mid;
else
begin = mid + 1;
}
temp = begin;
if (temp == 1)
return 0;
int tmp = len - 1;
while (temp.a[tmp] == 0)
{
temp.a[tmp] = 9;
tmp++;
}
temp.a[tmp]--;
return temp;
}
return temp;
}
When I run it, sometimes I get the error "malloc(): corrupted top size", sometimes it will run and then nothing happens, when I debug it, I find that the problem is in the "mygcd" function, the algorithm I use is too slow for a huge The algorithm I'm using is too slow for the huge number, but I don't know how to change it. I'm not sure where in the two files something is going wrong that I don't know about, and I can't guarantee that all the algorithms I'm using are correct and appropriate. Can anyone help me? Thanks a lot.
My system is Ubuntu 22.04.1LTS
gcc version 11.2.0
Now I deleted all the Chinese comments
After applying all of the changes suggested in the comments:
Remove using namespace std;
Remove superfluous BigNum::operator= and BigNum::BigNum(BigNum&)
Only implement fully BigNum::operator< and BigNum::operator==, and the other relational operators are based on those two operators
Make BigNum::operator << have the second argument as a const reference to BigNum.
the compiler here warns of j not being initialized.
BigNum BigNum::operator*(const BigNum &T) const //两个大数之间的相乘运算
{
BigNum ret;
int i, j, up;
//...
ret.len = i + j;
//...
}
You see the results of the run, with the Address Sanitizer showing that things are not working right.
When j is initialized to 0, then the program runs without error, at least the main you provided runs without error.
Edit:
On further inspection, you are accessing arr out-of-bounds. After changing the a to std::array<int, 999> a; and used at() within BigNum::operator *, a std::out_of_range exception is thrown:
Here is the updated code.
Also, please name your variables with meaningful names, not one letter names like a. Naming your variables properly will aid in understanding the code a lot better.
Hi I need help creating a < operator and Im not sure how.
#include "biguint.h"
#include <string>
#include <cstdlib>
#include <iostream>
biguint::biguint()
{
for(size_t i = 0; i < CAPACITY; i++){
data_[i]=0;
}
}
biguint::biguint(const std::string &s){
int templeng = s.length();
for(size_t i = 0; i < templeng; i++){
data_[i] = s[templeng -i - 1] -'0';
}
for(size_t i = templeng; i < CAPACITY; i++){
data_[i]=0;
}
}
unsigned short biguint::operator [](std::size_t pos) const{
unsigned short i = 0;
if(pos >= 0 && pos < CAPACITY){
i = data_[pos];
}
return i;
}
std::ostream& operator <<(std::ostream& out, const biguint& b)
{
for (int i = biguint::CAPACITY; i > 0; i--) {
out<<b[i-1];
}
return out;
}
void biguint::operator += (const biguint & b){
int k = 0;
int temp = 0;
for (size_t i = 0; i < CAPACITY; i++) {
temp = data_[i]+b.data_[i];
if(temp >= 10){
data_[i] = temp-10;
data_[i+1]+=1;
}
else{
data_[i]=temp;
}
}
}
biguint operator + (const biguint & lhs, const biguint & rhs)
{
int temp;
bool remainder = false;
std::string result = "";
std::string reverse = "";
if(lhs.CAPACITY != rhs.CAPACITY)
{
return biguint("0");
}
for(int i =0; i < (int)lhs.CAPACITY;i++)
{
temp = lhs[i]+rhs[i];
if(remainder)
{
temp++;
remainder = false;
}
if(temp<10)
{
result = result + std::to_string(temp);
}
else {
result += std::to_string(temp - 10);
remainder = true;
}
}
for (int i = result.size() - 1; i >= 0; i--) {
reverse += result[i];
}
return biguint(reverse);
}
int biguint::compare(const biguint & b) const
{
return this->toStdString().compare(b.toStdString());
}
std::string biguint::toStdString() const
{
bool start = false;
std::string result = "";
for (int i = (int) this->CAPACITY - 1; i >= 0; i--) {
if (this->data_[i] == 0 && !start) {
if (this->CAPACITY == 1)
result += std::to_string(this->data_[i]);
continue;
}
else {
start = true;
result += std::to_string(this->data_[i]);
}
}
return result;
}
bool operator < (const biguint & lhs, const biguint & rhs)
{
}
This my .cpp file Im kind of lost on how to create < operator. I have created the +,+=, and two string but I'm unsure of how to create the <. Im not sure how to access those numbers for example biguint one("233") how would i access that number
Tl;dr: Try to compare digit by digit while handling mismatched length cases.
Say your given any 2 numbers:
num1 = 12345
num2 = 57632
The intuitive way for you to determine that which is bigger:
Compare them starting from the most significant digit(eg. here 5 > 1)
When equal compare the next significant digit(eg. if the numbers were 92 and 93, you would have compared 2 < 3 to get your answer.
The only difference is here individual digits are stored in an array.
P.S. Your compare seems to do a lexicographic compare - Is that really what you want?
I already managed to implement most of what I planned to do correctly, but somehow I struggle with the unique and cut method.
The unique method should sort the vector and delete all entries that appear more than once and the original vector should be overwritten with the shortened on. The cut method should delete all entries < cMin or > cMax.
Here is my try so far:
#include <cassert>
#include <iostream>
using std::cout;
using std::endl;
class Vector {
private:
int n;
double* coeff;
public:
Vector(int, double = 0);
~Vector();
Vector(const Vector&);
Vector& operator=(const Vector&);
int size() const;
double& operator()(int);
const double& operator()(int) const;
double max() const;
void sort();
void unique();
void cut(double Cmin, double Cmax);
void print() const;
};
Vector::Vector(int n, double init)
{
assert(n >= 0);
this->n = n;
if (n == 0) {
coeff = (double*)0;
}
else {
coeff = new double[n];
}
for (int i = 0; i < n; i++) {
coeff[i] = init;
}
}
Vector::Vector(const Vector& rhs)
{
n = rhs.n;
if (n > 0) {
coeff = new double[n];
}
else {
coeff = (double*)0;
}
for (int i = 0; i < n; i++) {
coeff[i] = rhs.coeff[i];
}
}
Vector::~Vector()
{
if (n > 0) {
delete[] coeff;
}
}
Vector& Vector::operator=(const Vector& rhs)
{
if (this != &rhs) {
if (n != rhs.n) {
if (n > 0) {
delete[] coeff;
}
n = rhs.n;
if (n > 0) {
coeff = new double[n];
}
else {
coeff = (double*)0;
}
}
for (int i = 0; i < n; i++) {
coeff[i] = rhs.coeff[i];
}
}
return *this;
}
int Vector::size() const
{
return n;
}
double& Vector::operator()(int j)
{
assert(j >= 1 && j <= n);
return coeff[j - 1];
}
const double& Vector::operator()(int j) const
{
assert(j >= 1 && j <= n);
return coeff[j - 1];
}
double Vector::max() const
{
double max = coeff[0];
for (int i = 1; i < n; i++) {
if (coeff[i] > max) {
max = coeff[i];
}
}
return max;
}
void Vector::sort()
{ //bubble-sort
double tmp = 0;
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - 1; j++) {
if (coeff[j] > coeff[j + 1]) {
tmp = coeff[j];
coeff[j] = coeff[j + 1];
coeff[j + 1] = tmp;
}
}
}
}
void Vector::unique()
{
sort();
int counter = 0;
Vector kopie = *this;
for (int i = 0; i < n; i++) {
if (i == 0 && coeff[i] != coeff[i + 1]) {
counter++;
}
if (i == n - 1 && coeff[i] != coeff[i - 1]) {
counter++;
}
if (i != 0 && i != n - 1 && coeff[i] != coeff[i - 1] && coeff[i] != coeff[i + 1]) {
counter++;
}
}
delete[] coeff;
coeff = new double[counter];
//to be continued...
}
void Vector::cut(double Cmin, double Cmax)
{
sort();
int counter = 0;
int j = 0;
Vector kopie = *this;
for (int i = 0; i < n; i++) {
if (coeff[i] >= Cmin && coeff[i] <= Cmax) {
counter++;
}
}
delete[] coeff;
coeff = new double[counter];
for (int i = 0; i < n; i++) {
if (kopie.coeff[i] >= Cmin && kopie.coeff[i] <= Cmax) {
coeff[j] = kopie.coeff[i];
j++;
if (j == n) {
break;
}
}
}
}
void Vector::print() const
{
for (int i = 0; i < n; i++) {
cout << coeff[i] << " ";
}
}
int main()
{
Vector X(8);
X.print();
cout << endl;
X(1) = 1.;
X(2) = 7.;
X(3) = 2.;
X(4) = 5.;
X(5) = 6.;
X(6) = 5.;
X(7) = 9.;
X(8) = 6.;
X.print();
cout << endl;
X.sort();
X.print();
cout << endl;
//X.unique();
//X.print();
//cout << endl;
X.cut(2, 6);
X.print();
cout << endl;
return 0;
}
For the unique function, rather than checking if it's legal to move the counter forward, I would just check if your current element and the next element aren't the same. If they are, set the next element's pointer to skip over the duplicate element.
Pseduocode:
For(int i = 0; i < n-1; i++) {
if(coef[i] == coef[i+1]) {
//Keep moving next element pointer until not equal. Probably use a while loop
}
}
The simplest solution that I can think of is something like this:
void Vector::unique()
{
size_t counter = 0;
double* copy = new double[n];
copy[counter++] = coeff[0]; // The first element is guaranteed to be unique
// Since coeff is sorted, copy will be sorted as well.
// Therefore, its enough to check only the last element of copy to
// the current element of coeff
for (size_t i = 1; i < n; i++)
{
if (coeff[i] != copy[counter])
{
copy[counter++] = coeff[i];
}
}
// copy already contains the data in the format that you want,
// but the reserved memory size may be larger than necessary.
// Reserve the correct amount of memory and copy the data there
delete[] coeff;
coeff = new double[counter];
std::memcpy(coeff, copy, counter*sizeof(double));
}
For cut() you can use a similar algorithm:
void Vector::cut(double Cmin, double Cmax)
{
size_t counter = 0;
double* copy = new double[n];
for (size_t i = 0; i < n; i++)
{
if (coeff[i] > Cmin && coeff[i] < Cmax)
{
copy[counter++] = coeff[i];
}
}
// Same story with memory size here as well
delete[] coeff;
coeff = new double[counter];
std::memcpy(coeff, copy, counter*sizeof(double));
}
Is there any reason why you can't use the standard library?
void Vector::unique() {
std::sort(coeff, std::next(coeff, n));
auto it = std::unique(coeff, std::next(coeff, n));
double* tmp = new double[n = std::distance(coeff, it)];
std::copy(coeff, it, tmp);
delete[] std::exchange(coeff, tmp);
}
void Vector::cut(double Cmin, double Cmax) {
auto it = std::remove_if(coeff, std::next(coeff, n),
[=] (double d) { return d < Cmin || d > Cmax; });
double* tmp = new double[n = std::distance(coeff, it)];
std::copy(coeff, it, tmp);
delete[] std::exchange(coeff, tmp);
}
To remove duplicates and sort, you can achieve it in three ways
Just using vector, sort + unique
sort( vec.begin(), vec.end() );
vec.erase( unique( vec.begin(), vec.end() ), vec.end() );
Convert to set (manually)
set<int> s;
unsigned size = vec.size();
for( unsigned i = 0; i < size; ++i )
s.insert( vec[i] ); vec.assign( s.begin(), s.end() );
Convert to set (using a constructor)
set<int> s( vec.begin(), vec.end() );
vec.assign( s.begin(), s.end() );
All three has different performance. You can use one depending upon your size and number of duplicates present.
To cut you can use algorithm library
std::remove, std::remove_if
Syntax
template< class ForwardIt, class T >
constexpr ForwardIt remove( ForwardIt first, ForwardIt last, const T& value );
Possible implementation
First version
template< class ForwardIt, class T > ForwardIt remove(ForwardIt first, ForwardIt last, const T& value)
{ first = std::find(first, last, value);
if (first != last)
for(ForwardIt i = first; ++i != last; )
if (!(*i == value))
*first++ = std::move(*i); return first; }
Second version
template<class ForwardIt, class UnaryPredicate> ForwardIt remove_if(ForwardIt first, ForwardIt last, UnaryPredicate p)
{ first = std::find_if(first, last, p);
if (first != last)
for(ForwardIt i = first; ++i != last; )
if (!p(*i)) *first++ = std::move(*i);
return first; }
Examples
The following code removes all spaces from a string by shifting all non-space characters to the left and then erasing the extra. This is an example of erase-remove idiom.
Run this code
#include <algorithm>
#include <string>
#include <iostream>
#include <cctype>
int main()
{ std::string str1 = "Text with some spaces"; str1.erase(std::remove(str1.begin(), str1.end(), ' '), str1.end());
std::cout << str1 << '\n';
std::string str2 = "Text\n with\tsome \t whitespaces\n\n"; str2.erase(std::remove_if(str2.begin(), str2.end(), [](unsigned char x)
{return std::isspace(x);}), str2.end());
std::cout << str2 << '\n'; }
Output:
Textwithsomespaces
Textwithsomewhitespaces
I'm trying to set up operator that puts two arrays together but takes out dublicates in the array.
My idea is that I copy the first array in to the new one and then copy the "products" that are not in the first array in to the new array.
I'm trying to call a function that checks if the "product" is in the first array but I keep getting the error:
error: member function 'er_varan_eins' not viable: 'this' argument has type 'const Inventory', but function is not marked const
Here is my code:
#include <iostream>
using namespace std;
struct Varan{
string vara;
int fjoldi;
double verd;
};
class Inventory {
public:
Inventory();
void stafrofsrod();
void verdmaetisrod();
void setsortorder(string rodun);
void setsorting();
bool er_varan_eins(const Varan vara1);
~Inventory();
friend istream& operator >> (istream& ins, Inventory &inv);
friend ostream& operator << (ostream& outs, const Inventory &inv);
friend Inventory operator + (const Inventory &inv1, const Inventory &inv2);
private:
Varan *vorulisti;
int n;
string order;
};
Inventory::Inventory() {
n = 0;
vorulisti = new Varan[n];
}
void Inventory::stafrofsrod() {
Varan tmp;
int i, j;
for (i = 1; i < n; i++) {
tmp.vara = vorulisti[i].vara;
tmp.fjoldi = vorulisti[i].fjoldi;
tmp.verd = vorulisti[i].verd;
j = i;
while (j > 0 && vorulisti[j - 1].vara > tmp.vara) {
vorulisti[j].vara = vorulisti[j - 1].vara;
vorulisti[j].fjoldi = vorulisti[j - 1].fjoldi;
vorulisti[j].verd = vorulisti[j - 1].verd;
j--;
}
vorulisti[j].vara = tmp.vara;
vorulisti[j].fjoldi = tmp.fjoldi;
vorulisti[j].verd = tmp.verd;
}
}
void Inventory::verdmaetisrod() {
Varan tmp;
int i, j;
for (i = 1; i < n; i++) {
tmp.vara = vorulisti[i].vara;
tmp.fjoldi = vorulisti[i].fjoldi;
tmp.verd = vorulisti[i].verd;
j = i;
while (j > 0 && (vorulisti[j - 1].fjoldi * vorulisti[j - 1].verd) < (tmp.fjoldi * tmp.verd)) {
vorulisti[j].vara = vorulisti[j - 1].vara;
vorulisti[j].fjoldi = vorulisti[j - 1].fjoldi;
vorulisti[j].verd = vorulisti[j - 1].verd;
j--;
}
vorulisti[j].vara = tmp.vara;
vorulisti[j].fjoldi = tmp.fjoldi;
vorulisti[j].verd = tmp.verd;
}
}
void Inventory::setsortorder(string rodun) {
order = rodun;
setsorting();
}
void Inventory::setsorting() {
if (order == "Value") {
verdmaetisrod();
}
else {
stafrofsrod();
}
}
Inventory::~Inventory() {
delete [] vorulisti;
}
istream& operator >> (istream& ins, Inventory &inv) {
ins >> inv.n;
inv.vorulisti = new Varan[inv.n];
for (int i = 0; i < inv.n; i++) {
ins >> inv.vorulisti[i].vara;
ins >> inv.vorulisti[i].fjoldi;
ins >> inv.vorulisti[i].verd;
}
inv.stafrofsrod();
return ins;
}
ostream& operator << (ostream& outs, const Inventory &inv) {
for (int i = 0; i < inv.n; i++) {
outs << inv.vorulisti[i].vara << " " << inv.vorulisti[i].fjoldi << " " << inv.vorulisti[i].verd << endl;
}
return outs;
}
Inventory operator + (const Inventory &inv1, const Inventory &inv2) {
int counter = 0;
for (int i = 0; i < inv1.n; i++) {
for (int j = 0; j < inv2.n; j++) {
if (inv1.vorulisti[i].vara == inv2.vorulisti[i].vara) {
counter++;
}
}
}
int new_size = inv1.n + inv2.n - counter;
Inventory new_array;
new_array.n = new_size;
new_array.vorulisti = new Varan[new_size];
for (int i = 0; i < inv1.n; i++) {
new_array.vorulisti[i].vara = inv1.vorulisti[i].vara;
new_array.vorulisti[i].fjoldi = inv1.vorulisti[i].fjoldi;
new_array.vorulisti[i].verd = inv1.vorulisti[i].verd;
}
int teljari = 0;
for (int j = 0; j < inv2.n; j++) {
if( inv1.er_varan_eins(inv2.vorulisti[j].vara)) {
teljari++;
}
else {
new_array.vorulisti[j + inv1.n - teljari].vara = inv2.vorulisti[j].vara;
new_array.vorulisti[j + inv1.n - teljari].fjoldi = inv2.vorulisti[j].fjoldi;
new_array.vorulisti[j + inv1.n - teljari].verd = inv2.vorulisti[j].verd;
}
}
new_array.stafrofsrod();
return new_array;
}
bool Inventory::er_varan_eins(const Varan vara1) {
for (int i = 0; i < n; i++) {
if (vorulisti[i].vara == vara1.vara) {
return true;
}
}
return false;
}
int main()
{
Inventory inv1, inv2;
cin >> inv1 >> inv2;
cout << inv1 + inv2;
return 0;
}
Since inv1 is a const Inventory &, you can only call const member functions on it. Your er_varan_eins function can be made const since it does not modify any members of the Inventory class.
I'm getting an error regarding "disgarded qualifiers" when I use this. The Entier class is posted below.
cout << d // where d is of type dynamic_array.
The global overloaded function:
template <class T> std::ostream& operator<<(std::ostream& stream, dynamic_array<T> const& data)
{
data.print_array(stream);
return stream;
}
A public member of dynamic_array
void print_array(std::ostream &os = cout)
{
for (int i = 0; i < size; i++) os << array[i] << endl;
}
Entire Class dynamic array:
/*
Needs a reszie function added
Merge sort is better for sequential, stable(equal elements not re-arranged, or
*/
#include "c_arclib.cpp"
using namespace std;
template <class T> class dynamic_array
{
private:
T* array;
T* scratch;
void merge_recurse(int left, int right)
{
if(right == left + 1)
{
return;
}
else
{
int i = 0;
int length = right - left;
int midpoint_distance = length/2;
int l = left, r = left + midpoint_distance;
merge_recurse(left, left + midpoint_distance);
merge_recurse(left + midpoint_distance, right);
for(i = 0; i < length; i++)
{
if((l < (left + midpoint_distance)) && (r == right || array[l] > array[r]))
{
scratch[i] = array[l];
l++;
}
else
{
scratch[i] = array[r];
r++;
}
}
for(i = left; i < right; i++)
{
array[i] = scratch[i - left];
}
}
}
void quick_recurse(int left, int right)
{
int l = left, r = right, tmp;
int pivot = array[(left + right) / 2];
while (l <= r)
{
while (array[l] < pivot)l++;
while (array[r] > pivot)r--;
if (l <= r)
{
tmp = array[l];
array[l] = array[r];
array[r] = tmp;
l++;
r--;
}
}
if (left < r)quick_recurse(left, r);
if (l < right)quick_recurse(l, right);
}
public:
int size;
dynamic_array(int sizein)
{
size=sizein;
array = new T[size]();
}
void print_array(std::ostream &os = cout)
{
for (int i = 0; i < size; i++) os << array[i] << endl;
}
void print_array()
{
for (int i = 0; i < size; i++) cout << array[i] << endl;
}
int merge_sort()
{
scratch = new T[size]();
if(scratch != NULL)
{
merge_recurse(0, size);
return 1;
}
else
{
return 0;
}
}
void quick_sort()
{
quick_recurse(0,size);
}
void rand_to_array()
{
srand(time(NULL));
int* k;
for (k = array; k != array + size; ++k)
{
*k=rand();
}
}
void order_to_array()
{
int* k;
int i = 0;
for (k = array; k != array + size; ++k)
{
*k=i;
++i;
}
}
void rorder_to_array()
{
int* k;
int i = size;
for (k = array; k != array + size; ++k)
{
*k=i;
--i;
}
}
};
template <class T> std::ostream& operator<<(std::ostream& stream, dynamic_array<T> const& data)
{
data.print_array(stream);
return stream;
}
int main()
{
dynamic_array<int> d1(1000000);
d1.order_to_array();
clock_t time_start=clock();
d1.merge_sort();
clock_t time_end=clock();
double result = (double)(time_end - time_start) / CLOCKS_PER_SEC;
cout << result;
cout << d1;
}
The problem is in following lines:
template <class T>
std::ostream& operator<<(std::ostream& stream, dynamic_array<T> const& data)
^^^^^^
and
void print_array(std::ostream &os = cout) /* const */
^^^^^ missing
Since you are passing data as const& to operator <<, you have to maintain its const qualification. i.e. data cannot call any non-const member of class dynamic_array. You can solve this problem in 2 ways:
pass data as simple dynamic_array<T>& to operator <<
make print_array a const method (uncomment above)
"Discards const qualifiers", presumably...
Replace:
void print_array(std::ostream &os = cout)
{
for (int i = 0; i < size; i++) os << array[i] << endl;
}
void print_array()
{
for (int i = 0; i < size; i++) cout << array[i] << endl;
}
...with...
void print_array(std::ostream &os = cout) const
{
for (int i = 0; i < size; i++) os << array[i] << endl;
}
...or, better still ...
void print_array(std::ostream &os = cout) const
{
std::copy(array, array + size, std::ostream_iterator<T>(os, "\n"));
}
This member function can be declared const since it doesn't modify any attributes of the class. See the FAQ on Const-Correctness.
Your second print_array() method is redundant since the first takes a default argument of std::cout.