C strspn()的实施

C strspn()的实施,c,C,库函数strspn的定义是: size_t strspn(const char *str, const char *chars) /* Return number of leading characters at the beginning of the string `str` which are all members of string `chars`. */ e、 g.如果str是“fecxdy”而chars是“abcdef”,那么函数将返回3,因为f、e和c都出现在chars

库函数strspn的定义是:

size_t strspn(const char *str, const char *chars)

/* Return number of leading characters at the beginning of the string `str`
   which are all members of string `chars`. */
e、 g.如果
str
“fecxdy”
chars
“abcdef”
,那么函数将返回
3
,因为
f
e
c
都出现在
chars
的某个地方,给出
str
的3个前导字符,而
x
str
的第一个字符,它不是
chars
的成员

#include <string.h>

size_t strspn(const char *str, const char *chars) {
  int i;
  char ch[256] = {0};

  for (i = 0; i < strlen(chars); i++) {
    ch[chars[i]] = 1;
  }

  for (i = 0; i < strlen(str); i++) {
    if (ch[str[i]] == 0) {
      break;
    }
  }

  return i;
}

有人能帮我用C写一个strspn的实现吗?唯一允许我从实现中调用的库函数是strlen?

基本思想是逐步遍历字符串,每次一个字符,并测试它是否在字符集中。如果不是,请停止并返回答案。在伪代码中,这看起来像:

count = 0
for each character c in str
    if c is not in chars
        break
    count++
return count

通过迭代
chars
的所有字符并测试
c
是否匹配任何字符,可以实现
if c不在chars
测试。请注意,这不是最快的实现,因为它涉及到单步遍历
str
中每个字符的
chars
字符串。一种更快的实现方法是使用查找表来测试
c是否不在chars

中,而不必在过去几年中接触c编译器。从我的头顶上看,这样的事情应该会起作用:

int spn = 0;
while(*str++ != '\0')
{
  char *hay = chars;
  bool match = false;
  while(*hay++ != '\0')
  {
     if(*hay == *str)
     {
       match = true;
       break;
     }
  }

  if(match)
     spn++;
  else
     return spn;
}
return spn;
#include <string.h>

size_t strspn(const char *str, const char *chars) {
  int i;
  char ch[256] = {0};

  for (i = 0; i < strlen(chars); i++) {
    ch[chars[i]] = 1;
  }

  for (i = 0; i < strlen(str); i++) {
    if (ch[str[i]] == 0) {
      break;
    }
  }

  return i;
}

我在复习以前的考试时发现了这个问题。不允许使用索引或任何标准函数。以下是我尝试的解决方案:

#include <stdio.h>    
size_t myStrspn(const char *str1, const char *str2){
  size_t i,j;
  i=0;

  while(*(str1+i)){
    j=0;
    while(*(str2+j)){
      if(*(str1+i) == *(str2+j)){
        break; //Found a match.
      }
      j++;
    }
    if(!*(str2+j)){
      return i; //No match found.
    }
    i++;
  }
  return i;
}

void main(){
  char s[] = "7803 Elm St.";
  int n = 0;
  n = myStrspn(s,"1234567890");
  printf("The number length is %d. \n",n);
}
#包括
大小\u t myStrspn(常量字符*str1,常量字符*str2){
尺寸i,j;
i=0;
而(*(str1+i)){
j=0;
而(*(str2+j)){
如果(*(str1+i)=*(str2+j)){
break;//找到了匹配项。
}
j++;
}
如果(!*(str2+j)){
返回i;//未找到匹配项。
}
i++;
}
返回i;
}
void main(){
char s[]=“榆树街7803号”;
int n=0;
n=myStrspn(s,“1234567890”);
printf(“数字长度为%d.\n”,n);
}
以下是考试的答案:

#include<stdio.h>
size_t strspn(const char* cs, const char* ct) {
  size_t n;
  const char* p;
  for(n=0; *cs; cs++, n++) {
    for(p=ct; *p && *p != *cs; p++)
      ;
    if (!*p)
      break;
  }
  return n;
}
#包括
大小\u t strspn(常量字符*cs,常量字符*ct){
尺寸;
常量字符*p;
对于(n=0;*cs;cs++,n++){
对于(p=ct;*p&&*p!=*cs;p++)
;
如果(!*p)
打破
}
返回n;
}

For循环使它更加紧凑。

我认为这应该非常快

int my_strspn(const char *str1,const char *str2){
int i,k,counter=0;
for(i=0;str1[i]!='\0';i++){
 if(counter != i) break;
 for(k=0;str2[k]!='\0';k++){
  if(str1[i]==str2[k])
   counter++;
 }
}
 return counter;
}
size_t strspn(const unsigned char *str, const unsigned char *chars){
    unsigned char ta[32]={0};
    size_t i;
    for(i=0;chars[i];++i)
        ta[chars[i]>>3]|=0x1<<(chars[i]%8);
    for(i=0;((ta[str[i]>>3]>>(str[i]%8))&0x1);++i);
    return i;
}
size\u t strspn(常量无符号字符*str,常量无符号字符*chars){
无符号字符ta[32]={0};
尺寸i;
对于(i=0;字符[i];++i)
ta[chars[i]>>3]|=0x13]>>(str[i]%8))&0x1)++i);
返回i;
}

感谢其他人的健全性检查。

好吧,为我的操作系统实现一个标准库,这是我的解决方案(C++)


strspn()
的简单实现将在第一个字符串上迭代,只要它在第二个字符串中找到对应的字符:

#包括
大小strspn(常量字符*str,常量字符*chars){
尺寸i=0;
while(str[i]&&strchr(chars,str[i]))
i++;
返回i;
}
鉴于您不允许调用
strchr()
,下面是一个简单的本机实现:

size\u t strspn(常量字符*str,常量字符*chars){
尺寸i,j;
对于(i=0;str[i]!='\0';i++){
对于(j=0;chars[j]!=str[i];j++){
如果(字符[j]='\0')
return i;//未找到字符,返回到目前为止的索引
}
}
return i;//完整的字符串匹配,返回长度
}
重复扫描第二个字符串可能代价高昂。这里有一个备选方案,根据
字符的长度组合不同的方法,假设为8位字节:

size\u t strspn(常量字符*str,常量字符*chars){
尺寸i=0;
字符c=字符[0];
如果(c!='\0'){//如果第二个字符串为空,则返回0
如果(字符[1]='\0'){
//第二个字符串只有一个字符,请使用简单循环
while(str[i]==c)
i++;
}否则{
//第二个字符串包含更多字符,请构造位图
无符号字符x,位[256/8]={0};
对于(i=0;(x=chars[i])!='\0';i++)
位[x>>3]|=1>3]&(1为所有可能的ASCII字符创建一个查找表(穷人的集合),只需查找
str
中的每个字符。这是最坏的情况
O(max(N,M))
,其中
N
str
中的字符数,
M
中的字符数

#include <string.h>

size_t strspn(const char *str, const char *chars) {
  int i;
  char ch[256] = {0};

  for (i = 0; i < strlen(chars); i++) {
    ch[chars[i]] = 1;
  }

  for (i = 0; i < strlen(str); i++) {
    if (ch[str[i]] == 0) {
      break;
    }
  }

  return i;
}
#包括
大小strspn(常量字符*str,常量字符*chars){
int i;
char ch[256]={0};
对于(i=0;i

假设两个字符串都以零结尾,也可以不使用strlen解决此问题。此解决方案的缺点是查找表需要256字节的内存。

您需要帮助的部分是什么?太棒了!我也会这样做。其工作方式是识别只有256个字符可能。每个字符都可以对应256位宽数组上的一个位置:32字节。@AleksanderAlekseev有什么错误?@JL2210他是对的。我的解决方案是查找集合中的字符而不是集合中的字符。更改
if((ta[str[i]]>(str[i]%8))&0x1)break;
if(!((ta[str[i]>>(str[i]%8))&0x1))break;
修复如果
char
有符号且
char
包含负数字符,则此操作无效。此外,
i
应定义为
size\u t
。最后但并非最不重要的一点,函数应返回
i
,而不是
cnt-1
,它始终是
UINT\u MAX
@user1424589:仍然不正确ct:参数应该具有
常量字符*
类型,而不是
无符号字符
,并且您忘记了
>3