C++: Convert ushort, uint and ulong to vector<uchar> - c++

I'm building a numeric class to work with 1 to 8 bytes. The idea is: input the value by a string or a char*, then the program convert it to unsigned short, unsigned int or unsigned long, according to the string size (I've used stringstream to conversion, this part is ok). After the program separa the value in bytes, storing them in a vector<unsigned char>. To output the number, the program convert the vector<unsigned char> to unsigned short, unsigned int or unsigned long, according to the number of bytes and then convert to string.
The problem is: the program is storing/showing a value different to the inputed.
Here's the full code:
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
class Num
{
private:
vector<uchar> x;
ushort len;
template<typename T>
string str()
{
T val = 0;
for(ushort i = 0; i < len; i++)
{
val += x[i] * pow(256, i);
}
stringstream res;
res << val;
return res.str();
}
template<typename T>
void set(string a)
{
T val;
stringstream(a) >> val;
x.resize(0);
len = 0;
while(val > 255)
{
x.push_back((T)(val % 256));
len++;
val = (T)(val / 256);
}
len++;
for(ushort i = 0; i <= len / 2; i++)
{
uchar aux = x[i];
x[i] = x[len - 1 - i];
x[x.size() - 1 - i] = aux;
}
}
public:
Num()
{
x.resize(0);
len = 0;
}
Num(const Num& other)
{
*this = other;
}
friend bool operator>(const Num& l, const Num& r)
{
for(uchar i = l.len - 1; i >= 0; i--)
{
if(l.x[i] != r.x[i])
return (l.x[i] > r.x[i]);
}
}
friend bool operator<(const Num& l, const Num& r)
{
return r > l;
}
friend bool operator>=(const Num& l, const Num& r)
{
return !(l < r);
}
friend bool operator<=(const Num& l, const Num& r)
{
return !(l > r);
}
friend bool operator==(const Num& l, const Num& r)
{
return l >= r && l <= r;
}
friend bool operator!=(const Num& l, const Num& r)
{
return !(l == r);
}
Num& operator=(const string& l)
{
string a = l;
if(a.size() <= 4)
{
set<ushort>(a);
}
else if(a.size() <= 9)
{
set<uint>(a);
}
else
{
set<ulong>(a);
}
return *this;
}
Num& operator=(const char* l)
{
return (*this = string(l));
}
string get()
{
if(len == 0)
return "0";
if(len <= 2)
{
return str<ushort>();
}
else if(len <= 4)
{
return str<uint>();
}
else
{
return str<ulong>();
}
}
friend ostream& operator<<(ostream& os, Num& l)
{
return os << l.get();
}
friend istream& operator>>(istream& is, Num& l)
{
string x;
is >> x;
l = x;
return is;
}
};
int main()
{
Num x;
cout << "Entrada: ";
cin >> x;
cout << "Saida: "<< x << endl;
system("pause");
return 0;
}
The result can be:
Entrada: 572648319
Saida: 3136023423

Related

Big integer multiplication with Karatsuba crashes with Segementation Fault because of Stack Overflow

So I'm developing a class "bignum" to operate with integers of any size. The thing is I made two different functions to multiply bignums. One is the standard multiplication and the other one is based on the karatsuba algorithm. I've got a small program to run tests on my implementation so that I can tell whether its working or not. So far with the Standard multiplication everything runs perfectly, but when I switch to the Karatsuba multiplication once the inputs start to be very long my program crashes with Segmentation Fault because of a Stack Overflow. However, it seems not to be a matter of how big the entry is as there are inputs far bigger that are calculated correctly, though some of them do crash. I appreciate if anyone can take a look and give me some clue on how to continue. This is what valgrind tells me with one of the failing inputs:
Stack overflow in thread #1: can't grow stack to 0x1ffe801000
Here I'm posting the minimal reproducible example. I took out as much code as I could.
The main:
#include "bignum.h"
int main()
{
bignum result;
while(cin >> result)
cout << result << endl;
return 0;
}
The class bignum.cc:
#include "bignum.h"
bignum abs(const bignum &n)
{
bignum c = n;
c.sign = 0;
return c;
}
void remove_zeros(bignum &n)
{
if(n == 0)
n = 0;
else if(n.digits[0] == 0 && n.size > 1)
{
size_t zeros = 1;
while(n.digits[zeros] == 0)
zeros++;
n.size -= zeros;
short_t *aux = new short_t[n.size];
for(size_t i = 0; i < n.size; i++)
aux[i] = n.digits[i + zeros];
delete[] n.digits;
n.digits = new short_t[n.size];
for(size_t i = 0; i < n.size; i++)
n.digits[i] = aux[i];
delete[] aux;
}
}
bool size_even(const bignum &n)
{
if(n.size % 2 || n.size == 1)
return false;
return true;
}
bignum sum(const bignum &a, const bignum &b, const short_t &s)
{
size_t size = 0;
size_t aux_a = 0;
size_t aux_b = 0;
if(a.size >= b.size)
{
size = a.size + 1;
aux_a = a.size - b.size;
}
else
{
size = b.size + 1;
aux_b = b.size - a.size;
}
bignum c(size);
c.sign = s;
for(size_t i = c.size - 1; i < c.size; i--)
{
if(i - aux_b - 1 < a.size)
c.digits[i] += a.digits[i - aux_b - 1];
if(i - aux_a - 1 < b.size)
c.digits[i] += b.digits[i - aux_a - 1];
if(c.digits[i] > 9)
{
c.digits[i] -= 10;
c.digits[i - 1]++;
}
}
remove_zeros(c);
return c;
}
bignum subtraction(const bignum &a, const bignum &b)
{
short_t bigger = 0;
short_t count = 0;
size_t size = 0;
size_t diff = 0;
short aux = 0;
size = max(a.size, b.size);
diff = size - min(a.size, b.size);
bignum c(size);
if(abs(a) == abs(b))
return c = 0;
else if(abs(b) > abs(a))
bigger++;
if(bigger && b.sign && !a.sign)
c.sign = 1;
else if(!bigger && a.sign && !b.sign)
c.sign = 1;
else if(bigger && !b.sign && !a.sign)
c.sign = 1;
else if(!bigger && a.sign && b.sign)
c.sign = 1;
for(size_t i = size - 1; i < size; i--)
{
if(bigger)
{
if(i - diff < a.size)
aux = b.digits[i] - a.digits[i - diff];
else
aux = b.digits[i];
}
else
{
if(i - diff < b.size)
aux = a.digits[i] - b.digits[i - diff];
else
aux = a.digits[i];
}
if(count)
{
aux--;
count--;
}
if(aux < 0)
{
aux += 10;
count++;
}
c.digits[i] = aux;
}
remove_zeros(c);
if(c == 0)
c.sign = 0;
return c;
}
bignum reduce(const bignum &n, const size_t &from, const size_t &to)
{
if(to <= from)
{
bignum c = 0;
return c;
}
else
{
bignum c(to - from);
for(size_t i = 0; i < c.size; i++)
{
if(from + i < to)
c.digits[i] = n.digits[from + i];
}
// En caso de que haya agarrado solo ceros
if(c.digits[0] == 0 && c.size != 1)
{
for(size_t i = 0; i < c.size; i++)
if(c.digits[i] != 0)
return c;
return c = 0;
}
return c;
}
}
bignum enlarge(const bignum &n, const size_t &zeros)
{
bignum c(n.size + zeros);
if(!zeros)
c = n;
else
{
for(size_t i = 0; i < n.size; i++)
c.digits[i] = n.digits[i];
}
return c;
}
void add_zeros(bignum &n, const ssize_t &zeros)
{
if(zeros > 0)
{
short_t *aux = new short_t[n.size];
for(size_t i = 0; i < n.size; i++)
aux[i] = n.digits[i];
delete[] n.digits;
n.digits = new short_t[n.size += zeros];
for(size_t i = 0; i < n.size; i++)
{
if(i < n.size - zeros)
n.digits[i] = aux[i];
else
n.digits[i] = 0;
}
delete[] aux;
}
else if(zeros < 0)
{
short_t *aux = new short_t[n.size + zeros];
for(size_t i = 0; i < n.size + zeros; i++)
aux[i] = n.digits[i];
delete[] n.digits;
n.digits = new short_t[n.size += zeros];
for(size_t i = 0; i < n.size; i++)
n.digits[i] = aux[i];
delete[] aux;
}
}
bignum karatsuba(const bignum &a, const bignum &b)
{
bignum a_ = abs(a);
bignum b_ = abs(b);
bignum c;
// Casos base
if(a_ == 0 || b_ == 0)
return c = 0;
if(a_.size < 2 || b_.size < 2)
{
c = mult_rec(a_, b_);
if(a.sign != b.sign)
c.sign = 1;
return c;
}
size_t diff = max(a_.size, b_.size) - min(a_.size, b_.size);
if(!diff)
{
if(!size_even(a_.size) && !size_even(b_.size))
{
add_zeros(a_, 1);
add_zeros(b_, 1);
diff += 2;
}
}
else if(a_.size > b_.size)
{
if(!size_even(a_.size))
{
add_zeros(a_, 1);
add_zeros(b_, diff + 1);
diff += 2;
}
else
add_zeros(b_, diff);
}
else if(b_.size > a_.size)
{
if(!size_even(b_.size))
{
add_zeros(b_, 1);
add_zeros(a_, diff + 1);
diff += 2;
}
else
add_zeros(a_, diff);
}
size_t n = a_.size;
size_t m = n / 2;
bignum x = karatsuba(reduce(a_, 0, m), reduce(b_, 0, m));
bignum y = karatsuba(reduce(a_, m, a_.size), reduce(b_, m, b_.size));
bignum z = karatsuba(reduce(a_, 0, m) + reduce(a_, m, a_.size),
reduce(b_, 0, m) + reduce(b_, m, b_.size)) - x - y;
add_zeros(x, n);
add_zeros(z, m);
c = x + y + z;
if(diff)
add_zeros(c, -diff);
if(a.sign != b.sign)
c.sign = 1;
return c;
}
bignum mult_rec(const bignum &a, const bignum &b)
{
bignum c;
if(a == 0 || b == 0)
return c = 0;
if(a == 1)
return c = b;
if(b == 1)
return c = a;
return c = mult_rec(a, b - 1) + a;
}
bignum division(const bignum &a, const bignum &b, bignum &remainder)
{
bignum c;
if(a == 0 || b > a)
return c = 0;
bignum aux = a - b;
c = 1;
while(1)
{
aux = aux - b;
if(aux.sign)
{
remainder = aux + b;
break;
}
c = c + 1;
}
remove_zeros(c);
return c;
}
bignum division_rec(const bignum &a, const bignum &b)
{
bignum remainder = 0;
if(a.size < (b.size + 2))
return division(a, b, remainder);
return division_rec(reduce(a, b.size + 1, a.size) + (enlarge(remainder, a.size - b.size - 1)), b)
+ enlarge(division(reduce(a, 0, b.size + 1), b,remainder), a.size - b.size - 1);
}
bignum::bignum()
{
digits = NULL;
size = 0;
sign = 0;
}
bignum::bignum(const size_t &s)
{
if(s <= 0)
{
digits = NULL;
size = 0;
sign = 0;
}
digits = new short_t[s];
size = s;
sign = 0;
for (size_t i = 0; i < size; i++)
digits[i] = 0;
}
bignum::bignum(const string &str, short_t s = 0)
{
string aux;
size = str.size();
digits = new short_t[size];
for(size_t i = 0; i < size; i++)
{
aux = str[i];
digits[i] = (short_t)stoi(aux);
}
sign = s;
}
bignum::bignum(const bignum &n)
{
if(!n.digits)
{
digits = NULL;
size = 0;
sign = 0;
}
else
{
digits = new short_t[n.size];
size = n.size;
sign = n.sign;
for(size_t i = 0; i < size; i++)
digits[i] = n.digits[i];
}
}
bignum::bignum(const int &n)
{
if(n < 0)
sign = 1;
else
sign = 0;
string str = to_string(n);
string aux;
size = str.size()-sign;
digits = new short_t[size];
for(size_t i = 0; i < size; i++)
{
aux = str[i + sign];
digits[i] = (short_t)stoi(aux);
}
}
bignum& bignum::operator = (const bignum &right)
{
if(&right != this)
{
delete[] digits;
if(!right.digits)
{
digits = NULL;
size = 0;
sign = 0;
}
else
{
digits = new short_t[right.size];
size = right.size;
sign = right.sign;
for(size_t i = 0; i < size; i++)
digits[i] = right.digits[i];
}
}
return *this;
}
bignum& bignum::operator = (const int &right)
{
bignum aux(to_string(right));
return *this = aux;
}
bignum::~bignum() {delete[] digits;}
bignum operator + (const bignum &a, const bignum &b)
{
if(!a.sign && !b.sign)
return sum(a, b, 0);
if(!a.sign && b.sign)
return subtraction(a, b);
if(a.sign && !b.sign)
return subtraction(a, b);
return sum(a, b, 1);
}
bignum operator + (const bignum &a, const int &n)
{
return a + bignum(to_string(n));
}
bignum operator - (const bignum &a, const bignum &b)
{
if(!a.sign && !b.sign)
return subtraction(a, b);
if(!a.sign && b.sign)
return sum(a, b, 0);
if(a.sign && !b.sign)
return sum(a, b, 1);
return subtraction(a, b);
}
bignum operator - (const bignum &a, const int &n)
{
return a - bignum(to_string(n));
}
bignum operator * (const bignum &a, const bignum &b)
{
return karatsuba(a, b);
}
bignum operator / (const bignum &a, const bignum &b)
{
bignum c;
if(b == 0)
return c;
if(a == 0 || abs(b) > abs(a))
return c = 0;
if(abs(a) == abs(b))
{
if(a.sign != b.sign)
return c = -1;
return c = 1;
}
if(abs(b) == 1)
{
c = abs(a);
if(a.sign != b.sign)
c.sign = 1;
return c;
}
c = division_rec(abs(a), abs(b));
if(a.sign != b.sign)
c.sign = 1;
return c;
}
ostream& operator << (ostream &os, bignum &n)
{
if(n.digits == NULL)
return os;
if(n.sign && n != 0)
os << "-";
for (size_t i = 0; i < n.size; i++)
os << n.digits[i];
delete[] n.digits;
n.digits = NULL;
return os;
}
istream& operator >> (istream &is, bignum &result)
{
stack<char> operations;
queue<string> output;
string input;
getline(is, input);
if(input.empty())
return is;
for(size_t i = 0; i < input.size(); i++)
{
if(isblank(input[i])){}
else if(isdigit(input[i]))
{
size_t pos = i++;
size_t len = 1;
while(isdigit(input[i]))
{
len++;
i++;
}
i--;
output.push(input.substr(pos, len));
}
else if(input[i] == '-')
{
size_t j = i;
while(j != 0 && isblank(input[--j])){}
if(isdigit(input[j]) || input[j] == ')')
{
if(!operations.empty())
{
while(operations.top() == '-' || operations.top() == '+' || operations.top() == '*' || operations.top() == '/')
output.push(string{operations.pull()});
}
operations.push(input[i]);
}
else
output.push(string{"s"});
}
else if(input[i] == '+')
{
size_t j = i;
while(j != 0 && isblank(input[--j])){}
if(isdigit(input[j]) || input[j] == ')')
{
if(!operations.empty())
{
while(operations.top() == '-' || operations.top() == '+' || operations.top() == '*' || operations.top() == '/')
output.push(string{operations.pull()});
}
operations.push(input[i]);
}
}
else if(input[i] == '*' || input[i] == '/')
{
if(!operations.empty())
{
while(operations.top() == '*' || operations.top() == '/')
output.push(string{operations.pull()});
}
operations.push(input[i]);
}
else if(input[i] == '(')
operations.push(input[i]);
else if(input[i] == ')')
{
if(operations.empty())
{
cout << "Syntax Error" << endl;
return is;
}
while(!operations.empty() && operations.top() != '(')
output.push(string{operations.pull()});
if(!operations.empty())
operations.pull();
else
{
cout << "Syntax Error" << endl;
return is;
}
}
}
if(!operations.empty())
{
if(operations.top() == '(' && output.empty())
{
cout << "Syntax Error" << endl;
return is;
}
else
{
if(output.empty())
{
cout << "Syntax Error" << endl;
return is;
}
else
{
while(!operations.empty())
output.push(string{operations.pull()});
}
}
}
string aux;
short_t sign = 0;
stack<bignum> numbers;
while(!output.empty())
{
aux = output.pull();
if(isdigit(aux[0]))
{
numbers.push(bignum(aux, sign));
if(sign)
sign--;
}
else if(aux[0] == 's')
sign++;
else if(numbers.length() < 2)
{
cout << "Syntax Error" << endl;
return is;
}
else if(aux[0] == '+')
{
result = numbers.pull();
result = numbers.pull() + result;
numbers.push(result);
}
else if(aux[0] == '-')
{
result = numbers.pull();
result = numbers.pull() - result;
numbers.push(result);
}
else if(aux[0] == '*')
{
result = numbers.pull();
bignum auxiliar = numbers.pull();
//result = numbers.pull() * result;
result = auxiliar * result;
numbers.push(result);
}
else if(aux[0] == '/')
{
result = numbers.pull();
result = numbers.pull() / result;
numbers.push(result);
}
}
if(!numbers.empty())
result = numbers.pull();
else
{
cout << "Syntax Error" << endl;
return is;
}
return is;
}
bool operator == (const bignum &a, const bignum &b)
{
if(a.size != b.size)
{
for(size_t i = 0; i < a.size; i++)
{
if(a.digits[i] != 0)
return false;
}
for(size_t i = 0; i < b.size; i++)
{
if(b.digits[i] != 0)
return false;
}
return true;
}
if(a.sign != b.sign)
return false;
for (size_t i = 0; i < a.size; i++)
{
if (a.digits[i] != b.digits[i])
return false;
}
return true;
}
bool operator == (const bignum &a, const int &b)
{
bignum c(to_string(b));
if(a == c)
return true;
return false;
}
bool operator != (const bignum &a, const bignum &b)
{
if(a == b)
return false;
return true;
}
bool operator != (const bignum &a, const int &n)
{
bignum c(to_string(n));
if(a != c)
return true;
return false;
}
bool operator > (const bignum &a, const bignum &b)
{
if(a.size < b.size)
return false;
if(a.size > b.size)
return true;
if(!a.sign && b.sign)
return true;
if(a.sign && !b.sign)
return false;
if(a == b)
return false;
for (size_t i = 0; i < a.size; i++)
{
if (a.digits[i] > b.digits[i])
return true;
else if(a.digits[i] < b.digits[i])
return false;
}
return false;
}
bool operator < (const bignum &a, const bignum &b)
{
if(a > b)
return false;
if(a == b)
return false;
return true;
}
The bignum.h:
#include <iostream>
#include <cstring>
#include <string>
#include "queue.h"
#include "stack.h"
using namespace std;
class bignum
{
private:
short_t *digits;
short_t sign;
size_t size;
friend bignum abs(const bignum &);
friend void remove_zeros(bignum &);
friend void add_zeros(bignum &, const ssize_t &);
friend bool size_even(const bignum &);
friend bignum reduce(const bignum &, const size_t &, const size_t &);
friend bignum enlarge(const bignum &, const size_t &);
friend bignum sum(const bignum &, const bignum &, const short_t &);
friend bignum subtraction(const bignum &, const bignum &);
friend bignum karatsuba(const bignum &, const bignum &);
friend bignum mult_rec(const bignum &, const bignum &);
friend bignum division(const bignum &, const bignum &, bignum &);
friend bignum division_rec(const bignum &, const bignum &);
public:
bignum();
bignum(const size_t &);
bignum(const string &, short_t);
bignum(const bignum &);
bignum(const int &);
bignum& operator = (const bignum &);
bignum& operator = (const int &);
~bignum();
friend bignum operator+(const bignum &, const bignum &);
friend bignum operator+(const bignum &, const int &);
friend bignum operator-(const bignum &, const bignum &);
friend bignum operator-(const bignum &, const int &);
friend bignum operator*(const bignum &, const bignum &);
friend bignum operator/(const bignum &, const bignum &);
friend ostream& operator<<(ostream &, bignum &);
friend istream& operator>>(istream &, bignum &);
friend bool operator==(const bignum &, const bignum &);
friend bool operator==(const bignum &, const int &);
friend bool operator!=(const bignum &, const bignum &);
friend bool operator!=(const bignum &, const int &);
friend bool operator<(const bignum &, const bignum &);
friend bool operator>(const bignum &, const bignum &);
};
The makefile:
all: calc
calc: mre.o bignum.o
g++ -std=c++11 -Wall -pedantic -g3 mre.o bignum.o -o calc
mre.o: mre.cc bignum.h
g++ -std=c++11 -Wall -pedantic -g3 -c mre.cc
bignum.o: bignum.cc bignum.h stack.h queue.h debug.h
g++ -std=c++11 -Wall -pedantic -g3 -c bignum.cc
clean:
$(RM) calc *.o
Some other librarires I used, queue.h:
#ifndef _QUEUE_H_
#define _QUEUE_H_
#include <cstdlib>
#include <iostream>
#include "debug.h"
#include "stack.h"
using namespace std;
typedef unsigned short short_t;
template <typename T>
class queue
{
public:
queue();
queue(const queue &);
queue &operator=(const queue &);
~queue();
T pull();
void pull(T &);
void push(const T &);
bool empty() const;
size_t length() const;
private:
stack<T> egress_;
stack<T> ingress_;
};
template <typename T>
queue<T>::queue() {}
template<typename T>
queue<T>::queue(const queue &q)
: egress_(q.egress_),
ingress_(q.ingress_)
{
}
template<typename T>
queue<T> &queue<T>::operator=(const queue<T> &rhs)
{
if (this != &rhs) {
egress_ = rhs.egress_;
ingress_ = rhs.ingress_;
}
return *this;
}
template<typename T>
queue<T>::~queue(){}
template<typename T>
T queue<T>::pull()
{
if (egress_.empty()) {
while (ingress_.empty() == false)
egress_.push(ingress_.pull());
}
return egress_.pull();
}
template<typename T>
void queue<T>::pull(T &top)
{
return this->pull();
}
template<typename T>
void queue<T>::push(const T &item)
{
ingress_.push(item);
}
template<typename T>
bool queue<T>::empty() const
{
return egress_.empty() && ingress_.empty() ? true : false;
}
template<typename T>
size_t queue<T>::length() const
{
return egress_.length() + ingress_.length();
}
#endif
stack.h:
#ifndef _STACK_H_
#define _STACK_H_
#include <iostream>
#include <cstdlib>
#include "debug.h"
using namespace std;
template <typename T>
class stack
{
public:
stack();
stack(size_t);
stack(const stack &);
stack &operator=(const stack &);
~stack();
T pull();
T top();
void pull(T &);
void push(const T &);
bool empty() const;
size_t length() const;
private:
void expand();
void contract();
size_t tos_;
size_t len_;
T *ptr_;
};
template<typename T>
stack<T>::stack()
: tos_(0),
len_(0),
ptr_(0)
{
}
template<typename T>
stack<T>::stack(size_t len)
: tos_(0),
len_(0),
ptr_(0)
{
ptr_ = new T[len_ = len];
}
template<typename T>
stack<T>::stack(const stack &st)
: tos_(0),
len_(0),
ptr_(0)
{
ptr_ = new T[len_ = st.tos_];
for (tos_ = 0; tos_ < st.tos_; ++tos_)
ptr_[tos_] = st.ptr_[tos_];
ASSERT(tos_ <= len_);
ASSERT(tos_ == st.tos_);
}
template<typename T>
stack<T> & stack<T>::operator=(const stack<T> &rhs)
{
if (this != &rhs) {
if (rhs.tos_ > len_) {
delete[] ptr_, len_ = 0;
ptr_ = new T[len_ = rhs.tos_];
}
for (tos_ = 0; tos_ < rhs.tos_; ++tos_)
ptr_[tos_] = rhs.ptr_[tos_];
}
ASSERT(tos_ <= len_);
ASSERT(tos_ == rhs.tos_);
return *this;
}
template<typename T>
stack<T>::~stack()
{
delete[] ptr_;
}
template<typename T>
T stack<T>::pull()
{
ASSERT(tos_ != 0);
ASSERT(tos_ <= len_);
ASSERT(ptr_ != NULL);
return ptr_[--tos_];
}
template<typename T>
void stack<T>::pull(T &top)
{
top = this->pull();
}
template<typename T>
T stack<T>::top()
{
if(tos_ > 0)
return ptr_[tos_ -1];
return 0;
}
template<typename T>
void stack<T>::push(const T &top)
{
if (tos_ >= len_)
expand();
ptr_[tos_++] = top;
}
template<typename T>
bool stack<T>::empty() const
{
return tos_ == 0 ? true : false;
}
template<typename T>
size_t stack<T>::length() const
{
return tos_;
}
template<typename T>
void stack<T>::expand()
{
size_t len;
size_t tos;
T *ptr = 0;
if (len_ != 0)
len = len_ << 1;
else
len = 1;
ptr = new T[len];
for (tos = 0; tos < tos_; ++tos)
ptr[tos] = ptr_[tos];
delete[] ptr_;
tos_ = tos;
len_ = len;
ptr_ = ptr;
ASSERT(tos_ < len_);
ASSERT(ptr_ != NULL);
}
template<typename T>
void stack<T>::contract()
{
std::abort();
}
#endif
debug.h:
#ifndef _DEBUG_H_
#define _DEBUG_H_
#ifdef DEBUG
#include <cstdlib>
#include <iostream>
#define ASSERT(expr) \
do { \
if (!(expr)) { \
std::cerr << "assertion " \
<< (#expr) \
<< " failed :-\\ {" \
<< __FUNCTION__ \
<< "() " \
<< __FILE__ \
<< ":" \
<< __LINE__ \
<< "}" \
<< std::endl; \
std::abort(); \
} \
} while (0)
#else
#define ASSERT(expr) do {} while (0)
#endif
#endif
Last but not least, the input that breaks the program:
((((4)-(5)(((((3+9-(4)(-1))-((4)-1-(-4)0))-((6+5(0)+(-5))((-4)-(-7)(-7)(-8))))+((((8)(0)(0)+3)+((-3)+68+(6)))-0+(-3)))((1(-8)(-6)-(-6))((((-2)(-4)-2(-5))+(-2)(4))-(((3)-(5)-(-4)+(-1))(2)+(-5))))))((((6)-(4)(3)-(9))+(((((-4)(-2)0-(-6))1+(-7))-(1+(-3)(-7)(-9)))-((((-3)-8+1-(-8))(0+(8)+(0)+(-4)))1+7)))+1(3)))((-3)+(4)((((3+0+(-3)+(-1))(((-1)(-2)+((0)-(-3)+(8)+(-7)))+(((-3)+(3)+(6)-8)+(1)(6))))-(-4)8)(((8)-(-8)(((0)+(-9)+((3)+(0)(9)(-1)))-((4-(-9)02)-((-6)(-8)-(-7)(4)))))-(((((6)+7+(-3)5)((9)+(1)-3*(5)))-(((-2)-(-1)-4-0)+((8)-6-(-3)(-3))))+0-(5))))))-(((((((((8)(7)-(2)-(-9))+((9)(-8)(4)-0))-(((5)+(4)(4)+(3))((8)(-1)+6+8)))-((((-1)-(-9)+(9)(0))-(0-(-2)+(-2)+(-3)))+(0)0))+(-7)+(2))(((1-(-4)-(((2)-(-7)-(-9)(-3))-(-7)(4)))+(((5+(4)-1+(-2))+((4)-(-7)+(-6)-5))-((-2)+6+(0)+(-4))))+((((8+(-5)-(1)+(0))-((4)+(-2)(-6)-0))((-9)(6)-((-4)3+(-7)+0)))+((((-8)+(-9)-(-5)0)((-7)(5)-(2)-(-5)))-4+(-6)))))+((-9)+(-8)+(2)(-4)))-((((((-2)-(0)+(-1)(-4))((((-1)(7)-1(-1))+(-3)(4))(8)-5))-((-7)(-9)-(((5(2)(-4)-2)(2*(-8)(0)-8))+(((5)+(-3)(-4)(-9))((-2)-(-2)-2+(-9))))))+7+(4))+((-9)+5-(3+0+(((((-1)+(-2)(8)(-9))-((-5)-(-4)-(-3)-3))(((-7)+(-1)+(-3)+(-3))0(3)))-((((0)(7)-(8)-(0))(6+(-9)-0+(4)))-(5)(6)))))))

Repeating words in string class

So I have to write a string class, and I need help with reading from a file into a vector of string classes I've created. It somewhat works, as it reads from the file but it repeats the the word read in a few times depending on which word it's on.
// .h
/*Class description:
A string class. Various functions for the class.
String is passed into objects of the class. Reads
and writes to files.*/
#ifndef MYString12_H
#define MYString12_H
#include <fstream>
using namespace std;
class MYString12
{
public:
MYString12();
MYString12(const MYString12 & mstr);
MYString12(const char* ptr);
~MYString12();
MYString12& operator = (const MYString12& argStr);
friend MYString12 operator + (const MYString12& str1, const MYString12& str2);
char operator [] (int index);
bool operator > (const MYString12& argStr2);
bool operator < (const MYString12& argStr2);
bool operator == (const MYString12& argStr);
friend istream& operator >> (istream& istr, MYString12& argStr);
friend ostream& operator << (ostream& istr, MYString12& argStr);
int length() const;
int capacity()const;
char at(int index);
const char* c_str()const;
static int getCurrentCount();
static int getCreatedCount();
private:
char* str;
int cap = 20;
int end;
const int compareTo(const MYString12& argStr);
static int currentCount;
static int createdCount;
};
#endif
Here is class cpp file
// MYString12.cpp
#include "stdafx.h"
#include "MYString12.h"
#include <iostream>
#include <iomanip>
#include <math.h>
#include <cstdlib>
using namespace std;
int MYString12::createdCount = 0;
int MYString12::currentCount = 0;
// default constructor
MYString12::MYString12()
{
cap = 20;
end = 0;
str = new char[cap];
str[end] = '\0';
createdCount++;
currentCount++;
}
// copy constructor
MYString12::MYString12(const MYString12& mstr)
{
this->end = mstr.end;
this->cap = mstr.cap;
this->str = new char[mstr.cap];
while (end >= cap) {
cap += 20;
}
for (int i = 0; i < end; i++) {
str[i] = mstr.str[i];
}
//mstr.str[end] = '\0';
createdCount++;
currentCount++;
}
// constructor with string passed in
MYString12::MYString12(const char* ptr)
{
int i = 0;
while (ptr[i] != '\0') {
end++;
i++;
}
while (end >= cap) {
cap += 20;
}
str = new char[cap];
for (int j = 0; j < end; j++) {
str[j] = ptr[j];
}
createdCount++;
currentCount++;
}
// destructor
MYString12::~MYString12()
{
delete[] str;
currentCount--;
}
// overloaded assignment operator
GAString12& GAString12::operator = (const GAString12& mstr)
{
if (this == &mstr) {
return *this;
}
this->end = mstr.end;
this->cap = mstr.cap;
while (end >= cap) {
cap += 20;
}
for (int i = 0; i < end; i++) {
str[i] = mstr.str[i];
}
//mstr.str[end] = '\0';
return *this;
}
// overloaded concatanation operator
MYString12 operator + (const MYString12& str1, const MYString12& str2)
{
int temp = str1.end + str2.end + 1;
char tempArray[200];
int i = 0;
int j = 0;
while (i < temp)
{
if (i < str1.end)
{
tempArray[i] = str1.str[i];
i++;
} else {
tempArray[i] = str2.str[j];
i++;
j++;
}
}
tempArray[i] = '\0';
MYString12 concatenatedObj(tempArray);
return concatenatedObj;
}
// overloaded index operator
char MYString12::operator [] (int index)
{
return str[index];
}
// overloaded greater than operator
bool MYString12::operator > (const MYString12& argStr)
{
if ((*this).compareTo(argStr) > 0)
{
return true;
}
else {
return false;
}
}
// overloaded less than operator
bool MYString12::operator < (const MYString12& argStr)
{
if ((*this).compareTo(argStr) < 0)
{
return true;
}
else {
return false;
}
}
// overloaded equals equals operator
bool MYString12::operator == (const MYString12& argStr)
{
if ((*this).compareTo(argStr) == 0)
{
return true;
}
else {
return false;
}
}
// compares ascii values of objStr and argStr
const int MYString12::compareTo(const MYString12& argStr)
{
int asciiSubtraction = 0;
int limit = 0;
if (end <= argStr.end)
{
limit = end;
}
else {
limit = argStr.end;
}
int i = 0;
while (i <= limit && (str[i] == argStr.str[i])) {
i++;
}
asciiSubtraction = str[i] - argStr.str[i];
return asciiSubtraction;
}
// overloaded extraction operator
istream& operator >> (istream& istr, MYString12& argStr)
{
char temp[100];
istr >> temp;
argStr = GAString12(temp);
return istr;
}
// overloaded insertion operator
ostream& operator << (ostream& ostr, MYString12& argStr)
{
int i = 0;
while (argStr.str[i] != '\0')
{
ostr << argStr.str;
i++;
}
return ostr;
}
// returns size of passed in string
int MYString12::length() const
{
return end;
}
// returns size of memory allocated
int MYString12::capacity() const
{
return cap;
}
// returns a char of string at passed index
char MYString12::at(int index)
{
if (index < 0 || index > end) {
return '\0';
}
else {
return str[index];
}
}
// returns passed in string as c string
const char* MYString12::c_str() const
{
createdCount++;
currentCount++;
return str;
}
// returns the amount of alive instances of class
int MYString12::getCurrentCount()
{
return currentCount;
}
// returns the amount of overall created instances of class
int MYString12::getCreatedCount()
{
return createdCount;
}
And here is main
// main
int main()
{
vector<MYString12> word(100);
ifstream fin;
fin.open("infile3.txt");
if (fin.fail()) {
cout << "Error." << endl;
exit(1);
}
int wordCount = 0;
while (fin >> word[wordCount]) {
cout << word[wordCount];
system("pause");
wordCount++;
}
word.resize(wordCount);
fin.close();endl;
return 0;
}
It doesn't print out to the console any of the words. Nothing is printed. Why doesn't it print?

Why it's not possible to assign std::string to a subtring?

This is the code for my project which I want to compile. The error is stated at the end of the question.
#include <iostream>
#include <string>
#include <stdio.h>
class substring {
friend std::ostream& operator<<(std::ostream& output, substring const& sub);
public:
char *str;
int length;
substring();
~substring();
substring(std::string);
substring(const substring &);
substring& operator=(substring const& other);
substring& operator=(std::string const& strz);
substring& operator+=(substring const& other);
bool operator>(substring const& other) const;
bool operator<(substring const& other) const;
char& operator[](size_t idx);
char operator[](size_t idx) const;
};
std::ostream& operator<<(std::ostream& output, substring const& sub);
std::istream& operator >> (std::istream& input, substring const& sub);
bool operator==(substring const& one, substring const& another);
bool operator!=(substring const& one, substring const& another);
bool operator==(std::string const& str, substring const& sub);
bool operator==(substring const& sub, std::string const& str);
bool operator!=(std::string const& str, substring const& sub);
bool operator!=(substring const& sub, std::string const& str);
substring::substring()
{
length = 0;
}
substring::~substring()
{
delete str;
}
substring::substring(std::string)
{
}
substring::substring(const substring & sub)
{
str = new char[length];
}
std::ostream & operator<<(std::ostream & output, substring const & sub)
{
output << sub;
return output;
}
std::istream & operator >> (std::istream & input, substring const & sub)
{
std::cout << "Enter sub:";
input >> sub;
return input;
}
bool operator==(substring const & one, substring const & another)
{
if (one.length != another.length)
return false;
else
{
for (int i = 0; i < another.length; i++)
if (one[i] != another[i])
{
return false;
break;
}
}
return true;
}
bool operator!=(substring const & one, substring const & another)
{
if (one.length != another.length)
return true;
else
{
for (int i = 0; i < another.length; i++)
if (one[i] != another[i])
{
return true;
break;
}
}
return false;
}
bool operator==(std::string const & str, substring const & sub)
{
if (sub.length != str.length())
return false;
else
{
for (int i = 0; i < sub.length; i++)
if (str[i] != sub[i])
{
return false;
break;
}
}
return true;
}
bool operator==(substring const & sub, std::string const & str)
{
if (str.length() != sub.length)
return false;
else
{
for (unsigned int i = 0; i < str.length(); i++)
if (sub[i] != str[i])
{
return false;
break;
}
}
return true;
}
bool operator!=(std::string const & str, substring const & sub)
{
if (sub.length != str.length())
return true;
else
{
for (int i = 0; i < sub.length; i++)
if (str[i] != sub[i])
{
return true;
break;
}
}
return false;
}
bool operator!=(substring const & sub, std::string const & str)
{
if (sub.length != str.length())
return true;
else
{
for (int i = 0; i < sub.length; i++)
if (str[i] != sub[i])
{
return true;
break;
}
}
return false;
}
substring & substring::operator=(substring const & other)
{
delete str;
length = other.length;
str = new char[length];
for (int i = 0; i<length; i++)
{
str[i] = other.str[i];
}
return *this;
}
substring & substring::operator=(std::string const & strz)
{
length = strz.length();
str = new char[length];
for (int i = 0; i<length; i++)
{
str[i] = strz[i];
}
return *this;
}
substring & substring::operator+=(substring const & other)
{
char* new_str = new char[length + other.length];
for (int i = 0; i<length; i++)
{
new_str[i] = str[i];
}
for (int i = length; i<other.length; i++)
{
new_str[i] = other.str[i];
}
delete str;
str = new_str;
return *this;
}
bool substring::operator>(substring const & other) const
{
return true;
}
bool substring::operator<(substring const & other) const
{
return true;
}
char & substring::operator[](size_t idx)
{
return str[idx];
}
char substring::operator[](size_t idx) const
{
return str[idx];
}
int main()
{
std::string str = "abc";
substring sub = str;
std::cout << sub;
return 0;
}
The problem is that when I run this code, it seems that the compiler just skips this: substring sub = str;.
I cannot even change this line to substring sub = "aaa"; because it shows an error which says I cannot convert subtring to std::string (although there is an operation overloading for this in the code).
The problem is that when I run this code, it seems that the compiler just skips this: substring sub = str;
The compiler did not "skip it". It compiled succesfully, and the new object was created succesfully. However, the converting constructor that you defined leaves the objects members default initialized:
substring::substring(std::string)
{
}
I cannot even change this line to substring sub = "aaa"; because it shows an error which says I cannot convert subtring to std::string
I highly doubt that. I suspect that you misread.
My compiler says that const char [4] cannot be converted substring
(although there is an operation overloading for this in the code).
There certainly isn't a substring::substring(const char(&)[4]) (nor substring::substring(const char*)).

segmentation fault scrabble game

im working on a little scrabblegame which i read a txtfile and create a hashtable for all words inside. Word is a specific class which contains a vector of .
i want to create a hashmap by my own and define the length of my "Dictionary" is 50000. im using a nullpointer to reserve all index of my array. If i want to print to my hashtable, compiler tells me a segmentation fault. does any one seems the error?
the headerfile:
class Dictionary {
public:
Dictionary();
Dictionary(string filepath);
friend std::ostream& operator<<(std::ostream& os, const Dictionary& obj);
bool find(const Word& word);
vector<Word> allPossibleWords(const vector<Character>& tiles);
// struct compare {
//
// bool operator()(const Word& a, const Word& b) {
// return a.operator<(b);
// }
// } myCompare;
vector<Word> m_allWords;
vector<Word>::iterator itVecWords;
static const int table_size = 500000;
// std::array <Word*, table_size> arrWords = {nullptr};
Word* arrWords[table_size] = {nullptr};
int hash(Word new_word);
void addItem(Word word);
void printHashTable();
the cpp:
Dictionary::Dictionary(string filepath) {
ifstream datei(filepath.c_str());
while (datei.good() && !datei.eof()) {
string temp;
string temp1;
string::size_type pos;
getline(datei, temp);
pos = temp.find(" ");
temp1 = temp.substr(0, pos);
Word new_word(temp1);
addItem(new_word);
}
datei.close();
}
std::ostream& operator<<(std::ostream& os, const Dictionary& obj) {
for (int i = 0; i < obj.m_allWords.size(); i++) {
os << obj.m_allWords[i] << endl;
}
return os;
}
bool Dictionary::find(const Word& word) const {
if (std::binary_search(m_allWords.begin(), m_allWords.end(), word)) {
return true;
}
return false;
}
vector<Word> Dictionary::allPossibleWords(const vector<Character>& tiles) const {
vector<Word> ergebnis;
string tmp;
int cnt = 0;
for (int i = 0; i < tiles.size(); i++) {
tmp += tiles[i].GetC();
}
sort(tmp.begin(), tmp.end());
for (int i = 1; i <= tiles.size(); i++) {
do {
string piece = tmp.substr(0, i);
do {
Word search = Word(piece);
//Überschreibt immer der in Ergebnis existierte Wert
if (find(search) && std::find(ergebnis.begin(), ergebnis.end(), search) == ergebnis.end()) {
ergebnis.push_back(search);
}
} while (next_permutation(piece.begin(), piece.end()));
} while (next_permutation(tmp.begin(), tmp.end()));
}
return ergebnis;
}
int Dictionary::hash(Word new_word) {
int index = 0;
for (auto u : new_word.new_Character) {
index += (int) u.GetC();
}
index = index * (int) new_word.new_Character.at(0).GetC();
index = index * (int) new_word.new_Character.at(new_word.new_Character.size() - 1).GetC();
return index % table_size;
}
void Dictionary::addItem(Word word) {
int index = hash(word);
if (arrWords[index] == nullptr) {
arrWords[index] = new Word(word);
} else {
Word* ptr = arrWords[index];
Word* neu = new Word(word);
while (ptr->getNextWord() != nullptr) {
ptr = ptr->getNextWord();
}
ptr->setNextWord(neu);
}
}
void Dictionary::printHashTable() {
Word* tmp;
for (int i = 0; i < table_size; i++) {
tmp = arrWords[i];
if (tmp != nullptr) {
tmp->printWord();
cout << "Index : " << i;
}
tmp = tmp->getNextWord();
}
}
class Word {
public:
Word();
Word(string m_wort);
int length() const;
int points() const;
friend std::ostream& operator<<(std::ostream& os, const Word& obj);
bool operator==(const Word& right) const; /
bool operator!=(const Word& right) const;
bool contains(const Character& c) const;
Word substr(int start, int end) const;
bool operator<(const Word& right) const;
vector <Character> new_Character;
Word* Next = nullptr;
void setNextWord(Word*);
Word* getNextWord();
void printWord();
string getWordAsString();
CPP File:
void Word::setNextWord(Word* w) {
Next = w;
}
Word* Word::getNextWord() {
return Next;
}
void Word::printWord() {
string s = "";
for (int i = 0; i < new_Character.size(); i++) {
s += new_Character.at(i).GetC();
}
cout << s << endl;
}
string Word::getWordAsString() {
string s;
for (int i = 0; i < new_Character.size(); i++) {
s += new_Character.at(i).GetC();
}
return s;
}

Don't understand a seg fault

String is my own string class and Stack is my own stack class.
I am trying to change infix to postfix with values that are separated by spaces.
The function below pretty much works but also returns a "Segmentation fault (core dumped)".
String postfix(String infix){
std::vector<String> vec;
vec = infix.split(' ');
Stack<String> tmp;
String right, left, op;
int i = 0;
while (vec[i] != ';'){
if (vec[i] == ')'){
right = tmp.pop();
op = tmp.pop();
left = tmp.pop();
tmp.push(left + ' ' + right + ' ' + op);
}else{
if (vec[i] != '(' && vec[i] != ' ')
tmp.push(vec[i]);
}
++i;
}
String postfix = tmp.pop();
return postfix;
}
I do not understand why this is. Any help would be appreciated.
#ifndef STACK_HPP
#define STACK_HPP
template <typename T>
class Node{
public:
T data;
Node<T>* next;
Node() { data().next(0); } ;
Node (const T& x) : data (x), next(0) {};
};
template <typename T>
class Stack{
public:
Stack() : tos(0){};
~Stack();
Stack(const Stack<T>&);
void swap(Stack<T>& rhs);
Stack<T>& operator= (Stack<T> rhs) { swap(rhs); return *this; };
bool isEmpty() const { return tos == 0; };
T pop();
void push(const T&);
private:
Node<T> *tos;
};
///////////////////////////////////////////////////////////////
template <typename T>
Stack<T>::~Stack(){
while(tos != 0){
Node<T> *tmp = tos;
tos = tos -> next;
delete tmp;
}
}
template <typename T>
void Stack<T>::swap(Stack<T>& rhs){
Node<T> *tmp = tos;
tos = rhs.tos;
rhs.tos = tmp;
}
template <typename T>
Stack<T>::Stack(const Stack<T>& actual){
Node<T> *tmp = actual.tos, *bottom = 0;
tos = 0;
while (tmp != 0){
if(tos == 0){
tos = new Node<T>(tmp -> data);
bottom = tos;
}else{
bottom -> next = new Node<T>(tmp -> data);
bottom = bottom -> next;
}
tmp = tmp -> next;
}
}
template<typename T>
T Stack<T>::pop(){
T result = tos -> data;
Node<T> *tmp = tos;
tos = tos -> next;
delete tmp;
return result;
}
template <typename T>
void Stack<T>::push(const T& x){
Node<T> *tmp = new Node<T> (x);
tmp -> next = tos;
tos = tmp;
}
#endif
//bruce pucci
//string
//cs23001
#include <iostream>
#include <cassert>
#include <vector>
#include <fstream>
#include "string.hpp"
///////////////////////////////string class friend functions////////////////////////
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////I/O/////////////////////////////////////////////
std::ostream& operator<<(std::ostream& out, const String& print){//std::cout operator
int i = 0;
while (print.arr[i] > 0){
out << print.arr[i];
++i;
}
return out;
}
std::ifstream& operator>>(std::ifstream& in, String& rhs){//ifstream operator.
char tmp[stringSize];//grabs word by word (chars serperated by whitespace).
in >> tmp;
rhs = String(tmp);
return in;
}
////////////////////////////////string class public functions///////////////////////
////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////constructors///////////////////////////////////////
String::String(){//default constructor. default size
arr = new char[stringSize];
cap = stringSize;
arr[0] = 0;
}
String::String(const char a){//char constructor. default size
arr = new char[stringSize];
cap = stringSize;
arr[0] = a;
arr[1] = 0;
}
String::String(const char a[]){//char array constructor. default size
arr = new char[stringSize];
cap = stringSize;
int i = 0;
while (a[i] > 0){
arr[i] = a[i];
++i;
}
arr[i] = 0;
}
String::String(const int initSize, const char a[]){//char array constructor. size passed as a parameter
arr = new char[initSize];
cap = initSize;
int i = 0;
while (a[i] > 0){
arr[i] = a[i];
++i;
}
arr[i] = 0;
}
String::String(int initSize){//like default constructor. size passed as parameter
arr = new char[initSize];
cap = initSize;
}
//////////////////////////////////dynamic stuff/////////////////////////////////////////////////
String::String(const String& rhs){//big three. copy constructor
arr = new char[rhs.cap];
cap = rhs.cap;
for (int i = 0; i < cap; ++i)
arr[i] = rhs.arr[i];
}
String::~String(){//big three. destuctor.
delete [] arr;
}
String& String::operator=(String rhs){//big three. assignment operator.
swap(rhs);
return *this;
}
String String::swap(String& rhs){//swap the pointers on 2 char arrays.
int tmpCap = rhs.cap;
rhs.cap = cap;
cap = tmpCap;
char* tmp = rhs.arr;
rhs.arr = arr;
arr = tmp;
return *this;
}
///////////////////////////////////functions////////////////////////////////////////////////////////////////
void String::reallocate(int a){//changes the size of a dynamic String. size passed as parameter.
String tmp;
tmp.cap = a;
tmp.arr = new char[a];//allocate space of size passed.
int i = 0;
while (arr[i] != 0){//copy elements to newly allocated tmp array
tmp.arr[i] = arr[i];
++i;
}
tmp.arr[i] = 0;
swap(tmp);//swap pointers of tmp and passed array
}
std::vector<String> String::split(char splitter) const{//splits a String into a vecotr of
std::vector<String> vecOfStrings;//Strings besed on the delimited passed
int start = 0, end = 0;//returns that vector
bool doIt = false;
for (int i = 0; i < cap; ++i){//look if the delimiter exists
if (arr[i] == ' '){
doIt = true;
break;
}
}
if (doIt){//if the delimiter exists in the string start looping
for (int i = 0; i < cap; ++i){
if (arr[i] == splitter){//when each occurance of the delimiter is found create a
end = i;//node of String in the vector with the chars since the previous node
vecOfStrings.push_back(substr(start, end - 1));
start = (end + 1);
}
if (i == (cap - 1)){//do this until the no more delimiters are found
end = i;
vecOfStrings.push_back(substr(start, end));
}
}
}
return vecOfStrings;
}
int String::length() const{//returns the length of the String before the terminating char.
int counter = 0;
while (arr[counter] != 0)
++counter;
return counter;
}
int String::capacity() const{//accessor to capacity.
return cap;
}
String String::substr(int start, int end) const{//returns a subset string of string passed.
if ((start < 0) || (end < 0))//parameters are starting and ending points of the substring
return String();
String result;
int returnIndex = start;
for (int i = start; i <= end; ++i)
result[i - start] = arr[returnIndex++];
result[end - start + 1] = 0;
return result;
}
int String::findChar(const char target) const{//returns the position of the first occurance of the char
for (int i = 0; i < length(); ++i)//being searched for. returns -1 if the char is not found.
if (arr[i] == target)
return i;
std::cout << "The char was not found." << std::endl;
return -1;
}
int String::findStr(const char target[]) const{//searches for a substring in the string. returns the
String targetString(target);//position of the first char in the substring
return findStr(targetString);//uses the String version of findStr. look there for more info.
}
int String::findStr(const String& target) const{//searches for a substring in the string. returns the
int targetLength = target.length();//position of the first char in the substring
String candidate;//candidate is the string that
int candStart = 0, candEnd = candStart + (targetLength - 1), i = 0;//will be compared to other strings
//of the same length
while (i < (stringSize - targetLength)){//go through char by char and compare candidate to
candidate = substr(candStart++, candEnd++);//strings of the same length within the full string.
if (candidate == target)//ex String = "Hello World." looking for "llo"
return i;//"Hel" == "llo" no "Hel" == "ell" no "llo == "llo" yes.
i++;//return 2.
}
std::cout << "The string was not found." << std::endl;
return -1;//if not found at all return -1
}
int String::stringToInt(){
int result = 0, intTmp;
char charTmp;
for (int i = 0; i < length(); ++i){
charTmp = arr[i];
switch (charTmp){
case '0' : intTmp = 0; break;
case '1' : intTmp = 1; break;
case '2' : intTmp = 2; break;
case '3' : intTmp = 3; break;
case '4' : intTmp = 4; break;
case '5' : intTmp = 5; break;
case '6' : intTmp = 6; break;
case '7' : intTmp = 7; break;
case '8' : intTmp = 8; break;
case '9' : intTmp = 9; break;
case '-' : intTmp = 0; break;
}
if (result > 0)
result = result * 10;
result = result + intTmp;
}
return result;
}
/////////////////////////////////////////////operators////////////////////////////////////////////////////////////////////
char String::operator[](int i) const{//subscript operator. returns char whated in char array. const version.
return arr[i];//acts as an accessor to chars
}
char& String::operator[](int i){//subscript operator. returns char whated in char array. non const version.
return arr[i];//acts as an accessor to chars
}
String String::operator+(const String& rhs) const{//concatenate
String result(arr);
int start = length(), rhsIndex = 0;
while (rhs.arr[rhsIndex] != 0){
result.arr[start] = rhs.arr[rhsIndex];
start++;
rhsIndex++;
}
result.arr[start] = 0;
return result;
}
bool String::operator==(const String& rhs) const{
if (length() != rhs.length())
return false;
for (int i = 0; i < length(); ++i)
if (arr[i] != rhs.arr[i])
return false;
return true;
}
bool String::operator!=(const String& rhs) const{
if (*this == rhs)
return false;
return true;
}
bool String::operator<(const String& rhs) const{
int i = 0;
while (arr[i] != 0 && rhs.arr[i] != 0){
if ((arr[i] - rhs.arr[i]) < 0)
return true;
else if ((arr[i] - rhs.arr[i]) > 0)
return false;
i++;
}
if (length() < rhs.length())
return true;
return false;
}
bool String::operator>(const String& rhs) const{
if (*this == rhs)
return false;
if (*this < rhs)
return false;
return true;
}
bool String::operator<=(const String& rhs) const{
if (*this == rhs)
return true;
if (*this < rhs)
return true;
return false;
}
bool String::operator>=(const String& rhs) const{
if (*this == rhs)
return true;
if (*this < rhs)
return false;
return true;
}
//////////////////////////////free functions////////////////////////////////
////////////////////////////////////////////////////////////////////////////
///////////////they use the public functions of the String class////////////
String operator+(const char lhs[], const String& rhs){
String lhsString(lhs);
String result = lhsString + rhs;
return result;
}
String operator+(const char lhs, const String& rhs){
String lhsString(lhs);
String result = lhsString + rhs;
return result;
}
bool operator==(const char lhs[], const String& rhs){
String lhsString(lhs);
return lhsString == rhs;
}
bool operator==(const char lhs, const String& rhs){
String lhsString(lhs);
return lhsString == rhs;
}
bool operator!=(const char lhs[], const String& rhs){
String lhsString(lhs);
return lhsString != rhs;
}
bool operator!=(const char lhs, const String& rhs){
String lhsString(lhs);
return lhsString != rhs;
}
bool operator<(const char lhs[], const String& rhs){
String lhsString(lhs);
return lhsString < rhs;
}
bool operator<(const char lhs, const String& rhs){
String lhsString(lhs);
return lhsString < rhs;
}
bool operator>(const char lhs[], const String& rhs){
String lhsString(lhs);
return lhsString > rhs;
}
bool operator>(const char lhs, const String& rhs){
String lhsString(lhs);
return lhsString > rhs;
}
bool operator<=(const char lhs[], const String& rhs){
String lhsString(lhs);
return lhsString <= rhs;
}
bool operator<=(const char lhs, const String& rhs){
String lhsString(lhs);
return lhsString <= rhs;
}
bool operator>=(const char lhs[], const String& rhs){
String lhsString(lhs);
return lhsString >= rhs;
}
bool operator>=(const char lhs, const String& rhs){
String lhsString(lhs);
return lhsString >= rhs;
}
I've added some to the code for debugging purposes. The 6 never appears.
String postfix(String infix){
std::vector<String> vec;
vec = infix.split(' ');
Stack<String> tmp;
String right, left, op;
int i = 0;
while (vec[i] != ';'){
std::cout << 1 << std::endl;
if (vec[i] == ')'){
right = tmp.pop();
op = tmp.pop();
left = tmp.pop();
std::cout << 2 << std::endl;
tmp.push(left + ' ' + right + ' ' + op);
std::cout << 3 << std::endl;
}else{
if (vec[i] != '(' && vec[i] != ' ')
std::cout << 4 << std::endl;
tmp.push(vec[i]);
std::cout << 5 << std::endl;
}
++i;
}
std::cout << 6 << std::endl;
String postfix = tmp.pop();
return postfix;
}
Output is
-bash-4.1$ make tests
g++ -g -Wall -W -Wunused -Wuninitialized -Wshadow -iquote . -iquote ../string -c test_data3.cpp
g++ -g -Wall -W -Wunused -Wuninitialized -Wshadow string.o test_data3.o -o test_data3
./test_intStack
Everything looks good. Done testing an int Stack.
./test_stringStack
Everything looks good. Done testing a String Stack.
./test_data3
( AX + ( B * C ) ) ;
1
5
1
4
5
1
4
5
1
5
1
4
5
1
4
5
1
4
5
1
2
3
1
2
3
1
4
5
make: * [tests] Segmentation fault (core dumped)
rm test_data3.o
You almost certainly want to start by isolating the problem.
To do that, I'd start by doing a bit of rewriting to use your own code for the postfix conversion itself, but use std::string and std::stack for the string and stack type respectively.
If that makes the problem disappear, switch one (but not both) back to use your class. If it still works, switch the other to use your class.
Chances are very good that this will fairly quickly tell you whether the problem is in your postfix-conversion, your Stack, or your String. Once you've figured that out, I'd probably work at writing some decent unit tests for the component in question.
You could just debug it in context instead, but chances are pretty fair (at least in my experience) that doing so will often leave a number of similar problems, so the next time you try to use it, you'll run into similar problems under slightly different circumstances. By working at it more systematically you can eliminate entire classes of bugs instead of removing them one at a time.