Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C strlen()在一行代码中实现_C_Algorithm_Strlen - Fatal编程技术网

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

C strlen()在一行代码中实现,c,algorithm,strlen,C,Algorithm,Strlen,昨天我在面试时,被要求在C语言中实现strlen(),而不使用任何标准函数,全部是手工实现的。作为一个绝对的业余爱好者,我用while循环实现了原始版本。看到这一点,我的面试官说它只需要一行代码就可以实现。当时,我无法用这个术语生成这段代码。采访结束后,我问了我的同事,他们中最有经验的人给了我这篇文章,这篇文章非常有效: size_t str_len (const char *str) { return (*str) ? str_len(++str) + 1 : 0; } 所以有一个问

昨天我在面试时,被要求在C语言中实现strlen(),而不使用任何标准函数,全部是手工实现的。作为一个绝对的业余爱好者,我用while循环实现了原始版本。看到这一点,我的面试官说它只需要一行代码就可以实现。当时,我无法用这个术语生成这段代码。采访结束后,我问了我的同事,他们中最有经验的人给了我这篇文章,这篇文章非常有效:

size_t str_len (const char *str)
{
    return (*str) ? str_len(++str) + 1 : 0;
}
所以有一个问题,不使用递归是否可能,如果可能,如何实现? 条款:

  • 没有任何汇编程序
  • 库中不存在任何C函数
  • 而不只是在一个代码中拼写几个字符串

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

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

void my_strlen(const char *str, size_t *len)
{
        while(*(str++)) (*len)++;
}
我很好奇标准的strlen是如何在“一行代码”中实现的,因为它需要一个
返回值,这是“一行代码”,根据您发布的内容判断


也就是说,我同意有评论说这是一个极其愚蠢的面试问题。

那么空for循环呢。像

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

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

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

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

如果它必须是一个函数,那么就不能有一个确切的函数签名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] == '\0') return i;
}
有什么想法吗

更新

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

这可能有点难理解,尤其是如果你还没有学会指针的话

size_t strlen(char *str)
{
    register const char *s;
    for (s = str; *s; ++s);
    return(s - str);
}
与str[i]相比,上面增加指针的代码性能更好,因为索引str[i]的计算结果为:*(str+i),这是对每个循环执行的加法操作,而增量操作更快

此外,与strlen(const char*str,size_t*len)相比,调用方不需要提供额外的参数


最后,根据最初的请求,它在一行上。

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

  • 函数体中的一条非空语句或声明(具有非空体的复合语句至少总共有两条语句)
  • 与真实的strlen签名相同
  • 无递归
签名为strlen
的任何函数都必须有返回语句。return语句由
return
关键字和表达式组成。C语言没有执行循环的表达式。为此需要一个语句,但这个位置是为return语句保留的

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

本机代码

unsigned int strlen(const char *s)
{
    int l;for(l=0;s[l]!='\0';l++);return l;
}
您可以将“\0”替换为零,但我更喜欢它


希望能有所帮助。

对于代码来说,这可能更好,“一行”是一个非常松散的要求。能够在一行中实现strlen()是毫无意义的。我从来不会在面试或其他场合要求任何人这么做。@gnasher729:同意。再说一次,大多数面试“谜题”都是毫无意义的,除非是作为观察应聘者思维方式的机会。。。假设他们在TAP上没有答案,在这种情况下,它除了告诉你他们有一些经验之外,什么都不告诉你。在C++中你可以使用尾递归:<代码> SsiZeTyStLLN(const char * STR,sisietht ACC=0){Read * STR·StLLN(STR + 1,ACC+ 1):ACC;},应该编译成一个循环,我猜这不是完整的函数。
返回在哪里?@DanielKamilKozar编辑-计数器必须在循环外初始化。但它仍然在一行中计数!?这不构成strlen函数,所以如果这是所需的,则不算数。它看起来像两个linesAh,非常聪明!很明显,(*len=0;*str;++str,(*len)++)?这样,您就不必在每次迭代时取消对
len
的引用以索引到
str
。@RemyLebeau是的,这也行。我想,若你们在优化这个,你们需要在尊重或额外的增量中,找出最快的。无论哪种方式,编译器都可能将
str
len
放在寄存器中,因此这两种方式可能没有太大区别。strlen原型是
size\t strlen(const char*str)
这与strlen不是同一个签名。我会使用它:
for(size\t len=0;;+str,+len){如果(!*str)返回len;}
注意标准:
不只是在一行中拼写几个代码字符串
以换行结束。。你可能会想到“语句”+1,因为这个问题的表述非常模糊,我认为,这是最好的答案:它保留了
strlen()
的功能和签名,可以说是在一行中完成的。@MattMcNabb:从技术上讲,你是对的,问题描述肯定可以被改写得更精确;但是投三
size_t strlen(char *str)
{
    register const char *s;
    for (s = str; *s; ++s);
    return(s - str);
}
size_t strlen (const char* str) {
    for (const char* s1 = str; ; s1++) if (!(*s1)) return s1 - str; 
}
unsigned int strlen(const char *s)
{
    int l;for(l=0;s[l]!='\0';l++);return l;
}