Невозможно вернуть NULL, если символ не найден в функции xstrchr - PullRequest
0 голосов
/ 14 марта 2019

Я не могу использовать условие else в main().Код не работает, когда символ не найден в строке.Как мне изменить оператор return или условие else в main?

#include <stdio.h>

char *xstrchr(char *string, char ch);

void main() {
    char str[20], ch;
    printf("Enter a string :");
    gets(str);
    printf("Enter character to search in string :");
    scanf("%c", &ch);

    char *r = xstrchr(str, ch);
    printf("%c is stored at %d\n", *r, r);
    if (r != NULL)
        printf("Character '%c' found at %d index.\n", ch, (r - str + 1));
    else
        printf ("Character not found.");
}

char *xstrchr(char *s, char ch) {
    int flag = 0, i = 0;
    while (*(s + i) != '\0') {
        if (*(s + i) == ch) {
            flag = 1;
            return (s + i);
        }
        i++;
    }
    if (flag == 0) {
        return NULL;
    }
}

1 Ответ

3 голосов
/ 14 марта 2019

Ваша функция возвращает , возвращает 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;
    }
}
...