Найти первое вхождение неэкранированного персонажа - PullRequest
0 голосов
/ 13 марта 2012

Каков наилучший способ найти первое неэкранированное вхождение символа в заданной строке?

Вот как я это сделал, но у меня такое чувство, что это слишком сложно.

/*
 * 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;
}

1 Ответ

1 голос
/ 13 марта 2012

Если поиск символа встречается довольно редко, ваш подход разумен Как правило, подпрограммы библиотеки C, такие как strchr, написаны на жестком машинном языке и будут работать быстрее, чем практически любой цикл, который вы кодируете на 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;
...