Java教程

字符串函数与内存函数

本文主要是介绍字符串函数与内存函数,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

字符串和内存函数

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地址处的非法内存。如图:

img

  • strlen函数返回类型为size_t,注意无符号数的用法。
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)依次拷贝到目标空间。

函数用法

  • 源字符串以’\0’结尾,且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码值是否相等。

函数用法

  • 函数的返回值
    1.字符串1小于字符串2时,返回小于0的数字
    2.字符串1等于字符串2时,返回0
    3.字符串1大于字符串2时,返回大于0的数字
  • 二者都要以\0作为字符串的结尾,否则仍会越界访问。

模拟实现

#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填充。

函数用法

  • 目标字符串可修改且足够大
  • 若count小于源字符串个数则不追加\0,若大于源字符串个数则以\0填充到count个字符。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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。

函数用法

  • 追加到目标字符串末尾默认补’\0’,count超出源字符串个数不在追加。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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)]

这篇关于字符串函数与内存函数的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!