سؤال

Yesterday I was at interview and was asked to implement strlen() in C without using any standard functions, all by hands. As an absolute amateur, I implemented primitive version with while loop. Looking at this my interviewer said that it can be implemented at just one line of code. I wasn't be able to produce this code using that term at that moment. After interview I asked my colleagues, and the most experienced from them gave me this piece which really worked fine:

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

So there is a question, is it possible without using recursion, and if yes, how? Terms:

  • without any assembler
  • without any C functions existed in libraries
  • without just spelling few strings of code in one

Please, take note that this is not the question of optimization or real using, just the possibility of make task done.

هل كانت مفيدة؟

المحلول

Similar to @DanielKamilKozar's answer, but with a for-loop, you can do this with no for-loop body, and len gets initialized properly in the function:

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

نصائح أخرى

The best I could think of is this, but it's not the standard strlen since the function itself has a different prototype. Also, it assumes that *len is zero at start.

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

I'm curious how a standard strlen might be implemented in "one line of code", because it's going to require a return, which is "one line of code", judging by what you've posted.

That said, I do agree with the comments saying that it's an incredibly dumb interview question.

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

If this doesn't have to be a function, this one-liner is probably the simplest and shortest way to calculate the length of any null-terminated array (not including variable declarations and prints):

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

    while (s[++n]);

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

if it must be a function, then you can't have an exact function signature as strlen(), since a return have to be in separate line. Otherwise you can do this:

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

What about an empty for loop. Like

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

This seems to work fine.

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

Any thoughts?

UPDATE!

This is probably the most efficient way of implementing strlen. Most compilers use this one implemented in one way or another.

This may be a little harder to understand especially if haven't learned pointers.

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

Contrary to what others say, it is impossible if some sensible restrictions are followed. The restrictions are:

  • one non-empty statement or declaration in the body of the function (a compound statement with a non-empty body is at least two statements in total)
  • same signature as the real strlen
  • no recursion

Any function with the signature of strlen must have a return statement. A return statement consists of the return keyword and an expression. The C language doesn't have expressions that perform loops. One need a statement for that, but this position is reserved for the return statement.

If one relaxes these restrictions (say, change the signature, or don't count return statements and/or declarations and/or bodies of compound statements as long as they are "simple", as separate "lines") the task becomes possible and rather straightforward, as can be seen in many examples here and all over the internet.o

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

In comparison to str[i], the above code that increments the pointer would perform better, because indexing str[i] would evaluate to: *(str + i) which is an addition operation done with every loop, while increment operation is faster.

Also, in comparison to the strlen(const char *str, size_t *len) there is no need for an extra parameter that the caller would provide.

Finally, it's on one line as per the original request.

Native Code

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

You can replace '\0' with zero but i prefer as it

Hope it helps.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top