I'm using Visual C++ to compile my plug-in for Cinema 4D.
GeDebugOut("-->");
subroot = NULL;
head = NULL;
tail = NULL;
success = PolygonizeHierarchy(source, hh, head, tail, &subroot, malloc);
if (!success) {
/* .. */
}
String str("not set.");
if (subroot) {
GeDebugOut("yes");
str = "yes!";
GeDebugOut("Subroot name: " + subroot->GetName());
}
else {
GeDebugOut("no");
str = "no!";
}
GeDebugOut("Is there a subroot? " + str);
GeDebugOut("<--");
The expected output is the following:
-->
yes
Subroot name: Cube
Is there a subroot? yes
<--
(or the same with "no" instead.) But I get
-->
yes
<--
Why are two prints missing here?
This is the declaration of GeDebugOut.
void GeDebugOut(const CHAR* s, ...);
void GeDebugOut(const String& s);
The String class is concatenateable. It overloads the + operator.
String(void);
String(const String& cs);
String(const UWORD* s);
String(const CHAR* cstr, STRINGENCODING type = STRINGENCODING_XBIT);
String(LONG count, UWORD fillch);
friend const String operator +(const String& Str1, const String& Str2);
const String& operator +=(const String& Str);
You need to use GeDebugOut like you use printf:
GeDebugOut("Some message = %s ", whatever);
where whatever is a c-string, i.e its type is char*.
Since an overload of GeDebugOut accepts String type also, then I think you need to use unicode as:
GeDebugOut(L"Is there a subroot? " + str);
// ^ note this!
because my suspicion is that if unicode is enabled, then CHAR is basically wchar_t, not char. And because of this, the string concatenation doesn't work, as the string-literal doesn't implicitly get converted into String type, to be passed to + overload.
You cannot append a string to a string literal.
"Is there a subroot" is a string literal and the compiler will see the use of it as a pointer to that literal.
A better way would be to do:
GeDebugOut("Is there a subroot? %s ", str);
As you mentioned, there are two versions of GeDebugOut the compiler can choose from:
void GeDebugOut(const CHAR* s, ...);
void GeDebugOut(const String& s);
when it encounters:
GeDebugOut("Is there a subroot? " + str);
"Is there a subroot" is a string literal, which translates to type const char*. I suspect String has a conversion operator to some numeric type. So the compiler is choosing the first overload.
This is resulting in behavior you're not expecting, because the + operation for const char* is pointer arithmetic, not string concatenation, so you're calling GeDebugOut on the pointer sum of your string literal, and whatever the output of that const char* conversion of str is.
There's several ways you can correct this. As another mentioned, you can change it to printf-like syntax. Or you can force it to use the String overlaod like so:
GeDebugOut(String("Is there a subroot?") + str);
Related
Although my compiler doesn't throw an error while assigning const char* to a string, I am wondering if this assignment is really valid and will not throw some unexpected result
string name;
const char* name2 = "ABCD";
name = name2;
You absolutely can.
std::string was meant to replace the tedious and error-prone C strings const char* so for it to be a good replacement/successor it'd need backwards compatibility with const char* which it does.
name = name2; calls operator= so if we check basic_strings overloads for this operator we can see (3):
basic_string& operator=( const CharT* s );
Here CharT is of the type char so you get const char*
Which does what you'd expect it to do, it copies over the contents the const char* is pointing to, to the internal buffer of std::string:
Replaces the contents with those of null-terminated character string
pointed to by s as if by assign(s, Traits::length(s)).
In order to go the other route though, from a std::string to a const char*, you'd need to call its method c_str() on the std::string object.
I am wondering if this assignment is really valid
Yes it's valid:
string name;
const char *name2 = "ABCD";
name = name2;
Note name = name2 calls std::string assignment operator, after which the two variables are totally independent, ie you are free to change name, while name2 remains const (aka literal string).
i try to make exercises and have a problem.
I do not know how to overload the operator+ for char;
The aim is to solve those equation:
cout<<"Please enter here a title: "<<endl;
cin>>s2;
s1="I am a " + s2;
The private part of the String class:
private:
char * str; // pointer to string
int len; // length of string
static int num_strings; // number of objects
static const int CINLIM = 80;
i tried the following code, but it doesnt work:
String operator+(const String &st1, const String &st2)
{ String sum;
int len1=std::strlen(st1.str);
int len2=std::strlen(st2.str);
int lenges=len1+len2;
sum.str=new char[lenges+1];
char *a=st1.str;
char *b=st2.str;
while(*a++) {*a++;}
while(*b++) {*a=*b;}
sum.str=st1.str;
return sum.str;
}
Can someone give a tip?
P.S. The class String contains char * str and int len;
Overloaded operators are NOT considered unless at least one operand has a class or enumeration type. In the expression "Hello" + "I am", the operands have types const char[6] and const char[5], which can both decay to const char*, but since only builtin types are involved here, your custom operator+ doesn't do anything.
You will need to explicitly tell the compiler to convert at least one operand to your String type, as in String("Hello") + "I am".
(Or if you want to define a user-defined literal operator, you would be able to write that as something like "Hello"_str + "I am"_str.)
Why dont you try something like this
std::string str = "str1" + std::string("str2");
I am new to C++
and I know I shouldn't be using printf in c++ while I have cout but this was for experiment sake.
My Question here is Why we have to convert a string to c_str (c string) while passing to printf in c++ while it works fine without converting in cout.
Below is my code
#include<iostream>
#include<stdio.h>
using namespace std;
class A{
int i;
string str;
public:
A (int value, const string & s) : i(value), str(s){};// constructor
// setters
void setvalue(int value) {i = value;}
void setstr(const string & s) {str = s;}
//geters
int get_value() {return i;}
string get_str() {return str;}
const char *get_str_cstr() {return str.c_str();}// I didn't get why we have to declare constant
};
int main(){
// new code
A obj1 = {11, "Jill"};
cout<<"value is : "<<obj1.get_value()<<" string is "<<obj1.get_str()<<endl;
// Now we wil change the values in A
obj1.setvalue(2);
obj1.setstr("Jack");
cout<<"value after change is : "<<obj1.get_value()<<" string after change is "<<obj1.get_str()<<endl;
// now we will use printf where get_str dosen't not work
//Error: for below commented printf function
/*In function 'int main()':|
error: cannot pass objects of non-trivially-copyable type 'std::string {aka class std::basic_string<char>}' through '...'|
||=== Build finished: 1 errors, 0 warnings (0 minutes, 0 seconds) ===|
*/
//printf("Value is %d and String is %s",obj1.get_value(),obj1.get_str());
// hence we declare a new char * get_str_cstr to make it work in printf;
printf("Value is %d and String is %s",obj1.get_value(),obj1.get_str_cstr());
return 0;}
I have also provided the error in program comments.
Thank you!
printf comes from C library, which predates objects, templates, and function overloading. When you specify %s format, the function takes an address of a null-terminated character sequence, and prints it. printf has no idea where the string comes from. In fact, it has no idea of its parameter types, because it uses variable-length parameter list feature.
std::string is a C++ string. Calling c_str() on it produces a pointer to the beginning of a C string, which is suitable for passing to printf and other functions expecting a C string.
cout, on the other hand, has been built with classes and overloading in mind. There is a special overload for operator << for std::string, which lets cout and other output streams extract characters from a C++ string.
printf is originally from C, which does not have std::string, so the analogous argument type is const char* which is what you get when you call .c_str()
The reason std::cout works with std::string is because operator<< is defined for that class.
Because printf() has no idea what a std::string is. The protypes for printf() are
int printf( const char* format, ... );
int fprintf( std::FILE* stream, const char* format, ... );
int sprintf( char* buffer, const char* format, ... );
int snprintf( char* buffer, std::size_t buf_size, const char* format, ... );
The reason std::string works with cout is that std::string provieds operator << which works with cout
string is a class in c++ stl.
c_str() is a member function of class string .
The signature is:
const _CharT* c_str() const { return _M_start; }
now, coming to printf, its signature is:
int printf ( const char * format, ... );
now, as long as you give it an argument that meets const char * format, it accepts it.
I'm trying to concatenate strings using +, but there is some weird stuff going on. Here is my "Grade" class I have for a class project:
#pragma once
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Grade {
private:
string className;
string student;
string letter;
public:
Grade(string c, string s, string l) : className(c), student(s), letter(l) {}
string getLetterGrade() const { return letter; }
string getClassName() const { return className; }
string getStudent() const { return student; }
void setLetterGrade(string l) { letter = l; return;}
void setClassName(string c) { className = c; return;}
void setStudnet(string s) { student = s; return;}
string toString() const { string output = "hello"+student; return output; }
};
Obviously, the toString() method isn't currently what I want it to be.
If I run the toString() as above, I get "hello529173860" out, as expected. However, if I change the line to:
string toString() const { string output = student+"hello"; return output; }
then the output is "hello3860". This isn't just putting the hello string on the front, but its replacing characters from the student string in the process... somehow?
Furthermore, if I try to use:
string toString() const { string output = "hello"+" world"; return output; }
I get an error:
Grade.h: In member function ‘std::string Grade::toString() const’:
Grade.h:29:53: error: invalid operands of types ‘const char [6]’ and ‘const char [7]’ to binary ‘operator+’
string toString() const { string output = "hello"+" world"; return output; }
^
I'm really at a loss for what it going on here... especially since I have done string concatenation earlier in the program without issue.
What I would like is to output something like:
"student+[some white space]+letter+[some white space]+className"
A std::string can be added to anything (another std::string, double-quoted string literal, char) and provide intuitive results, but if you try to add a double-quoted string literal to another string literal or a char then it won't "work":
a string literal added to a char or other integral value will undergo Standard Conversion to a const char*, then any number added to the pointer will move along the literal that number of characters: if the offset isn't inside the string literal then you get undefined behaviour if you dereference (use) the resultant pointer,
two string literals just can't be added, even after decaying to two pointers, so you'll get a compile-time error.
Sometimes you will want to explicitly construct a std::string so that concatenation with other values works as you'd like: e.g. my_string = std::string("hello ") + my_const_char_ptr + '\n'.
Examples:
std::string s = "Hello";
s + " World"; // ok
"Hello " + s; // ok
"Hello " + "World"; // NOT ok - two string literals
s += " World"; // ok
s += " Goodbye " + "World"; // NOT ok - "+" evaluated before "+="
s += std::string(" Goodbye ") + "World"; // OK - right-hand-side no longer two literals
// BUT may be slower than two "s +="
The constant strings "hello" and "world" are nothing but compile time constants of type const char*. Just like you cannot add two int pointers:
int *p1, *p2;
p1+p1; // Error
You cannot add two (const) char* objects. This is against the C/C++ language rules. If you must concatenate two const-char-pointers, you can just place them together:
"hello" "world"
This technique is mainly useful if you use them along with macros. For example:
// Over simplified
#define ONE(_x) _x
#define TWO(_x) _X
ONE("This is") TWO(" concatenation")
If you are adding two (or more) runtime C-Strings, you must use strXXX functions (like strcat), or better use std::string.
There is no operator + for character arrays. So it is obvious that this code
string toString() const { string output = "hello"+" world"; return output; }
is invalid.
In this expression "hello"+" world" there are used two string literals that have the types correspondingly const char[6] and const char[7]. The operator + is not defined for arrays.
You could just write
string toString() const { return string( "hello" ) + " world"; }
In this case there is used the operator + overloaded for the class std::string. Declaration of the local variable input is redundant. So you could simplify the function even the following way
string toString() const { return "hello world"; }
EDIT: The code that immediately follows, is the working version, located within the header
inline char * operator & (const char String1 [], const MyStringClass & String2)
{
int length = strlen (String1) + String2.Length();
char * pTemp = new char [length + 1];
strcpy (pTemp, String1);
strcat (pTemp, String2.GetStr());
return pTemp;
}
This is the first time I've felt the need to ask a question, since I've been unable to find helpful information on my own (via search, Google, book, etc). My course book is C++ Primer 5th Edition and I've read Ch. 14 which covers operator overloading. I'm not necessarily looking for an "answer" but rather a nudge in the right direction (because I do want to learn this stuff).
The assignment has us creating our own string class and overloading a bunch of operators that will take a class object on either side - with exception to the assignment operator which may only take a class object on the left side. I've played around with all sorts of return types (this cannot be a member function; efforts to make this a friend function failed).
/*
Note: return by value, otherwise I get a warning of returning the address
of a local variable, temporary. But no matter the return type or what I'm
returning, I always get the error: C2677: binary '&' : no global operator
found which takes type 'MyStringClass' (or there is no acceptable
conversion)
*/
MyStringClass operator & (const char String1 [], const MyStringClass & String2)
{
/*
The only requirement is that the left side has const char [] so that
(const char []) & (MyStringClass &) will concatenate. There is no return
type requirement; so, I could either try and return a string object or
an anonymous C-type string.
cout << StringOject1 << endl; // this works
cout << (StringObject1 & "bacon") << endl; // so does this;
// another function overloads & such that: obj & const char [] works
cout << ("bacon" & StringObject1) << endl; // but not this
*/
MyStringClass S (String1); // initialize a new object with String1
S.Concat (String2); // public member function Concat() concatenates String2
// onto String1 in S
return S; // this does not work
/* a different way of trying this... */
int Characters = strlen (String1) + String2.Length();
int Slots = Characters;
char * pTemp = new char [Slots + 1];
strcpy (pTemp, String1);
strcat (pTemp, String2.pString); // this won't work; pString is a private
// member holding char * and inaccessible
// making it pointless to try and initialize and return an object with pTemp
}
Have looked at your code and from what I can understand, you're probably looking for something like this:
class MyStringClass
{
public:
const char* data() const;
private:
const char* charptr;
};
const char* MyStringClass::data() const
{
return charptr;
}
MyStringClass operator & (const char String1 [], const MyStringClass & String2)
{
/* a different way of trying this... */
int len = strlen(String1) + String2.Length();
char * pTemp = new char [len + 1]; //total length of both strings
strcpy (pTemp, String1);
strcat (pTemp, String2.data()); // you need to have a public member function that returns the string as const char*
MyStringClass str(pTemp); //requires MyStringClass to have constructor that takes char*
return str; //return the string
}