Overload operator>> in self-made class 'String' C++ - c++

I am creating class 'String'.
But I have a problem with overloading of operator>>.
I've tried to do like this:
istream& operator >> (istream& input, String& inputStr)
{
char str[] = "";
input >> str;
inputStr.size = strlen(str);
inputStr.str = new char[inputStr.size];
for (int i = 0; i < inputStr.size; i++)
{
inputStr.str[i] = str[i];
}
return input;
}
But it doesn't work =(
Can you help me to overload this operator ?
Here is a code:
#pragma once
#include<iostream>
using namespace std;
class String
{
private:
int size;
char* str;
public:
String();
~String();
String(char* arr);
String(const String& copy);
int sizeStr();
friend ostream& operator << (ostream& output, const String& outputStr);
friend istream& operator >> (istream& input, String& inputStr);
};
String::String()
{
this->size = 0;
this->str = nullptr;
}
String::String(char* str)
{
this->size = strlen(str);
this->str = new char[size];
for (int i = 0; i < size; i++)
{
this->str[i] = str[i];
}
}
String::~String()
{
delete[] str;
}
String::String(const String& copy)
{
if (this != &copy)
{
this->size = copy.size;
this->str = new char[size];
for (int i = 0; i < size; i++)
{
this->str[i] = copy.str[i];
}
}
}
int String::sizeStr()
{
return this->size;
}
ostream& operator << (ostream& output, const String& outputStr)
{
for (int i = 0; i < outputStr.size; i++)
{
output << outputStr.str[i];
}
return output;
}
istream& operator >> (istream& input, String& inputStr)
{
return input;
}
I`m looking forward to your help.

Related

Operator>> overloading to assign private pointer array [duplicate]

I realized string class MyString. Here is code:
#include <iostream>
#include <cstring>
using std::cout;
using std::endl;
class MyString{
private:
char * content;
int length;
void copy(const MyString & source);
public:
MyString();
MyString(const char * source);
~MyString();
MyString(const MyString & source);
void print(void);
MyString & operator = (const MyString &source);
friend std::ostream & operator << (std::ostream & out, const MyString& towrite);
friend std::istream & operator >> (std::istream & in, MyString & toread);
};
MyString::MyString(){
content = new char[1];
content[0] = '\0';
length = 0;
}
MyString::MyString(const char *source){
length = strlen(source);
content = new char[length + 1];
strcpy(content, source);
}
MyString::~MyString(){
delete[] content;
}
void MyString::copy(const MyString & source){
length = source.length;
content = new char[length + 1];
strcpy(content, source.content);
}
MyString::MyString(const MyString & source){
copy(source);
}
void MyString::print(void){
cout << "" << content << endl;
}
MyString &MyString::operator=(const MyString &source){
copy(source);
return *this;
}
std::ostream & operator<<(std::ostream & out,const MyString& towrite){
out << towrite.content;
return out;
}
std::istream & operator >> (std::istream & in, MyString & toread){
int length;
std::cout << "Enter length of word: " << endl;
std::cin >> length;
toread.length = length;
toread.content = new char[toread.length+1];
for (int i = 0; i < toread.length; i++){
in >> toread.content[i] ;
}
toread.content[toread.length] = '\0';
return in;
}
My question is related to overloaded operator >>.
For this main program:
int main(){
MyString word;
std::cout<<"Enter some word: "<<endl;
std::cin>>word;
std::cout<<"Your entered: "<<word<<endl;
}
this is output:
Enter some word:
Enter length of word:
5
stack
Your entered: stack
Process returned 0 (0x0) execution time : 8.313 s
Press any key to continue.
It prints correctly string user entered, but it doesn't "mimic" original string class on the way I want. Here is why.
In case of using C++ string class:
int main(){
std::string word;
std::cout<<"Enter some word: "<<endl;
std::cin>>word;
std::cout<<"Your entered: "<<word<<endl;
}
user doesn't need to enter length of word. Can I achieve this with my class?
EDIT1:
I did it on this way:
std::istream & operator >> (std::istream & in, MyString & toread){
char *temp;
temp = new char[100];
char c;
int i = 0;
while(c != '\n'){
c = getchar();
temp[i++] = c;
}
temp[i] = '\0';
int length = i-1;
toread.length = length;
toread.content = new char[toread.length+1];
for(int i = 0 ; i < toread.length ; i++){
toread.content[i] = temp[i];
}
delete [] temp;
toread.content[toread.length+1]='\0';
}
It works as it should. However, I get warning because I didn't return "in":
||=== Build: Debug in fdsfsdf (compiler: GNU GCC Compiler) ===|
C:\Users\hae\Desktop\fdsfsdf\main.cpp||In function 'std::istream& operator>>(std::istream&, MyString&)':|
C:\Users\hae\Desktop\fdsfsdf\main.cpp|137|warning: no return statement in function returning non-void [-Wreturn-type]|
||=== Build finished: 0 error(s), 1 warning(s) (0 minute(s), 4 second(s)) ===|
||=== Run: Debug in fdsfsdf (compiler: GNU GCC Compiler) ===|
Here's a stripped down version of a similar class I wrote a long time ago. It's an antique, but it should work, and solves some of the issues with your class.
class charray {
public:
charray();
~charray();
charray(const charray&);
charray(const char*);
charray& operator=(const charray&);
charray& operator=(const char*);
void swap(charray&);
const char* c_str() const
{ return m_elem; }
unsigned int size() const
{ return m_size; }
private:
void m_resize(unsigned int size);
char* m_elem;
unsigned int m_size;
};
// private.
void charray::m_resize(unsigned int size)
{
char* elem = new char[size+1];
memcpy(elem, m_elem, std::min(m_size, size));
elem[size] = '\0';
delete [] m_elem;
m_elem = elem;
m_size = size;
}
// public.
charray::charray()
: m_elem(0), m_size(0)
{
m_resize(0);
}
charray::~charray()
{
delete [] m_elem;
}
charray::charray(const charray& src)
: m_elem(0), m_size(0)
{
unsigned int size = src.size();
m_resize(size);
memcpy(m_elem, src.c_str(), size);
}
charray::charray(const char* src)
: m_elem(0), m_size(0)
{
unsigned int size = std::strlen(src);
m_resize(size);
memcpy(m_elem, src, size);
}
charray& charray::operator=(const charray& rhs)
{
charray temp(rhs);
this->swap(temp);
return *this;
}
charray& charray::operator=(const char* rhs)
{
charray temp(rhs);
this->swap(temp);
return *this;
}
void charray::swap(charray& b)
{
std::swap(m_elem, b.m_elem);
std::swap(m_size, b.m_size);
}
Here is what you're probably most interested in. Pay close attention to the details. When dealing with memory directly, the difference between a working implementation and a broken one is often very subtle.
Note: The operators are not friends. They do not access private data.
std::ostream& operator<<(std::ostream& out, const charray& in)
{
return out << in.c_str();
}
std::istream& operator>>(std::istream& in, charray& out)
{
// verify no errors are set, flush tied streams, strip leading
// whitespace.
std::istream::sentry sentry(in);
if (!sentry)
return in;
unsigned int size = 0;
unsigned int tail = 0;
char* temp = 0;
int next; // #note int not char (to record EOF).
while ((next = in.get()) != in.eof() && !std::isspace(next)) {
// if temp buffer is exhausted, then double the buffer size.
// (base size of 16).
if (tail == size) {
unsigned int newsize = std::max(2*size, 16u);
char* newtemp = new char[newsize+1];
memcpy(newtemp, temp, size);
delete [] temp;
temp = newtemp;
size = newsize;
}
temp[tail++] = next;
}
// #note because the stream is prepeared with istream::sentry, there
// will be at least one non-whitespace character in the stream.
assert(temp != 0);
temp[tail] = '\0';
out = temp;
delete [] temp;
return in;
}
A much easier and safer way to do the exact same thing,
#include <vector>
std::istream& operator>>(std::istream& in, charray& out)
{
std::istream::sentry sentry(in);
if (!sentry)
return in;
std::vector<char> temp;
int next;
while ((next = in.get()) != in.eof() && !std::isspace(next))
temp.push_back(next);
temp.push_back('\0');
out = &temp[0];
return in;
}
Edit
The above is outmoded (pre C++11). A modern implementation would likely handle construction and assignment differently. Here are updated versions of those methods,
Note: The method m_resize is gone. Everything is handled through constructors.
charray::charray(const char* src, unsigned int size)
: m_elem{ new char[size+1]{} }, m_size{ size }
{
std::copy(src, src + size, m_elem);
}
charray::charray()
: charray(nullptr, 0)
{}
charray::charray(const charray& src)
: charray(src.m_elem, src.m_size)
{}
charray::charray(const char* src)
: charray(src, std::strlen(src))
{}
charray::charray(charray&& src)
: m_elem{ src.m_elem }, m_size{ src.m_size }
{
src.m_elem = nullptr;
src.m_size = 0;
}
// handle both move and copy assignment.
charray& charray::operator=(charray rhs)
{
this->swap(rhs);
return *this;
}
Hope this helps. Good luck.

Overloading operator>> C++

I have a problem with operator>> when I try to use it in my class String. I need to make a string from keyboard, but all my tries make fails. Help me, please.
When I try to turn in this code, I always have a crash.
#include<iostream>
#include<fstream>
using namespace std;
class myString
{
public:
friend std::ostream& operator<< (std::ostream& out, const myString& other);
friend std::istream& operator>> (std::istream& in, myString& other);
myString()
{
str = nullptr;
length = 0;
}
myString(const char* str)
{
length = strlen(str);
this->str = new char[length + 1];
for (int i = 0; i < length; i++)
{
this->str[i] = str[i];
}
this->str[length] = '\0';
}
~myString()
{
delete[] this->str;
}
myString(const myString& other)
{
length = strlen(other.str);
this->str = new char[length + 1];
for (int i = 0; i < length; i++)
{
this->str[i] = other.str[i];
}
this->str[length] = '\0';
}
myString& operator =(const myString& other)
{
if (this->str != nullptr)
{
delete[] str;
}
length = strlen(other.str);
this->str = new char[length + 1];
for (int i = 0; i < length; i++)
{
this->str[i] = other.str[i];
}
this->str[length] = '\0';
return *this;
}
myString& operator =(const char* other)
{
if (this->str != nullptr)
{
delete[] str;
}
length = strlen(other);
this->str = new char[length + 1];
for (int i = 0; i < length; i++)
{
this->str[i] = other[i];
}
this->str[length] = '\0';
return *this;
}
myString& operator +=(myString const& other) {
return (this->operator=(this->operator+(other)));
}
myString operator +(const myString& other)
{
myString newStr;
int thisLength = strlen(this->str);
int otherLength = strlen(other.str);
newStr.length = thisLength + otherLength;
newStr.str = new char[thisLength + otherLength + 1];
int i = 0;
for (; i < thisLength; i++)
{
newStr.str[i] = this->str[i];
}
for (int j = 0; j < otherLength; j++, i++)
{
newStr.str[i] = other.str[j];
}
newStr.str[thisLength + otherLength] = '\0';
return newStr;
}
void Print()
{
cout << str;
}
int Length()
{
return length;
}
bool operator ==(const myString& other)
{
if (this->length != other.length)
{
return false;
}
for (int i = 0; i < this->length; i++)
{
if (this->str[i] != other.str[i])
{
return false;
}
}
return true;
}
bool operator !=(const myString& other)
{
return !(this->operator==(other));
}
char& operator [](int index)
{
return this->str[index];
}
private:
char* str;
int length;
};
ostream& operator<< (ostream& out, const myString& other)
{
out << other.str;
return out;
}
istream& operator >> (istream& in, myString& other)
{
in.getline(other.str, sizeof(other.str));
return in;
}
int main()
{
myString str_3;
cin >> str_3;
cout << str_3;
return 0;
}
sizeof(other.str) is not the size of allocated buffer but the size of the pointer.
other.str is initialized to nullptr in the constructor, so it will try to read into invalid place and it will lead to Segmentation Fault.
Changing the constructor to
myString()
{
str = new char[1];
length = 0;
}
to keep the buffer size always length + 1 and changing the operator>> to
istream& operator >> (istream& in, myString& other)
{
in.getline(other.str, other.length + 1);
return in;
}
will prevent it from getting Segmentation Fault.
This won't solve the problem that the reading will be limited to length of already assigned string.
Improving the behavior will require other modifications like reading characters one-by-one and allocating buffer according to the size read.
You are trying to read to a pointer initialized with nullptr and you use sizeof() of that pointer when you have length data member. Since you already defined assignment operator for char array you can just use it:
istream& operator >> (istream& in, myString& other)
{
char buffer[256];
in.getline(buffer, sizeof(buffer));
other = buffer;
return in;
}
note buffer size is arbitrary here, real application should handle different sizes and grow on need, but that would require more advanced string implementation than yours. For your simplified solution which looks like student task this could be fine.
Note: your operator<< also has issue, if you call it on default constructed object it would lead to UB, as std::ostream does not accept nullptr on const char *. Simple check for nullptr would be sufficient there:
ostream& operator<< (ostream& out, const myString& other)
{
if(other.str)
out << other.str;
return out;
}
Ironically you did check for nullptr for delete[] which is not necessary.
You do not allocate space for your data member str in the default constructor. So when you write
myString str_3;
cin >> str_3;
then your code in operator>> (i.e. in.getline(other.str, sizeof(other.str));) will write to memory that you did not allocate before).
Make sure that str provides enough allocated memory before writing to it, e.g. by using alloc or realloc.

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?

C++ - overloading operator >> for my string class

I realized string class MyString. Here is code:
#include <iostream>
#include <cstring>
using std::cout;
using std::endl;
class MyString{
private:
char * content;
int length;
void copy(const MyString & source);
public:
MyString();
MyString(const char * source);
~MyString();
MyString(const MyString & source);
void print(void);
MyString & operator = (const MyString &source);
friend std::ostream & operator << (std::ostream & out, const MyString& towrite);
friend std::istream & operator >> (std::istream & in, MyString & toread);
};
MyString::MyString(){
content = new char[1];
content[0] = '\0';
length = 0;
}
MyString::MyString(const char *source){
length = strlen(source);
content = new char[length + 1];
strcpy(content, source);
}
MyString::~MyString(){
delete[] content;
}
void MyString::copy(const MyString & source){
length = source.length;
content = new char[length + 1];
strcpy(content, source.content);
}
MyString::MyString(const MyString & source){
copy(source);
}
void MyString::print(void){
cout << "" << content << endl;
}
MyString &MyString::operator=(const MyString &source){
copy(source);
return *this;
}
std::ostream & operator<<(std::ostream & out,const MyString& towrite){
out << towrite.content;
return out;
}
std::istream & operator >> (std::istream & in, MyString & toread){
int length;
std::cout << "Enter length of word: " << endl;
std::cin >> length;
toread.length = length;
toread.content = new char[toread.length+1];
for (int i = 0; i < toread.length; i++){
in >> toread.content[i] ;
}
toread.content[toread.length] = '\0';
return in;
}
My question is related to overloaded operator >>.
For this main program:
int main(){
MyString word;
std::cout<<"Enter some word: "<<endl;
std::cin>>word;
std::cout<<"Your entered: "<<word<<endl;
}
this is output:
Enter some word:
Enter length of word:
5
stack
Your entered: stack
Process returned 0 (0x0) execution time : 8.313 s
Press any key to continue.
It prints correctly string user entered, but it doesn't "mimic" original string class on the way I want. Here is why.
In case of using C++ string class:
int main(){
std::string word;
std::cout<<"Enter some word: "<<endl;
std::cin>>word;
std::cout<<"Your entered: "<<word<<endl;
}
user doesn't need to enter length of word. Can I achieve this with my class?
EDIT1:
I did it on this way:
std::istream & operator >> (std::istream & in, MyString & toread){
char *temp;
temp = new char[100];
char c;
int i = 0;
while(c != '\n'){
c = getchar();
temp[i++] = c;
}
temp[i] = '\0';
int length = i-1;
toread.length = length;
toread.content = new char[toread.length+1];
for(int i = 0 ; i < toread.length ; i++){
toread.content[i] = temp[i];
}
delete [] temp;
toread.content[toread.length+1]='\0';
}
It works as it should. However, I get warning because I didn't return "in":
||=== Build: Debug in fdsfsdf (compiler: GNU GCC Compiler) ===|
C:\Users\hae\Desktop\fdsfsdf\main.cpp||In function 'std::istream& operator>>(std::istream&, MyString&)':|
C:\Users\hae\Desktop\fdsfsdf\main.cpp|137|warning: no return statement in function returning non-void [-Wreturn-type]|
||=== Build finished: 0 error(s), 1 warning(s) (0 minute(s), 4 second(s)) ===|
||=== Run: Debug in fdsfsdf (compiler: GNU GCC Compiler) ===|
Here's a stripped down version of a similar class I wrote a long time ago. It's an antique, but it should work, and solves some of the issues with your class.
class charray {
public:
charray();
~charray();
charray(const charray&);
charray(const char*);
charray& operator=(const charray&);
charray& operator=(const char*);
void swap(charray&);
const char* c_str() const
{ return m_elem; }
unsigned int size() const
{ return m_size; }
private:
void m_resize(unsigned int size);
char* m_elem;
unsigned int m_size;
};
// private.
void charray::m_resize(unsigned int size)
{
char* elem = new char[size+1];
memcpy(elem, m_elem, std::min(m_size, size));
elem[size] = '\0';
delete [] m_elem;
m_elem = elem;
m_size = size;
}
// public.
charray::charray()
: m_elem(0), m_size(0)
{
m_resize(0);
}
charray::~charray()
{
delete [] m_elem;
}
charray::charray(const charray& src)
: m_elem(0), m_size(0)
{
unsigned int size = src.size();
m_resize(size);
memcpy(m_elem, src.c_str(), size);
}
charray::charray(const char* src)
: m_elem(0), m_size(0)
{
unsigned int size = std::strlen(src);
m_resize(size);
memcpy(m_elem, src, size);
}
charray& charray::operator=(const charray& rhs)
{
charray temp(rhs);
this->swap(temp);
return *this;
}
charray& charray::operator=(const char* rhs)
{
charray temp(rhs);
this->swap(temp);
return *this;
}
void charray::swap(charray& b)
{
std::swap(m_elem, b.m_elem);
std::swap(m_size, b.m_size);
}
Here is what you're probably most interested in. Pay close attention to the details. When dealing with memory directly, the difference between a working implementation and a broken one is often very subtle.
Note: The operators are not friends. They do not access private data.
std::ostream& operator<<(std::ostream& out, const charray& in)
{
return out << in.c_str();
}
std::istream& operator>>(std::istream& in, charray& out)
{
// verify no errors are set, flush tied streams, strip leading
// whitespace.
std::istream::sentry sentry(in);
if (!sentry)
return in;
unsigned int size = 0;
unsigned int tail = 0;
char* temp = 0;
int next; // #note int not char (to record EOF).
while ((next = in.get()) != in.eof() && !std::isspace(next)) {
// if temp buffer is exhausted, then double the buffer size.
// (base size of 16).
if (tail == size) {
unsigned int newsize = std::max(2*size, 16u);
char* newtemp = new char[newsize+1];
memcpy(newtemp, temp, size);
delete [] temp;
temp = newtemp;
size = newsize;
}
temp[tail++] = next;
}
// #note because the stream is prepeared with istream::sentry, there
// will be at least one non-whitespace character in the stream.
assert(temp != 0);
temp[tail] = '\0';
out = temp;
delete [] temp;
return in;
}
A much easier and safer way to do the exact same thing,
#include <vector>
std::istream& operator>>(std::istream& in, charray& out)
{
std::istream::sentry sentry(in);
if (!sentry)
return in;
std::vector<char> temp;
int next;
while ((next = in.get()) != in.eof() && !std::isspace(next))
temp.push_back(next);
temp.push_back('\0');
out = &temp[0];
return in;
}
Edit
The above is outmoded (pre C++11). A modern implementation would likely handle construction and assignment differently. Here are updated versions of those methods,
Note: The method m_resize is gone. Everything is handled through constructors.
charray::charray(const char* src, unsigned int size)
: m_elem{ new char[size+1]{} }, m_size{ size }
{
std::copy(src, src + size, m_elem);
}
charray::charray()
: charray(nullptr, 0)
{}
charray::charray(const charray& src)
: charray(src.m_elem, src.m_size)
{}
charray::charray(const char* src)
: charray(src, std::strlen(src))
{}
charray::charray(charray&& src)
: m_elem{ src.m_elem }, m_size{ src.m_size }
{
src.m_elem = nullptr;
src.m_size = 0;
}
// handle both move and copy assignment.
charray& charray::operator=(charray rhs)
{
this->swap(rhs);
return *this;
}
Hope this helps. Good luck.

Overloading insertion and extraction operators for strings

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();