字符串函数

字符串函数

前言

C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在常量字符串中或者字符数组中。

字符串常量适用于那些对它不做修改的字符串函数

函数介绍

strlen

函数基础

函数介绍:strlen

size_t strlen ( const char * str );

头文件:string.h
函数名:strlen
函数参数:str,参数类型是const char* ,即需要进行求字符串长度的起始地址
函数返回类型: size_t,size_t是unsigned int的类型重定义,是无符号整型。库 函数使用size_t类型可能考虑的是字符串的长度不可能是负 数,所以用了无符号类型size_t。
函数功能:计算字符串的长度

在这里插入图片描述

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

'\0’的重要性

int main()
{
	char arr[] = { "abc" };
	int len = strlen(arr);// 3
	printf("%d\n", len);

	return 0;
}
int main()
{
	char arr[] = { 'a', 'b', 'c' };
	int len = strlen(arr);//随机值
	printf("%d\n", len);

	return 0;
}

函数strlen在字符串后找’\0’,直到找到后才会停下。

模拟实现

strlen函数的模拟实现三种方法:

1.计数器方法
2.递归方法(不创建临时变量求字符串长度)
3.指针 - 指针方法

#include<stdio.h>
#include<assert.h>
//1.计数器实现求字符串长度函数
int my_strlen1(const char* str)//整个过程不改变指针指向内容,加上const
{
	assert(str != NULL);//加上断言,防止接收空指针
	int count = 0;
	while (*str != '\0')//也可以直接用while(*str)
	{
		count++;
		str++;
	}
	return count;
}
//2.递归实现求字符串长度,不用创建临时变量
int my_strlen2(const char* str)
{
	assert(str != NULL);
	if (*str != '\0')//也可以直接用if(*str)
	{
		return 1 + strlen(str + 1);//不能直接使用str++,可以使用++str,建议直接用str+1
	}
	else
		return 0;
}
//3.指针-指针得到中间元素的个数,实现求字符串长度
int my_strlen3(const char* str)
{
	assert(str != NULL);
	const char* tmp = str;//创建临时指针变量保存str起始值
	while (*str != '\0')
	{
		str++;
	}
	return str - tmp;
}

int main()
{
	char arr[] = "abcdefgh";
	int ret1 = my_strlen1(arr);//1.计数器方法
	int ret2 = my_strlen2(arr);//2.递归方法
	int ret3 = my_strlen3(arr);//3.指针 - 指针方法
	printf("%d\n", ret1);
	printf("%d\n", ret2);
	printf("%d\n", ret3);
    return 0;
}
strcpy

函数介绍:strcpy

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

头文件:string.h
函数名:strcpy
函数参数:参数1:destination, 类型:char* ,表示将字符串拷贝的目的地位置
参数2:source,类型:char* ,表示被拷贝字符串拷贝的源地址起始位置。
函数返回类型: char*, 实际上就是返回destination(目的地)的起始位置
函数功能:字符串拷贝

在这里插入图片描述

  • Copies the C string pointed by source into the array pointed by destination, including the terminating nullcharacter (and stopping at that point).
  • 源字符串必须以 ‘\0’ 结束。
  • 会将源字符串中的 ‘\0’ 拷贝到目标空间。
  • 目标空间必须足够大,以确保能存放源字符串。
  • 目标空间必须可变。
  • 学会模拟实现。

模拟实现

版本一(基础版)

#include<stdio.h>
#include<assert.h>
char* my_strcpy1(char* dest, const char* src)
{
	assert(dest != NULL);
	assert(src != NULL);
	char* dest_start = dest;

//拷贝src指向字符串的内容到dest指向的空间,包括'\0'
	while (*src != '\0')
	{
		*dest = *src;
		dest++;
		src++;
	}
	*dest = *src;
    return dest_start;
}

int main()
{
	char arr1[] = "abcdefghik";
	char arr2[] = "hello";
	my_strcpy1(arr1, arr2);//模拟实现strcpy函数
	printf("%s", arr1);
	return 0;
}

版本二(精简版)

#include<stdio.h>
#include<assert.h>
char* my_strcpy2(char* dest, const char* src)
{
	assert(dest != NULL);
	assert(src != NULL);
	char* dest_start = dest;

	while (*dest++ = *src++)
	{
		;
	}
	return dest_start;
}

int main()
{
	char arr1[] = "abcdefghik";
	char arr2[] = "hello";
	my_strcpy2(arr1, arr2);//模拟实现strcpy函数
	printf("%s", arr1);
	return 0;
}
strcat

函数基础

函数介绍:strcat

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

头文件:string.h
函数名:strcat
函数参数:参数1:destination, 类型:char* ,表示将字符串追加的目的地位置
参数2:source,类型:char* ,表示被追加字符串的源地址起始位置。
函数返回类型: char*,实际上就是返回destination(目的地)的起始位置
函数功能:字符串追加

在这里插入图片描述

(1)Appends a copy of the source string to the destination string.The
terminating null character in destination is overwritten by the first character of source, and a null - character is included at the end ofthe new string formed by the concatenation of both in destination.
(2)源字符串必须以‘\0’结束。目标空间也必须包含’\0’,以确定追加的起始位置。
(3)目标空间必须有足够的大,能容纳下源字符串的内容。
(4)目标空间必须可修改。
(5)字符串自己给自己追加,如何 ?
用strcat自己给自己追加会导致程序崩溃,无法实现自己追加自己!(从’\0’开始追加,自己追加自己的时候,’\0‘改成了被追加的首字符,再寻找追加字符串结束的’\0’时,找不到’\0’,会导致死循环)

模拟实现

char* my_strcat(char* dest, const char* src)
{
	assert(dest != NULL);
	assert(src != NULL);
	char* dest_start = dest;
	//1.找到目的空间中的'\0'
	while ( *dest )//跳过不是'\0'的字符
	{
		dest++;
	}
    
	//2.追加
	while (*dest++ = *src++)
	{
		;
	}
	return dest_start;
}
int main()
{
	char arr1[30] = "hello";
	char arr2[] = "world";
	my_strcat(arr1, arr2);//模拟实现strcat
	printf("%s", arr1);
	return 0;
}
strcmp

函数基础

函数介绍:strcmp

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

在这里插入图片描述

(1)This function starts comparing the first character of each string.lf they are equal to each other, itcontinues with the following pairs until the characters differ or until a terminating null - character isreached.
标准规定︰
(2)第一个字符串大于第二个字符串,则返回大于O的数字。
(3)第一个字符串等于第二个字符串,则返回0
(4)第一个字符串小于第二个字符串,则返回小于0的数字

模拟实现

#include<stdio.h>
#include<assert.h>
int my_strcmp(const char* p1, const char* p2)
{
	assert(p1 && p2);
	while (*p1 == *p2)
	{
		if (*p1 == '\0')
		{
			return 0;
		}
		p1++;
		p2++;
	}

if (*p1 > *p2)
{
	return 1;
}
else
{
	return -1;
}
    
int main()
{
	char* p1 = "abcdef";
	char* p2 = "abqwt";
    
    int ret = my_strcmp(p1, p2);
    if(ret = 0)
        printf("p1 = p2\n");
    else
        if (ret = -1)
            printf("p1 < p2\n");
    	else	printf("p1 > p2\");
    
    return 0;
}
    
strncpy

strncpy与strcpy相比较多了一个字母n,这个n代表的是需要拷贝字符的个数,也就是说strncpy需要关注拷贝字符的个数,而不是像strcpy那样关注’\0’。

char * strncat ( char * destination, const char * source, size_t num );
  • Copies the fifirst num characters of source to destination. If the end of the source C string (which is signaled by a null-character) is found before num characters have been copied, destination is padded with zeros until a total of num characters have been written to it.

  • 拷贝num个字符从源字符串到目标空间。

  • 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。

基础版

#include<stdio.h>
#include<assert.h>
char* my_strncpy(char* dest, const char* src, size_t n)
{
	char* dest_start = dest;
	while ((n > 0) && (*src != '\0'))
	{
		*dest = *src;
		dest++;
		src++;
		n--;
	}
	while (n > 0)
	{
		*dest = '\0';
		dest++;
		n--;
	}
	return dest_start;
}

int main()
{
	char arr1[10] = "abcdefg";
	char arr2[] = "1234";
	size_t len = 0;
	scanf("%d", &len);
	my_strncpy(arr1, arr2, len);
	printf("%s", arr1);
	return 0;
}

进阶版

#include<stdio.h>
#include<assert.h>

char* my_strncpy(char* dest, const char* src, size_t count)
//count比n更有实际意义
{
	assert(dest != NULL);//引用断言
	assert(src != NULL);
	char* start = dest;
	while (count && (*dest++ = *src++) != '\0')
	{
		count--;
	}
	if (count)
	{
		while (count--)
		{
			*dest++ = '\0';
		}
	}
	return start;
}

int main()
{
	char arr1[10] = "abcdefg";
	char arr2[] = "1234";
	size_t len = 0;
	scanf("%d", &len);
	my_strncpy(arr1, arr2, len);
	printf("%s", arr1);
	return 0;
}
strcat

strcat函数是字符串追加,在使用的时候以src的’\0’作为追加结束标志,因此在使用strcat来追加一个字符串数组本身的时候,会因\0被提前覆盖而无法追加成功。

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

(1)Appends the first num characters of source to destination, plus a terminating null - character.
(2)lf the length of the C string in source is less than num, only the content up to the terminating null - character is copied.
(3)如果追加的字符长度大于目的地空间的剩余容量,则出现越界访问,要避免这种情况发生。

模拟实现

基础版

#include<stdio.h>
#include<assert.h>

char* my_strncat(char* dest, const char* src, size_t count)
{
	char* start = dest;
	//dest找到\0的位置
	while (*dest!='\0')
	{
		dest++;
	}
	while (count)
	{
		//将src中的字符追加给dest
		*dest = *src;
		dest++;
		src++;
		//如果src以及指向\0的位置,提前结束循环
		if (*src == '\0')
		{
			break;
		}
		count--;
	}
	*dest = '\0';//字符个数追加完毕后,再单独追加'\0'
	return start;
}

int main()
{
	char arr1[15] = "12345\0xxxxxxx";
	char arr2[] = "abcd";
	size_t count = 0;
	scanf("%d", &count);
	my_strncat(arr1, arr2, count);
	printf("%s", arr1);
	return 0;
}

进阶版

#include<stdio.h>
#include<assert.h>

char* my_strncat(char* dest, const char* src, size_t count)
{
	assert(dest != NULL && src != NULL);
	char* start = dest;
	while (*dest++)
		;
	dest--;
	while (count--)
		if ((*dest++ = *src++) == '\0')
			return start;
	*dest = '\0';
	return start;
}
int main()
{
	char arr1[15] = "12345\0xxxxxxx";
	char arr2[] = "abcd";
	size_t count = 0;
	scanf("%d", &count);
	my_strncat(arr1, arr2, count);
	printf("%s", arr1);
	return 0;
}
strncmp
int strncmp ( const char * str1, const char * str2, size_t num );
  • 比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完。

库函数源代码:

int __cdecl strncmp
(
	const char* first,
	const char* last,
	size_t      count
)
{
	size_t x = 0;
	if (!count)
	{
		return 0;
	}
	/*
	 * This explicit guard needed to deal correctly with boundary
	 * cases: strings shorter than 4 bytes and strings longer than
	 * UINT_MAX-4 bytes .
	 */
	if (count >= 4)
	{
		/* unroll by four */
		for (; x < count - 4; x += 4)
		{
			first += 4;
			last += 4;
			if (*(first - 4) == 0 || *(first - 4) != *(last - 4))
			{
				return(*(unsigned char*)(first - 4) - *(unsigned char*)(last - 4));
			}
			if (*(first - 3) == 0 || *(first - 3) != *(last - 3))
			{
				return(*(unsigned char*)(first - 3) - *(unsigned char*)(last - 3));
			}
			if (*(first - 2) == 0 || *(first - 2) != *(last - 2))
			{
				return(*(unsigned char*)(first - 2) - *(unsigned char*)(last - 2));
			}
			if (*(first - 1) == 0 || *(first - 1) != *(last - 1))
			{
				return(*(unsigned char*)(first - 1) - *(unsigned char*)(last - 1));
			}
		}
	}
	/* residual loop */
	for (; x < count; x++)
	{
		if (*first == 0 || *first != *last)
		{
			return(*(unsigned char*)first - *(unsigned char*)last);
		}
		first += 1;
		last += 1;
	}
	return 0;
}

strstr
#include <stdio.h>
#include <assert.h>

char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);
	const char* s1 = NULL;
	const char* s2 = NULL;
	char* cp = str1;

	while (*cp)
	{
		s1 = cp;
		s2 = str2;
		if (*s2 == '\0')
		{
			return s1;
		}//判断条件str2为空
		while (s1 && s2 && (*s1 == *s2))//避免s1='\0'或者s2='\0',即字符串结束仍未找到的情况
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
		{
			return cp;
		}
		cp++;
	}
	return NULL;
}

int main()
{
	char arr1[] = "abbbcdef";
	char arr2[] = "bbc";
	//在arr1中查找是否包含arr2
	char* ret = my_strstr(arr1, arr2);

	if (ret == NULL)
	{
		printf("can't search \n");
	}
	else
	{
		printf("can search:-> %s\n", ret);
	}

	return 0;
}
strtok
char* strtok(char* str, const char* sep)

字符串分割函数

#include<stdio.h>
#include<string.h>
int main()
{
	//192.168.31.121  网络ip地址 --点分十进制
	//192 168 31 121  ---strtok  .
	char arr[] = "abcdefg@123.com";
	char* p = "@.";
	char buf[100] = { 0 };
	char* ret = 0;//用于接收分割后标记的位置
	//分割字符串之前先进行临时拷贝
	strcpy(buf, arr);
	//分割buf中的字符串

	//ret = strtok(buf, p);
	//printf("%s\n", ret);

	//ret = strtok(NULL, p);
	//printf("%s\n", ret);

	//ret = strtok(NULL, p);
	//printf("%s\n", ret);

	//一次性打印
	for (ret = strtok(buf, p); ret != NULL; ret = strtok(NULL, p))
	{
		printf("%s\n", ret);
	}

	return 0;
}
字符分类函数

img

字符转换函数

img

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值