I have two string declarations:
killerName
victimName
I need to convert these two string values to const* char.
Example of how I use my method:
if (killer.IsRealPlayer) {
killerName = killer.GetName(); -- need to convert to const* char
victimName = victim.GetName(); -- need to convert to const* char
Notice(killerName + "has slain:" + victimName, killer.GetMapIndex(), false);
}
Some error I receive:
Error 111 error C2664: 'Notice' : cannot convert parameter 1 from 'std::basic_string<_Elem,_Traits,_Ax>' to 'const char */
It seems that function Notice have the first parameter of type const char * However the expression passed to it as the first argument
killerName + "has slain:" + victimName
has type std::string
Simply call the function the following way
Notice( ( killerName + "has slain:" + victimName ).c_str(), killer.GetMapIndex(), false);
Notice(string(killerName + "has slain:" + victimName).c_str(), killer.GetMapIndex(), false);
std::string::c_str() gives the const char* to the buffer. I think that's what you want.
See: http://www.cplusplus.com/reference/string/string/c_str/
As others already wrote, the result of killerName + "has slain:" + victimName is of type std::string. So, if your Notice() function expects a const char* as first parameter, you must convert from std::string to const char*, and since there is no implicit conversion defined for std::string, you must call the std::string::c_str() method:
Notice((killerName + "has slain:" + victimName).c_str(), killer.GetMapIndex(), false);
However, I'd like to ask: why do you have Notice() expecting a const char* as first parameter?
Would it be better to just use const std::string&? In general, in modern C++ code, you may want to use string classes like std::string instead of raw char* pointers.
(Another option would be to have two overloads of Notice(): one expecting a const std::string& as first parameter, and the other one expecting a const char*, if for some reason the const char* version does make sense in your particular context; this double overload pattern is used e.g. in the std::fstream constructor.)
Related
Today I was surprised when trying to concatenate an std::string with an int. Consider the following MWE:
#include <iostream>
#include <string>
void print(const std::string& text)
{
std::cout << "The string is: " << text << ".\n";
}
int main()
{
print("iteration_" + 1);
return 0;
}
Instead of printing
The string is: iteration_1.
which I would expect, it prints
The string is: teration_.
What exactly is going on in the background? Does the string for some reason get converted into char[] or something of the sort? The documentation of operator+ does not list any with an std::string and int.
And what is the proper way of concatenating an std::string with a number? Do I really have to throw them both into an std::stringstream or convert the number into std::string explicitely with std::to_string()?
Does the string for some reason get converted into char[]
Actually it is the other way around. "iteration_" is a char[11] which decays to a const char* when you add 1. Incrementing the pointer by one makes it point to the next character in the string. This is then used to construct a temporary std::string that contains all but the first character.
The documentation you link is for operator+ of std::string, but to use that you need a std::string first.
This line is the problem:
print("iteration_" + 1);
The string literal is decaying to a char*. You are adding 1 to this char*, moving it to the next character.
If you wanted to add the string "1" to the end of your literal, a fairly simple way is to pass the string literal to the std::string constructor and convert the 1 to a string manually. For example:
print(std::string("iteration_") + std::to_string(1));
"iteration_" is not std::string, but const char[]. Which decays to const char*, and "iteration_" + 1 just performs pointer arithmetic and move the pointer pointing to the next char (i.e. 't'), then you got the c-style string "teration_".
You can use std::to_string to convert int to std::string, then concatenate them. e.g.
print("iteration_" + std::to_string(1));
For this case std::operator+(std::basic_string) is called and the 1st argument "iteration_" is converted to std::string implicitly and then passed to operator+, then the concatenated std::string is passed to print.
LIVE
If you try to use the following:
std::string str = "iteration" + 1;
compiler will throw the warning:
warning: adding 'int' to a string does not append to the string
[-Wstring-plus-int]
It is because you are incrementing the pointer to "iteration" string by 1 which means that now "teration" string is being assigned to str variable.
The proper way of concatenating would be:
std::string str = "iteration" + std::to_string(1);
The expression "iteration_" + 1 is a const char[11] literal added to the int 1.
In that expression, "iteration_" decays to a const char* pointer to the first element of the array. + 1 then takes place in pointer arithmetic on that pointer. The entire expression evaluates to a const char* type (pointing to the first t) which is a valid NUL-terminated input to a std::string constructor! (The anonymous temporary std::string binds to the const std::string& function parameter.)
This is completely valid C++ and can occasionally be put to good use.
If you want to treat + as a concatenation, then
print("iteration_" + std::to_string(1));
is one way.
I am trying to make a new const char* b by adding a new string "hello" to original const char* a:
const char* a = some_code_here;
const char* b = (a + "_hello").c_str();
And the error I get is:
error: invalid operands of types const char* and const char [6] to binary operator+
Is there anything wrong I am doing?
Switch to strings, that is std::string.
Repeat after me, forget about using char or C-style strings.
As you have demonstrated, this is one of many issues.
Did I say switch to std::string?
Your char * is a pointer. Nothing more, nothing less, a pointer. A pointer to a single char; not a structure. The char data type doesn't have methods.
Switch to std::string.
You can add (concatenate) std::string.
Switch to std::string.
The std::string has the c_str() method. Don't use unless you understand the consequences; completely.
You can't arbitrarily add const char* in C++. These objects are just pointers to a contiguous section of memory, so adding them doesn't make sense. Instead, you should use the std::string class:
std::string a = "something";
std::string b = a + "_hello";
So I have this char const* blahblahblah(const char* s) function but when I try to use strcat(s, " ") or return s[k]in it it says
const char*s
Error: argument of type "const char*" is incompatible of parameter of type "char"
If I want the function to stay as is what should I change in my parameters in order for it to work?
If you declare const char* s, then you should not write strcat(s, " "), because strcat modifies s.
if you declare char const* reverseWordsOnly, then why do you return s[k]? s[k] is not a pointer.
EDIT:
This depends on what you want to do. I don't know what you want to do in this function.
If you don't modify s, then declaring const char* s is OK.
If you want to return char const *, then maybe you want to return &s[k] instead of s[k].
Maybe you want to return char *, then you can cast &s[k] using (char *)&s[k].
It's because the const on the left-hand-side of the * means that what's pointed to is immutable: strcat obviously needs to alter its parameter. And s[k] will refer to a char, not any sort of char *.
I am converting a project written in C++ for windows. Everything is going fine (meaning I clearly see what needs to be changed to make things proper C++) until I hit this, which is my own little routine to find a keyword in along string of keyword=value pairs:
bool GetParameter(const char * haystack, const char *needle) {
char *search, *start;
int len;
len = strlen(needle) + 4; // make my own copy so I can upper case it...
search = (char *) calloc(1,len);
if (search == NULL) return false;
strcpy(search,needle);
strupr(search);
strcat(search,"="); // now it is 'KEYWORD='
start = strstr(haystack,search); <---- ERROR from compiler
g++ is telling me "Invalid conversion from const char * to char * "
(the precise location of the complaint is the argument variable 'search' )
But it would appear that g++ is dyslexic. Because I am actually going the other way. I am passing in a char * to a const char *
(so the conversion is "from char * to const char *" )
The strstr prototype is char * strstr(const char *, const char *)
There is no danger here. Nothing in any const char * is being modified.
Why is it telling me this?
What can I do to fix it?
Thanks for any help.
The background to the problem is that C defines the function strstr as:
char* strstr(const char*, const char*);
This is because C doesn't allow overloaded functions, so to allow you to use strstr with both const and non-const strings it accepts const strings and returns non-const. This introduces a weakness in C's already fragile type-system, because it removes const-ness from a string. It is the C programmer's job to not attempt to write via a pointer returned from strstr if you pased in non-modifiable strings.
In C++ the function is replaced by a pair of overloaded functions, the standard says:
7. The function signature strstr(const char*, const char*) shall be replaced by the two declarations:
const char* strstr(const char* s1, const char* s2);
char* strstr( char* s1, const char* s2);
both of which shall have the same behavior as the original declaration.
This is type-safe, if you pass in a const string you get back a const string. Your code passes in a const string, so G++ is following the standard by returning a const string. You get what you asked for.
Your code compiles on Windows because apparently the standard library you were using on Windows doesn't provide the overloads and only provides the C version. That allows you to pass in const strings and get back a non-const string. G++ provides the C++ versions, as required by the standard. The error is telling you that you're trying to convert the const return value to a non-const char*. The solution is the assign the return value to a const char* instead, which is portable and compiles everywhere.
Error is not regarding the arguments to stsrtr. Compiler is complaining about the conversion of the 'const char *' returned by strstr. You can't assign it to *start which is just char *
You can try one of these:
const char *start;
or
string start(strstr(haystack,search));
Although declaring start as const char* might suffice, what seems more appropriate to me is to use std::string objects instead:
#include <string>
#include <cctype>
#include <algorithm>
bool GetParameter(const char * haystack, const char *needle) {
std::string hstr(haystack), nstr(needle);
std::transform(nstr.begin(), nstr.end(),nstr.begin(), ::toupper);
nstr += "=";
std::size_t found = hstr.find(nstr);
if (found != std::string::npos) {
... // "NEEDLE=" found
}
else {
...
}
...
}
The conversion it is complaining about is from strstr(...) to start. Change the declaration of start to const char* start;
you can use such like:
start = const_cast<char *>(strstr( haystack, static_cast<const char *>(search) ));
I have a function which is expecting a string, I was wanting to concatenate const char * to a string to be returned.
Here is example code to help illustrate this scenario:
void TMain::SomeMethod(std::vector<std::string>* p)
{
p->push_back(TAnotherClass::Cchar1 + "/" + TAnotherClass::Cchar2);
}
and here is the other class these are from:
class TAnotherClass
{
public:
static const char * Cchar1;
static const char * Cchar2;
};
const char * TAnotherClass::Cchar1 = "Home";
const char * TAnotherClass::Cchar2 = "user";
im getting the following error:
invalid operands of types 'const char*' and 'const char*' to binary operator +
Why is this not valid? please help
char const* cannot be used with + operator, as the error says.
What you need to do is this:
p->push_back(std::string(TAnotherClass::Cchar1) + "/" + TAnotherClass::Cchar2);
//^^^^^^^^^^^^ notice this
It creates a temporary object of type std::string, then you can use + with it. It concatenates the strings, creating temporaries all the way, and finally passes the final string to push_back.
Apart from that, as #Konrad noted in the comment, don’t pass a pointer into the method, use a reference instead, as:
void TMain::SomeMethod(std::vector<std::string> & p) //<-- note &
{
p.push_back(std::string(TAnotherClass::Cchar1)+"/"+TAnotherClass::Cchar2);
}
Because you're trying to add two pointers. The + operator can't be overridden for char*.
You can do this:
p->push_back(std::string(TAnotherClass::Cchar1) + "/" + TAnotherClass::Cchar2);
Keep in mind the fact that std::string(...) as used above is a C-style cast using functional notation. It's equivalent, in this case, to static_cast<std::string>(...).
Whether you allow function style casts in your code is up to you. Some policies are against ALL C-style casts. In my previous workplace this particular use of them was allowed, but no other.