椋鸟C语言笔记#23

字符函数、字符串函数

Featured image

萌新的学习笔记,写错了恳请斧正。

字符分类函数

在 ctype.h 头文件中有一些用于字符分类的函数,用于判断字符属于哪种类型

其中常见的有:

这些函数如果判断为假,则返回 0,否则返回非零

比方说可以写一个识别小写字母并转换为大写的函数:

#include <stdio.h>
#include <ctype.h>
 
char* caps(char* s)
{
	char* ret = s;
	do
	{
		if (islower(*s))
			*s -= 32;
	} while (*s++);
	return ret;
}
 
int main()
{
	char s[] = "ajiofe";
	printf("%s", caps(s));
	return 0;
}

字符转换函数

其实 ctype.h 头文件中其实已经内置了可以用于大小写转换的函数,即字符转换函数

其中就包括 tolower 和 toupper,所以上述代码也可以改为:

#include <stdio.h>
#include <ctype.h>
 
char* caps(char* s)
{
	char* ret = s;
	do
	{
		if (islower(*s))
			*s = toupper(*s);
	} while (*s++);
	return ret;
}
 
int main()
{
	char s[] = "ajiofe";
	printf("%s", caps(s));
	return 0;
}

其实并没有方便多少,感觉用处不大

strlen

#include <string.h>
size_t strlen(const char* str);

strlen 用于计算字符串的长度,其返回值 size_t 是无符号整数

strlen 函数将会返回从传递给它的指针开始直到第一个 “\0” 为止的非零元素的数量

使用 strlen 函数需要先包含 string.h 头文件

模拟实现

最简单的就是循环计数了:

#include <stdio.h>
#include <assert.h>
 
size_t my_strlen(const char arr[])
{
	assert(arr);
	int i = 0;
	while (*(arr + i))
		i++;
	return i;
}

当然如果使用递归也可以不用循环计数:

size_t my_strlen(const char arr[])
{
	assert(arr);
	return *(arr) ? 1 + my_strlen(arr + 1) : 0;
}

双指针也可以实现:

size_t my_strlen(const char arr[])
{
	assert(arr);
	char* p = arr;
	while (*p)
		p++;
	return p - arr;
}

strcpy

#include <string.h>
char* strcpy(char* dest, const char* src);

strcpy 用于复制字符串,使用需要先包含 string.h 头文件

strcpy 将从 src 指针头开始直到‘\0’结尾的部分复制到 dest 指针指向的地方

注意:

模拟实现
char* my_strcpy(char* dest, const char* src)
{
    assert(dest && src);
	char* ret = dest;
	while (*dest++ = *src++);
	return ret;
}

strcat

#include <string.h>
char* strcat(char* dest, const char* src);

strcat 用于字符串的追加,使用需要先包含 string.h 头文件

strcat 将从 dest 指向的位置开始寻找,直到找到‘\0’,然后将从 src 指向的位置开始到第一个‘\0’为止的部分复制到‘\0’的位置(包括‘\0’)

注意:

模拟实现
char* my_strcat(char* dest, const char* src)
{
    assert(dest && src);
	char* ret = dest;
	while (*++dest);
	while (*dest++ = *src++);
	return dest;
}

strcmp

#include <string.h>
int strcmp(const char* str1, const char* str2);

strcmp 用于字符串之间的比较(逐字符),使用需要先包含 string.h 头文件

strcmp 会分别从 str1 与 str2 指向的位置开始对比 ASCII 码值,如果有一方先出现不等情况。则按照规定输出(str1 大于 str2 输出正数,反正负数,如果直到两边都遇到‘\0’都没有不等的情况则输出 0)

常用于按字母排序

模拟实现
int my_strcmp(const char* str1, const char* str2)
{
	assert(str1 && str2);
	while (*str1 == *str2)
	{
		if (!*str1)
			return 0;
		str1++, str2++;
	}
	return *str1 - *str2;
}

strncpy

#include <string.h>
char* strncpy(char* dest, const char* src, size_t n);

strncpy 与 strcpy 功能一致,但是只复制前 n 个字符(如果位数足够最后不补 0)

如果先碰到‘\0’则后续一直补 0 直到满足 n 个字符的要求

strncat

#include <string.h>
char* strncat(char* dest, const char* src, size_t n);

同样的,是拼接前 n 个字符,但是会追加一个‘/0’

如果先遇到‘\0’则停止拼接,不需要补 0

strncmp

#include <string.h>
int strncmp(const char* str1, const char* str2, size_t n);

同样的,比较前 n 个字符,比较方法同 strcmp

strstr

#include <string.h>
char* strstr(const char* str1, const char* str2);

strstr 用于寻找字符串的子序列

strstr 会从 str1 指向的位置开始,寻找第一个与 str2 相同的序列,并返回找到的序列头的地址

如果没有与 str2 相同的子序列,则返回空指针 NULL

模拟实现
char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);
	char* sign1 = (char*)str1;
	char* sign2 = (char*)str1;
	char* sign = (char*)str2;
	while (*sign1)
	{
		if (!*sign)
			return sign1;
		sign1++;
		sign2 = sign1;
		sign = (char*)str2;
		while (*sign2 && *sign && !(*sign2 - *sign))
			sign2++, sign++;
	}
	return NULL;
}

strtok

#include <string.h>
char* strtok(char* str, const char* sep);

strtok 用于分割字符串

sep 参数指向一个字符串,定义了用作分隔符的字符集合

第一个参数指定一个字符串,它包含了 0 个或者多个由 sep 字符串中一个或者多个分隔符分割的非空子串

注意!!!strtok 会改变原字符串!!!

使用实例
#include <stdio.h>
#include <string.h>
 
int main()
{
	char arr[] = "192.168.0.1:23333";
	char* sep = ".:";
	char* str = NULL;
	for (str = strtok(arr, sep); str != NULL; str = strtok(NULL, sep))
		printf("%s\n", str);
	return 0;
}

strerror

#include <string.h>
char* strerror(int errnum);

strerror 函数可以把参数部分错误码对应的错误信息的字符串地址返回

在不同的系统和 C 语言标准库的实现中都规定了一些错误码,一般在 errno.h 头文件中说明

程序启动的时候就会使用一个全局变量 errno 来记录程序的当前错误码(初始为 0 表示无错)

使用实例
#include <stdio.h>
#include <string.h>
 
int main()
{
	int i = 0;
	for (i = 0; i < 44; i++)
		printf("%s\n", strerror(i));
	return 0;
}