I am trying to write my own string class using the library for preparing my exam .But I had this error saying that
main.cpp:9:22: error: no match for ‘operator+’ (operand types are ‘const
char [5]’ and ‘MyString’)
MyString c = "Hola" + b;
My main is like this. It works file then "Hola" and b change place.
MyString b("Mundo\n");
MyString c = "Hola" + b;
I think it doesn't call the constructor there .
My class has these in private.
char * _str
int _length
My constructor.
MyString::MyString(const char * str){
int length = 0;
for(char c = str[0]; c != '\0' ; c++)
++length;
_length = length;
_str = new char[length+1];
strcpy(_str,str);
}
And my + overload
const MyString MyString::operator+(const MyString& mS) const{
char * tempChar = new char[_length + mS._length];
MyString tempStr(tempChar);
delete[] tempChar;
strcpy(tempStr._str,_str);
strcat(tempStr._str,mS._str);
return tempStr;
}
Edit : I solved it by making operator+ a friend function but I want to know why
when you write
MyString b{"Mundo\n"};
MyString c = b + "Hola";
string literal will be sent your operator+ function paremeter, and MyString object created with "Holla"(You can test it with write a text in your constructor).
Besides, when you didn't write your friend function and write
MyString b{"Mundo\n"};
MyString c = "Holla" + b;
compiler will search function which has first parameter is const char * and can't find.(and no match error show this). this is the reason for writing friend function.
I hope you can understand reason
Related
I have a String struct that I overloaded the subscript operator on. But it doesn't seem to work.
//my_string.h
struct String {
char* Text;
uint64 Length;
char& operator[](int32 index);
}
//my_string.cpp
char& String::operator[](int32 index) {
ASSERT(index >= 0);
return Text[index];
}
//main.cpp
String* test = string_create("Hello world");
char c = test[0];
Visual Studio gives me the following error:
no suitable conversion function from "String" to "char" exists
The compiler issued an error because in this statement
char c = test[0];
the expression test[0] has the type String.
In this declaration
String* test = string_create("Hello world");
you declared a pointer instead of an object of the type String.
If it is not a typo then in this case you have to write
char c = ( *test )[0];
or
char c = test->operator []( 0 );
Also it looks strange that the data member Length has the type uint64
uint64 Length;
while the index used in the operator has the type int32.
I have a derived class called Mystring that is derived from std::string, and I would like to set the value of the string that I am working with.
From my understanding to access the string object from std::string I would use *this to get the string that I am currently working with.
I would like to set *this to a string of my choosing, I did this my setting *this = n; but it crashes my code and returns a "Thread 1: EXC_BAD_ACCESS (code=2, address=0x7ffeef3ffff8)" my code is below:
So my question is, how can I set the value of std::string to something through my derived class. Much thanks!
class Mystring : public std::string
{
public:
Mystring(std::string n);
std::string removePunctuation();
std::string toLower();
};
Mystring::Mystring(std::string n)
{
*this = n;
}
std::string Mystring::removePunctuation()
{
long int L = length();
char *cstr = new char[L + 1];
strcpy(cstr, c_str());
//cout << cstr[L-1] << endl; // last character of c string
if(!isalpha(cstr[L-1]))
{
pop_back() ;
}
return *this;
}
std::string Mystring::toLower()
{
long int L = length();
char *cstr = new char[L + 1];
strcpy(cstr, c_str());
for(int i = 0; i < L;i++)
{
int buffer = cstr[i];
cstr[i] = tolower(buffer);
std::cout << cstr[i];
}
std::string returnstring(cstr);
delete [] cstr;
return returnstring;
}
int main() {
Mystring temp("dog");
std::cout << "Hello World";
return 0;
}
Style aside, the fundamental idea of using an assignment operator to "reset" an inherited subobject is not necessarily incorrect.
However, a conversion is required to get from std::string (the type of the RHS) to Mystring (the type of the LHS, i.e. *this). The only way to perform that conversion is to use the constructor Mystring(std::string). Except… you're already in it. Hence that function is effectively recursive and will repeat forever until you exhaust your stack.
You need to upcast *this to a std::string in order to make this work:
static_cast<std::string&>(*this) = n;
I do agree with the other people here that you shouldn't be deriving from std::string, and certainly not just to add a couple of utility functions that ought to be free functions taking std::string (perhaps in a nice namespace, though?).
Don't do it. Derivation provides no benefit in this situation.
Create your added functions as free functions that operate on a string. For example:
void remove_punctuation(std::string &s) {
if (!std::isalpha(s.back()))
s.pop_back();
}
void tolower(std::string &s) {
for (auto &c : s)
c = std::tolower(c);
}
Making either/both of these a member function serves no purpose and provides no benefit.
References
GOTW #84: Monoliths Unstrung
How Non-Member Functions Improve Encapsulation
Hello i made a variable storage like string and this is the source
class str
{
private:
const char * _mystring;
public:
// Using this function to made new str
str(const char * _str) { _mystring = _str; }
// Get the content of this str
const char * read() { return _mystring; }
// Get the content in char *
char * read_c() { return strdup(_mystring); }
// Operator for equal action with extern const char
str & operator = (const char * _str) { _mystring = _str; return *this; }
// Operator for equal action with extern str storage
str & operator = (str _str) { _mystring = _str.read(); return *this; }
// Operator for add action
str operator + (const char * _str) {
return str(strcat(read_c(), _str));
}
// Operator for add action with new str
str operator + (str & _str) {
return str(strcat(read_c(), _str.read()));
}
};
and this is my test program
int main() {
str var1("Var1"); // No problem
str var2("Var2"); // No problem
str var3 = var1 + var2; // No problem
str var4 = var1 + "tempStr"; // I got runtime error !
str var5 = "tempStr" + var2; // I got error before compile
cout << var1.read() << endl;
cout << var2.read() << endl;
cout << var3.read() << endl;
cout << var4.read() << endl;
return 0;
}
what is the problem that i can't create something like var3 and var4 and i got error (i get error while i want to merge const char with my str ... i set + operator but there is problem for when i want to merge const char with my str (not my str with const char... on this action, there is no problem)
but wait i got error (debug (close program)) after compile and print var7 too !
For str var3 = "tempTxt0" + "tempTxt1" + "tempTxt2"; // Error:
This does not work because the compiler sees these types (omitting variable names): str = const char* + const char* + const char *. Adding char pointers together is not what you want. However, if you only had one of them to be type of class str, it would work. E.g. str = str(const char*) + const char* + const char * would call the str::operator+, which returns a new object of type str and the rest will follow the same way.
For str var4 = "tempTxt3" + var1; // Error:
This does not work because you declare operator+ as a member function. Again compiler sees these types (omitting variable names): str = const char* + str. There is no operator+ declared for const char* as the first operand and str as the second operand. You have a member operator+ but that operator works on a class str so you would need a class str on the left hand side; as in str + const char*. Think of it like a function call because it is exactly a member function call. It is the same as typing str = str.operator+("text"). Now you see, str = "text".operator+(str) does not work because it does not exist.
If you declared a non-member function str operator+(const char* first, const str& second);, it would work. The compiler will look for operators that matches what you want in outer namespace scopes of the parameters up to the global scope (this is called ADL). But there is a better way:
Declare str operator+(const str& lhs, const str& rhs);. If you declare your operators this way in the namespace scope of the class str, then compiler will use ADL (on Wikipedia) using the second argument's type (which is class str) and find this operator. Then, the compiler can see that class str has a non-explicit constructor which can take const char*: str(const char * str). It can then create a temporary object of class str and use the operator+ you defined.
So for your example, as you do not have any namespaces, you would need this at its simplest (notice I have added a few const keywords):
class str
{
private:
const char * _mystring;
public:
// Using this function to made new str
str(const char * _str) { _mystring = _str; }
// Get the content of this str
const char * read() const { return _mystring; }
// Get the content in char *
char * read_c() const { return strdup(_mystring); }
// Operator for equal action with extern const char
str & operator = (const char * _str) { _mystring = _str; return *this; }
// Operator for equal action with extern str storage
str & operator = (str _str) { _mystring = _str.read(); return *this; }
};
// Operator for add action with new str
str operator+ (const str& lhs, const str& rhs) {
return str(strcat(lhs.read_c(), rhs.read()));
}
P.S.
Your example has more problems. read_c duplicates the string (let say) of 10 bytes and you concatenate more bytes at the end of it. That is an overflow because your duplicated buffer is 10 bytes. You have to allocate and free the memory properly but that is for another question I guess. E.g.
str operator+(const str& lhs, const str& rhs) {
const std::size_t ls = lhs.size();
const std::size_t rs = rhs.size();
char* n = new char[ls + rs + 1];
std::memcpy(n, lhs.read(), ls);
std::memcpy(n + ls, rhs.read(), rs);
n[ls + rs] = '\0';
return str(n);
}
Then you still have the problem of when to delete.
str var3 = "tempTxt0" + "tempTxt1" + "tempTxt2"; // Error
str var4 = "tempTxt3" + var1; // Error
In these lines you're trying to add 2 pointers to some static memory (in other words your operator isn't called)
On the left side of the operator plus needs to be your class
Having an empty (only with \0) instance of your class will fix your error (as you might have already noted):
str var4 = str("") + "tempTxt3" + var1; //now it is okay
Also, note that strcat doesn't allocate memory for concatening, you have to do it with realloc yourself
When you override a binary operator such as +, the left operand has to be the object in question. The reason you get errors is because the left operand is a string constant and this the default + is used.
You need to create friend functions for these operators that accept a const char * for the first parameter and either str or a const char * for the second parameter.
str var4 = var1 + "tempStr"; // I got runtime error !
in this case following operator+ overload is called:
str operator + (const char * _str) {
return str(strcat(read_c(), _str));
}
you call strcat on a pointer which points to a buffer not large enough to contain both current string and _str. The fastest solution is to use std::string, otherwise you need to allocate large enough buffer and also remember to keep care of its lifetime (adhere to rule of three etc.)
str var5 = "tempStr" + var2; // I got error before compile
You need a global operator overload of following signature:
str operator + (const char * _str, const str& s);
class mystring
{
public:
mystring(const char x[])
: capacity(1024)
{
for (int i = 0; i < capacity; ++i)
{
if (x[i] == '\0') break;
s[i] = x[i];
length++;
}
}
mystring()
: capacity(1024), s('\0'), length(0)
{}
//etc...
private:
const int capacity;
char s[1024];
int length;
};
I'm getting this error:
In file included from main.cpp:19:0:
mystring.h: In constructor ‘mystring::mystring()’:
mystring.h:21:44: error: incompatible types in assignment of ‘char’ to ‘char [1024]’
: capacity(1024), s('\0'), length(0)
I don't under stand what's going on. I'm a bit new to constructors. Thanks in advance!
Change s('\0') to s("\0")
WHEN you use single quotes, it's a single character. You must use double quotes to test it as a string.
The error you are getting right now is because that you are trying to put char into char[].
char[] is an array of char and char itself is just a char;
regularly, char[] is defined as char str[] = "Test";
Think about that and try to fix your code!
Hope this helps
I started writing a very simple implementation of a string class in c++, here is the code:
class String
{
public:
String()
{
this->_length = 0;
this->_size = 0;
this->_string = NULL;
}
String(const char* str)
{
this->_length = strlen(str);
this->_size = this->_length + 1;
this->_string = new char[this->_size];
strcpy_s(this->_string, this->_size, str);
}
~String()
{
if (this->_string != NULL)
{
delete[] this->_string;
this->_string = NULL;
}
}
String& operator+(const char* str)
{
String* temp = new String();
temp->_length = strlen(str) + strlen(this->_string);
temp->_size = temp->_length + 1;
temp->_string = new char[temp->_size];
strcpy_s(temp->_string, temp->_size, this->_string);
strcat_s(temp->_string, temp->_size, str);
return (String&)*temp;
}
int Length()
{
return this->_length;
}
private:
int _size;
int _length;
char* _string;
};
You can see that my implementation of operator+ is absolutely wrong, in fact there is a memory leak.
Writing the operator+= is way simpler because I can simply concatenate the char* with this->_string and return *this.
I need help with the operator+ implementation.
Note: This is homework so I don't want the solution the copy-paste but it would be awesome if someone could point me in the right direction...
Thanks
Edit:
I added the copy constructor:
String(const String& str)
{
this->_length = str._length;
this->_size = str._size;
this->_string = new char[this->_size];
strcpy_s(this->_string, this->_size, str._string);
}
the operator= and the operator+=:
String& operator=(const String& str)
{
if (this != &str)
{
this->_length = str._length;
this->_size = str._size;
this->_string = new char[this->_size];
strcpy_s(this->_string, this->_size, str._string);
}
return *this;
}
String& operator+=(const String& str)
{
this->_length = this->_length + str._length;
this->_size = this->_length + 1;
char* buffer = new char[this->_size];
strcpy_s(buffer, this->_size, this->_string);
strcat_s(buffer, this->_size, str._string);
delete[] this->_string;
this->_string = buffer;
return *this;
}
but there is still something wrong because if I run a while(true) loop like this:
while (true)
{
String a = String("string a");
String b = a;
b = "string b";
b += " string c";
}
the memory used by the process will increase continuously
You could reuse the operator+= in the operator+:
(The code below assumes that you have an operator+=, a copy constructor and an assignment operator which is NOT the case in the code you pasted).
EDIT: As suggested by Jerry Coffin the following operator should NOT be a class member but a free operator:
EDIT2: And to allow the compiler a bit more optimizations the first argument is not a const-reference anymore:
String operator+(String a, String const &b) {
a += b;
return a;
}
By this you can have a more simple operator+= and simply copy constructor and build the complex thing on the simple ones.
And do not forget:
You MUST implement a copy constructor and assignment operator. Otherwise the compiler generates it for you in a wrong way: The compiler generates code that simply copies the content. So it also copies the pointer but does not allocate new memory for the copy. Then you have two instances referencing the same memory and both try to deallocate it in the destructor which is undefined behavior.
One easy way to implement your operator+ is in terms of +=. Create a copy of the left operand, then use += to add the right operand to it, and finally return the result.
Also note that operator+ shouldn't usually be a member function -- it should normally be a free function. The basic difference is that as a member function, the left operand must already be a string for it to work. As a free function, your string constructor can be used to convert (for example) a string literal. For example, string+"something"; will work with a member function, but "something" + string; won't. With + overloaded as a free function, both of them will work.