在C语言中,将字符串中的字符与一组特定字符进行比较

3

我一直在从事一个需要验证字符串中字符的项目。

例如,我的有效字符集是“abcde”,其中所有字符都启动不同的功能。

首先,代码要求用户输入。然后,将其与此集合进行比较,以检查是否存在任何无效输入(除了abcde之外的任何字母)。在此之后,字符将启动其各自的功能。

我知道可以使用以下方法来实现:

    for (i = 0; i <= sizeof(string) - 1; i++) {
        if (string[i] != 'a' || string[i] != 'b' || string[i] != 'c' || 
            string[i] != 'd' || string[i] != 'e') {
            printf("Invalid Input");
        }
    }

用户可以输入集合中任意组合的三个或四个字母。
除了在if语句中打出整个条件之外,还有没有更简单的方法?感谢您的帮助。

1
如果(string[i] < 'a' || string[i] > 'e') { /* 错误 */ } 另外,您是否意味着在if语句中使用&&而不是|| - flau
2
在一个静态的常量字符数组中查找字符,例如“abcde”。 - Martin James
for循环语句应该是size_t len = strlen(string) ; for(i=0; i < len; i++),因为sizeof会根据指针的大小而给出4或8。 - JeremyP
4个回答

5

编辑: 感谢评论中提到标准的strspn()函数,它已经超出了我的关注范围,我们可以这样实现:

const size_t num_valid = strspn(string, "abcde");
if(string[num_valid] != '\0')
  printf("Invalid input: '%s'\n", string + num_valid);

这样做可以将循环从用户代码中推出,使其更简单。

最初我声称这是一个典型的 [strchr()] (https://linux.die.net/man/3/strchr) 案例,我仍然认为它是:

for(size_t i = 0; string[i] != '\0'; ++i)
{
  if(strchr("abcde", string[i]) == NULL)
  {
    printf("Invalid input: '%c'\n", string[i]);
    break;
  }
}

1
谢谢,愚蠢的错误。我重写了它,没有使用索引。 - unwind
3
应该是 strchr("abcde", *string) 吗? - vgru
1
@MananVora 这可能是因为string在本地作用域中是一个实际的数组。我会重新编写的。 :) - unwind
1
实际上有一个更简单的解决方案:这个问题是 strspn() 的典型用例。 - chqrlie
@chqrlie 谢谢!我完全忘记了,或者可能从未吸收过那个函数。 - unwind
显示剩余5条评论

2
听起来你需要使用 strpbrk 函数,它正好可以做到你需要的功能:从一组字符中查找任意字符的第一个出现位置。例如:
#include <string.h>
#include <stdio.h>

int main()
{
  const char STR_VALID[] = "abcde";
  char data[] = "invalid code";

  for(char* ptr=strpbrk(data, STR_VALID); ptr!=NULL; ptr=strpbrk(ptr+1, STR_VALID))
  {
    putc(*ptr, stdout);
  }
}

输出:

adcde

1
你目前的做法是相当优化的,尽管你可以考虑使用 strchr。不要被诱惑通过写貌似华丽的 if(string[i] < 'a' || string[i] > 'e') 来牺牲可移植性。

我对 sizeof(string) - 1 有更多问题。如果 string 已经退化为指针,那么 sizeof(string) 将无法给出元素数量。此外,sizeof 返回一个无符号类型,而 -1 可能会将您推到零的另一侧,达到最大的 size_t 值!

请使用预先计算好的 strlen


如果它是一个指针,大概会有多大?只是出于好奇,大小会改变多少? - Ahmed Can Unbay
1
如果string是一个指针,那么sizeof(string)sizeof(char*)相同,这将是您平台上char*指针类型的大小。 - Bathsheba

0

对于您的用例来说,最简单的解决方案是使用标准但很少使用的库函数strspn()进行一次调用:

size_t i = strspn(string, "abcde");
if (string[i] != '\0') {
    printf("Invalid input: '%c'\n", string[i]);
}

strspn() 函数计算 string 开头与 "abcde" 中任意一个字符匹配的字符数。 i 是第一个不匹配 abcde 的字符的偏移量。如果它不是字符串的结尾,则输入无效。

请注意,问题中的代码存在一些问题:

  • 循环测试i <= sizeof(string) - 1容易出错,如果string是一个指针,sizeof(string)将与它所指向的数组中的字符数(如果有)无关;如果string是一个数组,sizeof(string)是数组的大小,而不是字符数加一。请改用:

    for (i = 0; string[i] != '\0'; i++)
    
  • 你应该使用&&代替||。发布的版本总是打印字符串的第一个字符,除非它是空的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接