当在函数xstrchr中找不到字符时,无法返回NULL

时间:2019-03-14 05:43:03

标签: c null return c-strings return-type

我无法利用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 个答案:

答案 0 :(得分:3)

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

还有其他问题:

  • 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);
    
  • 两个指针的差为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()的返回值,以检测文件过早结束或其他输入失败。

  • 索引值可能超出类型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;
}

最后,xstrchr()函数与标准strchr()函数的规范不完全匹配:

  • ch的参数类型为int,但出于比较目的将其值转换为char

  • s的参数类型为const char *,因为此函数未修改字符串,但是返回类型为char *,因此返回值必须转换为(char *),这是不幸但必要的步骤。

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

  • 增加s而不使用索引变量是许多C程序员更喜欢的选择。

这是修改后的版本:

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