常用字符串函数编写
已有代码在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 }