Как я могу сделать так, чтобы моя функция strchr принимала оба массива 'const char' и 'char' в качестве первого параметра? - PullRequest
0 голосов
/ 03 мая 2019

Я ожидаю, что моя функция будет работать так же, как функция "strchr", которую я использую из библиотеки cstring / string.h. Я понимаю, что не могу привести переменную / массив "const char *" к "char *". Тем не менее, как предопределенная функция "strchr" может передавать массивы типов данных "const char" и "char" и работать просто отлично? Как я могу изменить мой, чтобы он тоже работал?

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;
}

Как вы уже, наверное, уже сказали, мой третий cout<< не работает. Я ищу способ изменить свою функцию (я предполагаю, что первый параметр должен как-то быть typecast).

Ответы [ 3 ]

2 голосов
/ 03 мая 2019

Как сделать так, чтобы моя функция strchr принимала оба массива 'const char' и 'char' в качестве первого параметра?

Вы можете изменить аргумент на const char*. Это позволило бы передать оба указателя на char, а также const char.

Однако вы возвращаете неконстантный указатель на этот массив, чего не следует делать, если указатель на константный массив. Таким образом, при передаче const char* ваша функция также должна возвращать const char*

И все же, как предопределенной функции "strchr" можно передавать массивы типов данных "const char" и "char" и работать просто отлично?

Есть две предопределенные функции std::strchr. Тот, который принимает и возвращает char*, а другой, который принимает и возвращает const char*:

const char* strchr(const char* str, int ch);
      char* strchr(      char* str, int ch);

Если вы хотите вернуть char* в случае аргумента char*, вам нужно иметь разные функции для каждого случая, как в стандартной библиотеке. Вы можете использовать перегрузку, как в стандартной библиотеке, или использовать шаблон функции для генерации обоих вариантов без повторений:

template<class Char>
Char* my_strchr(Char *place_to_find, char what_to_find)

Обратите внимание, что версия функции на C объявлена ​​char *strchr(const char *str, int ch). Это делает единственную функцию пригодной для использования в обоих случаях, но небезопасно, поскольку система типов не сможет помешать пользователю функции изменить хотя возвращенный неконстантный указатель, даже когда константный массив был передан в качестве аргумента.

0 голосов
/ 03 мая 2019

Сделайте две перегрузки, как это делается в стандартной библиотеке C ++:

char*       my_strchr(      char *place_to_find, char what_to_find)
const char* my_strchr(const char *place_to_find, char what_to_find)

Даже если в вашем случае будет достаточно только второй перегрузки ( demo ), вы не сможете поддерживать важный вариант использования, когда вам нужно найти символ и затем заменить его:

// This would not work with only one overload:
char *ptr = my_strchr(vocals2,'e');
if (ptr) {
    *ptr = 'E';
}

Вот почему необходима перегрузка без const.

Примечание: Я предполагаю, что вы делаете это как учебное упражнение, потому что строковые функции в стиле C больше не нужны для новой разработки, их заменили функциональностью std::string.

0 голосов
/ 03 мая 2019

Краткий ответ: укажите тип place_to_find const char *

Причина вашей ошибки в том, что вы не можете неявно преобразовать указатель на const char в указатель на неконстантный char.Если бы вы могли, то вы могли бы изменить символ, на который указывает указатель, и это не помогло бы изначально иметь тип символа const.

Вы можете неявно преобразовать указатель в неконстантный тип.char на указатель на const char, потому что он не снимает никаких ограничений.

LE: Кроме того, возвращаемое значение должно быть const char *, потому что, опять же, если вы этого не сделаете, он удалит constограничение, которое не допускается.Единственная проблема в том, что вы не сможете изменить массив с помощью возвращаемого указателя.Если вы тоже этого хотите, то вам придется перегружать метод как в char, так и в const char.

...