I have just started learning C++ a few days back. I was given an assignment to demonstrate + operator overloading to concatenate two strings. I came up with this solution:
#include <iostream>
using namespace std;
class Strcpy{
private:
char* wrd;
int len;
public:
Strcpy();
Strcpy(char* );
void Display();
friend Strcpy operator + (Strcpy, Strcpy);
friend Strcpy concatinator(Strcpy, Strcpy);
};
Strcpy :: Strcpy(){
wrd = '\0';
len = 0;
}
Strcpy :: Strcpy(char* w){
int i; len = 0;
for(i = 0; w[i] != '\0' ; i++)
len ++;
wrd = w;
}
void Strcpy :: Display(){
cout << "\nOutput: " << wrd << " "<< len;
}
Strcpy operator + (Strcpy obj1, Strcpy obj2){
Strcpy temp;
int i;
temp.wrd = new char[obj1.len + obj2.len];
temp = concatinator(temp, obj1);
temp = concatinator(temp, obj2);
temp.wrd[temp.len] = '\0';
return temp;
}
Strcpy concatinator(Strcpy obj, Strcpy temp){
for(int i = 0; temp.wrd[i] != '\0'; i++)
{
obj.wrd[obj.len] = temp.wrd[i];
obj.len++;
}
return obj;
}
int main(){
Strcpy word, word_I("Hello"), word_II("World");
word = word_I + word_II;
word.Display();
return 1;
}
Some things to be noted:
deprecated conversion from string constant to 'char*' [-Wwrite-strings] I realize this is being caused because I am converting an immutable type to a mutable one but what alternative approach can I try to get rid of this.
I want to avoid using friend functions, but the overloaded operator needs two arguments which isn't possible if it remains a class member.
The following line works the same even if it is changed, why is this happening:
temp.wrd = new char[obj1.len + obj2.len];
//changed to
temp.wrd = new char[//any number here];
I want avoid using string functions if that is possible at all.
Whenever i try taking an input in the following form, it crashes:
char* Strcpy :: get(){
char* temp;
cin >> temp;
return temp;
}
int main(){
Strcpy word;
Strcpy word_I(word.get()), word_II(word.get());
word = word_I + word_II;
word.Display();
return 1;
}
Lastly, I would appreciate any help that would help me improve on the existing solution and some explanation so as to why it is better and the mistakes I am making.
deprecated conversion from string constant to 'char*' [-Wwrite-strings] I realize this is being caused because I am converting an immutable type to a mutable one but what alternative approach can I try to get rid of this.
You never modify *w, so you can use a pointer to const instead.
I want to avoid using friend functions, but the overloaded operator needs two arguments which isn't possible if it remains a class member.
The first argument of a member operator overload is the implicit this pointer. If you declare Strcpy Strcpy::operator+(const Strcpy&) const, it will be a binary operator. That said, the friend operator is probably a better approach.
The following line works the same even if it is changed, why is this happening:
temp.wrd = new char[obj1.len + obj2.len];
//changed to
temp.wrd = new char[//any number here];
It will work as long as "any number" is large enough to contain the entire string. If you write outside of the bounds, the behaviour is undefined.
Whenever i try taking an input in the following form, it crashes:
char* temp;
cin >> temp;
The stream extraction operator requires that a char* passed to it must point to an array sufficiently large to contain the user input. You forgot to initialize temp, so the requirement is not satisfied. As a result, the behaviour of the program is undefined. Solution: Allocate some memory and initialize temp to point to that memory.
The same bug occurs the constructor Strcpy(char*). You don't initialize this->wrd, but you dereference it. Therefore the behaviour is undefined. The solution is the same as above.
If I understood this right
I want to avoid using friend functions, but the overloaded operator
needs two arguments which isn't possible if it remains a class member.
your statement is wrong.
Sample for a binary + operator in a class:
#include <iostream>
class Int {
private: int _i;
public:
Int(int i = 0): _i(i) { }
Int operator + (const Int &i) const
{
return Int(_i + i._i);
}
int get() const { return _i; }
};
int main(int, char**)
{
Int i1(1), i2(2);
Int i;
i = i1 + i2;
std::cout << "i: " << i.get() << std::endl;
return 0;
}
Compiled and tested with gcc on cygwin:
$ g++ -o test-op-plus test-op-plus.cc
$ ./test-op-plus.exe
i: 3
Related
This question already has answers here:
What is a debugger and how can it help me diagnose problems?
(2 answers)
Closed 1 year ago.
I want to overload operator + in array that consider char .I want to print Hello Jack But it has eror in my program . How can I fix it?
class Test
{
private:
char s1, s2;
public:
Test() {}
Test(char a, char b) { s1 = a; s2 = b; }
void Print() { cout << "String1 :" << s1 << "\tString2 :" << s2 << endl; }
Test operator+(const Test& r)
{
Test temp;
temp.s1 = s1 + r.s1;
temp.s2 = s2 + r.s2;
return temp;
}
};
//////////////////////////////////////////////////////////////////////////
int main()
{
char str1[] = "Hello";
char str2[] = " Jack ";
Test t1(str1[]);
Test t2(str2[]);
Test temp;
temp = t1 + t2;
temp.Print();
}
You're defining pretty much everything wrong.
Your +operator overload sums up the two chars that are part of the "Test", but you only ever pass one of the two to separate Test objects.
If you want to use strings, use std::string instead of arrays of chars, unless you have a particular reason to do so, but at this point this is the least of your problems.
friend Test operator+(Test lhs, const Test& rhs) is how you'd define the return of a new object based on the values of two of the same objects.
You'd then have no need for a print function as it would just be put as-is in an iostream once you override that functionality as well, which would really amount to just returning the stored string (string singular, you only need one per object here).
In its current state, I highly doubt your code even compiles as you are passing one argument to an object that only takes none or two.
I got this error while coding a simple function. This is my function specification.
string studentName;
string courseTaken[3];
void setStudent(string, string[]);
void Student::setStudent(string n, string a[])
{
studentName= n;
courseTaken = a;
}
This is the error I have gotten:
incompatible types in assignment of string* to string [3] on this line courseTaken = a;
In my code, I never declared any pointer or char.
I don't quite understand what is going wrong here.
You can not assign array of strings string a[] to array courseTaken using = operator. The expression string a[] is equivalent to std::string*. That is why you get the compiler error.
This may be what you wanted:
#include <iostream>
using namespace std;
class Student
{
public:
string studentName;
string courseTaken[3];
void setStudent(string n, string a[]);
};
void setStudent(string n, string a[]);
void Student::setStudent(string n, string a[])
{
studentName = n;
for(int i=0; i < sizeof(courseTaken)/sizeof(courseTaken[0]); i++)
courseTaken[i] = a[i];
}
int main()
{
Student student;
string courses[3] = {"Cobol","C++","Fortran"};
student.setStudent("Eva", courses);
for (int i = 0; i < 3; i++){
cout << student.courseTaken[i] << endl;
}
return 0;
}
Output:
Cobol
C++
Fortran
It seems you don't understand array decay mechanism of C-format arrays.
For many context, an array name will be explained as a pointer to the first element of the array. And this pointer is a prvalue which just like this pointer, you can NOT assign to it.
the "modern Cpp way"(C++11) is to use std::array, which overloaded the =operator and stores the size of the array so that it won't be decayed while passing to a function.
The second way is to pass the reference, with a template you can ensure the array's size, then use std::memcpy. And you can add a parameter stores the array's size, and then you can use memcpy too.
I hope you use the first way, don't forget -std=c++11
This is because you are passing an array to a variable that's why this error occurs. To solve this problem you may use pointer in argument to solve this problem. Change your function to this.
void Student::setStudent(string n, string* a)
{
studentName= n;
courseTaken = a;
}
I have a class named Fstring, it has a wchar_t* in it.
I wrote the following to copy the string literal into Fstring:
#include <iostream>
using namespace std;
class Fstring{
wchar_t *arr;
public:
Fstring& operator = (const wchar_t temp[])
{
delete [] arr;
arr=new wchar_t[wcslen(temp)];
for(int i=0;i<=wcslen(temp);i++)
arr[i]=temp[i];
return *this;
}
};
int main()
{
Fstring test=L"Hello World";
return 0;
}
But it did not work. The compiler gave me the following error:
error C2440: 'initializing' : cannot convert from 'const wchar_t [12]'
to 'Fstring'
I'm really confused, I googled "Overloading operators" but all of results have the same way I used to overload the operator. So why does this not work?
When you see Type name = initializer it does not use the assignment operator. It is declaring a variable and is therefore initialization(technically copy-initialization or copy-list-initialization). That means it calls a constructor. Since you do not have a constructor that takes a const wchar_t* you will get an error.
What you need is to implement a constructor that takes a const wchar_t* and initialize arr with that. That would look like
Fstring(const wchar_t temp*) : arr(new wchar_t[wcslen(temp) + 1])
{
size_t size = wcslen(temp);
for(int i = 0; i < size; i++)
arr[i] = temp[i];
arr[size] = L'\0'
}
You are also going to have to implement a copy constructor. For more on why see What is The Rule of Three?
Do note that you are reinventing the wheel. If you want a wide character string you can use std::wstring which has all this done for you.
I have simple class which holds array of integers. I want to overload + to merge two ararys together. I have defined two overloadors. + and =
class Money{
Money & operator =( const Money &a )
{
for( int i = 0; i < size ;i++ ) arr[i] = a.arr[i];
return *this;
}
Money & operator +( const Mone &a )
{
Money temp;
for( int i = 0; i < size ;i++ ){
temp.arr[i] = arr[i] + a.arr[i];
}
return temp;
}
private:
int arr[50];
int size = 50;
}
The problem is index 0, it returns random number from memory . I have seen some question about similliar problem but with * operator ( i will try to find it and link it ), where i got my operator = from. What is causing this? I am invoking it as
Money a;
Money b;
Money d;
d = a + b;
// print array;
I am new to overloading so i have harder time analyzing and understaning concept.
The basic problem is here, and has nothing really to do with overloading:
Money & operator +( const Mone &a ) {
Money temp;
:
return temp;
The problem being that you return a reference to a local variable, which is destroyed when the function returns so is a dangling reference, leading to undefined behavior.
Change it to return Money by value.
As I understand the problem in operator + you are creating a temporary variable temp. That variable will live until the code of "operator+" is finished. As you are returning a reference to that variable id est essentially a hidden pointer to it when the code finishes that reference isn't any more valid. If instead you change the code and return by value everything should work correctly. Instead things work correctly for the =operator because the reference you return is tied to an object that will exist after the end of the "operator=" call.
I wrote a simple test program in c++ but why does this crash on:
s[i] = s[i] - 'a' + 'A';
with the exception: Access violation writing location 0x01327808
#include "stdafx.h"
#include <iostream>
using namespace std;
class String
{
public:
char *s;
int len();
void upper();
String(char*);
};
String::String(char*x)
{
s = x;
}
int String::len()
{
return strlen(s);
}
void String::upper()
{
for (int i = 0; i < len(); i++)
{
if (s[i] >= 'a' && s[i] <= 'z')
{
cout << s[i] << endl;
s[i] = s[i] - 'a' + 'A';
}
}
};
int main()
{
String s("test");
s.upper();
cout << s.len() << endl;
cout << s.s << endl;
system("pause");
}
It's because of:
String s("test");
What this does is to pass the const char * "test" to your constructor which then simply stores the address of that string.
Later, when you try to modify the memory that the pointer points to, that's undefined behaviour.
Typically, string literals will be stored in read-only memory to allow certain optimisations to take place, and any attempt to modify them will result in a access violation.
If you were to change:
String s("test");
into:
char cp[] = "test";
String s(cp);
you may well find it will work.
However, your class should really be making a copy of the string for its own purposes - a mere pointer is unsafe, since the code that passed you that pointer can change the contents of it as well.
Things you should change in your code to make it safer:
s should be a private member, not a public one.
your constructor should make its own copy of the string:s = new char[strlen(x)+1];strcpy (s,x);.
add a destructor to take care of that as well:String::~String() { delete[] s; }.
consider having your constructor receive a const char * (since you're not changing it).
consider using toupper(ch) instead of ch - 'a' + 'A'. While your formula works for ASCII, I don't believe it's guaranteed by the standard.
cout stuff should be handled by the class rather then code outside of it (this will be mandatory once you make s private.
consider having a no-argument constructor so that string arrays will work okay.
String literals are constant (you're exploiting a deprecated automatic conversion to char *), and you're trying to modify one inside your class, which is undefined behavior.
In practice, the access violation happens because newer versions of VC++ put string literals in a section of the executable which is mapped in memory as read-only (which is definitely a good thing), and any attempt to write it results (correctly) in an access violation.
Solution: copy the string passed to the constructor (which, by the way, should take a const char *) in a buffer local to your class, probably dynamically allocated. In this last case, if you don't want to implement a copy constructor and an assignment operator, make them private thus avoiding that the default ones are executed, otherwise you'll get troubles (double frees and other nasty stuff) if you create copies of a String object.
Better solution: in real projects, don't reinvent the wheel and use a good pre-made string class like std::string/CString/wxString/whatever the framework you're using provides you.
String::String(char*x)
{
s = x;
}
You shouldn't copy string literals address just like above. Behavior is undefined.
you need to allocate memory and copy it.
size_t len = strlen(x);
s = new char[len+1];
strcpy(s,x);
Make sure to delete it in destructor of your String class.
You tried to assign to a string literal. They are not char*, they are const char*. Attempting to modify a string literal is undefined behaviour.
"test" is a const string, you cannot write to it.
Instead of
s = x;
try doing strcpy, so that s will have a non-const copy of x, rather than the const original.
You cannot modify "test" string by accessing with [].
The error is s[i] = something.
Infact, char* is only a pointer to an IMMUTABLE string.
In the constructor you must allocate space internally for handle "test" string literal and then you can modify single character accessing with [] operator.
Example to solve (with basic copyng):
String::String(char *original)
{
size_t len = strlen(original) + 1;
s = new char[len];
for ( size_t i = 0; i < len; ++i )
{
s[i] = original[i];
}
}