2012-03-13 3 views
0

Что является лучшим способом для поиска first unescaped появление символа в данной строке?Найти первое появление unescaped character

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

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

Зависит от определения лучшего, но ваше решение кажется больше работы, чем необходимо. Скорее, используя strchr и backtracking (который смотрит на каждую обратную косую черту дважды), вы можете читать вперед и отслеживать состояние (escaped/unescaped), таким образом, глядя только на каждого персонажа один раз. –

+0

Я понимаю, что вы имеете в виду. С другой стороны, это позволяет мне проверять только экраны, когда я знаю, что это действительно необходимо. С вашим решением стоимость отслеживания побегов будет выплачиваться за каждый проверенный персонаж, независимо от того, есть ли у него побеги или нет. Я думаю, что лучше всего зависит от характера тестируемых строк, т. Е. Отношения экранированных символов. –

+0

Зависит от того, что вы подразумеваете под «стоимостью». strchr() смотрит на все те символы, которые ваш код избегает проверки на бегство, поэтому его не так, как будто они не тестируются, хотя вам нужно будет проверить каждый символ как для c, так и для \ (который не кажется очень дорогостоящим, хотя, если вы использовали справочную таблицу, вы можете проверить оба сразу). –

ответ

1

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