how do i write an overload operator>> function of class string? - c++

class string
{
public:
friend istream& operator >> ( istream& is, string& str);
private:
char *m_data;
};
int main()
{
string str;
freopen("in.txt","r",stdin);
while( cin >> str)
{
cout < < str < < endl;
}
return 0;
}
the content of in.txt are:
asdfsfgfdgdfg
in the overload function, i use is.get() to read those charaters one by one,but program jump out the circle when cin finish,that means cout will not run. on the other way,i try getchar() instead, but it can not jump out the circle.
question: is there any wrong in my idea towards this function? or there is another better way to fulfill. thx :)
=========================================================================================
new edit:
here my code:
#Artem Barger
code detail
#include <iostream>
namespace Str
{
class string
{
public:
string():k(0){}
friend bool operator >> ( std::istream& is, string& str)
{
int size = 100;
char m;
if( (m = getchar()) && m == -1)
return false;
str.m_data = new char[size];
do
{
if( str.k == size)
{
size *= 2;
char *temp = new char[size];
for( int j = 0; j < str.k; ++j)
{
char *del = str.m_data;
temp[j] = *str.m_data++;
delete del;
}
str.m_data = temp;
temp = NULL;
}
str.m_data[str.k++] = m;
}while( (m = getchar()) && m != -1);
return true;
}
friend void operator << ( std::ostream& os, string& str)
{
os << str.m_data;
str.k = 0;
delete []str.m_data;
}
private:
char *m_data;
int k;
};
}
using namespace Str;
int main()
{
string str;
while( std::cin >> str)
{
std::cout << str;
}
return 0;
}
still have some problem in the content of
do
{
}while();

Perhaps you could rewrite your code like this, which should fix your problem:
bool success = true;
while (sucess) {
success = cin >> str;
cout << str;
}
However, I don't understand why you still want the cout to go ahead - if the cin call didn't succeed, you will only be printing the old contents of the string - you do not clear it anywhere (unless you do so in other code which you haven't posted here).

Related

I have a problem with reading & printing my class

I have a problem with printing my class. I want this class to read a binary number and then print it. I am a Beginner, so here can be a really dumb mistake.
This code has a wrong output, but a correct input.
I tried to fix this, but I couldn't. I hope you will find the mistake.
Please help. Thanks!
Here is the code:
#include <iostream>
using namespace std;
class Binary
{
int len;
bool* arr;
public:
Binary();
Binary(const Binary&);
friend istream& operator >> (istream&, Binary&);
friend ostream& operator << (ostream&, const Binary&);
};
Binary::Binary()
{
len = 0;
arr = new bool[0];
}
Binary::Binary(const Binary& b)
{
len = b.len;
arr = new bool[len];
for (int i = 0; i < len; i++) {
arr[i] = b.arr[i];
}
}
istream& operator>>(istream& in, Binary& b)
{
char line[101];
in.getline(line, 100);
b.len = strlen(line);
b.arr = new bool[b.len];
for (int i = 0; i < b.len; i++) {
b.arr[i] = (line[i] == '0' ? 0 : 1);
}
return in;
}
ostream& operator<<(ostream& out, const Binary& b)
{
for (int i = 0; i < b.len; i++) {
out << b.arr;
}
return out;
}
int main() {
Binary a;
cin >> a;
cout << a;
return 0;
}
The problem is with this line of code:
out << b.arr;
You are printing the array pointer, b.arr, instead of a value in the array.
This will work:
out << b.arr[i] ? '1' : '0';
You should also consider writing a destructor to free your previously allocated memory, and also free the previous array before overwriting it's pointer on this line:
b.arr = new bool[b.len];

Recursion returning function without returning in special cases

I need to combine a given password by bruteforce. So I decided to use recursion function which returns string
string bruteforce(string password, string forcedPassword)
{
if (password.length() == forcedPassword.length())
{
if (password == forcedPassword)
{
return forcedPassword;
}
// What can I do here to return nothing and continue from the previous step?
}
for (int j = 32; j <= 126; j++)
{
forcedPassword += char(j);
bruteforce(password, forcedPassword);
}
}
int main()
{
...
cin >> password;
cout << bruteforce(password, "");
...
}
The problem is when I get password.length() == forcedPassword.length() but they are not the same. I need to exit only the last step of the recursion without any returning values. Is there any way to make it?
Assuming non empty password (else use optional), you may write:
std::string bruteforce(const std::string& password, const std::string& forcedPassword)
{
if (password.length() == forcedPassword.length())
{
if (password == forcedPassword)
{
return forcedPassword;
}
return "";
}
for (int j = 32; j <= 126; j++)
{
auto res = bruteforce(password, forcedPassword + char(j));
if (!res.empty()) {
return res;
}
}
return "";
}
I don't know if this will help you or not in your specific case:
std::string bruteforce( const std::string& enteredPassword, std::string& forcedPassword ) {
if ( enteredPassword.length() == forcedPassword.length() ) {
if ( enteredPassword == forcedPassword ) {
return forcedPassword;
}
return "";
}
static int j = 31;
while ( j <= 126 ) {
++j;
// Display forcedPassword to test it for each recursive iteration
std::cout << forcedPassword << "\n";
return bruteforce( enteredPassword, forcedPassword + char( j ) );
}
return "";
}
int main() {
std::string password;
std::string forcedPassword( "Hello" );
std::cout << "Enter the password\n";
std::cin >> password;
std::cout << bruteforce( password, forcedPassword );
std::cout << "\Press any key and enter to quit.\n";
char q;
std::cin >> q;
return 0;
}
But this does compile, build and run without errors, and there is no stack overflow here.
I made the enteredPassword a const ref since it will not be modified by this function. For the forcedPassword since you are showing that you are concatenating to this string I choose to make this a non const reference that will be modified. Instead of a for loop from [32,126], I choose to use a while loop using a static int counter. I initially set this value to 31 and check this loop while it is <= 126. Then within the loop I pre-increment the static counter, I then display the forcedPassword value for debugging purposes. Finally I return this recursive function passing in the original non modified enteredPassword along with the forcedPassword while updating it with char(j). For control paths where there are no operations to be made I simply just returned "";
Using bool function as suggested in comments you can do
#include <iostream>
using namespace std;
bool bruteforce(const string& password, string& forcedPassword, unsigned int length=0)
{
if (password.length() == length)
{
if (password == forcedPassword)
{
return true;
}
return false;
}
for (int j = 32; j <= 126; ++j)
{
forcedPassword[length] = char(j);
if ((bruteforce(password, forcedPassword, length+1)))
return true;
}
}
std::string findpassword(const string& password) {
std::string forcedPassword = "";
while (forcedPassword.length() < password.length())
forcedPassword.push_back('a');
if (bruteforce(password, forcedPassword))
return forcedPassword;
else
return "failed";
}
int main()
{
std::string password;
cin >> password;
cout << findpassword(password);
}

C++ Overloading operator >> (input) doesn't change original

I'm trying to build a custom dictionary class with custom string and definition classes. While trying to overload the >> (input) I get some kind of a problem. when the function ends the dictionary sent to it doesn't change. attaching the code:
This is the overloading:
istream& operator>>(istream& ip, Dictionary& var) {
Definition temp;
ip >> temp;
var += temp;
return ip;
}
and some other functions used in it:
Dictionary& Dictionary::operator+=(Definition& input) {
if (!checkCopy(input))
{
Definition** temp;
temp = new Definition*[numWords + 1];
for (int i = 0; i < numWords; i++)
{
temp[i] = book[i];
}
numWords++;
temp[numWords - 1] = &input;
delete[] book;
book = temp;
}
return *this;
}
Dictionary::Dictionary(Dictionary& input) {
*this = input;
}
Dictionary& Dictionary::operator=(Dictionary& input) {
if (numWords != 0)
delete[] book;
book = new Definition*[input.numWords];
for (int i = 0; i < input.numWords; i++)
{
*this += *input.book[i];
}
return *this;
}
And the class itself:
class Dictionary
{
private:
int numWords = 0;
Definition** book;
public:
Dictionary();
~Dictionary();
Dictionary(Dictionary&);
bool operator==(Dictionary&) const;
Dictionary& operator=(Definition&);
Dictionary& operator=(Dictionary&);
friend ostream& operator<<(ostream&, const Dictionary&);
friend istream& operator>>(istream&, Dictionary&);
Dictionary& operator-=(int);
Dictionary& operator+=(Definition&);
bool checkCopy(Definition&);
Definition& operator[](int); //left side brackets for input
Definition operator[](int) const; //right side brackets for output
};
EDIT: here is also the overloading operator for definition input:
istream& operator>>(istream& ip, Definition& var)
{
cout << "Please enter a word: " << endl;
ip >> var.word;
cout << "Please enter the number of definitions for this word: " << endl;
int idx;
cin >> idx;
while (idx<0)
{
cout << "Error: number of definitions not possible. Please Try again: " << endl;
cin.clear();
cin.ignore(INT_MAX, '\n');
cin >> idx;
}
cin.clear();
cin.ignore(INT_MAX, '\n');
String* temp = new String[idx];
for (int i = 0; i < idx; i++) {
cout << "Please enter the " << i + 1 << "th definition: " << endl;
cin >> temp[i];
var += temp[i];
}
var.sortDefinition();
return ip;
}
Help is indeed needed.
You should really stick to std::vector and other collection types rather than juggling around with pointers and new/delete as you do here.
In your operator+= function you're copying the address of a temporary variable into your array:
temp[numWords - 1] = &input;
Once the calling function operator>> ends, this pointer is less than worthless, because the original object (Definition temp;) does not exist any longer. Therefore the behaviour of that code is undefined!
You might get around this by defining a copy c'tor for Definition and then changing above line to:
*temp[numWords - 1] = input;
Also in your assignment operator you're making use of the operator+= function. However, your numWords member is not set appropriately at this time, so operator+= will likely do the wrong thing. So add a line to the assignment operator like this:
if (numWords != 0)
{
delete[] book;
numWords = 0; // add this line
}
There were 2 problems:
what Alexander said about the temporary variable. changed it to:
Dictionary& Dictionary::operator+=(Definition& input) {
if (!checkCopy(input))
{
Definition** temp;
temp = new Definition*[numWords + 1];
temp[0] = new Definition[numWords];
for (int i = 0; i < numWords; i++)
{
temp[i] = book[i];
}
temp[0][numWords] = input;
delete[] book;
book = temp;
numWords++;
}
return *this;
}
The second was that in the Definition class when I tried to access the number of definitions in an object that wasn't created due to the double pointer:
Definition** temp;
temp = new Definition*[numWords + 1];
So I changed it so it won't access it but first build it.
Thanks for the help Alexander!

c++ getting error trying to call a function that reads a file

I have a function Readf I'm trying to call to fill in an array inside each constructor, I tried only with the default constructor with a code statement ReadF(cap,*point,counter);.
The second argument is what's giving me a problem in figuring out, I would get an error with '&' beside it or ' '. And I get an external error with the '*', I'm still new to c++ so I'm not experienced in dealing with classes.
I have to use the ReadF member function, are there other ways instead of calling it to get the results I need.
Also some of the code for the functions I have might not be perfect, but I would like to deal with this problem first before I move on to another.
array.h:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
class AR {
public:
AR();
AR(int);
AR(const AR&);
//~AR();
void ReadF(const int, string&, int);
AR& operator=(const AR&);
friend ostream& operator<<(ostream&, AR&);
friend ifstream & operator>>(ifstream&, AR&);
private:
string* point;
int counter;
int cap;
};
array.cpp:
#include "array.h"
AR::AR() {
counter = 0;
cap = 2;
point = new string[cap];
}
AR::AR(int no_of_cells) {
counter = 0;
cap = no_of_cells;
point = new string[cap];
}
AR::AR(const AR& Original) {
counter = Original.counter;
cap = Original.cap;
point = new string[cap];
for(int i=0; i<counter; i++) {
point[i] =Original.point[i];
}
}
// AR::~AR() {
// delete [ ]point;
//}
ostream& operator<<(ostream& out, AR& Original) {
cout << "operator<< has been invoked\n";
for (int i=0; i< Original.counter; i++) {
out << "point[" << i <<"] = " << Original.point[i] << endl;
}
return out;
}
AR& AR::operator=(const AR& rhs) {
cout << "operator= invoked\n";
if (this == &rhs)
return *this;
point = rhs.point;
return *this;
}
void ReadF(const int neocap, string& neopoint, int neocounter) {
ifstream in;
in.open("sample_strings.txt"); //ifstream in; in.open("sample_data.txt");
if (in.fail())
cout<<"sample_data not opened correctly"<<endl;
while(!in.eof() && neocounter < neocap) {
in >> neopoint[neocounter];
neocounter++;
}
in.close();
}
ifstream& operator>>(ifstream& in, AR& Original) {
Original.counter = 0;
while(!in.eof() && Original.counter < Original.cap) {
in >> Original.point[Original.counter];
(Original.counter)++;
}
return in;
}
It appears you are missing AR:: in the ReadF definition.
On second thought you are reading into an index of neopoint that likely isn't allocated yet. You could change ReadF to read:
void ReadF(const int neocap, string& neopoint,int neocounter)
{
ifstream in;
in.open("sample_strings.txt"); //ifstream in; in.open("sample_data.txt");
if (in.fail())
{
cout<<"sample_data not opened correctly"<<endl;
return;
}
neopoint.resize(neocap);
while(neocounter < neocap && in >> neopoint[neocounter])
{
neocounter++;
}
in.close();
}
Although you probably want to look into stringstream
std::ifstream in("sample_strings.txt");
if (in)
{
std::stringstream buffer;
buffer << in.rdbuf();
in.close();
inneopoint= buffer.str();
}

Function to find a string within a larger string

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?"