In some function calls I see stuff like this.
function(variable1, "someValue");
I have some questions based on this
1) How does c++ treat the second argument ?
2) if some function takes a cstring then why do we get error when we do the following
functionTakingCString(stringVariable.c_str() + "someValue");
Is there some way around instead of declaring a const char variable? Please correct me if I m wrong some where.
They are called string literals and if you want to take an argument that is a string literal like that you normally pass a const std::string& or a const char*, depending on what your API requires.
2) if some function takes a cstring then why do we get error when we do the following
That's because the '+' operator is not overloaded for char * type. You could concatenate it to stringVariable of type string for which the + operator has been overloaded to concatenate two strings, and then get the c_str() to pass to a function accepting char * or const char *.
const char*
Binary operator + cannot be applied on const char* operand types. If one is a std::string, then it works because of operator overloading.
The second argument is a const char*. In some cases you may be able convert from one type to another if you have a special converting constructor of the desired type that takes in the given type. The compiler can do this for you in some cases.
In this example string has a constructor that takes in a const char* so the compiler can turn a const char* into a string for you under the covers. If you want to stop this kind of behavior look into the explicit keyword.
The char* type isn't actually an class so it doesn't have a + operator that works for strings. However,
(stringVariable + "someValue").c_str()
will work because stringVariable is a string and it's plus operator can cooerce a char* into a string.
Related
I am expecting my function to work just the same as the function "strchr" I am using from the cstring / string.h library.
I understand that I cannot cast a " const char* " variable / array to " char* ". Yet, how is the predefined "strchr" function able to be passed both "const char" and "char" data type arrays and work just fine ? How could I change mine so that it works, too ?
char* my_strchr(char *place_to_find, char what_to_find)
{
for(int i=0;place_to_find[i];i++)
if(what_to_find==place_to_find[i]) return place_to_find+i;
return NULL;
}
...
int main()
{
const char vocals1[]="AEIOUaeiou";
char vocals2[]="AEIOUaeiou";
cout<<strchr(vocals1,'e');
cout<<strchr(vocals2,'e');
cout<<my_strchr(vocals1,'e');
cout<<my_strchr(vocals2,'e');
return 0;
}
As you could probably already tell, my third cout<< does not work.
I am looking for a way to change my function ( I am guessing the first parameter should somehow be typecast ).
How can I make my strchr function take both 'const char' and 'char' arrays as first parameter?
You could change the argument to be const char*. That would allow passing both pointers to char as well as const char.
However, you return a non-const pointer to that array, which you shouldn't do if the pointer is to a const array. So, when passing a const char*, your function should also return const char*
Yet, how is the predefined "strchr" function able to be passed both "const char" and "char" data type arrays and work just fine ?
There are two predefined std::strchr functions. One that accepts and returns char* and another that accepts and returns const char*:
const char* strchr(const char* str, int ch);
char* strchr( char* str, int ch);
If you would wish to return char* in case of char* argument, you need to have a different function for each case, like the standard library has. You can use an overload like the standard library does, or you can use a function template to generate both variations without repetition:
template<class Char>
Char* my_strchr(Char *place_to_find, char what_to_find)
Note that the C version of the function is declared char *strchr(const char *str, int ch). This makes the single function usable in both cases, but is unsafe, since the type system won't be able to prevent the user of the function from modifying though the returned non-const pointer even when a const array was passed as an argument.
Make two overloads, the way it is done in the C++ standard library:
char* my_strchr( char *place_to_find, char what_to_find)
const char* my_strchr(const char *place_to_find, char what_to_find)
Even though in your case only the second overload would be sufficient (demo) you would not be able to support an important use case, when you need to find a character and then replace it:
// This would not work with only one overload:
char *ptr = my_strchr(vocals2,'e');
if (ptr) {
*ptr = 'E';
}
That is why the non-const overload is necessary.
Note: I assume that you are doing this as a learning exercise, because C-style string functions are no longer necessary for new development, having been replaced with std::string functionality.
Short answer: make the type of the place_to_find const char*
The reason for your error is that you cannot implicitly convert a pointer to a const char to a pointer to a non-const char. If you could, then you could change the char that the pointer points to and it would defeat the purpose of having it a const char type in the first place.
You can implicitly convert a pointer to a non-const char to a pointer to a const char because it does not remove any restrictions.
L.E.: Also, the return value should be a const char*, because again, if you don't, it would remove the const restriction which is not allowed. The only problem with that is that you would not be able to modify the array through the pointer returned. If you also want that, then you would have to overload the method on both char and const char.
I am trying to write a Fopen statement like this:
FILE *fp;
fp = fopen("client." + receiver->get_identifier().c_str() + ".vol", "a+");
where receiver->get_identifier() returns a string. However, I am getting the error in the title. I read the question here but wasn't having any luck because the first argument of fopen is const char*. What do I have to change to get this to compile?
receiver->get_identifier().c_str()
returns a const char*, not a std::string, so operator+ cannot kick in (one argument of it must be a std::string). Removing the c_str() and converting at the end with std::string::c_str() should do the trick
fopen(("client." + receiver->get_identifier() + ".vol").c_str(), "a+");
This is because you'd have a const char* plus a std::string, and operator+ will work.
If you may wonder why one cannot define an operator+ for const char*s, that's because C++ does not allow operator overloading for fundamental types; at least one argument must be of a user-defined type.
Try changing the first argument to
(string("client.") + receiver->get_identifier() + ".vol").c_str()
This will add std::string objects with C-Style strings, which can be done, and only take the character pointer at the end (via .c_str()). Your code now tries to add C-Style strings, which is not possible.
Let's say I have function foo(string& s). If I would get C string, foo(char* s), I would simply call the function as foo("bar").
I wonder if I can somehow do it in the C++ String?
Somehow to shorten this:
string v("bar");
foo(v)
I'm using Linux GCC C++.
It is not working because the argument has to be a const reference:
void foo( const std::string& s )
// ^^^^^
foo( "bar" ); // will work now
If you want foo to only read from the argument you should write foo(const string& s).
If you want foo to save the string somewhere (a class member..) you should write foo(string s).
Both versions allow you to write foo("bar"); which would't make any sense with a non const reference.
You could also try foo(string("bar")); to get your desired results, but since it is expecting a reference this wont work either.
So that means that your best bet is overloading for const char * to call the string method (this way you maintain only one method).
The std::string class does have an implicit conversion from const char*, so normally, passing a string literal into a function taking std::string works just fine.
Why it fails in your case is that the function takes its parameter as a non-const lvalue reference, and thus it requires an actual std::string lvalue to operate on.
If the function actually wants to take a non-const lvalue reference (i.e. it modifies the argument), you have to create an lvalue std::string and pass it (just like you do).
If the function does not modify the argument, change it to take by const-reference (const std::string&) or by value (std::string) instead; for both of these, passing an rvalue (like the std::string created by implicit conversion from const char*) will work and you can thus call the function with string literals.
I have a function that will pass a string and manipulate. in the function call i am passing the string as such like myfunc ("hello");
In the function definition i have
myfunc (char *array)
{
xxxx
};
The program is working fine, but it throws a warning "pointer targets in passing argument 1 of 'myfunc' differ in signedness".
How to rectify this problem?
Strings are actually arrays of constant characters. That is, the type of "hello" is const char[6].
What this means is you cannot modify it. However, due to a silly conversion in C++, the array (in string literal form) can be implicitly converted to a non-const pointer to the first element. This is misleading, and dangerous. (Indeed, a const-stripping implicit conversion doesn't exist anywhere else.)
You should make sure you have a modifiable buffer instead:
char buffer[] = "hello";
myfunc(buffer);
Make sure your definition for myfunc() function has char* as parameter. I think, it has unsigned char* as parameter. or somewhere else in your code, you are passing unsigned char* as argument to myfunc(char*). Look at the warning line in your code.
I think Prasoon is right. Your compiler is treating "string literals" as unsigned char. Just change your function to accept unsigned char ...or change the compiler setting which decides if a "string literal" is signed/unsigned.
what if you declare your function like myfunc (const char *array)
Why does the following not invoke the overloaded operator== (const String &, const String &)?
"cobble" == "stone"
Because in C++, string literals are of the type const char[] (also called a zero-terminated string constant), not std::string, let alone String (whatever that is).
There's a built-in operator== comparing two char* by comparing their addresses. Since arrays are implicitly convertible into pointers to their first elements (due, you guessed right, the C heritage), this operator steps in and what you compare are the addresses of these literals in memory.
Supposing your String class has an implicit conversion constructor from const char* (String::String(const char*)), you could convert one of the two to String. The other string would then be converted implicitly:
String("cobble") == "stone"
(Unless overloads of operator== taking a String and a const char* are provided for efficiency. If they are provided, they step in.)
Because implicitly existing operator==(char*, char*) matches your usage of == better.
The operator == in code "cobble" == "stone" can be matched in different ways: operator==(char[], const String&), operator==(const String&, String), operator==(const String&, const std::string&) etc., provided that the conversion from the parameter type (char*) to the type of arguments (String*, etc.) exists. However the usual char* comparison matches the input best of all.
Because those are simple sequences of characters as in C but no instances of the string class.
"cobble" ist interpreted as a char*, and the compiler uses pointer comparison to compare char*. If you want to compare the contents of the strings, use
std::string("cobble") == std::string("stone")
instead, and the compiler will use operator== (const std::string &, const std::string &).