0

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 ).

M.Ionut
  • 187
  • 1
  • 3
  • 15
  • 2
    If you don't edit the values, you should accept and return `const char*` types instead. Then when provided with a `char*`, it will implicitly cast it to a `const char*` – Kyle Willmon May 03 '19 at 16:19
  • As you can see from [doc](https://en.cppreference.com/w/cpp/string/byte/strchr), there are 2 overloads. (and you have several ways to factorize implementation). – Jarod42 May 03 '19 at 16:20
  • As Kyle said, if your function is not going to modify the value, you should always use const char*. They it is OK to pass char* to it. If your function is going to modify the value, then the const version should not apply. – Tony May 03 '19 at 16:23
  • @KyleWillmon -- your comment is correct, except that "implicitly cast" should be "implicitly convert". A cast is something you write in your source code to tell the compiler to do a conversion. There is no such thing as an implicit cast. – Pete Becker May 03 '19 at 18:55
  • @PeteBecker Thanks. I can no longer edit it, but I'll try to use the correct language in the future. I also have since realized that two overloads is a better solutions since, in the case of a mutable string, you may want to mutate the string using the returned pointer (so the return when given a `char*` should be a `char*` rather than a `const char*`) – Kyle Willmon May 03 '19 at 19:08

3 Answers3

3

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.

eerorika
  • 232,697
  • 12
  • 197
  • 326
1

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.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
MciprianM
  • 513
  • 1
  • 7
  • 18
1

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.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523