椋鸟C语言笔记#23:字符函数、字符串函数

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


目录

字符分类函数

字符转换函数

strlen

模拟实现

strcpy

模拟实现

strcat

模拟实现

strcmp

模拟实现

strncpy

模拟实现

strncat

模拟实现

strncmp

strstr

模拟实现

strtok

使用实例

strerror与perror

使用实例


字符分类函数

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

其中常见的有:

  • iscntrl:任意控制字符
  • isspace:空白字符:空格、换页(\f)、换行(\n)、回车(\t、制表符\t\v
  • isdigit:十进制数字0~9
  • isxdigit:十六进制数字0~9、a~f、A~F
  • islower:小写字母a~z
  • isupper:大写字母A~Z
  • isalpha:字母a~z或A~Z
  • isalnum:字母或数字
  • ispunct:标点符号
  • isgraph:图形字符
  • isprint:任何可打印字符,包括图形字符和空白字符

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

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

#include 
#include 

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 
#include 

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 
size_t strlen(const char* str);

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

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

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

模拟实现

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

#include 
#include 

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 
char* strcpy(char* dest, const char* src);

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

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

注意:

  • ‘\0’也会被复制过去
  • 目标空间可用部分需要足够大
  • 目标空间应当可修改
模拟实现
char* my_strcpy(char* dest, const char* src)
{
    assert(dest && src);
	char* ret = dest;
	while (*dest++ = *src++);
	return ret;
}

strcat

#include 
char* strcat(char* dest, const char* src);

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

strcat将从dest指向的位置开始寻找,直到找到‘\0’,然后将从src指向的位置开始到第一个‘\0’为止的部分复制到‘\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 
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 
char* strncpy(char* dest, const char* src, size_t n);

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

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

模拟实现
char* my_strncpy(char* dest, const char* src, size_t n)
{
	assert(dest && src);
	char* ret = dest;
	while (n-- && *src)
		*dest++ = *src++;
	while (n--)
		*dest++ = 0;
	return ret;
}

strncat

#include 
char* strncat(char* dest, const char* src, size_t n);

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

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

模拟实现
char* my_strncat(char* dest, const char* src, size_t n)
{
	assert(dest && src);
	char* ret = dest;
	while (*++dest);
	while (n--)
	{
		if (0 == *src)
			break;
		else
			*dest++ = *src++;
	}
	*dest = 0;
	return ret;
}

strncmp

#include 
int strncmp(const char* str1, const char* str2, size_t n);

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

strstr

#include 
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 
char* strtok(char* str, const char* sep);

strtok用于分割字符串

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

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

  • 如果str不为NULL,strtok函数找到str中的第一个被分割的子串,并将其用‘\0’结尾(覆盖后面的分隔符)返回一个指向这个子串头的指针
  • 如果str为NULL,strtok函数会从上一次使用该函数分割的位置开始,寻找下一个被分割的子串,并将其用‘\0’结尾(覆盖后面的分隔符)返回一个指向这个子串头的指针
  • 如果已经分割完了,没有什么能返回的了,就返回NULL

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

使用实例
#include 
#include 

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与perror

#include 
char* strerror(int errnum);

#include     //or 
void perror( const char *string );

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

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

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

使用实例
#include 
#include 

int main()
{
	int i = 0;
	for (i = 0; i < 44; i++)
		printf("%s\n", strerror(i));
	return 0;
}

而perror函数则进一步,可以直接打印“输入的字符串+冒号+错误信息”一条龙。


你可能感兴趣的:(C语言笔记,笔记,c语言,开发语言)