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 }
文章写来不易,转载请标注。。。欢迎关注!