【问题标题】:Find first occurrence of unescaped character查找第一次出现的未转义字符
【发布时间】:2012-03-13 00:01:14
【问题描述】:

在给定字符串中查找第一个未转义字符的最佳方法是什么?

我就是这样做的,但我觉得它过于复杂。

/*
 * Just like strchr, but find first -unescaped- occurrence of c in s.
 */
char *
strchr_unescaped(char *s, char c) 
{
  int i, escaped;
  char *p;

  /* Search for c until an unescaped occurrence is found or end of string is
     reached. */
  for (p=s; p=strchr(p, c); p++) {
    escaped = -1;
    /* We found a c. Backtrace from it's location to determine if it is
       escaped. */
    for (i=1; i<=p-s; i++) {
      if (*(p-i) == '\\') {
        /* Switch escaped flag every time a \ is found. */
        escaped *= -1;
        continue;
      }
      /* Stop backtracking when something other than a \ is found. */
      break;
    }
    /* If an odd number of escapes were found, c is indeed escaped. Keep 
       looking. */
    if (escaped == 1) 
      continue;
    /* We found an unescaped c! */
    return p;
  }
  return NULL;
}

【问题讨论】:

  • 取决于最佳的定义,但您的解决方案似乎比必要的工作更多。而不是使用 strchr 和回溯(每个反斜杠查看两次),您可以向前读取并跟踪状态(转义/未转义),因此只查看每个字符一次。
  • 我明白你的意思。另一方面,这允许我仅在我知道确实有必要时才测试转义。使用您的解决方案,无论是否有逃逸,都会为每个检查的角色支付跟踪逃逸的成本。我猜哪个更好取决于测试字符串的性质,即转义字符的比例。
  • 取决于您所说的“成本”。 strchr() 正在查看您的代码避免检查是否为转义的所有这些字符,因此它不像它们没有被测试,尽管您必须检查每个字符的 c 和 \ (这不会看起来非常昂贵,但如果您使用查找表,您可以同时检查两者)。

标签: c string strchr


【解决方案1】:

如果搜索字符相当罕见,那么您的方法是合理的。一般来说,像strchr 这样的C 库例程是用严格的机器语言编写的,运行速度几乎比用C 编写的任何循环都快。某些硬件模型具有用于搜索内存块的机器指令;一个 C 库例程,使用它的运行速度比您可以用 C 编写的任何循环都要快。

为了稍微收紧你的方法,这样怎么样:

#define isEven(a) ((a) & 1) == 0)

char* p = strchr( s, c );
while (p != NULL) {   /* loop through all the c's */
    char* q = p;   /* scan backwards through preceding escapes */
    while (q > s && *(q-1) == '\\')
        --q;
    if (isEven( p - q ))   /* even number of esc's => c is good */
        return p;
    p = strchr( p+1, c );   /* else odd escapes => c is escaped, keep going */
}
return null;

【讨论】:

    猜你喜欢
    • 2021-08-14
    • 1970-01-01
    • 1970-01-01
    • 2011-02-04
    • 2017-11-12
    • 2012-10-17
    • 1970-01-01
    • 1970-01-01
    • 2018-03-22
    相关资源
    最近更新 更多