常用字符串函数编写

已有代码在linux-gcc中编译通过

  1 #include <stdio.h>
  2 #include <assert.h>
  3 #include <string.h>
  4 #include <stdlib.h>
  5 
  6 // 内存copy函数
  7 void *my_memcpy(void *dest, const void *src, int n)
  8 {
  9     assert((NULL != dest) && (NULL != src));    //判断指针的有效性
 10     char *pdest = (char *)dest;              
 11     char *psrc = (char *)src;       //转换成char类型,一个字节一个字节的传输
 12     while(n--)
 13         *pdest++ = *psrc++;     //每次传输一字节
 14     return pdest;
 15 }
 16 
 17 /**
 18  * memcpy在内存没有重复的情况下能够正确复制,若有重叠情况则复制结果错误,但是它的效率比memmove高。
 19  * 所以,在确定没有重复的情况下用memcpy,在不确定是否有内存重复的情况用memmove。
 20  */
 21 void *my_memmove(void *dest, const void *src, int n)
 22 {
 23     assert((NULL != dest) && (NULL != src));
 24     char *pdest = (char *)dest;                 //转换成char类型,一个字节一个字节的传输
 25     char *psrc = (char *)src;   
 26     if((pdest <= psrc) || (pdest >= psrc + n))  //从前往后复制,则不会出现覆盖src中没有复制的内容
 27     {
 28         while(n--)
 29             *pdest++ = *psrc++;
 30     }
 31     else
 32     {
 33         pdest = pdest + n -1;   //有内存重叠时,从高字节开始传输
 34         psrc = psrc + n -1;     //移动到末尾
 35         while(n--)
 36         *pdest-- = *psrc--; //每次移动一个字节
 37     }
 38     return pdest;
 39 }
 40 
 41 // 作用:将已开辟内存空间 s 的首 n 个字节的值设为值 c。
 42 void *my_memset(void *s, int c, int n)
 43 {
 44     assert(NULL != s);
 45     unsigned char *buff = (char *)s;
 46     while(n--)
 47     {
 48         *(buff++) = (char)c;
 49     }
 50     return buff;
 51 }
 52 
 53 /** memcmp函数会逐字节比较s1和s2所指内存区,
 54  * s1 > s2 —-> 返回 >0 的值 
 55  * s1 = s2 —-> 返回 =0 的值 
 56  * s1 < s2 —-> 返回 <0 的值
 57  */
 58 int my_memcmp(const void *s1, const void *s2, int n)
 59 {
 60     assert((NULL != s1) && (NULL != s2));
 61 
 62     int result;
 63     while(!(result = *(unsigned char *)s1 - *(unsigned char *)s2) && (n--))
 64     {
 65         s1++; s2++;
 66     }
 67     return result;
 68     
 69 }
 70 
 71 // 当第一次遇到字符c时停止查找。如果成功,返回指向字符c的指针;否则返回NULL。
 72 void *my_memchr(const void *s, int c, int n)
 73 {
 74     assert(NULL != s);
 75     int result;
 76     while((*(unsigned char *)(s) != (unsigned char)c) && (n--))
 77     {
 78         s++;
 79     }
 80         return (n ? (void *)s : NULL);
 81 }
 82 
 83 char *my_strcpy(char *dest, const char *src)
 84 {
 85     assert((NULL != dest) && (NULL != src));//判断指针的有效性
 86     char *addr = dest;
 87     while((*dest++ = *src++) != '\0');
 88     return addr;            //返回 char *,使函数支持链式表达式
 89 }
 90 
 91 char *my_strncpy(char *dest, const char *src, int n)
 92 {
 93     assert((NULL != dest) && (NULL != src));
 94     char *addr = dest;
 95     while((n--) && (*dest++ = *src++) != '\0');
 96     return addr;            //返回 char *,使函数支持链式表达式
 97 }
 98 
 99 char *my_strcat(char *dest, const char *src)
100 {
101     assert((NULL != dest) && (NULL != src));
102     char *addr = dest;
103     while(*dest!= '\0') //若使用while(*strDest++),则会出错,因为++是不受循环约束的
104     {
105         *dest++;    //要使dest最后指向该字符的结束标志\0,就必须在内部循环
106     }
107     while((*dest++ = *src++) != '\0');
108     return addr;    //为了实现链式操作,将目的地址返回
109 }
110 
111 /**
112  * my_strncat其原理与my_strcat相同,只是在判断条件中加入边界条件;
113  * while(((i++ < n) && (*dest++ = *src++)) != '\0')中,i++<n 为边界,当i = n-1时,退出循环
114  */
115 char *my_strncat(char *dest, const char *src, int n)
116 {
117     assert((NULL != dest) && (NULL != src));
118     char *addr = dest;
119     while(*dest != '\0')
120     {
121         *dest++;
122     }
123     while((n--) && (*dest++ = *src++) != '\0');
124     return addr;
125 }
126 
127 /**
128  * 使用*(unsignedchar*)str1而不是用*str1。这是因为传入的参数为有符号数,有符号字符值的范围
129  * 是-128~127,无符号字符值的范围是0~255,而字符串的ASCII没有负值,若不转化为无符号数这会在
130  * 减法实现时出现错误。例如str1的值为1,str2的值为255。
131  *
132  * While循环中(!(result = *(unsigned char *)s1 - *(unsigned char *)s2) && *s1),最后与上str1
133  * 也可以换成str2,因为前面已经做了相减,无论哪个先为‘\0’都会退出。因为最后与上str1是为了判
134  * 断str1是否结束,即是否为‘\0’。
135  */
136 int my_strcmp(const char *s1, const char *s2)
137 {
138     assert((NULL != s1) && (NULL != s2));
139     int result;
140     while(!(result = *(unsigned char *)s1 - *(unsigned char *)s2) && *s1)
141     {
142         s1++; s2++; //字符串比较是一位一位的比较,s1++,s2++的作用是循环比较下一位
143     }
144     if(result > 0) {return 1;}
145     else if(result < 0) {return -1;}
146     else {return 0;}
147 }
148 
149 /**
150  * my_strncmp的实现原理与my_strcmp相同,但是相对于my_strcmp多了边界条件n;
151  */
152 int my_strncmp(const char *s1, const char *s2, int n)
153 {
154     
155     assert((NULL != s1) && (NULL != s2));
156     int result;
157     while(!(result = *(unsigned char *)s1 - *(unsigned char *)s2) && *s1 && (n--))
158     {
159         s1++; s2++;
160     }
161     if(result > 0) {return 1;}
162     else if(result < 0) {return -1;}
163     else {return 0;}
164 
165 }
166 
167 // 查找字符串s中首次出现字符c的位置
168 char *my_strchr(const char *s, int c)
169 {
170     assert(NULL != s);
171     while(*s != (char)c)
172     {   
173         if ( *s == '\0' )
174             return NULL;
175         s++;
176     }
177     return (char *)s;
178 
179 }
180 
181 int my_strlen(const char *str)
182 {
183     assert(NULL != str);
184     int len = 0;
185     while(*str++ != '\0')   //strlen计算字符长度是不计算'\0'的,这是函数原型决定的
186     {
187         len++;
188     }
189     return len;
190 }
191 
192 char *my_strdup(const char *src)
193 {
194     assert(NULL !=src);
195     char *psrc = (char *)src;
196     char *p_src = NULL;
197     p_src = psrc ;
198     int len = 0 + 1;
199     while(*p_src++ != '\0')
200          len++;
201     p_src = psrc;
202     char *new_addr  = (char *)malloc(sizeof(char)*(len));
203     while((*new_addr++ = *p_src++)  != '\0');
204     return (new_addr - len);
205 }
206 
207 char *my_strndup(const char *s, int n)
208 {
209     assert(NULL != s);
210     
211 }
212 
213 //搜索一个字符串 *needle 在 *haystack 字符串中的第一次出现。
214 char *my_strstr(const char *haystack, const char *needle)
215 {
216     assert((NULL != haystack) && (NULL != needle));
217     while(*haystack++ !='\0')
218     {
219         if((*haystack - *needle) == 0)
220             return (char *)haystack;
221         haystack++;
222     }
223     return NULL;
224 }
225 
226 char *my_strtok(char *str, const char *delim)
227 {
228     
229 }
230 int my_strcoll(const char *s1, const char *s2)
231 {
232     
233 }
234 
235 int main(void)
236 {
237     char dest[20] = {}, src[] = "abcde";
238     char dest1[20] = {}, src1[] = "linux";
239 
240 /*    //my_memcpy功能验证
241     printf("my_strcpy= %s\n", my_strcpy(dest1, src1));
242     printf("strcpy   = %s\n", strcpy(dest, src));
243 
244     // memcpy(dest+2, dest, 5); 
245     // printf("memcpy   = %s\n", dest);//输出:my_memcpy  = abababa
246     // memcpy(dest, dest1, strlen(dest1)); 
247     // printf("memcpy   = %s\n", dest);//输出:my_memcpy  = linuxba  
248 
249     my_memcpy(dest+2, dest, 5); 
250     printf("my_memcpy= %s\n", dest);//输出:my_memcpy  = abababa
251     my_memcpy(dest, dest1, strlen(dest1)); 
252     printf("my_memcpy= %s\n", dest);//输出:my_memcpy  = linuxba      
253 */ 
254 
255 /*    //my_memmove功能验证
256     printf("my_strcpy= %s\n", my_strcpy(dest1, src1));
257     printf("strcpy   = %s\n", strcpy(dest, src));
258 
259     // memmove(dest+2, dest, 5); 
260     // printf("memmove  = %s\n", dest);    //输出:memmove  = ababcde
261     // memmove(dest, dest1, strlen(dest1)); 
262     // printf("memmove  = %s\n", dest);    //输出:memmove  = linuxde
263      
264     my_memmove(dest+2, dest, 5);
265     printf("my_memmove  = %s\n", dest);//输出:my_memmove  = ababcde
266     my_memmove(dest, dest1, strlen(dest1)); 
267     printf("my_memmove  = %s\n", dest);//输出:my_memmove  = linuxde            
268 */   
269 
270 /*    //my_memset功能验证
271     my_memset(dest, '2', 20);
272     printf("my_memset  = %s\n", dest);  //输出:22222222222222222222
273     memset(dest, 'A', 5);
274     printf("memset     = %s\n", dest);  //输出:AAAAA222222222222222
275 */
276 
277 /*    //my_memcmp功能验证
278     printf("dest1     = %s\n", my_strncpy(dest1, src1,5));  //dest1 = linux
279     printf("dest      = %s\n", my_strncpy(dest, src, 5));   //dest  = liabc
280     
281     printf("my_memcmp = %d\n", my_memcmp(dest1, dest, 2));
282     printf("memcmp    = %d\n", memcmp(dest1, dest, 3));
283 
284 */
285 
286 /*    //my_memchr功能验证
287 
288     printf("dest  = %s\n", my_strcpy(dest, "arm - linux - gcc"));
289     printf("dest1 = %s\n", my_strcpy(dest1, "gcc"));
290  
291     printf("dest1:%s =%s\n",dest1,(char *)memchr(dest,'-',my_strlen(dest)));
292     printf("dest1:%s =%s\n",dest1,(char *)my_memchr(dest,'-',my_strlen(dest)));
293 */
294 
295 /*    //my_strcpy功能验证
296     printf("my_strcpy  = %s\n", my_strcpy(dest1, src1));
297     printf("strcpy     = %s\n", strcpy(dest, src));
298 */
299 
300 /*    //my_strncpy功能验证
301     printf("my_strncpy = %s\n", my_strncpy(dest1, src1, 5));
302     printf("strncpy    = %s\n", strncpy(dest, src, 5));
303 */
304 
305 
306 /*    //my_strcat功能验证
307     printf("my_strncpy = %s\n", my_strncpy(dest1, src1, 2));
308     printf("my_strcat  = %s\n", my_strcat(dest1, src1));
309     printf("strcat     = %s\n", strcat(dest1, src));
310 */
311 
312 /*    //my_strncat功能验证
313     printf("my_strncpy = %s\n", my_strncpy(dest1, src1, 2));
314     printf("my_strncat = %s\n", my_strncat(dest1, src1, 2));
315     printf("strncat    = %s\n", strncat(dest1, src, 2));
316 */
317 
318 /*    //my_strcmp功能验证
319     printf("my_strncat = %s\n", my_strncat(dest1, src1, 3));
320     printf("my_strncat = %s\n", my_strncat(dest, src1, 2));
321     printf("my_strcmp  = %d\n", my_strcmp(dest1, dest));
322     printf("   strcmp  = %d\n", strcmp(dest1, dest));
323     printf("my_strcmp  = %d\n", my_strcmp(src, src1));
324     printf("   strcmp  = %d\n", strcmp(src, src1));
325 */
326 
327 /*    //my_strncmp功能验证
328     printf("my_strncpy  = %s\n", my_strncpy(dest1, src1,5));
329     printf("my_strncpy  = %s\n", my_strncpy(dest, src, 5));
330     printf("my_strncmp  = %d\n", my_strncmp(dest1, dest, 1));
331     printf("   strncmp  = %d\n", strncmp(dest1, dest, 1));
332     printf("my_strncmp  = %d\n", my_strncmp(src, src1, 1));
333     printf("   strncmp  = %d\n", strncmp(src, src1, 1));
334 */
335 
336 /*    //my_strchr功能验证
337     char *dest2 = "arm-linux-gcc";
338     
339     printf("strchr    = %s\n", strchr(dest2, 'r'));
340     printf("my_strchr = %s\n", my_strchr(dest2, 'r'));
341 */
342 
343     
344 /*    //my_strlen功能验证
345     printf("my_strncpy = %s\n", my_strncpy(dest1, src1, 5));
346     printf("my_strlen  = %d\n", my_strlen(dest1));
347     printf("strlen     = %d\n", strlen(dest1));  
348 */
349 
350 /*    //my_strdup功能验证
351     char *src2 = "arm-linux-gcc";
352     char *dest2 , *dest3;
353     dest2 = strdup(src2);
354     dest3 = my_strdup(src2);
355     printf("strdup string is: %s\n", dest2);
356     printf("strdup string is: %p\n", dest2);
357     printf("my_strdup string is: %s\n", dest3);
358     printf("my_strdup string is: %p\n", dest3);
359     free(dest2);
360     free(dest3);
361 */
362 
363 /*    //my_strndup功能验证
364     char *src2 = "arm-linux-gcc";
365     char *dest2 , *dest3;
366     dest2 = strndup(src2, 2);
367     dest3 = my_strndup(src2, 2);
368     printf("strndup string is: %s\n", dest2);
369     printf("strndup string is: %p\n", dest2);
370     printf("my_strndup string is: %s\n", dest3);
371     printf("my_strndup string is: %p\n", dest3);
372    // free(dest2);
373    // free(dest3);
374 */
375 
376 ///*    //my_strstr功能验证
377     char *src2 = "arm-linux-gcc";
378     char *dest2= "ux";
379     char *dest3, *dest4;
380 
381     dest3 = my_strstr(src2, dest2);
382     dest4 = strstr(src2, dest2);
383     printf("strstr string is: %s\n", dest3);
384     printf("my_strstr string is: %s\n", dest4);
385 //*/
386 
387 
388 
389 
390     return 0;
391 }

 

posted @ 2017-10-10 16:53  常瑟  阅读(493)  评论(0编辑  收藏  举报