Ваша функция возвращает , возвращает NULL
, когда символ не найден, но у вас есть неопределенное поведение в main()
, когда это происходит, поскольку вы разыменовываете r
в операторе printf
перед тестированиемдля результата NULL
, вызывающего сбой вашей программы.
Существуют и другие проблемы:
прототип для main
должен быть int main(void)
или int main(int argc, char *argv[])
или возможно int main()
.
Вы не должны использовать gets()
.Эта функция была удалена из языка Си, потому что ее нельзя безопасно использовать.Если пользователь вводит более 19 символов в приглашении, ваша программа будет иметь неопределенное поведение, так как gets()
будет писать за пределами массива.
указатели не должны печататься с %d
, вы должны написать:
printf("%c is stored at %p\n", *r, (void *)r);
разница в 2 указателя имеет тип ptrdiff_t
, который может быть больше int
и не должен печататься с %d
,Стандартный формат для этого - %td
, но многие библиотеки C не поддерживают это, поэтому преобразование разницы в int
может быть предпочтительным:
printf("Character '%c' found at %d index.\n", ch, (int)(r - str + 1));
значения индекса начинаются с0
в C. Первый элемент массива сбивает с толку, как индекс 1.
. Вы должны проверить возвращаемые значения fgets()
и scanf()
, чтобы обнаружитьпреждевременное завершение файла или другие ошибки ввода.
Значения индекса могут превышать диапазон типа int
.Вы должны использовать тип size_t
для i
в xstrchr()
.
flag
не используется в функции xstrchr
: код обновления и тест являются избыточными иможет быть удалено.
*(s + i)
можно записать s[i]
, что гораздо более читабельно.Если вам не требуется явно использовать арифметический синтаксис указателя, вам следует использовать синтаксис в квадратных скобках.
Вот исправленная версия:
#include <stdio.h>
char *xstrchr(char *string, char ch);
int main() {
char str[200], ch;
printf("Enter a string: ");
if (!fgets(str, sizeof str, stdin))
return 1;
printf("Enter character to search in string: ");
if (scanf("%c", &ch) != 1)
return 1;
char *r = xstrchr(str, ch);
if (r != NULL) {
printf("Character '%c' found at %d index.\n", ch, (int)(r - str));
else
printf("Character not found.\n");
return 0;
}
char *xstrchr(char *s, char ch) {
size_t i = 0;
while (s[i] != '\0') {
if (s[i] == ch) {
return s + i;
}
i++;
}
return NULL;
}
Наконец, *Функция 1078 * не полностью соответствует спецификации стандартной функции strchr()
:
тип аргумента для ch
равен int
, но его значение преобразуется в char
для сравнения.
тип аргумента для s
равен const char *
, так как строка не изменяется этой функцией, но тип возвращаемого значения char *
, поэтому возвращаемое значение должно бытьзатем приведите к (char *)
, что является неудачным, но необходимым шагом.
нулевой терминатор в конце строки будет совпадать, если ch
имеет нулевое значение.
увеличение s
вместо использования индексной переменной - альтернатива, которую предпочитают многие программисты на Си.
Вот измененная версия:
char *xstrchr(const char *s, int ch) {
for (;; s++) {
if (*s == (char)ch)
return (char *)s;
if (*s == '\0')
return NULL;
}
}