#include <stdio.h>
#include <ctype.h>
/* in: the string to abbreviate
out: output abbreviation. Function assumes there's enough room */
void abbrev(const char in[], char out[])
{
const char *p;
int zbPosOut = 0; /* current zero-based position within the `out` array */
for (p = in; *p; ++p) { /* iterate through `in` until we see a zero terminator */
/* if the letter is uppercase
OR if (the letter is alphabetic AND we are not at the zero
position AND the previous char. is a space character) OR if the
letter is lowercase and it is the first char. of the array... */
if (isupper(*p) || (isalpha(*p) && (p - in) > 0 && isspace(p[-1]))
|| (islower(*p) && p == in)) {
out[zbPosOut++] = *p; /* ... then the letter is the start letter
of a word, so add it to our `out` array, and
increment the current `zbPosOut` */
}
}
out[zbPosOut] = 0; /* null-terminate the out array */
}
Этот код говорит о многом в нескольких строках.Давайте посмотрим:
isupper(*p) || (isalpha(*p) && (p - in) > 0 && isspace(p[-1]))
|| (islower(*p) && p == in)
Если текущий символ (*p
) является заглавным символом ИЛИ, если это алфавит (isalpha(*p)
, а предыдущий символ p[-1]
является пробелом, то мы можемсчитать *p
первым символом слова, и его следует добавить в наш массив out
. Мы включаем тест (p - in) > 0
, потому что если p == in
, то мы находимся в нулевой позиции массива и, следовательно,p[-1]
не определено.
Порядок в этом выражении имеет большое значение. Если бы мы поставили (p - in) > 0
после теста isspace(p[-1])
, то мы бы не воспользовались преимуществомлень оператора &&
: как только он встречает ложный операнд, следующий операнд не вычисляется. Это важно, потому что если p - in == 0
, то мы не хотим вычислять выражение isspace(p[-1])
.мы написали тесты, чтобы убедиться, что isspace(p[-1])
вычисляется после того, как мы не на нулевой позиции.
Финальное выражение (islower(*p) && p == in)
обрабатывает случай, когда первая буква строчная.ase.
out[zbPosOut++] = *p;
Мы добавляем символ *p
в массив out
.Текущее положение out
отслеживается переменной zbPosOut
, которая впоследствии увеличивается (поэтому мы используем postscript ++
вместо префикса).
Код для проверки работы abbrev
:
int main()
{
char jordan1[] = " electronic frontier foundation ";
char out[16];
abbrev(jordan1, out);
puts(out);
return 0;
}
В качестве выхода выдается eff
.Чтобы это выглядело как аббревиатура, мы можем изменить код, добавив к буквам от *p
до out
:
out[zbPosOut++] = toupper(*p);
, которые пишут с заглавной буквы каждую букву, добавленную в массив out
(если *p
уже в верхнем регистре, toupper
просто возвращает *p
).