1. C/C++项目一

需求: 使用C语言封装string 字符串,实现字符串的增、删、改、查等API函数。

要求: 不能使用 string 库函数,所有库函数必须自己手动实现。

 【项目实现】

myString.h 代码如下:

 1 #include <stdlib.h>
 2 #include <string.h>
 3 #include <stdio.h>
 4 
 5 //字符串封装,需要库函数
 6 //不需要库函数
 7 struct CString
 8 {
 9     char *p;        //保存字符串首地址
10     int realLen;    //字符串实际长度
11 };
12 
13 typedef struct CString myString;    //相当于myString就是struct CString的简写
14 
15 //字符串封装需要实现:初始化、打印、增[尾部增加/任意位置增加](字符/字符串)、删(字符/字符串)、查(字符/字符串)、改(字符/字符串)
16 
17 void init(myString *string);                                //原封不动初始化
18 void initWithLen(myString *string, int len);                //开辟长度,内存清零
19 void initWithString(myString *string, char *copyString);    //初始化并拷贝字符串
20 void printString(myString *string);                         //打印字符串
21 
22 void run(myString *string);                                 //将字符串string按照指令来执行
23 
24 //增[尾部增加](字符/字符串):
25 void backAddChar(myString *string,char ch);                 //尾部增加字符
26 void backAddStr(myString *string,char *str);                //尾部增加字符串
27 
28 //查(字符/字符串):
29 char *findFirstChar(myString *string, char ch);    //在字符串string中查找第一个出现的字符ch,返回第一个找到的字符
30 char *findFirstStr(myString *string, char *str);   //在字符串string中查找第一个子串str,返回第一个找到的子串的地址
31 
32 //删(字符/字符串)
33 int delFirstChar(myString *string, const char ch);          //成功返回0,失败返回-1;依赖于查找函数;删除第一个找到的字符
34 int delFirstStr(myString *string, char * const str);        //删除第一个找到的字符串
35 
36 //增[任意位置增加](字符/字符串):
37 void addChar(myString *string, char ch, char *pos);     //任意位置增加字符
38 void addStr(myString *string, char *str, char *pos);    //任意位置增加字符串
39 
40 //改(字符/字符串)
41 void changeFirstChar(myString *string, const char oldChar, const char newChar);     //修改字符
42 void changeFirstStr(myString *string, char * const oldStr, char * const newStr);    //修改字符串

myString.c 代码如下:

  1 #define _CRT_SECURE_NO_WARNINGS
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #include <stdio.h>
  5 #include "myString.h"
  6 
  7 //实现库函数strlen():
  8 int mystrlen(const char *p)
  9 {
 10     if (p == NULL)
 11         return -1;        //失败
 12     int len = 0;
 13     while (*p != '\0')    //字符串终止条件
 14     {
 15         len++;            //长度自增
 16         p++;              //指针不断向前
 17     }
 18     return len;
 19 }
 20 
 21 //实现库函数strcpy():
 22 char *mystrcpy(char *strDest, const char *strSrc)    //const限定不被意外修改
 23 {
 24     if (strDest == NULL || strSrc == NULL)           //异常处理
 25         return NULL;
 26 
 27     char *destbak = strDest;    //destbak保留strDest的初始位置,因为循环结束后strDest指向了末尾
 28     while (*strSrc != '\0')
 29     {
 30         *strDest = *strSrc;     //赋值字符
 31         strSrc++;
 32         strDest++;              //指针不断向前,字符挨个赋值
 33     }
 34     *strDest = '\0';            //注意:此处需要添加'\0'作为结束
 35     return destbak;             //返回的是strDest的起始位置,所以用destbak
 36 }
 37 
 38 //初始化结构体字符串
 39 void init(myString *string)
 40 {
 41     string->p = NULL;
 42     string->realLen = 0;
 43 }
 44 
 45 void initWithLen(myString *string, int len)
 46 {
 47     //string->p = (char *)malloc(sizeof(char *)*len);    //分配内存,但是分配的内存不为‘0’,可以使用calloc函数
 48     string->p = (char *)calloc(len, sizeof(char *));     //分配内存并清0,避免了垃圾数据的影响
 49     string->realLen = len;                               //长度
 50 }
 51 
 52 void initWithString(myString *string, char *copyString)
 53 {
 54     int length = mystrlen(copyString);                      //获取字符串长度,需实现strlen()库函数
 55     string->p = (char *)calloc(length + 1, sizeof(char));   //分配内存
 56     mystrcpy(string->p, copyString);                        //拷贝字符串,需实现strcpy()库函数
 57     string->realLen = length + 1;                           //设置长度
 58 }
 59 
 60 //打印字符串
 61 void printString(myString *string)
 62 {
 63     printf("%s\n", string->p);
 64 }
 65 
 66 void run(myString *string)
 67 {
 68     system(string->p);        //执行指令
 69 }
 70 
 71 //-----------------------------------增[尾部增加](字符/字符串)-------------------------------------------------
 72 //实现库函数strcat():
 73 char *mystrcat(char *strDest, const char *strSrc)
 74 {
 75     if (strDest == NULL || strSrc == NULL)    
 76         return NULL;          //失败
 77     
 78     char *destbak = strDest;
 79     while (*strDest != '\0')
 80     {
 81         strDest++;            //strDest指针向前移动,一直到最后一个字符'\0'的位置
 82     }
 83     while (*strSrc != '\0')   //从strDest尾部开始拷贝
 84     {
 85         *strDest = *strSrc;
 86         strSrc++;
 87         strDest++;
 88     }
 89     *strDest = '\0';
 90     return destbak;
 91 }
 92 
 93 //尾部增加字符
 94 void backAddChar(myString *string, char ch)
 95 {
 96     if (mystrlen(string->p) + 1 == string->realLen)    //意味着满了
 97     {
 98         //重新分配内存,增加一个字符的位置
 99         string->p = realloc(string->p, string->realLen + 1);
100         string->realLen += 1;        //注意:不能用 string->realLen++; 若用++,这个值在寄存器中而并没有赋值
101 
102         string->p[string->realLen - 2] = ch;
103         string->p[string->realLen - 1] = '\0';
104     }
105     else
106     {
107         int nowLen = mystrlen(string->p);    //求出当前长度
108         string->p[nowLen] = ch;
109         string->p[nowLen + 1] = '\0';        //字符增加
110     }
111 }
112 
113 //尾部增加字符串
114 void backAddStr(myString *string, char *str)
115 {
116     int nowStrLen = mystrlen(string->p);           //获取当前字符串长度
117     int addStrLen = mystrlen(str);                  //要增加的字符串的长度
118     if (nowStrLen + addStrLen + 1 > string->realLen)    //判定是否越界
119     {
120         int needAddLen = nowStrLen + addStrLen + 1 - string->realLen;            //需要扩展的长度
121         string->p = (char *)realloc(string->p, string->realLen + needAddLen);    //增加字符串长度
122 
123         mystrcat(string->p, str);            //拷贝字符串,需要自己实现库函数strcat()
124         string->realLen += needAddLen;       //增加长度
125     }
126     else
127     {
128         mystrcat(string->p, str);            //拷贝字符串
129     }
130 }
131 
132 //-----------------------------------查(字符/字符串)-------------------------------------------------
133 //在字符串string中查找第一个出现的字符ch,返回第一个找到的字符
134 //实现库函数strchr():在字符串string中查找第一个出现的字符ch
135 //函数原型:  char *strchr(char *str,char c);
136 char *mystrchr(const char *str, const char c)
137 {
138     if (str == NULL)        //异常情况
139         return NULL;
140 
141     while (*str != '\0')
142     {
143         if (*str == c)
144         {
145             return str;     //找到返回地址
146         }
147         str++;
148     }
149     return NULL;            //没有找到返回NULL
150 }
151 char *findFirstChar(myString *string, char ch)
152 {
153     char *p = mystrchr(string->p, ch);
154     return p;
155 }
156 //在字符串string中查找第一个子串str,返回第一个找到的子串的地址
157 //实现库函数strstr():在字符串str1中查找指定子串str2,返回第一个找到的子串的地址
158 //函数原型:  char *strstr(char *str1,char *str2);
159 char *mystrstr(const char * const str1, const char * const str2)    //注意这里第二个const的使用,不允许str1指针后移
160 {
161     if (str1 == NULL || str2 == NULL)  //异常
162         return NULL;
163 
164     char *p = NULL;                    //保存找到的地址
165     char *strbak1 = str1;              //对str1的起始位置作备份
166     
167     while (*strbak1 != '\0')
168     {
169         int flag = 1;                //标识符,一开始假定是相等的
170         char *strbak2 = str2;        //此语句放在循环中,每次循环都需要重新赋值
171         char *nowstrbak1 = strbak1;
172 
173         while (*strbak2 != '\0')
174         {
175             if (*nowstrbak1 != '\0')        //没有到str1的末尾
176             {
177                 if (*strbak2 != *nowstrbak1)//有一个不等
178                 {
179                     flag = 0;    //赋值为0,代表不等
180                 }
181                 nowstrbak1++;
182                 strbak2++;
183             }
184             else
185             { 
186                 flag = 0;
187                 break;
188             }
189         }
190 
191         if (flag == 1)
192         {
193             p = strbak1;    //当前位置
194             return p;
195         }
196         strbak1++;
197     }
198     
199     return NULL;
200 }
201 char *findFirstStr(myString *string, char *str) 
202 {
203     char *pres = mystrstr(string->p, str);
204     return pres;        //返回地址
205 }
206 
207 //-----------------------------------删(字符/字符串)-------------------------------------------------
208 //删除第一个找到的字符
209 int delFirstChar(myString *string, const char ch)    //成功返回0,失败返回-1;依赖于查找函数
210 {
211     char *p = mystrchr(string->p, ch);        //查找
212     
213     if (p == NULL)
214         return 0;
215     else
216     {
217         char *pnext = p + 1;
218         while (*pnext != '\0')
219         {
220             *p = *pnext;     //删除一个字符,整体向前移动
221             p++;
222             pnext++;
223         }
224         *p = '\0';            //字符串一定要有结尾
225 
226         return 1;
227     }
228 }
229 
230 //删除第一个找到的字符串
231 int delFirstStr(myString *string, char * const str)
232 {
233     char *p = mystrstr(string->p, str);    //查找
234 
235     if (p == NULL)
236         return 0;
237     else
238     {
239         int length = mystrlen(str);        //求子串的长度
240         char *pnext = p + length;
241         while (*pnext != '\0')
242         {
243             *p = *pnext;    //删除一个字符,整体向前移动
244             p++;
245             pnext++;
246         }
247         *p = '\0';
248 
249         return 1;
250     }
251 }
252 
253 //-----------------------------------增[任意位置增加](字符/字符串)-------------------------------------------------
254 //任意位置增加字符
255 void addChar(myString *string, char ch, char *pos)
256 {
257     if (pos == NULL || string == NULL)    //异常情况
258         return;
259 
260     if (mystrlen(string->p) + 1 == string->realLen)    //意味着满了
261     {
262         //重新分配内存,增加一个字符的位置
263         string->p = realloc(string->p, string->realLen + 1);
264         string->realLen += 1;        //注意:不能用 string->realLen++; 若用++,这个值在寄存器中而并没有赋值
265 
266         int nowLen = mystrlen(string->p);       //求出当前长度
267         int moveLen = mystrlen(pos);            //求出现在要移动的长度
268         for (int i = nowLen - 1; i > (nowLen - moveLen); i--)
269         {
270             string->p[i] = string->p[i - 1];    //轮询移动
271         }
272         string->p[nowLen - moveLen] = ch;       //先移动,再插入
273 
274         string->p[nowLen + 1] = '\0';           //注意结尾
275     }
276     else
277     {
278         int nowLen = mystrlen(string->p);       //求出当前长度
279         int moveLen = mystrlen(pos);            //求出现在要移动的长度
280         for (int i = nowLen - 1; i > (nowLen - moveLen); i--)
281         {
282             string->p[i] = string->p[i - 1];    //轮询移动
283         }
284         string->p[nowLen - moveLen] = ch;       //先移动,再插入
285         
286         string->p[nowLen + 1] = '\0';           //注意结尾
287     }
288 }
289 
290 //任意位置增加字符串
291 void addStr(myString *string, char *str, char *pos)
292 {
293     if (pos == NULL || string == NULL)      //异常情况
294         return;
295 
296     int nowStrLen = mystrlen(string->p);    //获取当前字符串长度
297     int addStrLen = mystrlen(str);          //要增加的字符串的长度
298     if (nowStrLen + addStrLen + 1 > string->realLen)    //判定是否越界
299     {
300         int needAddLen = nowStrLen + addStrLen + 1 - string->realLen;            //需要扩展的长度
301         string->p = (char *)realloc(string->p, string->realLen + needAddLen);    //增加字符串长度
302         string->realLen += needAddLen;                 //增加长度
303 
304         //移动,拷贝
305         int nowStrLen = mystrlen(string->p);     //获取当前字符串长度
306         int moveStrLen = mystrlen(pos);          //求出现在要移动的长度
307         int insertStrLen = mystrlen(str);        //要插入的长度
308 
309         for (int i = nowStrLen; i >= nowStrLen - moveStrLen; i--)
310         {
311             string->p[i + insertStrLen] = string->p[i];        //字符移动
312         }
313         for (int j = 0; j < insertStrLen; j++)
314         {
315             string->p[nowStrLen - moveStrLen + j] = str[j];    //赋值拷贝
316         }
317     }
318     else
319     {
320         mystrcat(string->p, str);            //拷贝字符串
321     }
322 }
323 
324 //-----------------------------------//改(字符/字符串)-------------------------------------------------
325 //修改字符
326 void changeFirstChar(myString *string, const char oldChar, const char newChar)
327 {
328     char *pstr = string->p;
329     while (*pstr != '\0')
330     {
331         if (*pstr == oldChar)   //查找
332         {
333             *pstr = newChar;    //赋值
334             return;
335         }
336         pstr++;
337     }
338 }
339 
340 //修改字符串
341 void changeFirstStr(myString *string, char * const oldStr, char * const newStr)
342 {
343     char *pfind = findFirstStr(string, oldStr); //找到位置
344     if (pfind != NULL)
345     {
346         delFirstStr(string, oldStr);            //删除
347         addStr(string, newStr, pfind);          //插入
348     }
349 }
350 
351 
352 void main()
353 {
354     myString str1;
355     initWithString(&str1,"note");
356 
357     printString(&str1);                            //note
358     
359     /* 测试一:****************************************************************/
360     //backAddChar(&str1, 'd');
361     //printString(&str1);                        //noted
362     //run(&str1);
363 
364     //backAddStr(&str1, "pad");
365     //printString(&str1);                        //notepad
366     //run(&str1);
367 
368     /* 测试二:****************************************************************/
369     //backAddStr(&str1, "pad");
370     //printString(&str1);                        //notepad
371     //char *strp = findFirstChar(&str1, 'a');
372     //*strp = 'A';
373     //printString(&str1);                        //notepAd
374 
375     //backAddStr(&str1, "pad");
376     //printString(&str1);                        //notepad
377     //char *strp = findFirstStr(&str1, "te");
378     //*strp = 'X';
379     //printString(&str1);                        //noXepad
380 
381     //backAddStr(&str1, "pad");
382     //printString(&str1);                        //notepad
383     //char *strp = findFirstStr(&str1, "ad");
384     //*strp = 'X';
385     //printString(&str1);                        //notepXd
386 
387     //backAddStr(&str1, "pad");
388     //printString(&str1);                        //notepad
389     //char *strp = findFirstStr(&str1, "ada");
390     //if (strp != NULL)
391     //{
392     //    *strp = 'X';
393     //}
394     //printString(&str1);                        //notepad(并没有改变,没有找到相应子串)
395 
396     /* 测试三:****************************************************************/
397     //backAddStr(&str1, "pad");                    
398     //printString(&str1);                        //notepad
399     //delFirstChar(&str1,'e');
400     //printString(&str1);                        //notpad
401 
402     //backAddStr(&str1, "padnotepad");
403     //printString(&str1);                        //notepadnotepad
404     //delFirstStr(&str1, "pad");
405     //printString(&str1);                        //notenotepad
406 
407     /* 测试四:****************************************************************/
408     //backAddStr(&str1, "padnotepad");
409     //printString(&str1);                        //notepadnotepad
410     //char *p = findFirstChar(&str1, 't');//查找第一个t的位置
411     //if (p != NULL)
412     //{
413     //    addChar(&str1, 'A', p);            //在p的前面位置插入'A'
414     //}
415     //printString(&str1);                        //noAtenotepa
416 
417     //backAddStr(&str1, "padnotepad");
418     //printString(&str1);                        //notepadnotepad
419     //char *p = findFirstChar(&str1, 't');//查找第一个t的位置
420     //if (p != NULL)
421     //{
422     //    addStr(&str1, "12345", p);            //在p的前面位置插入'A'
423     //}
424     //printString(&str1);                        //no12345tepadnotepad
425 
426     /* 测试五:****************************************************************/
427     //backAddStr(&str1, "padnotepad");
428     //printString(&str1);                        //notepadnotepad
429     //changeFirstChar(&str1, 'a', 'i');
430     //printString(&str1);                        //notepidnotepad
431 
432     backAddStr(&str1, "padnotepad");
433     printString(&str1);                        //notepadnotepad
434     changeFirstStr(&str1, "notepad", "123456789");
435     printString(&str1);                        //123456789notepad
436 
437     system("pause");
438     return ;
439 }

 

posted @ 2018-08-11 11:42  博观&约取  阅读(238)  评论(0编辑  收藏  举报