摘要:参数指向的字符串必须要以结束。需要注意的是源字符串必须以结束。会将源字符串中的拷贝到目标空间。目标空间必须足够大,以确保能存放源字符串。举例最终字符串函数的模拟实现定义两个数组,首先遍历到,然后和函数相似开始拷贝即可。
前言:
C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,
字符串
通常放在常量字符串
中或者字符数组
中。
字符串常量
适用于那些对它不做修改的字符串函数.
size_t strlen ( const char * str );
这里我们可以看到strlen函数的返回值是size_t
?:1.字符串已经 ‘/0’ 作为结束标志,strlen函数返回的是在字符串中 ‘/0’ 前面出现的字符个数(不包
含 ‘/0’ )。
?:2.参数指向的字符串必须要以 ‘/0’ 结束。
?:3.注意函数的返回值为size_t,是无符号的( 易错 )
例子:?
#include #include int main(){ if (strlen("abc") - strlen("abcdef") > 0) { printf("hehe/n"); } else { printf("haha/n"); } return 0;}
这里输出的结果是hehe,因为返回的是无符号整数,这两哥字符串无论怎么减都是正数。
这里直接计算个数即可,较为简单,不做赘述。
#include #include size_t my_strlen(const char* str){ int count = 0; assert(str != NULL); while (*str) { count++; str++; } return count;}int main(){ char arr[] = "pwh"; int len = my_strlen(arr); printf("%d", len); return 0;}
?:strcpy把含有’/0’结束符的字符串复制到另一个地址空间,返回值的类型为char*。
char* strcpy(char * destination, const char * source );
需要注意的是:?
1.源字符串必须以 ‘/0’ 结束。
2.会将源字符串中的 ‘/0’ 拷贝到目标空间。
3.目标空间必须足够大,以确保能存放源字符串。
4.目标空间必须可变。
为什么返回值为char*
返回strDest的原始值使函数能够支持链式表达式,增加了函数的“附加值”。同样功能的函数,如果能合理地提高的可用性,也就就更加理想。
int iLength=strlen(strcpy(strA,strB));char * strA=strcpy(new char[10],strB);
举例:?
char a[10],b[]={"PWH"};//定义字符数组a,bstrcpy(a,b);//将数组b中的PWH复制到数组a中
该代码与strlen函数类似,只需要注意代码的严谨,源地址的不可变性,拷贝至’/0’,数组空间够大即可。且一定要是字符数组!
#include #include char* my_strcpy(char* dest, const char* src){ assert(dest != NULL); assert(src != NULL); char* ret = dest; while (*dest++ = *src++) { ; } return ret;}int main(){ char arr1[] = "abcdefghi"; char arr2[] = "bit"; my_strcpy(arr1, arr2); printf("%s", arr1); return 0;}
int strcmp(const char *s1,const char *s2);
?:1.第一个字符串大于第二个字符串,则返回大于0的数字
?:2.第一个字符串等于第二个字符串,则返回0
?:3.第一个字符串小于第二个字符串,则返回小于0的数字
?:注意:
比较的是字符串的ASCII码值!
从第一个字符开始比较,第一个相等就从第二个字符比较,第一个大于返回正数,小于返回负数;然后从第二个开始比较。
#include #include int main(){ char* p1 = "abcdef";//6 char* p2 = "aqwer";//5 //if("abcdef"=="sqwer")//比较的是地址,所以肯定不相等 int ret = strcmp(p1, p2);//strcmp比较的是每个字符的ASCII码值 //从第一个开始比较,第一个相等就从第二个字符比较,第一个大于返回1,小于返回-1;然后从第二个 printf("%d/n", ret); return 0;}
strcmp函数的实现思路为定义两个数组,且都为不可变,使用while循环
从第一个字符开始比较,如果相等则返回0,如果不相等则继续比较下个字符,字符地址+1,如果大于,返回正数,小于返回负数。
#include #include int my_strcmp(const char* str1, const char* str2){ assert(str1 && str2); //比较 while (*str1 == *str2) { if (*str1 == "/0") { return 0;//相等 } str1++; str2++; } if (*str1 > *str2) { return 1;//大于 } else { return -1;//小于 }}int main(){ char* p1 = "abcdef"; char* p2 = "abqwe"; int ret = my_strcmp(p1, p2); printf("ret=%d/n", ret); return 0;}
char *strcat(char *dest, const char *src);
?:把src所指向的字符串(包括“/0”)复制到dest所指向的字符串后面(删除dest原来末尾的“/0”)。要保证dest足够长,以容纳被复制进来的*src。*src中原有的字符不变。返回指向dest的指针。
举例:?
#include #include int main (){ char src[50]="source"; char dest[50]="destination"; strcat(dest, src); printf("最终字符串:%s", dest); return 0;}
?:定义两个数组,首先遍历到’/0’,然后和strcpy函数相似开始拷贝即可。
#include #include char* my_strcat(char *dest, const char *src){ assert(dest && src); char *tmp = dest; while (*tmp != "/0") { tmp++; } while ((*tmp++ = *src++) != "/0"); return dest;}int main(){ char arr1[10] = "pwh"; char arr2[] = "hxs"; char* arr3 = my_strcat(arr1, arr2); printf("str1=%s/n", arr1); printf("str2=%s/n", arr2); printf("str3=%s/n", arr3); return 0;}
?:返回字符串中首次出现子串的地址
举例:
int main(){ char* p1 = "abcdefghi"; char* p2 = "defq"; char* ret = strstr(p1, p2);//查找第一次出现的位置 if (ret == NULL) { printf("子串不存在/n"); } else { printf("%s/n", ret); } return 0;}
思路:
尽量不要让p1,p2走,这样无法记住它的位置
当相等时,cur作为一个大前提,先在cur的位置使用s1 s2进行查找,如果没找到,cur++,从下一个字符查找。
这里定义了cur s1 s2,这样可以互不干扰,然后s1重新等于cur,从此位置++。
char* my_strstr(const char* p1, const char* p2){ assert(p1 != NULL); assert(p2 != NULL); //这样写可以互不干扰,适用于比较复杂的场景 char* s1 = p1; char* s2 = p2; char* cur =(char*) p1; if (*p2 == "/0") { return p1; } while (*cur) { s1 = cur; s2 = (char*)p2; while (*s1 && *s2 && (*s1 == *s2)) { s1++; s2++; } if (*s2 == "/0") { return cur; } cur++; } return NULL;}int main(){ char* p1 = "abbbcdef"; char* p2 = "bbc"; char* ret = my_strstr(p1, p2);//查找第一次出现的位置 if (ret == NULL) { printf("子串不存在/n"); } else { printf("%s/n", ret); } return 0;}
char * strncpy ( char * destination, const char * source, size_t num );
?:拷贝num个字符从源字符串到目标空间。
?:如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
?:strncpy越界之后,拷贝完毕会把数组后面的内容全部变为0。
只需要在strcpy基础上加一个n的限制条件即可。
#include #include char*my_strncpy(char*dest, const char*src, size_t n){ assert(dest != NULL); assert(src != NULL); char*ret = dest; while (n) { *dest = *src; src++; dest++; n--; } return ret;} int main(){ char arr1[20] = "hxs"; char arr2[20]= "pwh"; int n = 0; printf("请输入需要拷贝的字符个数:/n"); scanf("%d", &n); char*ret = my_strncpy(arr1,arr2,n); printf("%s/n", ret); return 0;}
?:strncat越界之后,追加完毕后依旧会自动添加’/0’,但和strncpy区别在于,不会把数组后面的元素变为0
先遍历到目标字符串/0处,加一个n的限制条件即可。
#include #include char* my_strncat(const char* dest, const char* src,unsigned n){ assert(dest && src); char* tmp = dest; while (*tmp != "/0") { tmp++; } while (n) { *tmp = *src; tmp++; src++; n--; }; return dest;}int main(){ char arr1[10] = "pwh"; char arr2[10] = "hxs"; int n = 0; printf("请输入你要拷贝的字符个数"); scanf("%d", &n); my_strcat(arr1, arr2,n); printf("arr1=%s/n", arr1); return 0;}
?:比较的字符数可控。
没什么好说的,就是很简单!这里用for循环更加方便一些。
#include #include int my_strncmp(const char* str1, const char* str2,unsigned n){ assert(str1 && str2); //比较 unsigned i = 0; for (i = 0; i < n - 1 && *str1 && *str2; i++) { if (*str1 != *str2) { break; } str1++; str2++; } return (*str1 - *str2);}int main(){ char* p1 = "abcdef"; char* p2 = "abqwe"; int n = 0; printf("请输入要检验的字符数"); scanf("%d", &n); int ret = my_strcmp(p1, p2,n); printf("ret=%d/n", ret); return 0;}
内存函数可以对任意类型的值操作,而字符串函数只能对字符串操作!
void * memcpy ( void * destination, const void * source, size_t num );
?:1.函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
?:2.这个函数在遇到 ‘/0’ 的时候并不会停下来。
?:3.如果source和destination有任何的重叠,复制的结果都是未定义的。
将所传入的指针强制类型转换为char*类型,这样可以对于各种类型的数据进行操作,其余过程和strncpy函数比较相似。
struct S{ char name[20]; int age;};void my_memcpy(void* dest, const void* src, size_t num)//void类型不可解引用也不能算术运算{ assert(dest); assert(src); void* ret = dest; while (num--) { *(char*)dest = *(char*)src; ++(char*)dest; ++(char*)src; } return dest;}int main(){ struct S arr3[] = { {"张三",20},{"李四",30} }; struct S arr4[3] = { 0 }; my_memcpy(arr4, arr3, sizeof(arr3)); //char *dest, const char*src //memcpy(arr2, arr1, sizeof(arr1)); printf("%d", arr4->age); return 0
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/120810.html
摘要:性能,大量运用在哈希的处理中,由于的不可变性,可以只计算一次哈希值,然后缓存在内部,后续直接取就好了。这是目前的一个底层字节码的实现,那么是不是没有使用或者的必要了呢。 凯伦说,公众号ID: KailunTalk,努力写出最优质的技术文章,欢迎关注探讨。 1. 前言 最近看到几个有趣的关于Java核心类String的问题。 String类是如何实现其不可变的特性的,设计成不可变的好处...
摘要:编写工作首先介绍了一个称为的内部组件表示,并解释了变更检测过程在视图上运行。本文主要由两部分组成第一部分探讨错误产生的原因,第二部分提出可能的修正。它对我意义重大,它能帮助其他人看到这篇文章。 在过去的8个月里,我大部分空闲时间都是reverse-engineering Angular。我最感兴趣的话题是变化检测。我认为它是框架中最重要的部分,因为它负责像DOM更新、输入绑定和查询列表...
摘要:本文仅用于学习和交流目的,不得用于商业目的。今年,我们依然会组织。随着语言的发展,这种情况将不再适用。本系列主要讨论如何获得这些高度模块化的应用程序。这一系列内的后续图书会讨论测试及部署等内容。更多精彩,加入图灵访谈微信 本文仅用于学习和交流目的,不得用于商业目的。非商业转载请注明作译者、出处,并保留本文的原始链接:http://www.ituring.com.cn/art... 访谈...
阅读 3141·2021-11-23 10:02
阅读 3117·2021-11-16 11:53
阅读 3092·2021-09-23 11:21
阅读 3368·2019-08-30 13:02
阅读 1621·2019-08-29 16:18
阅读 1556·2019-08-29 12:55
阅读 1456·2019-08-26 12:24
阅读 2084·2019-08-26 10:36