如何编写C字符串函数:strncpy,strncat和strncmp

时间:2010-01-04 00:41:57

标签: c string function

我正在解决这个K& R练习:

编写库函数strncpy,strncat和strncmp的版本,它们最多只能运行参数字符串的前n个字符。例如,strncpy(s,t,n)最多复制t到s的n个字符。完整说明见附录B.

所以,如果有一个包含这些字符串函数的源代码的网站,我就会徘徊,所以我可以检查一下我是否做错了。

这些是我写的版本:如果您告诉我是否在函数中有一些错误或我应该添加/更正/改进的东西,我将不胜感激!

int strncmp(char *s, char *t, int n)
{

     if(strlen(s) == strlen(t)) {

         while(*s == *t && *s && n) 
            n--, s++, t++;

         if(!n) 
             return 0; /* same length and same characters */
         else 
             return 1; /* same length, doesnt has the same characters */         
     }
     else
        return strlen(s) - strlen(t);
}

char *strncpy(char *s, char *t, int n)
{
     while(n-- && *s) {
        *s = *t;
        s++, t++;
     }

     if(strlen(t) < n)
        *s = '\0';

     return s;
}

char *strncat2(char *s, char *t, int n)
{
     while(*s)
       s++;

     while(n-- && *t) 
       *s = *t, s++, t++;

     *s = '\0';
     return s;
}

5 个答案:

答案 0 :(得分:4)

快速浏览似乎至少可以揭示一些问题:

  • 在strncmp中:对输入的strlen()调用无效。它们不必被空终止。此外,返回值应为&lt; 0,= 0,&gt; 0,具体取决于相等。
  • strncpy:我相信库版本用\ 0填充字符串到最后。

答案 1 :(得分:3)

当然,有很多strncmp和朋友的开源实现(例如,strncmp here),但它们不一定对你有所帮助。

你的strncmp例如只是实现了错误的算法:它是的情况是较短的字符串始终“小于”较长的字符串,例如,"z"小于"aa" - 因此您无法仅通过比较长度来开始。

您的strncpy正在检查*s应该检查*t的位置,以及其他问题。

查看备用开源实现对诊断错误没有多大帮助:对代码进行同行评审,将其发布到SO时可能会有所帮助; - )

答案 2 :(得分:2)

Google代码搜索非常适合查找标准函数的实现:) 例如函数strncpy:

http://www.google.com/codesearch/p?hl=en#XAzRy8oK4zA/libc/string/strncpy.c&q=strncpy&sa=N&cd=1&ct=rc

答案 3 :(得分:0)

有关解决方案,请参阅CLC Wiki page

现在有一些关于你的代码的评论:

strncmp

if(strlen(s) == strlen(t)) {

您不需要此检查。 strlen()遍历字符串,因此如果长度相等,您将处理字符串两次。这可能会变得昂贵。一般来说,像这样的低级函数,在任何程序中都可以被大量调用,应该是有效的(尽管过早的优化是万恶之源!)。此外,如果长度不相等,您将再次为这两个字符串调用strlen()。除了昂贵之外,它也是错误的,但我们稍后会谈到这一点。关于您的while循环:

while(*s == *t && *s && n) 
    n--, s++, t++;

为什么要滥用逗号运算符?我会简化并编写上面的内容(未经测试,毕竟,这是正在解决的练习!):

while (*s && *t && *s == *t && n--) {
    s++;
    t++;
}
if (!n) return 0;
else return *s - *t;

您的返回值是错误的。 strncmp()应返回0,小于0或大于0,具体取决于第一个字符串的第一个n字符是否等于,小于或大于(按字典顺序排列)第二个字符串

同样,您应该更改strncpy()strncat2()功能。我没有详细研究过这两个,但由于这是一个练习,你可能想要自己做出改变。

答案 4 :(得分:0)

供参考:

char* strncpy(char* s, const char* t, size_t n)
{
    char* ret = s; // need to return this
    while (n-- && *s++ = *t++)
         ;
    if (n) *s = 0;
    return ret;
}

// be lazy, there's no reason to write the copy part of strncpy and strncat twice.
char* strncat(char* s, const char* t, size_t n)
{
     char *ret = s;
     strncpy(s+strlen(s), t, n);
//
//   // if you don't want to call strlen, you can do this
//   while (*s++) ;
//   strncpy(s, t, n);
//
     return ret;
}

int strncmp(const char* s, const char* t, size_t n)
{
    while (n-- && *s == *t) {
          ++s;
          ++t;
    }
    if (n) return *s - *t;
    return 0;
}