Hello I am getting compile errors and I don't understand why
2 IntelliSense: expected an identifier c:\Users\Sean\Documents\Visual Studio 2013\Projects\mystring\mystring\mystring.cpp 93 7 mystring
3 IntelliSense: expected a ';' c:\Users\Sean\Documents\Visual Studio 2013\Projects\mystring\mystring\mystring.cpp 93 10 mystring
4 IntelliSense: member function "main_savitch_4::mystring::operator=" may not be redeclared outside its class c:\Users\Sean\Documents\Visual Studio 2013\Projects\mystring\mystring\mystring.cpp 106 17 mystring
5 IntelliSense: expected a ';' c:\Users\Sean\Documents\Visual Studio 2013\Projects\mystring\mystring\mystring.cpp 107 2 mystring
6 IntelliSense: more than one operator ">>" matches these operands:
function "operator>>(std::istream &ins, main_savitch_4::mystring &target)"
function "main_savitch_4::operator>>(std::istream &ins, main_savitch_4::mystring &target)"
operand types are: std::istream >> main_savitch_4::mystring c:\Users\Sean\Documents\Visual Studio 2013\Projects\mystring\mystring\mystring.cpp 246 7 mystring
#include <iostream>
#include "mystring.h"
#include <cstring>
using namespace std;
using namespace main_savitch_4;
//Constructors- sets initial values for memeber variables
mystring::mystring(const char str[] = "")
//returns a pointer referencing [0] in an array
{
current_length = 0;
int pt = 0;
if (str[pt] != '\0') //this increases the array size to the string size
{
++current_length;
++pt;
}
sequence = new char[current_length + 1];
while (current_length >= pt)
{
sequence[pt] = str[pt];
++pt;
}
allocated = current_length + 1;
}
mystring::mystring(const mystring& source)
{
sequence = new char[source.allocated];
current_length = source.current_length; //returns mystring object with same
allocated = source.allocated; //length and allocation as source
for (int i = 0; i <= allocated; ++i)
{
sequence[i] = source.sequence[i]; //copies characters to new object
}
}
//Destructor- frees space
mystring::~mystring()
{
delete[] sequence;
}
void mystring::operator +=(const mystring& addend)//adds another string ontop of the original
{
reserve(current_length + addend.current_length + 1);
strcpy(sequence + current_length, addend.sequence);
current_length += addend.current_length;
}
void mystring::operator +=(const char addend[])
{
int leng = current_length + strlen(addend);
if (leng >= allocated)
{
reserve(leng + 1);
}
strcpy(sequence + current_length, addend);
current_length = leng;
}
void mystring::operator +=(char addend)
{
while (current_length >= allocated)
{
reserve(current_length + 1);
}
sequence[current_length] = addend;
sequence[current_length + 1] = '\0'; //increases size to allow for \0 character
++current_length;
}
void mystring::reserve(size_t n) //size_t represents the size of object
// n is the size
{
if (allocated < n)
{
char[] sequence = new char[n];
for (int i = 0; i <= current_length; ++i)
{
sequence + i;
allocated = n;
}
}
/////////////////////
void mystring::operator =(const mystring& source)
{
delete[] sequence;
sequence = new char[source.allocated];
allocated = source.allocated;
current_length = source.current_length;
for (int idx = 0; idx <= source.allocated; ++idx)
{
sequence[idx] = source.sequence[idx];
}
}
char mystring::operator [ ](size_t position) const
{
return sequence[position];
}
std::ostream& operator <<(std::ostream& outs, const mystring& source)
{
outs << source.sequence;
return outs;
}
bool operator ==(const mystring& s1, const mystring& s2)
{
int length = 0;
bool gate = false;
if (s1.length() >= s2.length())
length = s1.length();
else
length = s2.length();
for (int idx = 0; idx < length; ++idx)
{
if (s1[idx] - s2[idx] == 0 && idx == length - 1)
gate = true;
}
return gate;
}
bool operator !=(const mystring& s1, const mystring& s2)
{
return !(s1 == s2);
}
bool operator >=(const mystring& s1, const mystring& s2)
{
if (s1 < s2)
return false;
else
return true;
}
bool operator <=(const mystring& s1, const mystring& s2)
{
if (s1 > s2)
return false;
else
return true;
}
bool operator > (const mystring& s1, const mystring& s2)
{
bool gate = false;
int length = 0;
if (s1.length() <= s2.length())
length = s1.length();
else if (s1.length() > s2.length())
length = s2.length();
for (int idx = 0; idx < length; ++idx)
{
if (s1[idx] - s2[idx] < 0)
{
gate = true;
idx = length;
}
else if (idx == length - 1 && s1.length() < s2.length())
{
gate = true;
}
}
return gate;
}
bool operator < (const mystring& s1, const mystring& s2)
{
if (s1 != s2 && s2 > s1)
return true;
return false;
}
mystring operator +(const mystring& s1, const mystring& s2)
{
mystring temp(s1);
temp += s2;
return temp;
}
std::istream& operator >>(std::istream& ins, mystring& target)
{
while (ins && isspace(ins.peek()))
{
ins.ignore();
}
target = ""; //Clear out any junk in the target
while (ins.peek() != '\n')
target += ins.get();
return ins;
}
std::istream& getline(std::istream& ins, mystring& target)
{
ins >> target;
return ins;
}
This if statement in function reserve:
void mystring::reserve(size_t n)
{
if (allocated < n)
{
char[] sequence = new char[n];
for (int i = 0; i <= current_length; ++i)
{
sequence + i;
allocated = n;
}
}
Doesn't appear to be closed. Try adding a }.
Related
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?
I am having trouble getting my string class working. My istream function seems to read the data in, and I confirmed that the += was adding the characters, but after the first character, what is added is garbage. I have tried everything I can think of to get it working. Can someone please provide some insight as to what is going wrong. Thanks.
istream& operator >>(istream& ins, string& target)
{
char newInput;
while (ins && isspace(ins.peek()))
ins.ignore();
target = ("");
//int count = 0;
while (ins && !isspace(ins.peek())) //(ins.peek())))
{
ins >> newInput;
target.operator+=(newInput);
}
return ins;
}
void string::operator +=(char addend)
{
if (this->current_length + 1 > this->allocated)
{
reserve(allocated + 1);
}
sequence[current_length] = addend;
current_length += 1;
}
void string::reserve(size_t n)
{
assert(n > current_length);
char *newSequence = new char[n];
if (n == allocated)
{
return;
}
for (size_t i = 0; i < n; i++)
{
newSequence[i] = sequence[i];
}
//destroy old array
delete[] sequence;
//update capacity
allocated = n;
//point data at new array
sequence = newSequence;
}
Full Code: **
#pragma warning(disable : 4996)
#ifndef MAIN_SAVITCH_CHAPTER4_MYSTRING_H
#define MAIN_SAVITCH_CHAPTER4_MYSTRING_H
#include <cstdlib> // Provides size_t
#include <cassert>
#include <string.h>
#include <iostream>
#include <ctype.h>
#include <algorithm>
using namespace std;
namespace main_savitch_4
{
class string
{
public:
// CONSTRUCTORS and DESTRUCTOR
string(const char str[] = "");
string(const string& source);
~string() { delete[] sequence; }
// MODIFICATION MEMBER FUNCTIONS
void operator +=(const string& addend);
void operator +=(const char addend[]);
void operator +=(char addend);
void reserve(size_t n);
void operator =(const string& source);
// CONSTANT MEMBER FUNCTIONS
size_t length() const { return current_length; }
char operator [ ](size_t position) const;
// FRIEND FUNCTIONS
friend ostream& operator <<(ostream& outs, const string& source);
friend bool operator ==(const string& s1, const string& s2);
friend bool operator !=(const string& s1, const string& s2);
friend bool operator >=(const string& s1, const string& s2);
friend bool operator <=(const string& s1, const string& s2);
friend bool operator > (const string& s1, const string& s2);
friend bool operator < (const string& s1, const string& s2);
private:
char *sequence;
size_t allocated;
size_t current_length;
};
// CONSTRUCTOR for the string class:
// string(const char str[ ] = "") -- default argument is the empty string.
// Precondition: str is an ordinary null-terminated string.
// Postcondition: The string contains the sequence of chars from str.
string::string(const char str[])
{
current_length = strlen(str);
allocated = current_length + 1;
sequence = new char[allocated];
for (size_t i = 0; i < allocated; i++)
{
sequence[i] = str[i];
}
}
string::string(const string& source)
//copy constructor
{
current_length = source.current_length;
allocated = current_length + 1;
sequence = new char[allocated];
for (size_t i = 0; i < allocated; i++) {
sequence[i] = source.sequence[i];
}
}
//~string();
// CONSTANT MEMBER FUNCTIONS for the string class:
// size_t length( ) const
// Postcondition: The return value is the number of characters in the
// string.
//
// char operator [ ](size_t position) const
// Precondition: position < length( ).
// Postcondition: The value returned is the character at the specified
// position of the string. A string's positions start from 0 at the start
// of the sequence and go up to length( )-1 at the right end.
char string::operator [ ](size_t position) const
{
assert(position < length());
return (sequence[position]);
}
// MODIFICATION MEMBER FUNCTIONS for the string class:
// void operator +=(const string& addend)
// Postcondition: addend has been catenated to the end of the string.
//
void string::operator =(const string& source)
{
//string assigned to self
if (sequence == source.sequence)
{
return;
}
if (source.current_length > this->allocated)
reserve(source.current_length);
delete[] sequence;
current_length = source.current_length;
allocated = current_length + 1;
for (size_t i = 0; i < allocated; i++) {
sequence[i] = source.sequence[i];
}
}
void string::operator +=(const string& addend)
{
if (this->current_length + addend.current_length > this->allocated)
{
reserve(current_length + addend.allocated);
}
//copy addend to sequence
for (size_t i = 0; i < addend.current_length; i++)
{
sequence[i + current_length] = addend.sequence[i];
}
current_length = current_length + addend.current_length;
}
// void operator +=(const char addend[ ])
// Precondition: addend is an ordinary null-terminated string.
// Postcondition: addend has been catenated to the end of the string.
void string::operator +=(const char addend[])
{
if (this->current_length + strlen(addend) > this->allocated)
reserve(current_length + strlen(addend));
//copy addend to sequence
for (size_t i = 0; i < strlen(addend); i++)
{
sequence[i + current_length] = addend[i];
}
current_length += strlen(addend);
}
// void operator +=(char addend)
// Postcondition: The single character addend has been catenated to the
// end of the string.
//
void string::operator +=(char addend)
{
if ((this->current_length + 1) > (this->allocated))
{
reserve(allocated + 1);
}
//copy addend to sequence
sequence[current_length] = addend;
current_length += 1;
}
// void reserve(size_t n)
// Postcondition: All functions will now work efficiently (without
// allocating new memory) until n characters are in the string.
void string::reserve(size_t n)
{
assert(n > current_length);
//create new array
char *newSequence = new char[n];
if (n == allocated)
{
return;
}
if (n < current_length + 1)
{
n = current_length + 1;
}
for (size_t i = 0; i < current_length; i++)
{
newSequence[i] = sequence[i];
}
delete[] sequence;
//update capacity
allocated = n;
//point data at new array
sequence = newSequence;
}
//Friend Functions
bool operator ==(const string& s1, const string& s2)
{
return (s1 == s2);
}
bool operator !=(const string& s1, const string& s2)
{
return !(s1 == s2); //(strcmp(s1.sequence, s2.sequence) == 0);
}
bool operator >=(const string& s1, const string& s2)
{
return (s1 >= s2); //(strcmp(s1.sequence, s2.sequence) >= 0);
}
bool operator <=(const string& s1, const string& s2)
{
return (s1 <= s2); //(strcmp(s1.sequence, s2.sequence) <= 0);
}
bool operator > (const string& s1, const string& s2)
{
return (s1 > s2); //(strcmp(s1.sequence, s2.sequence) > 0);
}
bool operator < (const string& s1, const string& s2)
{
return (s1 < s2); // (strcmp(s1.sequence, s2.sequence) < 0);
}
// NON-MEMBER FUNCTIONS for the string class
// string operator +(const string& s1, const string& s2)
// Postcondition: The string returned is the catenation of s1 and s2.
//
string operator +(const string& s1, const string& s2)
{
string temp = s1;
temp = s1 + s2;
return temp;
}
// istream& operator >>(istream& ins, string& target)
// Postcondition: A string has been read from the istream ins, and the
// istream ins is then returned by the function. The reading operation
// skips white space (i.e., blanks, newlines, tabs) at the start of ins.
// Then the string is read up to the next white space or the end of the
// file. The white space character that terminates the string has not
// been read.
//
istream& operator >>(istream& ins, string& target)
{
char newInput;
while (ins && isspace(ins.peek()))
ins.ignore();
target = ("");
while (ins && !isspace(ins.peek())) //(ins.peek())))
{
ins >> newInput;
cout << newInput;
target.operator+=(newInput);
}
return ins;
}
// ostream& operator <<(ostream& outs, const string& source)
// Postcondition: The sequence of characters in source has been written
// to outs. The return value is the ostream outs.
ostream& operator <<(ostream& outs, const string& source)
{
outs << source.sequence;
return outs;
}
//
// void getline(istream& ins, string& target, char delimiter)
void getline(istream& ins, string& target, char delimiter)
{
{
int count = 0;
char newLine;
while (ins)
{
ins.get(newLine);
target.operator+=(newLine);
}
}
}
}
#endif
#pragma once
The new[] and delete[] must be balanced.
The string::operator=(const string&) routine is delete[] the sequence array, which later gets delete[] again in the reserve routine.
while (ins && !isspace(ins.peek())) //(ins.peek())))
{
ins >> newInput;
target.operator+=(newInput);
}
Here you:
Check whether the stream has had any errors or attempted to read past the end
Extract the next character, assume this succeeded, then see whether it's a space
Read said character, and again assume this succeeded — if it did, it is assigned to newInput
Insert the contents of newInput to target (with a direct function call for some reason)
If the next read fails, you have no checking of that, and newInput isn't what you think it is.
You've only checked for errors before doing a thing.
Perhaps something like this would better suit:
while (true) {
const auto next = ins.peek();
if (!ins) break;
if (isspace(next)) break;
ins >> newInput;
target += newInput;
}
I'm assuming that if the peek succeeded then the >> will also, but in practice I'd probably put another check for !ins before the target += line, unless I were concerned about speed. In particular, you should double-check whether peek() sets eofbit, because I can't remember and, if it doesn't, you'll definitely need another if.
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.
Here are the full codes that I am using to implement this program. Everything seems to compile and run, but once it runs my find method, the program seems to stop and does not execute the last line stating the matching substring within the main.cpp file. Any help is definitely appreciated!
.h file:
#include <iostream>
using namespace std;
class MyString
{
public:
MyString();
MyString(const char *message);
MyString(const MyString &source);
~MyString();
const void Print() const;
const int Length() const;
MyString& operator()(const int index, const char b);
char& operator()(const int i);
MyString& operator=(const MyString& rhs);
bool operator==(const MyString& other) const;
bool operator!=(const MyString& other) const;
const MyString operator+(const MyString& rhs) const;
MyString& operator+=(const MyString& rhs);
friend ostream& operator<<(ostream& output, const MyString& rhs);
const int Find(const MyString& other);
MyString Substring(int start, int length);
private:
char *String;
int Size;
};
istream& operator>>(istream& input, MyString& rhs);
.cpp file:
#include <iostream>
#include <cstdlib>
#include "MyString.h"
using namespace std;
//default constructor that sets the initial string to the value "Hello World"
MyString::MyString()
{
char temp[] = "Hello World";
int counter(0);
while(temp[counter] != '\0')
{
counter++;
}
Size = counter;
String = new char [Size];
for(int i=0; i < Size; i++)
String[i] = temp[i];
}
//alternate constructor that allows for setting of the inital value of the string
MyString::MyString(const char *message)
{
int counter(0);
while(message[counter] != '\0')
{
counter++;
}
Size = counter;
String = new char [Size];
for(int i=0; i < Size; i++)
String[i] = message[i];
}
//copy constructor
MyString::MyString(const MyString &source)
{
int counter(0);
while(source.String[counter] != '\0')
{
counter++;
}
Size = counter;
String = new char[Size];
for(int i = 0; i < Size; i++)
String[i] = source.String[i];
}
//Deconstructor
MyString::~MyString()
{
delete [] String;
}
//Length() method that reports the length of the string
const int MyString::Length() const
{
int counter(0);
while(String[counter] != '\0')
{
counter ++;
}
return (counter);
}
/*Parenthesis operator should be overloaded to replace the Set and Get functions of your previous assignment. Note that both instances should issue exit(1) upon violation of the string array bounaries.
*/
MyString& MyString::operator()(const int index, const char b)
{
if(String[index] == '\0')
{
exit(1);
}
else
{
String[index] = b;
}
}
char& MyString::operator()(const int i)
{
if(String[i] == '\0')
{
exit(1);
}
else
{
return String[i];
}
}
/*Assignment operator (=) which will copy the source string into the destination string. Note that size of the destination needs to be adjusted to be the same as the source.
*/
MyString& MyString::operator=(const MyString& rhs)
{
if(this != &rhs)
{
delete [] String;
String = new char[rhs.Size];
Size = rhs.Size;
for(int i = 0; i < rhs.Size+1 ; i++)
{
String[i] = rhs.String[i];
}
}
return *this;
}
/*Logical comparison operator (==) that returns true iff the two strings are identical in size and contents.
*/
bool MyString::operator==(const MyString& other)const
{
if(other.Size == this->Size)
{
for(int i = 0; i < this->Size+1; i++)
{
if(&other == this)
return true;
}
}
else
return false;
}
//Negated logical comparison operator (!=) that returns boolean negation of 2
bool MyString::operator!=(const MyString& other) const
{
return !(*this == other);
}
//Addition operator (+) that concatenates two strings
const MyString MyString::operator+(const MyString& rhs) const
{
char* tmp = new char[Size + rhs.Size +1];
for(int i = 0; i < Size; i++)
{
tmp[i] = String[i];
}
for(int i = 0; i < rhs.Size+1; i++)
{
tmp[i+Size] = rhs.String[i];
}
MyString result;
delete [] result.String;
result.String = tmp;
result.Size = Size+rhs.Size;
return result;
}
/*Addition/Assigment operator (+=) used in the following fashion: String1 += String2 to operate as String1 = String1 + String2
*/
MyString& MyString::operator+=(const MyString& rhs)
{
char* tmp = new char[Size + rhs.Size + 1];
for(int i = 0; i < Size; i++)
{
tmp[i] = String[i];
} for(int i = 0; i < rhs.Size+1; i++)
{
tmp[i+Size] = rhs.String[i];
}
delete [] String;
String = tmp;
Size += rhs.Size;
return *this;
}
istream& operator>>(istream& input, MyString& rhs)
{
char* t;
int size(256);
t = new char[size];
input.getline(t,size);
rhs = MyString(t);
delete [] t;
return input;
}
ostream& operator<<(ostream& output, const MyString& rhs)
{
if(rhs.String != '\0')
{
output << rhs.String;
}
else
{
output<<"No String to output\n";
}
return output;
}
const int MyString::Find(const MyString& other)
{
int nfound = -1;
if(other.Size > Size)
{
return nfound;
}
int i = 0, j = 0;
for(i = 0; i < Size; i++)
{
for(j = 0; j < other.Size; j++)
{
if( ((i+j) >= Size) || (String[i+j] != other.String[j]) )
{
break;
}
}
if(j == other.Size)
{
return i;
}
}
return nfound;
}
/*MyString::Substring(start, length). This method returns a substring of the original string that contains the same characters as the original string starting at location start and is as long as length.
*/
MyString MyString::Substring(int start, int length)
{
char* sub;
sub = new char[length+1];
while(start != '\0')
{
for(int i = start; i < length+1; i++)
{
sub[i] = String[i];
}
}
return MyString(sub);
}
//Print() method that prints the string
const void MyString::Print() const
{
for(int i=0; i < Size; i++)
{
cout<<String[i];
}
cout<<endl;
}
main.cpp file:
#include <cstdlib>
#include <iostream>
#include "MyString.h"
using namespace std;
/*
*
*/
int main (int argc, char **argv)
{
MyString String1; // String1 must be defined within the scope
const MyString ConstString("Target string"); //Test of alternate constructor
MyString SearchString; //Test of default constructor that should set "Hello World". W/o ()
MyString TargetString (String1); //Test of copy constructor
cout << "Please enter two strings. ";
cout << "Each string needs to be shorter than 256 characters or terminated by /\n." << endl;
cout << "The first string will be searched to see whether it contains exactly the second string. " << endl;
cin >> SearchString >> TargetString; // Test of cascaded string-extraction operator
if(SearchString.Find(TargetString) == -1) {
cout << TargetString << " is not in " << SearchString << endl;
}
else {
cout << TargetString << " is in " << SearchString << endl;
cout << "Details of the hit: " << endl;
cout << "Starting poisition of the hit: " << SearchString.Find(TargetString) << endl;
cout << "The matching substring is: " << SearchString.Substring(SearchString.Find(TargetString), TargetString.Length());
}
return 0;
}
It appears the inner loop's invariant is that j is between 0 and end-2 inclusive. Hence j will NEVER equal end (the "matching" condition).
Looks like you have a problem with your found logic.
Your for loop is defined as for(int j = 0; j < end -1; j++)
but then you test for if(j == end)
j can never be equal to end in this for loop. Consider what you're actually trying to test for in your if statement.
I think you need to declare i and j outside the loops.
I think you meant j < end and not j < end - 1
I think you need to if((i+j>=end1) || String[i+j] != other.String[j]) and not just if(String[i+j] != other.String[j])
and if(j == end) needs to be outside the inner loop.
Here is a similar implementation.
#include <string>
#include <iostream>
using namespace std;
class MyString
{
private:
string String;
unsigned int Size;
public:
MyString() {
this->String = "";
this->Size = 0;
}
MyString(string initial_value) {
this->String = initial_value;
this->Size = initial_value.length();
}
const int Find(const MyString& other);
};
const int MyString::Find(const MyString& other)
{
if (other.Size > Size)
return -1; // if the substring is greater then us, there's no way we can have it as a substring
int i = 0, j = 0;
for (i = 0; i < Size; i++)
{
for (j = 0; j < other.Size; j++)
if ( ((i + j) >= Size) || (String[i + j] != other.String[j]) ) // if they don't match, offset exceeded Size, break
break ;
if (j == other.Size) // We went through the entire substring, didn't hit break so j == Other.size
return i; // return index
}
return -1; // if we never return anything means, we didn't find it, so return -1
}
int main()
{
string temp1, temp2;
getline(std::cin, temp1, '\n');
getline(std::cin, temp2, '\n');
MyString main_string(temp1), sub_string(temp2);
cout << main_string.Find(sub_string) << endl;
return 0;
}
MyString MyString::Substring(int start, int length)
{
char* sub = new char[length + 2]; // 2 byte buffer to be safe
int i = 0;
for (i = 0; i < length; i++)
sub[i] = String[start + i];
sub[i] = '\0'; // always null terminated to be safe!
return MyString(sub);
}
if theres any bugs or issues, I apologize, haven't tested it.
Along with what everyone else said, in your Substring method you have the following bit of code:
while(start != '\0')
{
for(int i = start; i < length+1; i++)
{
sub[i] = String[i];
}
}
Take a moment to go over the logic of the while loop and ask yourself "what am I trying to achieve here, and what does this code actually do?"
I would like to implement both of these functions so that I would be able to input and output objects of my class. I have gotten the >> operator to work but not so much <<.
Here is my code in my .h file:
class MyString
{
public:
MyString();
MyString(char *message);
~MyString();
void Print();
void Copy(MyString& rhs);
int Length();
MyString& operator()(const int index, const char b);
char& operator()(const int i);
MyString& operator=(const MyString& rhs);
bool operator==(const MyString& other) const;
bool operator!=(const MyString& other) const;
const MyString operator+(const MyString& rhs) const;
MyString& operator+=(const MyString& rhs);
private:
char *String;
int Size;
};
istream& operator>>(istream& input, MyString& rhs);
ostream& operator<<(ostream& output, const MyString& rhs);
Here is my code for the two functions in my .cpp file:
MyString::MyString()
{
char temp[] = "Hello World";
int counter(0);
while(temp[counter] != '\0') {
counter++;
}
Size = counter;
String = new char [Size];
for(int i=0; i < Size; i++)
String[i] = temp[i];
}
MyString::MyString(char *message)
{
int counter(0);
while(message[counter] != '\0') {
counter++;
}
Size = counter;
String = new char [Size];
for(int i=0; i < Size; i++)
String[i] = message[i];
}
MyString::~MyString()
{
delete [] String;
}
int MyString::Length()
{
int counter(0);
while(String[counter] != '\0')
{
counter ++;
}
return (counter);
}
const MyString MyString::operator+(const MyString& rhs) const
{
char* tmp = new char[Size + rhs.Size +1];
for(int i = 0; i < Size; i++)
{
tmp[i] = String[i];
}
for(int i = 0; i < rhs.Size+1; i++)
{
tmp[i+Size] = rhs.String[i];
}
const MyString MyString::operator+(const MyString& rhs) const
{
char* tmp = new char[Size + rhs.Size +1];
for(int i = 0; i < Size; i++)
{
tmp[i] = String[i];
}
for(int i = 0; i < rhs.Size+1; i++)
{
tmp[i+Size] = rhs.String[i];
}
MyString result;
delete [] result.String;
result.String = tmp;
result.Size = Size+rhs.Size;
return result;
}
MyString& MyString::operator()(const int index, const char b)
{
if(String[index] == '\0')
{
exit(1);
}
else
{
String[index] = b;
}
}
MyString& MyString::operator=(const MyString& rhs)
{
if(this != &rhs)
{
delete [] String;
String = new char[rhs.Size];
Size = rhs.Size;
for(int i = 0; i < rhs.Size+1 ; i++)
{
String[i] = rhs.String[i];
}
}
return *this;
}
void MyString::Copy(MyString& rhs)
{
delete [] String;
Size = rhs.Size;
String = new char[rhs.Size];
String = rhs.String;
}
MyString& MyString::operator+=(const MyString& rhs)
{
char* tmp = new char[Size + rhs.Size + 1];
for(int i = 0; i < Size; i++)
{
tmp[i] = String[i];
}
for(int i = 0; i <rhs.Size+1; i++)
{
tmp[i+Size] = rhs.String[i];
}
delete [] String;
String = tmp;
Size += rhs.Size;
return *this;
}
bool MyString::operator!=(const MyString& other) const
{
return !(*this == other);
}
bool MyString::operator==(const MyString& other)const
{
if(other.Size == this->Size)
{
for(int i = 0; i < this->Size+1; i++)
{
if(&other == this)
return true;
}
}
else
return false;
}
char& MyString::operator()(const int i)
{
if( String[i] == '\0')
{
exit(1);
}
else
{
return String[i];
}
}
void MyString::Print()
{
for(int i=0; i < Size; i++)
cout << String[i];
cout << endl;
}
istream& operator>>(istream& input, MyString& rhs)
{
char* temp;
int size(256);
temp = new char[size];
input.getline(temp,size);
rhs = MyString(temp);
delete [] temp;
return input;
}
ostream& operator<<(ostream& output, const MyString& rhs)
{
char* p;
int size(256);
p = new char[size];
output << rhs.MyString(p);
delete [] p;
return output;
}
Here is how it is called in the main.cpp file:
cin >> SearchString >> TargetString; // Test of cascaded string-extraction operator<</*
if(SearchString.Find(ConstString) != -1) {
cout << ConstString << " is not in " << SearchString << endl; }
else {
cout << ConstString << " is in " << SearchString << endl;
cout << "Details of the hit: " << endl;
cout << "Starting poisition of the hit: " << SearchString.Find(ConstString) << endl;
cout << "The matching substring is: " << SearchString.Substring(SearchString.Find(ConstString), ConstString.length()); }
Again, the cin>> operator works perfectly but please help me to figure out how to output the string.
Not really sure what you are asking. The implementation depends on how you want to output the string.
For some raw output the code will most likely look like this:
output << rhs.get_data();