面试题:实现strcpy,strlen,strcmp,strcat,memcpy 之c-style字符串

哪里可以看到c库函数的源码?

gnu的c运行库glibc,但是源码的实现却是复杂的,需要考虑效率,stlen源码分析

c-style字符串有个约定,以空字符结尾,即 '\0' 。

1 char ch[] = { '1', '2' };
2 char ch1[] = { "12" };
3 char ch2[] = "12";

ch存了2个字符,ch1与ch2一样,存了3个字符,即结尾含有 '\0' 。

1 char *c = "djawj\0p";

c不会存字符p,\0标识了结尾。

1 strlen(ch);//stlen沿着ch的内存一直扫描,直到遇到空字符,这就导致了错误
1 size_t strlen(const char *src)
2 {
3     assert(src!=NULL);//if (src == NULL) return 0; 发生意外情况不返回,直接结束
4     const char *temp = src;
5     while (*temp++);
6     return (temp - src - 1);
7 }

1 char* strcpy(char* dst, const char* src)
2 {
3     assert((dst != NULL) && (src != NULL));//断言,如果条件为false,停止程序运行
    char
4 while ((*dst++ = *src++) != '\0'); 5 return dst; 6 }
1 char* strcpy(char* dst, const char* src)
2 {
3     assert((dst != NULL) && (src != NULL));
4     char *tmp = dst;
5     while ((*dst++ = *src++) != '\0');
6     return tmp;  //返回目的地址,支持链式操作strlen(dst2,strlen(dst1,src))
7 }

 下面代码的问题是返回值不是1,0,-1,有多种值

int strcmp(const char *src, const char *dst)
{
    assert((src != NULL) && (dst != NULL));
    int result = 0;

    while (*src != '\0'&& *dst != '\0')
    {
        if (*src == *dst) {
            src++; dst++; //相等就比较下一个字符
        }
        else if (*src > *dst) return result = 1;//src>dst
        else return result = -1; //src<dst
    }
    return  *src - *dst; //三种情况,"abc" "abc" "abcd"
}

修改为为用result存两个字符之差来进行循环检测

 1 int strcmp(const char *src, const char *dst)
 2 {
 3     assert((src != NULL) && (dst != NULL));
 4     int result = 0;
 5 
 6     while (!(result = (*src - *dst)) && (*src != '\0'&& *dst != '\0'))
 7     { //修改为(!(result = (*src - *dst)) && ( *dst != '\0'))比较简洁
 8         dst++;
 9         src++; }
10     if (result < 0) return -1;
11     else if(result > 0) return 1;
12     else return 0;
13 }

 参考:http://www.cnblogs.com/xuhj001/archive/2013/11/17/3428088.html  

C标准库strcmp实现

1 int Strcmp2(char *str1, char *str2)
2 {
3     assert(str1 != NULL&&str2 != NULL);
4     for (; *str1 == *str2; str1++, str2++)
5         if (*str1 == '\0') return 0;
6     return *str1 < *str2 ? -1 : 1;
7 }

自己写的麻烦的实现:

 1 int Strcmp(char *s1, char *s2)
 2 {
 3     assert(s1 != NULL&& s2 != NULL);
 4     int ret;
 5     while (*s1 != '\0'&&*s2 != '\0')
 6     {
 7         //while (*s1++ == *s2++);
 8         if (*s1 == *s2) { s1++; s2++; }
 9         else {
10             ret = *s1 - *s2;
11             cout << ret << endl;
12             return ret <0 ? -1 : 1;//不等<会返回1,大于则返回0,而不是-1
13 
14         }
15     }
16         ret = *s1 - *s2;
17         if (ret < 0) return -1;
18         else return ret == 0 ? 0 : 1;
19     }
View Code

 

char *strcat(char *s1,const char *s2) 可以用strcpy(s1+=strlen(s1),s2)实现

 1 char *Strcat(char *s, const char *s2)// Strcat不会另申请空间,而是需要s1有足够的空间可以容纳原s1与s2的字符
 2 {
 3     char *p = s;
 4     while (*s++) //s的递增不影响实参指针的值,为了返回字符串的首地址,用p存下来
 5     {
 6         cout <<1<< *s << " ";
 7     }
 8     s--;
 9     while (*s++ = *s2++);//‘\0'的ascii值为0,结果为假,即表达式的值会转换为真或假
10     return p;
11 }

 由于strcat一次拼接返回的是首指针,频繁拼接需要再次从开始位置扫描,找字符串的尾部,这样效率就低了

posted @ 2017-08-09 01:04  hchacha  阅读(454)  评论(0)    收藏  举报