【问题标题】:Realization of strtok in CC中strtok的实现
【发布时间】:2016-12-05 21:02:00
【问题描述】:
char* my_strtok (char* s1,const char* s2){
    char *res = NULL;
    size_t i, j, len1 = mstrlen(s1), len2 = mstrlen(s2);
    for(i=0U; i< len1; i++) {
        for(j=0U; j<len2; j++) {
            if(s1[i] == s2[j]) {
                s1[i] = '\0'; res = (s1 + i+ 1);
                break;
            }
        }
    }
    return res;
}

你能说它是strtok的正确实现吗? 或者你可以展示你的实现?

【问题讨论】:

  • 当使用NULL 调用第一个参数时,这里没有处理。这根本行不通。
  • "能展示你的实现吗?" - 不,这不是代码编写服务。
  • 谷歌搜索souce strtok.c

标签: c strtok string.h


【解决方案1】:

你需要有一个地方来保存输入指针的当前位置。使用strspn()strcspn() 作为获取分隔符位置的方法的示例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// SOME CHECKS OMMITTED!

// helper for testing, not necessary for strtok()
static char *strduplicator(const char *s)
{
  char *dup;
  dup = malloc(strlen(s) + 1);
  if (dup != NULL) {
    strcpy(dup, s);
  }
  return dup;
}


// thread-safe (sort of) version
char *my_strtok(char *in, const char *delim, char **pos)
{
  char *token = NULL;

  // if the input is NULL, we assume that this
  // function run already and use the new position
  // at "pos" instead
  if (in == NULL) {
    in = *pos;
  }
  // skip leading delimiter that are left
  // there from the last run, if any
  in += strspn(in, delim);
  // if it is still not the end of the input
  if (*in != '\0') {
    // start of token is at the current position, set it
    token = in;
    // skip non-delimiters, that is: find end of token
    in += strcspn(in, delim);
    // strip of token by setting first delimiter to NUL
    // that is: set end of token
    if (*in != '\0') {
      *in = '\0';
      in++;
    }
  }
  // keep current position of input in "pos"
  *pos = in;
  return token;
}


int main(void)
{

  char *in_1 = strduplicator("this,is;the:test-for!strtok.");
  char *in_2 = strduplicator("this,is;the:test-for!my_strtok.");

  char *position, *token, *s_in1 = in_1, *s_in2 = in_2;
  const char *delimiters = ",;.:-!";

  token = strtok(in_1, delimiters);
  printf("BUILDIN: %s\n", token);
  for (;;) {
    token = strtok(NULL, delimiters);
    if (token == NULL) {
      break;
    }
    printf("BUILDIN: %s\n", token);
  }

  token = my_strtok(in_2, delimiters, &position);
  printf("OWNBUILD: %s\n", token);
  for (;;) {
    token = my_strtok(NULL, delimiters, &position);
    if (token == NULL) {
      break;
    }
    printf("OWNBUILD: %s\n", token);
  }

  free(s_in1);
  free(s_in2);

  exit(EXIT_SUCCESS);
}

如果你想拥有普通的char *strtok(char *str, const char *delim);,你可以这样做:

static char *pos;
char *own_strtok(char *in, const char *delim)
{
   return my_strtok(in, delim, &pos);
}

函数str[c]spn() 非常简单。引用strspn()的手册页

strspn() 函数返回 s 的初始段中的字节数,该段仅包含来自 accept 的字节。

size_t my_strspn(const char *s, const char *accept)
{
  const char *delim;
  size_t size = 0;

  // step through the input
  while (*s != '\0') {
    // step through delimiters and test
    for (delim = accept; *delim != '\0'; delim++) {
      if (*s == *delim) {
        break;
      }
    }
    // we are through all of the delimiters without success,
    // terminate
    if (*delim == '\0') {
      break;
    } else {
      size++;
    }
    s++;
  }
  return size;
}

反函数strcspn() 更简单。再次引用手册页:

strcspn() 函数返回 s 的初始段中不在字符串 reject 中的字节数。

size_t my_strcspn(const char *s, const char *reject)
{
  const char *delim;
  size_t size = 0;

  // step through the input
  while (*s != '\0') {
    // step through delimiters and test
    for (delim = reject; *delim != '\0'; delim++) {
      if (*s == *delim) {
        return size;
      }
    }
    size++;
    s++;
  }
  return size;
}

n 是输入的大小,k 是分隔符集的大小,时间复杂度为 O(kn)。理论上 k 的大小不能超过输入字母的大小,我们应该能够假设k &lt;&lt; n。但这假设包含分隔符的字符串是唯一的。情况并非总是如此。

strtok(
   "This is a sentence without the last letter of the alphabet.",
   "zzz/* 1,000,000,000 other z's omitted */zzz"
);

因此,请小心使用自动生成的分隔符集,并额外检查该危险是否真实(例如:使用用户输入)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-11
    • 2013-05-24
    相关资源
    最近更新 更多