C语言本身并无字符串类型但其对字符串的操作却较为频繁。本章节介绍这些函数的用法和实现。
strlen
size_t strlen(const char* str) Return Value This function returns the number of characters in string, excluding the terminal NULL. No return value is reserved to indicate an error. Parameter string - Null-terminated string
‘\0’为字符串结束标志,故strlen
函数计算\0
之前的字符个数。
参数是字符串首字符地址,而字符串必须为以\0
结尾的字符串。
//1. char arr1[] = "abcd"; printf("%d\n", strlen(arr1));//4 //2. char arr2[] = { 'a','b','c','d' }; printf("%d\n", strlen(arr2));//随机值 //3. int a = 10; printf("%d\n", strlen(a));//报错
1.传参过去的是以\0结尾的字符串地址,满足strlen的要求。
2.传参的虽然是字符串的地址但未以\0结尾,故strlen会一直找下去,直至找到\0。
传参根本不是地址,该整型会被strlen当作地址看待,故访问到0x0A地址处的非法内存。如图:
size_t ret = strlen("abcdef"); printf("%u\n", ret);
无符号数接收,以无符号的形式打印。不要使用无符号数运算结果比大小:
if (strlen("abc") - strlen("abcdef") < 0) { printf("hehe\n"); } else { printf("haha\n"); }
无符号数的运算结果被整形提升为无符号数,故二者相减所得被视为无符号数是不会小于零的。
//1.计算器 #include <stdio.h> #include <assert.h> size_t my_strlen(const char* p) { assert(p); size_t ret = 0; while (*p++ != '\0') { ret++; } return ret; } int main() { char arr[] = "abcdef"; size_t ret = my_strlen(arr); printf("%u\n", ret); return 0; } //2.用指针 - 指针 size_t my_strlen(char* p) { char* s = p; while (*p) { p++; } return p - s; } int main() { char arr[] = "abcdef"; size_t ret = my_strlen(arr); printf("%u\n", ret); return 0; }
strcpy
char* strcpy ( char* strDestination, const char* strSource ); Return Value This function returns the destination string. No return value is reserved to indicate an error. Parameters 1. strDestination - Destination string 2. strSource - Null-terminated source string Remarks 1The strcpy function copies the string pointed by strSource to the array pointed by strDestination,including the terminating null character. No overflow checking(溢出检查) is performed when strings are copied. The behavior of strcpy is undefined(未定义的) if the source and destination strings overlap(重叠).
strcpy将源字符串的内容(包括\0)依次拷贝到目标空间。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mY0d4jlE-1632139207004)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210920174627738.png)]
拷贝时会把\0也一同拷贝。若源字符串中有\0,其后的元素自然是不会被拷贝的,因为在读取时也就把\0作为结束标志。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LsDz9YN0-1632139207007)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210920174720243.png)]
若源字符串不以\0结尾,则strcpy会向后一直访问到非法内存。
//1. char arr1[] = "xxx";//目标空间不够大 char arr2[] = "abcdef"; //.2 const char arr1[] = "xxxxxxxxxx";//目标空间不可修改 char arr2[] = "abcdef"; strcpy(arr1, arr2);
以上两种情况同样是需要避免的。
strcpy在vs2019环境下使用会报出不安全的警告,该函数在拷贝前不会去检查是否会发生数组越界,警告也是正常的。但作为合格的程序员,我们有义务排除风险。
#include <stdio.h> #include <assert.h> char* my_strcpy(char* p1, const char* p2) { assert(arr1 && arr2); char* tmp = p1; while (*p1++ = *p2++) { ; } return tmp; } int main() { char arr1[] = "xxxxxxxxxxxxxxxx"; char arr2[] = "abcdef"; char* ret = my_strcpy(arr1, arr2); printf("%s\n", ret); return 0; }
strcat
char* strcat ( char* strDestination, const char* strSource ); Return Value This function returns the destination string. No return value is reserved to indicate an error. Parameters 1. strDestination - Null-terminated destination string 2. strSource - Null-terminated source string Remarks The strcat function appends strSource to strDestination and terminates the resulting string with a null character. The initial character of strSource overwrites the terminating null character of strDestination. No overflow checking is performed when strings are copied or appended. The behavior of strcat is undefined if the source and destination strings overlap.
strcat将源字符串包括\0,追加到目标字符串的结尾并覆盖掉目标空间的\0。
源字符串必须以’\0’结尾,strcat会将\0追加到目标空间的末尾作字符串结束标志。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rA7DadoQ-1632139207009)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210920175328212.png)]
该例子同样是源字符串不以\0结尾,从而访问到非法空间。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B3Y55F2Z-1632139207014)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210920175441173.png)]
目标字符串以初始化内容确定大小,这种初始化的方式显然是不能追加字符串的。同样目标字符串不可加const修饰。strcat在调用时仍然不作溢出检查,只有到溢出后才报错。
#include <stdio.h> #include <assert.h> char* my_strcat(char* p1, char* p2) { char* tmp = p1; while (*p1) { p1++; } while (*p1++ = *p2++) { ; } return tmp; } int main() { char arr1[20] = "xxxx"; char arr2[] = "abcdef"; char* ret = my_strcat(arr1, arr2); printf("%s\n", ret); return 0; }
strcmp
int strcmp ( const char* string1, const char* string2 ); Return Value The return value for this function indicates the relation of string1 to string2. +-------+------------------------------------+ | Value | Relationship of string1 to string2 | +-------+------------------------------------+ | <0 | string1 less than string2 | | 0 | string1 identical to string2 | | >0 | string1 greater than string2 | +-------+------------------------------------+ Parameters 1. string1, string2 2. Null-terminated strings to compare Remarks The strcmp function compares string1 and string2, what starts comparing the first character of each string, if are equal, continuing with the follows until the differ or a null-character is reached, and returns a value indicating their relationship.
strcmp遍历比较两个字符串对应位置的字符的ASCII码值是否相等。
#include <stdio.h> #include <assert.h> int my_strcmp(char* p1, char* p2) { assert(p1 && p2); while (*p1 == *p2) { if (*p1 == '\0') return 0; p1++; p2++; } return *p1 - *p2; } int main() { char arr1[] = "abcdef"; char arr2[] = "abc"; int ret = my_strcmp(arr1, arr2); if (ret > 0) { printf(">\n"); } else if (ret < 0) { printf("<\n"); } else { printf("=\n"); } return 0; }
strncpy
- 长度受限制char* strncpy ( char* strDest, const char* strSource, size_t count ); Return Value This function returns strDest. No return value is reserved to indicate an error. Parameters 1. strDest - Destination string 2. strSource - Source string 3. count - Number of characters to be copied Remarks The strncpy function copies the initial count characters of strSource to strDest and returns strDest. If count is less than or equal to the length of strSource, a null character is not appended automatically to the copied string. If count is greater than the length of strSource, the destination string is padded(填充) with null characters up to length count. The behavior of strncpy is undefined if the source and destination strings overlap.
strcpy函数从源字符串拷贝count个字符到目标字符串,若count大于源字符串长度则以\0填充。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xLpMumuO-1632139207016)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210920181214589.png)]
#include <stdio.h> #include <assert.h> char* my_strncpy(char* p1, char* p2, int n) { char* tmp = p1; assert(p1 && p2); while (n-- && *p1++ = *p2++) { ; } while (n) { *p1++ = '\0'; n--; } return tmp; } int main() { char arr1[] = "xxxxxxxxxxx"; char arr2[] = "abc"; int input = 0; scanf("%d", &input); char* ret = my_strncpy(arr1, arr2, input); printf("%s\n", ret); return 0; }
strncat
- 长度受限制char* strncat ( char* strDest, const char* strSource, size_t count ); Return Value This function returns a pointer to the destination string. No return value is reserved to indicate an error. Parameters 1. strDest - Null-terminated destination string 2. strSource - Null-terminated source string 3. count - Number of characters to append Remarks The strncat function appends, at most, the first count characters of strSource to strDest. The initial character of strSource overwrites the terminating null character of strDest. If a null character appears in strSource before count characters are appended, strncat appends all characters from strSource, up to the null character. If count is greater than the length of strSource, the length of strSource is used in place of count. The resulting string is terminated with a null character. If copying takes place between strings that overlap, the behavior is undefined.
在目标字符串末尾追加count个源字符串的字符,结尾默认添加\0。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tnvPp1yD-1632139207017)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210920181952737.png)]
#include <stdio.h> #include <assert.h> char* my_strncat(char* p1, char* p2, int n) { assert(p1 && p2); char* tmp = p1; while (*p1) { p1++; } while (n-- && *p1++ = *p2++) { ; } if (n == 0) { *p1 = '\0'; } return tmp; } int main() { char arr1[20] = "xxxx"; char arr2[] = "abcd"; int intput = 0; scanf("%d", &input) char* ret = my_strncat(arr1, arr2, input); printf("%s\n", ret); return 0; }
strncmp
- 长度受限制int strncmp ( const char* string1, const char* string2, size_t count ); Return Value The return value for each of these functions indicates the relation of string1 to string2. +-------+------------------------------------+ | Value | Relationship of string1 to string2 | +-------+------------------------------------+ | <0 | string1 less than string2 | | 0 | string1 identical to string2 | | >0 | string1 greater than string2 | +-------+------------------------------------+ Parameters 1. string1, string2 - Null-terminated strings to compare. 2. count - Number of characters to compare Remarks The strncmp function lexicographically compares, at most, the first count characters in string1 and string2 and returns a value indicating the relationship between the substrings.
比较两个字符串的前count个字符,并返回相关的数值。
#include <stdio.h> #include <assert.h> int my_strncmp(char* p1, char* p2, int n) { assert(p1 && p2); while (*p1++ == *p2++ && --n) { if (*p1 == '\0') return 0; } return *p1 - *p2; } int main() { char arr1[] = "abcdef"; char arr2[] = "abc"; int input = 0; scanf("%d", &input); int ret = my_strncmp(arr1, arr2, input); printf("%d\n", ret); return 0; }
strstr
char* strstr ( const char* string, const char* strCharSet ); Return Value This function returns a pointer to the first occurrence of strCharSet in string, or NULL if strCharSet does not appear in string. If strCharSet points to a string of zero length, the function returns string. Parameters 1. string - Null-terminated string to search 2. strCharSet - Null-terminated string to search for Remarks The strstr function returns a pointer to the first occurrence of strCharSet in string. The search does not include terminating null characters.
查找子字符串在目标字符串中首次出现的位置,有则返回之起始位置,无则返回空指针。
#include <stdio.h> #include <assert.h> char* my_strstr(const char* p1, const char* p2) { assert(p1 && p2); char* s1; char* s2; char* cp = p1; while (*cp) { s1 = cp; s2 = p2; while (*s2 && *s1 && *s1 == *s2) { s1++; s2++; } if (*s2 == '\0') return cp; cp++; } return NULL; } int main() { char arr1[] = "i am a good student,hehe student"; char arr2[] = "student"; char* ret = my_strstr(arr1, arr2); if (ret == NULL) { printf("找不到\n"); } else { printf("%s\n", ret); } return 0; }
memcpy
void* memcpy ( void* dest, const void* src, size_t count ); Return Value memcpy returns the value of dest. Parameters 1. dest - New buffer 2. src - Buffer to copy from 3. count - Number of characters to copy(bytes) Remarks The memcpy function copies count bytes of src to dest. If the source and destination overlap(重叠), this function does not ensure that the original source bytes in the overlapping region(区域) are copied before being overwritten. Use memmove to handle overlapping regions.
memcpy将源内存的前count个字节的内容拷贝到目标内存中。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nKaB06QN-1632139207019)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210920192543934.png)]
C标准并未要求memcpy完成发生内存重叠的内容拷贝,但编译器也可能对其进行优化。对内存重叠的内容进行拷贝时,可以使用memmove。
#include <stdio.h> #include <assert.h> void* my_memcpy(void* p1, const void* p2, size_t num) { assert(p1 && p2); void* ret = p1; while (num--) { *(char*)p1= *(char*)p2; (char*)p2 = (char*)p2 + 1; (char*)p1 = (char*)p1 + 1; } return ret; } int main() { int arr1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; int arr2[20] = { 0 }; my_memcpy(arr2, arr1, 10 * sizeof(arr1[0])); int i = 0; for (i = 0; i < 20; i++) { printf("%d ", arr2[i]); } return 0; }
memmove
void* memmove ( void* dest, const void* src, size_t count ); Return Value memmove returns the value of dest. Parameters 1. dest - Destination object 2. src - Source object 3. count - Number of bytes of characters to copy Remarks The memmove function copies count bytes of characters from src to dest. If some regions of the source area and the destination overlap, memmove ensures that the original source bytes in the overlapping region are copied before being overwritten.
memmove将源空间的前count个字节的内容拷贝到目标空间中,并支持完成内存重叠的拷贝。
#include <stdio.h> #include <assert.h> void* my_memmove(void* dest, void* src, size_t count) { void* tmp = dest; assert(dest && src); if (dest < src) { while (count--) { //从前往后 *(char*)dest = *(char*)src; (char*)dest = (char*)dest + 1; (char*)src = (char*)src + 1; } } else { while (count--) { //从后往前 *((char*)dest+count) = *((char*)src + count); } } return tmp; } int main() { int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; //my_memmove(arr, arr+2, 4*sizeof(arr[0])); my_memmove(arr+2, arr, 4*sizeof(arr[0])); int i = 0; for (i=0; i<10; i++) { printf("%d ", arr[i]); } return 0; }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JE1gnHug-1632139207020)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210917154241067.png)]
memcmp
int memcmp ( const void* buf1, const void* buf2, size_t count ); Return Value The return value indicates the relationship between the buffers. +-------+------------------------------------+ | Value | Relationship of string1 to string2 | +-------+------------------------------------+ | <0 | string1 less than string2 | | 0 | string1 identical to string2 | | >0 | string1 greater than string2 | +-------+------------------------------------+ Parameters 1. buf1 - First buffer 2. buf2 - Second buffer 3. count - Number of characters Remarks The memcmp function compares the first count bytes of buf1 and buf2 and returns a value indicating their relationship.
比较两块内存空间的前count个对应字节内容,并返回相关的数值。
int my_memcmp(const void* buf1, const void* buf2, size_t count) { assert(buf1 && buf2); while (count-- && (*(char*)buf1 == *(char*)buf2)) { (char*)buf1 += 1; (char*)buf2 += 1; } return *(char*)buf1 - *(char*)buf2; } int main() { int arr1[] = { 1,2,3,4,5 }; int arr2[] = { 1,2,3,4,6 }; int ret = my_memcmp(arr1, arr2, 1 * sizeof(int)); printf("%d\n", ret); return 0; }
memset
void* memset ( void* dest, int c, size_t count ); Return Value memset returns the value of dest. Parameters 1. dest - Pointer to destination 2. c - Character to set 3. count - Number of characters Remarks The memset function sets the first count bytes of dest to the character c.
将目标空间前count个字节初始化为整形数据c。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4DeFA5Rd-1632139207021)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210920194823468.png)]
) {
assert(buf1 && buf2);
while (count-- && ((char)buf1 == (char)buf2)) {
(char*)buf1 += 1;
(char*)buf2 += 1;
}
return (char)buf1 - (char)buf2;
}
int main()
{
int arr1[] = { 1,2,3,4,5 };
int arr2[] = { 1,2,3,4,6 };
int ret = my_memcmp(arr1, arr2, 1 * sizeof(int));
printf("%d\n", ret);
return 0;
}
### 内存初始化函数`memset` #### 函数声明 ````c void* memset ( void* dest, int c, size_t count ); Return Value memset returns the value of dest. Parameters 1. dest - Pointer to destination 2. c - Character to set 3. count - Number of characters Remarks The memset function sets the first count bytes of dest to the character c.
将目标空间前count个字节初始化为整形数据c。
[外链图片转存中…(img-4DeFA5Rd-1632139207021)]