C strlen()实现在一行代码中

时间:2014-03-19 23:30:28

标签: c algorithm strlen

昨天我在接受采访时被要求在C中实现strlen()而不使用任何标准函数,所有这些都是手工完成的。作为一个绝对的业余爱好者,我用while循环实现了原始版本。看看这个,我的面试官说它可以只用一行代码实现。我当时无法使用该术语生成此代码。在采访之后,我问了我的同事,他们中最有经验的人给了我这件真的很好的作品:

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

所以有一个问题,是否可以不使用递归,如果是,怎么样? 术语:

  • 没有任何汇编程序
  • 库中没有任何C函数
  • ,而不只是在一个
  • 中拼写少量代码

请注意,这不是优化或实际使用的问题,只是完成任务的可能性。

9 个答案:

答案 0 :(得分:10)

与@ DanielKamilKozar的答案类似,但是使用for循环,你可以在没有for-loop body的情况下执行此操作,len在函数中正确初始化:

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

答案 1 :(得分:6)

我能想到的最好的是这个,但它不是标准strlen,因为函数本身有不同的原型。此外,它假设*len在开始时为零。

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

我很好奇标准strlen如何在"一行代码"中实现,因为它需要return,是"一行代码",根据您发布的内容判断。

那就是说,我同意评论说这是一个非常愚蠢的面试问题。

答案 2 :(得分:5)

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

答案 3 :(得分:2)

如果这不是一个函数,这个单行可能是计算任何以null结尾的数组长度的最简单和最短的方法(不包括变量声明和打印):

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

答案 4 :(得分:2)

这似乎工作正常。

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

有什么想法吗?

UPDATE!

这可能是实现strlen的最有效方法。大多数编译器使用以某种方式实现的编译器。

如果没有学过指针,这可能有点难以理解。

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

答案 5 :(得分:1)

空循环怎么样?像

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

答案 6 :(得分:0)

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)相比,不需要调用者提供的额外参数。

最后,根据原始请求,它在一行上。

答案 7 :(得分:0)

与其他人所说的相反,如果遵循一些合理的限制,则不可能。限制是:

  • 函数体中的一个非空语句声明(具有非空体的复合语句总共至少有两个语句)
  • 与真实strlen
  • 相同的签名
  • 没有递归

签名为strlen的任何函数都必须有return语句。 return语句由return关键字和表达式组成。 C语言没有执行循环的表达式。需要一个声明,但这个位置是为return语句保留的。

如果放宽这些限制(例如,更改签名,或者不计算复合语句的返回语句和/或声明和/或正文,只要它们“简单”,作为单独的“行”)任务变得可能而且相当简单,正如在这里和整个互联网上的许多例子中都可以看到的那样.o

答案 8 :(得分:0)

原生代码

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

您可以替换' \ 0'零,但我更喜欢它

希望它有所帮助。