C语言——字符串函数

298 阅读6分钟

1 strlen函数

原型:

size_t strlen(const char* string)

功能:

字符串都以'\0'作为结束标志,strlen会返回字符串中'\0'前面出现的字符个数.

image.png

注意事项:

I 指向的字符串必须以'\0'结尾.

II 函数返回值类型是size_t.[可考虑强制类型转换]

image.png

image.png

实现方法:

A 计数器方法

即遍历字符串,直到找到'\0'停止计数.

size_t my_strlen(const char* arr)
{
	assert(arr);//断言不为空指针
	size_t num = 0;//统计数目
	while (*arr)//*arr是否为'\0'
	{
		num++;
                arr++;
	}
	return num;
}

B 递归方法

例如:

strlen("abc") = 1 + strlen("bc").

size_t my_strlen(const char* arr)
{
    assert(arr);//断言不为空指针
    if(*arr == '\0')
        return 0;
    else
        return 1+my_strlen(arr+1);
}

C 指针 - 指针方法

(同一数组中的)两个指针相减可得到它们之间的元素个数.

size_t my_strlen3(const char* arr)
{
	assert(arr);//断言不为空指针
	const char* init = arr;//保留arr的初始值
	while (*arr)//使arr指向'\0'
	{
		arr++;
	}
	size_t num = arr - init;//两个指针相减得到它们之间的元素个数
	return num;
}

2 strcpy函数

原型:

char* strcpy(char* strDestination, const char* strSource)

功能:

将源字符串的内容拷贝给目标字符串,拷贝的内容将覆盖目标字符串相应位置的内容,并返回目标字符串首字符的地址.

拷贝前:

image.png

拷贝后:

image.png

注意事项:

I 会将源字符串的'\0'拷贝到目标空间.

II 目标空间必须足够大,以确保能存放源字符串.

III 目标空间必须可变.(目标字符串不能是常量字符串) image.png

实现方法:

遍历源字符串的同时,把源字符串的内容赋给目标字符串,赋值到源字符串的'\0'为止.

char* my_strcpy(char* dest, const char* source)
{
	assert(dest && source);//断言皆不为空指针
	char* re = dest; //函数最后返回目标字符串首地址
	while (*dest++ = *source++)//先把source指向的字符赋给dest指向位置,再使它们的指向位置向后一位,	
	{                          //直到把'\0'赋给*dest时,表达式整体的值为0,跳出循环
		;
	}
	return re;
}

3 strcat函数

原型:

char* strcat(char* strDestination, const char* strSource)

功能:

将源字符串内容追加到目标字符串末尾,并返回目标字符串的首字符地址

追加前:

image.png

追加后:

image.png

注意事项:

I 也会把源字符串的'\0'追加到目标字符串尾部,以上的dest[11]没有变红是因为原来也是'\0'.

II 目标空间要足够大.

III 目标空间必须可修改(不能指向常量字符串).

实现方法:

找到目标字符串的'\0',然后在遍历源字符串的同时,把内容赋给目标字符串,直到赋值到'\0'

(从目标字符串的'\0'开始赋值)

char* my_strcat(char* dest, const char* source)
{
	assert(dest && source);//断言都不是空指针
	char* re = dest;      //记住目标字符串的首位置
	while (*dest != '\0')      //使dest指向'\0'
	{
		dest++;
	}
	while (*dest++ = *source++)//把源字符串的内容赋给目标字符串尾部
	{                          //每次赋给一个字符,地址向后移动一位
		;                  //当找到源字符串的'\0'时,先把它赋给目标字符串,再退出循环
	}
	return re;
}

4 strcmp函数

原型:

int strcmp(const char* string1, const char* string2)

功能:

比较两个字符串从左到右对应位置上的字符大小(ASCII码值).

str1 > str2 返回大于0的数字;

str1 < str2 返回小于0的数字;

str1 == str2 返回0.

实现方法:

int my_strcmp(const char* arr1, const char* arr2)
{
	assert(arr1 && arr2);
	//从左到右依次比较字符串相应位置的字符大小, 直到*arr1!=*arr2或同时为'\0'
	while (*arr1 == *arr2)
	{
		if (*arr1 == '\0')//说明两字符串相同
		{
			return 0;
		}
		arr1++;//比较下一对
		arr2++;
	}
	//一旦有一次不相等
	if (*arr1 > *arr2)
		return 1;
	else
		return -1;
}

5 strncpy函数

原型:

char* strncpy(char* strDest, const char* strSource, size_t count)

功能:

将源字符串的count个字节拷贝到目标字符串的相应位置,比strcpy多了一层思考,返回目标字符串首元素地址.

注意事项:

I 目标字符串一定要足够大

II 若源字符串的字符个数小于count,拷贝的字符会拿'\0'填充,阴间案例如下

image.png

拷贝前:

image.png

拷贝后:

image.png

实现方法:

char* my_strncpy(char* destination,const char* source, size_t count)
{
	//(从左到右)从源字符串中拷贝count个字节(字符)到目标字符串相应位置
        assert(destination && source);
	char* re = destination;
	for (int i = 0; i < count; i++)
	{
		//要拷贝count次
		if (*source == '\0')//如果已经拷贝到源字符串末尾,那就用'\0'填充
		{
			*destination = '\0';
			destination++;
		}
		else//正常拷贝
		{
			*destination = *source;
			destination++;
			source++;
		}
	}
	return re;
}

6 strncat函数

原型:

char* strncat(char* strDest, const char* strSource, size_t count)

功能:

将源字符串的count个字符/字节(因为一个字符的大小就是1byte)追加到目标字符串第一个'\0'处.

注意事项:

I 追加完count个字符后,会自动再添加一个'\0'.

image.png

追加前:

image.png

追加后:

image.png

II 源字符串的字符不够count个,不会进行填充.

image.png

image.png

III 若源字符串的第count个字符本身就是'\0',不会自动去添加'\0'.

image.png

追加前:

image.png

追加后:

image.png

实现方法:

char* my_strncat(char* destination, char* source, size_t num)
{
        assert(destination && source);
	//将源字符串的num个字符追加到目标字符串第一个'\0'处
	//若源字符串追加完则停止
	char* re = destination;//保存目标字符串初始值
	while (*destination)//使*destination找到'\0'
	{
		destination++;
	}
	//开始追加
	for (int i = 0; i < num; i++)
	{
		//追加num个字符
		if (*source != '\0')//正常追加
		{
			*destination = *source;
			destination++;
			source++;
		}
		else if(*source == '\0')//源字符串已经全部追加完了
		{
			*destination = *source;
			return re;//直接结束函数
		}
	}
	//追加的num个字符都没有'\0'
	*destination = '\0';//末尾自动添加'\0'
	return re;
}

7 strncmp函数

原型:

int strncmp(const char* string1, const char* string2, size_t count)

功能:

从左向右比较,只比较两字符串对应位置的前count个字符,返回值规则和strcmp一样。

实现方法:

int my_strncmp(char* str1, char* str2, size_t num)
{
	assert(str1 && str2);
	for (int i = 0; i < num; i++)
	{
		//比较num对
		if (*str1 == *str2)//如果相同比较下一对
		{
			str1++;
			str2++;
		}
		else if (*str1 > *str2)//一旦有一对不同函数就可以返回结束
		{
			return 1;
		}
		else
		{
			return -1;
		}
	}
	//比较完num对后都是相等的
	return 0;
}

8 strstr函数

原型:

char* strstr(const char* string, const char* strCharSet)

功能:

看strCharSet指向的字符串是否是string的子串,就是在一个字符串里找另一个字符串.

如果是,则返回子串第一次出现在string中的位置,否则返回NULL.

image.png

实现方法:

//思路:定义2个指针p2,p1分别指向 要查找的子串 和 源字符串   首元素      
// 定义1个指针record负责指向开始对照的位置
//当*p1!=*p2时,record++, p1++

//当*p1 == *p2时,record不变,p1++,p2++,逐个对照,
//直到p2指向'\0'(要查找的子串找到了)或者*p1!=*p2(没找到该子串)

char* my_strstr(const char* source, const char* search)
{
	assert(source && search);
	const char* p1 = source;
	const char* p2 = search;
	const char* record = p1;//记录当前开始对照的位置
	while (*record != '\0')//若*record == '\0',说明源字符串中找不到字串
	{
		//p1和record一开始都指向开始对照的位置,但p1之后要用来与p2指向的元素逐个对照
		p1 = record;
		while (*p1 == *p2 && *p2)//*p2为'\0'时已经找到了   ///////
		{
			p1++;
			p2++;
		}
		if (*p2 == '\0')//对照完成后子串的p2指向'\0',说明找到了,返回开始对照的位置record
			return record;
		//如果没找到,p2要重新指向子串的首字符
		p2 = search;
		//同时下一次开始对照的位置+1
		record++;
	}
	return NULL;
}

9 strtok函数

原型:

char* strtok(char* strToken, const char* strDelimit)

功能:

在str中找到sep中的符号,并用'\0'结尾,并返回这次分割开的字段的首字符地址.

例如:

image.png

image.png

image.png

具体使用方法

A

strtok的第一个参数不为NULL,函数会找到str中的第一个分隔符标记,并保存这个分割符的位置,返回这次分割开的字段的首字符地址.

strtok的第一个参数为NULL,函数将在同一个字符串中被保存的位置开始,继续往后查找下一个标记.并返回这次分割开的字段的首字符地址.例:

image.png

B 若字符串中不存在更多标记,返回NULL.

那如何做到不管原字符串里有多少个分割符,都能一次性打印全部分开的字符串呢?

image.png

注意事项:

I strtok会改变被操作的字符串,所以最好临时拷贝一份,来使用该函数.(此时可使用strcpy/strcnpy)

II 这两个参数指向的是字符串首元素地址,都要以'\0'结尾.

image.png

10 strerror函数

在库函数调用失败时,会留下一个错误码error,它是一个全局变量,一开始默认是0

原型:

char* strerror(int errnum)

功能:

返回错误码所对应的错误信息.//每个错误码都对应一个错误信息

例:

image.png

image.png