C реализация strlen() в одной строке кода

вчера я был на собеседовании и меня попросили реализовать strlen() в C без использования каких-либо стандартных функций, все вручную. Как абсолютный любитель, я реализовал примитивную версию с while loop. Глядя на это, мой интервьюер сказал, что он может быть реализован только в одной строке кода. В тот момент я не смог создать этот код, используя этот термин. После интервью я обратился к коллегам, и самые опытные из них дали мне это произведение, которое действительно сработало отлично:

size_t str_len (const char *str)
{
    return (*str) ? str_len(++str) + 1 : 0;
}

итак, возникает вопрос, возможно ли это без использования рекурсии, и если да, то как? Условия:

  • без какого-либо ассемблера
  • без каких-либо функций C существовали в библиотеках
  • без просто написания нескольких строк кода в одном

пожалуйста, обратите внимание, что это не вопрос оптимизации или реального использования, просто возможность сделать задачу.

9 ответов


подобно ответу @DanielKamilKozar, но с for-loop, вы можете сделать это без тела for-loop, и len инициализируется должным образом в функции:

void my_strlen(const char *str, size_t *len)
{
    for (*len = 0; str[*len]; (*len)++);
}

лучшее, что я мог придумать, это это, но это не стандарт strlen поскольку сама функция имеет другой прототип. Кроме того, предполагается, что *len равен нулю на старте.

void my_strlen(const char *str, size_t *len)
{
        while(*(str++)) (*len)++;
}

мне любопытно, как стандартный strlen может быть реализовано в "одной строке кода", потому что для этого потребуется return, что является "одной строкой кода", судя по тому, что вы опубликовали.

тем не менее, я согласен с комментариями о том, что это невероятно глупое интервью вопрос.


size_t str_len (const char *str)
{
    for (size_t len = 0;;++len) if (str[len]==0) return len;
}

Если это не должно быть функцией, этот однострочный, вероятно, самый простой и короткий способ вычислить длину любого массива с нулевым завершением (не включая объявления переменных и печати):

int main() {
    const char *s = "hello world";
    int n = 0;

    while (s[++n]);

    printf ("%i\n", n);
    return 0;
}

если это должна быть функция, то вы не можете иметь точную сигнатуру функции как strlen(), поскольку возврат должен быть в отдельной строке. В противном случае вы можете сделать это:

void my_strlen(int* n, const char* s) {
    while (s[++(*n)]);
}

int main() {
    const char *s = "hello world";
    int n = 0;

    my_strlen(&n, s);

    printf ("%i\n", n);
    return 0;
}

Это, кажется, работает нормально.

unsigned short strlen4(char *str)
{
    for (int i = 0; ; i++) if (str[i] == '') return i;
}

какие мысли?

обновление!

это, вероятно, самый эффективный способ реализации strlen. Большинство компиляторов используют этот реализованный так или иначе.

Это может быть немного сложнее понять, особенно если вы не изучили указатели.

size_t strlen(char *str)
{
    register const char *s;
    for (s = str; *s; ++s);
    return(s - str);
}

Как насчет пустого цикла for. Как

int i=0;
for(; str[i]!=0; ++i);

вопреки тому, что говорят другие, это невозможно если соблюдаются некоторые разумные ограничения. Ограничения:

  • одно непустое утверждение или объявление в теле функции (составной оператор с непустым телом составляет не менее двух операторов в общей сложности)
  • та же подпись, что и настоящая strlen
  • нет рекурсии

любая функция с подписью strlen должен иметь оператор возврата. Оператор return состоит из return ключевое слово и выражение. Язык C не имеет выражений, которые выполняют циклы. Для этого требуется оператор, но эта позиция зарезервирована для оператора return.

если ослабить эти ограничения (скажем, изменить подпись или не считать операторы возврата и / или объявления и / или тела составных операторов, пока они "просты", как отдельные" строки"), задача становится возможной и скорее простой, как видно из многих примеров здесь и во всем интернете.o


size_t strlen (const char* str) {
    for (const char* s1 = str; ; s1++) if (!(*s1)) return s1 - str; 
}

по сравнению со str[i] приведенный выше код, который увеличивает указатель, будет работать лучше, потому что индексирование str[i] будет оцениваться как: *(str + i), что является операцией сложения, выполняемой с каждым циклом, в то время как операция приращения быстрее.

кроме того, по сравнению с strlen(const char *str, size_t *len) нет необходимости в дополнительном параметре, который предоставил бы вызывающий.

наконец, он находится на одной строке в соответствии с исходным запросом.


Машинный Код

unsigned int strlen(const char *s)
{
    int l;for(l=0;s[l]!='';l++);return l;
}

вы можете заменить '\0 ' на ноль, но я предпочитаю, как это

надеюсь, что это помогает.