在函数 xstrchr 中找不到字符时无法 return NULL

Unable to return NULL when character not found in the function xstrchr

我无法在 main() 中使用 else 条件。当在字符串中找不到字符时,代码不起作用。我应该如何修改 return 语句或 main 中的 else 条件?

#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) != '[=11=]') {
        if (*(s + i) == ch) {
            flag = 1;
            return (s + i);
        }
        i++;
    }
    if (flag == 0) {
        return NULL;
    }
}

你的函数 执行 return NULL 当找不到字符时,但你在 main() 中有未定义的行为当您在测试 NULL 结果之前在 printf 语句中取消引用 r 时,会导致程序崩溃。

还有其他问题:

  • main 的原型应该是 int main(void)int main(int argc, char *argv[]) 或者可能是 int main().

  • 你不能使用 gets()。此函数已从 C 语言中删除,因为它不能安全使用。如果用户在提示符下键入超过 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));
    
  • 索引值在 C 中从 0 开始。将数组的第一个元素称为索引 1 会造成混淆。

  • 您应该测试 fgets()scanf() 的 return 值以检测文件过早结束或其他输入失败。

  • 索引值可能超出类型int的范围。您应该在 xstrchr().

  • 中为 i 使用类型 size_t
  • flagxstrchr功能中没有使用:更新代码和测试是多余的,可以去掉。

  • *(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] != '[=12=]') {
        if (s[i] == ch) {
            return s + i;
        }
        i++;
    }
    return NULL;
}

最后,xstrchr()函数不完全符合标准strchr()函数的规范:

  • ch的参数类型为int,但其值被转换为char以供比较。

  • s的参数类型是const char *因为字符串没有被这个函数修改,但是return类型是char *所以然后必须将 return 值转换为 (char *),这是一个不幸但必要的步骤。

  • 如果ch有空值,将匹配字符串末尾的空终止符。

  • 递增 s 而不是使用索引变量是许多 C 程序员更喜欢的替代方法。

这是修改后的版本:

char *xstrchr(const char *s, int ch) {
    for (;; s++) {
        if (*s == (char)ch)
            return (char *)s;
        if (*s == '[=13=]')
            return NULL;
    }
}