Просто сделав это
Вы можете сделать что-то вроде этого:
const char * split = "--";
int i;
for(i=0; s[i]; strncmp(&s[i], split, strlen(split)) ? *s++ : i++);
Обратите внимание, что я перевернул *s++
и i++
, потому что strncmp возвращает 0 на равном. Кроме того, вы можете изменить его в зависимости от того, как вы хотите обработать строку, такую как "xi---len----xia"
.
Сделать ее читабельной
Если вы спросите меня, приведенный выше фрагмент выглядит немного неуклюжим исложно понять. Если бы вы спросили меня, что он делает, мне понадобилось бы некоторое время, чтобы понять это. Это выглядит как «посмотри, что я могу сделать».
Поместите это в функцию
Я бы добавил это в функцию, подобную этой, чтобы скрыть этот ужасный цикл для того, кто читает ваш код.
size_t no_splits(const char *s, const char *split)
{
size_t i;
for(i=0; s[i]; strncmp(&s[i], split, strlen(split)) ? *s++ : i++)
; // Put semicolon here to suppress warnings
return i;
}
Makeчитаемая логика
Но опять же, когда вы вставили код в хорошо названную функцию, необходимость в сокращении кода до такой степени практически исчезла. Поэтому для удобства чтения я бы переписал его следующим образом:
size_t no_splits(const char *s, const char *split)
{
size_t i=0;
// Not only more readable, but also better for performance
const size_t len=strlen(split);
while(s[i]) {
if(strncmp(&s[i], split, len))
// The only reason to use * in above code was to suppress a warning
s++;
else
i++;
}
return i;
}
Обратите внимание, что в последнем фрагменте кода я удалил две вещи, единственной целью которых было подавление предупреждений. Я не говорю, что всегда неправильно делать что-то только для подавления предупреждений, но когда вы это делаете, это признак того, что вам следует подумать о редизайне своего кода. Несмотря на то, что он может использоваться по-разному, обычный способ использования цикла for - for(<init>; <condition>; <inc/dec>)
, и это часто плохо, что расходится с этим соглашением. Не только из-за читабельности, но и потому, что это усложняет работу оптимизатора. Причина в том, что оптимизатор распознает общие шаблоны и имеет правила для их оптимизации.
Измените логику на что-то более интуитивное
На самом деле, я также считаю, что чередование приращений s
и i
очень запутанно. Вот версия, которая (для меня) имеет гораздо больше смысла. Измените цикл while на:
while(*s) {
if(strncmp(s, split, len) == 0)
i++;
s++;
}
А если вы ДЕЙСТВИТЕЛЬНО хотите сжать его, измените на:
// *s++ is back, but this time with another purpose than suppressing warnings
while(*s++) // Or for(; *s; s++) which I personally think looks better
if(strncmp(s, split, len) == 0)
i++;
Нарушение синтаксиса
Вот примеркак вы действительно можете злоупотреблять синтаксисом цикла for. Это умножение матриц, которое я написал с пустым для тела:
// Do NOT do like this!!!
void matrix_multiply(int *A, int *B, int *C, int N)
{
for( int i=0,j=0,k=0;
k++<N ? 1 : ++j<N ? k=1 : ++i<N ? k=1+(j=0) : 0;
C[i*N + j] = A[i*N + k -1] * B[(k-1)*N + j] + (k==1 ? 0 : C[i*N + j])
);
}
А вот пример сортировки вставки:
// Do NOT do like this either!!!
void insertionSort(int *list, int length)
{
for(int i=0, j=0, max=0;
++j<length ? 1 : i<length-1 ? max=j=i+++1+ 0*
(0*((0*(j=list[i-1])) ? 0 : ((0*(list[i-1]=list[max]))
? 0 : list[max]=j))) : 0;
list[j]>list[max] ? max=j : 0
);
}
Приведенные выше фрагменты являются примерами, которые в основном ваши для цикла forВзятый до абсолютного предела.
Резюме
В общем, я бы сказал, что у вас должны быть очень веские причины для написания функции no_splits
иначе, чем я делал с более читаемыми версиями сцикл времени. Производительность является веской причиной, но сначала убедитесь, что этот код действительно является узким местом. И помните, что короткий код не означает быстрый код. Если вы действительно хотите вместо этого использовать цикл for, то, по крайней мере, поместите его в функцию, подобную той, что я делал, и дайте ей комментарий с описанием того, что он делает. Но этот фрагмент - моя последняя рекомендация для вашей цели:
// Count the number of occurrences of substr in str
size_t no_splits(const char *str, const char *substr)
{
size_t ret = 0;
const size_t len = strlen(substr);
for(; *str; str++)
if(strncmp(str, substr, len) == 0)
ret++;
return ret;
}
Если вы хотите сделать это немного быстрее, особенно для длинных substr
, вы можете сделать так:
size_t no_splits(const char *str, const char *substr)
{
size_t ret = 0;
const size_t len = strlen(substr);
for(size_t n = strlen(str) - len; n >= 0; n--)
if(strncmp(&str[n], substr, len) == 0)
ret++;
return ret;
}