字符函数与字符串函数

字符函数与字符串函数

  • 求字符串长度
    • strlen
  • 长度不受限制的字符串函数
    • strcpy
    • strcat
    • strcmp
  • 长度受限制的字符串函数介绍
    • strncpy
    • strncat
    • strncmp
  • 字符串查找
    • strstr
    • strtok
  • 错误信息报告
    • strerror
  • 内存操作函数
    • memcpy
    • memmove
    • memset
    • memcmp

求字符串长度

strlen

size_t strlen ( const char * str );

1.字符串已经 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前面出现的字符个数(不包含 ‘\0’ )。
2.参数指向的字符串必须要以 ‘\0’ 结束。
3.注意函数的返回值为size_t,是无符号的( 易错 )

int main()
{
 const char*str1 = "abcdef";
 const char*str2 = "bbb";
 if(strlen(str2)-strlen(str1)>0)
 {
 printf("str2>str1\n");
 } 
 else
 {
 printf("srt1>str2\n");
 }
 return 0;
}

我们会发现,不管怎样,最后都会打印‘>’。为什么呢?因为strlen返回值是一个无符号数,总是大于0的;
正确做法:

int main()
{
	const char* str1 = "abcdef";
	const char* str2 = "bbb";
	if (strlen(str2) > strlen(str1))
	//if ((int)strlen(str2) - (int)strlen(str1)>0)
	{
		printf("str2>str1\n");
	}
	else
	{
		printf("srt1>str2\n");
	}
	return 0;
}

strlen函数的模拟实现:
1.直接计算数值;

int my_strlen(char* str)
{
	assert(str);
	int count = 0;
	while (*str++)
	{
		count++;
	}
	return count;
}
int main()
{
	char* arr = "abcdef";
	int ret = my_strlen(arr);
	printf("%d", ret);
	return 0;
}

2.递归方式

int my_strlen(char* str)
{
	assert(str);
	if (*str == '\0')
	{
		return 0;
	}
	else
		return 1 + my_strlen(str + 1);
}
int main()
{
	char* arr = "abcdef";
	int ret = my_strlen(arr);
	printf("%d", ret);
	return 0;
}

3.指针-指针

int my_strlen(char* str)
{
	assert(str);
	char* start = str;
	char* end = str;
	while (*end++)
	{
	     ;
	}
	return (end - start - 1);
}
int main()
{
	char* arr = "abcdef";
	int ret = my_strlen(arr);
	printf("%d", ret);
	return 0;
}

长度不受限制的字符串函数

strcpy

char* strcpy(char * destination, const char * source )

1.源字符串必须以 ‘\0’ 结束。
2.会将源字符串中的 ‘\0’ 拷贝到目标空间。
3.目标空间必须足够大,以确保能存放源字符串。
4.目标空间必须可变
strcpy函数的模拟实现:

char* my_strcpy(char* dest, const char* src)
{
	assert(dest && src);
	char* ret = dest;
	while (*dest++=*src++)
	{
		;
	}
	return ret;
}
int main()
{
	char arr1[20] = "ABCDEF";
	char* arr2 = "abc";
	char* ret = my_strcpy(arr1, arr2);
	printf("%s", ret);
	return 0;
}

strcat

char * strcat ( char * destination, const char * source )

1.源字符串必须以 ‘\0’ 结束。
2.目标空间必须有足够的大,能容纳下源字符串的内容。
3.目标空间必须可修改。
strcat函数的模拟实现:

char* my_strcat(char* dest, const char* src)
{
	assert(dest && src);
	char* ret = dest;
	while (*dest)
	{
		dest++;
	}
	while (*dest++=*src++)
	{
		;
	}
	return ret;
}
int main()
{
	char arr1[10] = "ABCDEF";
	char* arr2 = "abc";
	char* ret = my_strcat(arr1, arr2);
	printf("%s", ret);
	return 0;
}

这儿要注意的是自己给自己追加时就会出现问题,会把‘\0’给覆盖掉,程序无法停止就会崩溃;

strcmp

int strcmp ( const char * str1, const char * str2 );

1.第一个字符串大于第二个字符串,则返回大于0的数字;
2.第一个字符串等于第二个字符串,则返回0;
3.第一个字符串小于第二个字符串,则返回小于0的数字;
strcmp函数的模拟实现:

int my_strcmp(const char* str1, const char* str2)
{
	assert(str1 && str2);
	while (*str1 == *str2 )
	{
		if (*str1 == '\0')
		{
			return 0;
		}
		str1++;
		str2++;
	}
	return *str1 - *str2;
}
int main()
{
	char* arr1 = "abc";
	char* arr2 = "abc";
	int ret = my_strcmp(arr1, arr2);
	if (ret > 0)
	{
		printf(">");
	}
	else if (ret < 0)
	{
		printf("<");
	}
	else
	{
		printf("=");
	}
	return 0;
}

长度受限制的字符串函数介绍

strncpy

char * strncpy ( char * destination, const char * source, size_t num )

1.拷贝num个字符从源字符串到目标空间。
2.如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
strncpy函数的模拟实现:

char* my_strncpy(char* dest, const char* src, size_t num)
{
	assert(dest && src);
	char* ret = dest;
	while ((*dest++ = *src ++) && num--)
		{
			;
		}
	return ret;
}
int main()
{
	char arr1[20] = "ABCDEF";
	char* arr2 = "abcdef";
	char* ret = my_strncpy(arr1, arr2,3);
	printf("%s", ret);
	return 0;
}

strncat

char * strncat ( char * destination, const char * source, size_t num );

strncat函数的模拟实现:

char* my_strncat(char* dest, const char* src, size_t num)
{
	assert(dest && src);
	char* ret = dest;
	while (*dest)
	{
		dest++;
	}
	while ((*dest++ = *src ++) && num--)
		{
			;
		}
	return ret;
}
int main()
{
	char arr1[20] = "ABCDEF";
	char* arr2 = "abcdef";
	char* ret = my_strncat(arr1, arr2,3);
	printf("%s", ret);
	return 0;
}

strncmp

int strncmp ( const char * str1, const char * str2, size_t num );

比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完。
strncmp函数的模拟实现:

int my_strncmp(const char* str1, const char* str2, size_t num)
{
	assert(str1 && str2);
	if (!num)
	{
		return 0;
	}
	while (*str1 == *str2 && (num--) && str1 != '\0' && str2 != '\0')
	{
		str1++;
		str2++;
	}
	if (*str1 == *str2 || num == 0)
	{
		return 0;
	}
	else
	return *str1 - *str2;
}
int main()
{
	char* arr1 = "abcdef";
	char* arr2 = "abc";
	int ret = my_strncmp(arr1, arr2,3);
	if (ret > 0)
	{
		printf(">");
	}
	else if (ret < 0)
	{
		printf("<");
	}
	else
	{
		printf("=");
	}
	return 0;
}

字符串查找

strstr

char * strstr ( const char *str1, const char *str2 );

返回指向str1中str2第一次出现的指针,如果str2不是str1的一部分,则返回空指针。
strstr函数的模拟实现:

char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);
	const char* s1 = str1;
	const char* s2 = str2;
	const char* q = str1;
	while (*q)
	{
		s1 = q;
		s2 = str2;
		while (*s1 == *s2 && *s1 != '\0' && *s2 != '\0')
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
		{
			return (char*)q;
		}
		q++;
	}
	return NULL;
}
int main()
{
	char arr1[] = "abcbcdef";
	char* arr2 = "bcd";
	char* arr3 = "";
	char* arr4 = "ABC";
	char* ret1 = my_strstr(arr1, arr2);
	printf("%s\n", ret1);
	char* ret2 = my_strstr(arr1, arr3);
	printf("%s\n", ret2);
	char* ret3 = my_strstr(arr1, arr4);
	printf("%s\n", ret3);
	return 0;
}

strtok

char * strtok ( char * str, const char * sep );

1.sep参数是个字符串,定义了用作分隔符的字符集合
2.第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
3.strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
4.strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
5.strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
6.如果字符串中不存在更多的标记,则返回 NULL 指针。

int main()
{
	char arr1[] = { "[email protected]#1234*wer" };
	char sep[] = { "@.#*" };
	char ch[100] = { 0 };
	strcpy(ch, arr1);
	printf("%s\n", strtok(ch, sep));
	printf("%s\n", strtok(NULL, sep));
	printf("%s\n", strtok(NULL, sep));
	printf("%s\n", strtok(NULL, sep));
	printf("%s\n", strtok(NULL, sep));
	return 0;
}

但是这样看着代码好搓哦,我们修改一下:

int main()
{
	char* arr1 = "[email protected]#1234*wer";
	const char* sep = "@.#*";
	char ch[100] ;
	char* str = NULL;
	strcpy(ch, arr1);
	for (str = strtok(ch, sep); str != NULL;str=strtok(NULL,sep))
	{
		printf("%s\n", str);
	}
	return 0;
}

错误信息报告

strerror

char * strerror ( int errnum );

返回错误码,所对应的错误信息。
举个例子:

int main()
{
	printf("%s\n", strerror(1));
	printf("%s\n", strerror(2));
	printf("%s\n", strerror(3));
	printf("%s\n", strerror(4));
	return 0;
}

字符函数与字符串函数_第1张图片

int main()
{
	int* p = (int*)malloc(1000000000000000 * sizeof(int));
	if (NULL == p)
	{
		printf("%s\n",strerror(errno));
		return;
	}
	return 0;
}

在这里插入图片描述

内存操作函数

memcpy

void * memcpy ( void * destination, const void * source, size_t num )

1.函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
2.这个函数在遇到 ‘\0’ 的时候并不会停下来。
3.如果source和destination有任何的重叠,复制的结果都是未定义的。
memcpy函数的模拟实现:

void* my_memecpy(void* dest, const void* src, size_t num)
{
	assert(dest && src);
	void* ret = dest;
	while (num--)
	{
		*((char*)dest) = *((char*)src);
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return ret;
}
int main()
{
	int i = 0;
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[] = { 4,5,6,7,8 };
	 my_memecpy(arr1, arr2,20);
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

我们会发现自己给自己追加时就会出现问题,达不到我们想要的结果:

int main()
{
	int i = 0;
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[] = { 4,5,6,7,8 };
	 my_memecpy(arr1+2, arr1,20);
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

字符函数与字符串函数_第2张图片
此时就会用到我们的memmove函数了;

memmove

void * memmove ( void * destination, const void * source, size_t num )

1.和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
2.如果源空间和目标空间出现重叠,就得使用memmove函数处理。
memmove函数的模拟实现:

void* my_memmove(void* dest, const void* src, size_t num)
{
	assert(dest && src);
	void* ret = dest;
	while (num--)
	{
		if (dest < src)
		{
			*((char*)dest) = *((char*)src);
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
		else
		{
			*((char*)dest + num) = *((char*)src + num);
		}
	}
	return ret;
}
int main()
{
	int i = 0;
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[] = { 4,5,6,7,8 };
	my_memmove(arr1+2 , arr1, 20);
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

memset

void *memset( void *dest, int c, size_t count );

他其实就是一个初始化函数;

int main()
{
	int i = 0;
	int arr[10];
	memset(arr, 1, sizeof(arr));
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

不过要注意的是memset是一个字节一个字节进行初始化的:
字符函数与字符串函数_第3张图片

memcmp

int memcmp( const void *buf1, const void *buf2, size_t count );

memcmpt是一个字节一个字节进行比较的:

int main()
{
	int arr1[] = { 0x11223344,2,3,4 };
	int arr2[] = { 0x11223355,2,3,4};
	int ret=memcmp(arr1, arr2, 4);
	printf("%d\n", ret);
	return 0;
}

字符函数与字符串函数_第4张图片
以上如有错误,请批评指正!!!!

你可能感兴趣的:(数学建模,算法,蓝桥杯,c语言)