字符函数和字符串函数

发布于:2025-05-10 ⋅ 阅读:(14) ⋅ 点赞:(0)

字符函数:

1.字符分类函数

C语言中有一系列的函数是专门做字符分类的,也就是一个字符是属于什么类型的字符的。

这些函数的使用都需要包含一个头文件:<ctype.h>

函数                       如果他返回下列条件就返回

iscntrl                     任何控制字符

isspace                  任何字符:空格 ‘’,换页 ‘\f’ ,换行  '\n',回车 ‘\r’,制表符'\t'或者垂直制表符‘\v’

isdigit                     十进制数字 ‘0’ ~ ‘9’ 字符

isxdigit                   十进制数字,包括所有十进制数字字符,小写字母 a~f ,大写字母 A~F

islower                   小写字母 a~z

isupper                  大写字母 A~Z

isalpha                  字母 a~z 或 字母 A~Z     

isalnum                 字母或者数字,a~z ,A~Z ,0~9

ispunct                  标点符号,任何不属于数字或者字母的图形字符(可打印)

isgraph                  任何图形字符

isprint                     任何可打印字符,包括图形字符和空白字符     

islower 是能够判断参数部分的 c 是否是小写字母的。

通过返回值来说明是否是小写字母,如果是小写字母就返回非0的整数,如果不是小写字母,则返回0。    

//判断字母的大小写
int main()
{

	int ch = getchar();//getchar()接受一个字符,直接返回来,会让我们输入一个值
	if (ch >= 'a' && ch <= 'z')
	{
		printf("小写\n");
	}
	else if (ch >= 'A' && ch <= 'Z')
	{
		printf("大写\n");
	}
	
	//putchar(ch);//直接输出(打印)上面getchar输入的值
	//在ASCII码中0-31这32个字符是不可打印字符

	return 0;
}

#include<ctype.h>
int main()
{
	int ch = getchar();
	if (islower(ch))
	{
		printf("小写\n");
	}
	else if (isupper(ch))
	{
		printf("大写\n");
	}

	return 0;
}

2.字符转换函数

例子:将字符串中的小写字母转换成大写字母,其余的字符不变。

int tolower ( int c );  将参数传进去的大写字母转为小写

int toupper ( int c );  将参数传进去的小写字母转为大写

//将一个字符串转换全小写
int main()
{
	char arr[] = "I Am A Student";
	int i = 0;
	while (arr[i])
	{
		if (isupper(arr[i]))
		{
			arr[i] = arr[i] + 32;
			// a 对应的ASCII码值:97
			// A 对应的ASCII码值:65
		}
		putchar(arr[i]);
		i++;
	}

	return 0;
}

字符串函数:

3.strlen 的使用和模拟实现

size_t strlen ( const char * str );

  • 字符串以 ' \0 ' 作为结束标志,strlen函数返回的是在字符串中 ' \0 ' 之前的字符的个数(不包含' \0 ') 
  • 参数指向的字符串必须以 ' \0 ' 结束
  • 注意函数返回的类型是 size_t , 是无符号的(易错)
  • strlen的头文件是<string.h>
#include<string.h>
//strlen() 函数  求字符串长度的函数
int main()
{
	//char arr[] = "zxcvbn";// 数组内容:z x c v b n \0
	//char arr[] = { 'z','x','c' };//随机值 没有找到 \0
	char arr[] = { 'z','x','c','\0'};// 3
	size_t len = strlen(arr);
	printf("%zd\n", len);
	return 0;
}

看个有趣的代码:

int main()
{   //			3-7=-4 ??
	if (strlen("asd") - strlen("asdfghj") > 0)
	{
		printf("大于\n");
	}
	else
	{
		printf("小于等于");
	}
	return 0;
}

运行出的结果: 

 

为什么上面显示的是 “大于”??

strlen 返回的值是 无符号类型的整数,无符号类型的整数的加减的结果也是无符号类型的整数,所以不会出现负数

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

#include<assert.h>

//方法1:

size_t my_strlen1(char * str)
{
	assert(str);
	size_t count = 0;
	while (*str)
	{
		count++;
		str++;
	}
	return count;
}

//方法2:

size_t my_strlen2(char* str)
{
	assert(str);
	char *start = str;
	
	while (*str)
	{
		str++;
	}
	return str-start;//指针减指针的应用
}

//方法3:

//不创建变量实现 strlen()函数的实现 ---- 递归的方法来实现
size_t my_strlen3(char* str)
{
	assert(str);
	if (*str == '\0')
		return 0;
	else
		return  1 + my_strlen3(str + 1);
	
}

// ch arr[]="zxcvbn" --> [z x c v b n \0]
//1+my_srtrlen("xcvbn")
//1+1+my_srtrlen("cvbn")
//1+1+1+my_srtrlen("vbn")
//1+1+1+1+my_srtrlen("bn")
//1+1+1+1+1+my_srtrlen("n")
//1+1+1+1+1+1+my_srtrlen("")

int main()
{
	char arr[] = "abc";
	//size_t len = my_strlen1(arr);
	//size_t len = my_strlen2(arr);
	size_t len = my_strlen3(arr);
	printf("%zd\n", len);
	return 0;
}

4.strcpy 的使用和模拟实现

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

  • 源字符串必须以 ' \0 ' 结束
  • 会将源字符串中的 ' \0 ' 拷贝到目标空间
  • 目标空间必须足够大,以确保能存放源字符串
  • 目标空间必须可以修改 
int main()
{
	char arr1[] = "xxxxxxxxxxxxxxxxxx";
	char arr2[] = "hehehe";
	strcpy(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}

调试看看是否将arr2的内容拷贝到了arr1中,同样也将arr2中的 '\0' 也拷贝到了arr1中??

确实是:将arr2的内容拷贝到了arr1中,同样也将arr2中的 '\0' 也拷贝到了arr1中 

int main()
{
	char arr1[3] = { 0 };//目标空间必须足够大,否则会出现错误
	char arr2[] = "hello hello world";
	strcpy(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}
int main()
{
	char* pch = "abcdefghiasdfg";//常量字符串是不可修改的
	char arr[] = "hello world";
	strcpy(pch, arr);
	printf("%s\n", pch);//目标空间必须是可以修改的
	return 0;
}

strcpy 的模拟实现:

char * my_strcpy(char* str1,const char* str2)
{
	char* ret = str1;
	while (*str2 !='\0')
	{
		*str1 = *str2;
		str1++;
		str2++;
	}
	*str1 = *str2;
	return ret;
}

//优化如下:

#include <assert.h>
char* my_strcpy(char* str1, const char* str2)
{
	assert(str1 && str2);
	char* ret = str1;
	while (*str1++ = *str2++)
	{
		;
	}
	
	return ret;
}

int main()
{
	char arr1[20] = {0};
	char arr2[] = "hello world";
	printf("%s\n",my_strcpy(arr1, arr2));
	return 0;
}

 5.strcat 的使用和模拟实现

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

  • 源字符串必须以 ' \0 ' 结束
  • 目标空字符串中也得有 ' \0 ',否则没办法知道从哪里开始追加
  • 目标空间必须足够大,能容下源字符串的内容
  • 目标空间必须可修改
  • 字符串自己给自己追加,是什么情况?? 
int main()
{
	char arr1[25] = "Hello ";
	char arr2[] = "World";
	char *ret=strcat(arr1, arr2);
	printf("%s\n", ret);
	return 0;
}

模拟实现strcat函数:

char* my_strcat(char* dest, const char* sour)
{
	
	char* ret = dest;
	assert(dest && sour);
	//1.找到目标空间中的\0
	while (*dest)
	{
		dest++;
	}
	//2.拷贝sour中的内容到dest中
	while (*dest++ = *sour++)
	{
		;
	}
	return ret;
}

int main()
{
	char arr1[25] = "Hello ";
	char arr2[] = "World";
	char* ret = my_strcat(arr1, arr2);
	printf("%s\n", ret);
	return 0;
}

字符串自己给自己追加的情况:

#include <assert.h>
char* my_strcat(char* dest, const char* sour)
{

	char* ret = dest;
	assert(dest && sour);
	//1.找到目标空间中的\0
	while (*dest)
	{
		dest++;
	}
	//2.拷贝sour中的内容到dest中
	while (*dest++ = *sour++)
	{
		;
	}
	return ret;
}

int main()
{
	char arr1[25] = "Hello ";
	char* ret = my_strcat(arr1, arr1);
	printf("%s\n", ret);
	return 0;
}

6.strcmp 函数的使用

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

标准规定:

  • 第一个字符串大于第二个字符串,则返回大于0的数字
  • 第一个字符串等于第二个字符串,则返回0
  • 第一个字符串小于第二个字符串,则返回小于0的数字
  • 是根据两个字符串上对应的字符ASCII码值的大小的比较
int main()
{
	int ret = strcmp("bbq", "abcdef");
	printf("%d\n", ret);
	return 0;
}
int main()
{
	int ret = strcmp("bbq", "abcdef");
	if (ret > 0)
	{
		printf("大于\n");
	}
	else if (ret < 0)
	{
		printf("小于\n");
	}
	else
		printf("等于\n");
	return 0;
}

 strcmp函数的模拟实现:

int my_strcmp(const char* dest, const char* sour)
{

	while (*dest == *sour)
	{
		if (*dest == '\0')
			return 0;
		dest++;
		sour++;
		
	}
	if (*dest - *sour > 0)
		return 1;
	else
		return -1;

}

//方法二:
int my_strcmp(const char* dest, const char* sour)
{

	while (*dest == *sour)
	{
		if (*dest == '\0')
			return 0;
		dest++;
		sour++;

	}
	return *dest - *sour;

}
int main()
{
	int ret = my_strcmp("bbq", "abcdef");
	if (ret > 0)
	{
		printf("大于\n");
	}
	else if (ret < 0)
	{
		printf("小于\n");
	}
	else
		printf("等于\n");
	return 0;
}

7.strncpy 函数的使用

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

  •  Copies the first 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个。 

 8.strncat 函数的使用

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

  • Appends the first num characters of source to destination, plus a terminating null-character(将source指向字符串的前num个字符追加到destination指向的字符串末尾,再追加⼀个 \0 字符)。
  • If the length of the C string in source is less than num, only the content up to the terminatingnull-character is copied.(如果source 指向的字符串的⻓度⼩于num的时候,只会将字符串中到\0 的内容追加到destination指向的字符串末尾)。 
//strncat 比strcat多了一个参数:可以限制追加的字符的个数
int main()
{
	char arr1[20] = "xxxxxxxxxx";
	char arr2[] = "world";
	strncat(arr1, arr2, 7);
	//调试就会发现:看不出是否追加arr2的\0
	return 0;
}
int main()
{
	char arr1[20] = "hello\0xxxxxxxx";
	char arr2[] = "world";
	strncat(arr1, arr2, 7);
	//将w o r l d \0拷贝到了arr1中,是从arr1中的第一个\0开始拷贝
  //可以看出是要将arr2中的\0追加到arr1中的
	return 0;
}

 

9.strncmp函数的使用

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

比较str1和str2的前num个字符,如果相等就继续往后⽐较,最多比较num个字⺟,如果提前发现不⼀样,就提前结束,⼤的字符所在的字符串⼤于另外⼀个。如果num个字符都相等,就是相等返回0。

int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abcq";
	int ret = strncmp(arr1, arr2, 3);
	//将arr1和arr2中的前3个字母进行比较,有字母长度的限制
	printf("%d\n", ret);
	return 0;
}

10.strstr 函数的使用

  • Returns a pointer to the first occurrence of str2 in str1, or a null pointer if str2 is not part of str1.(函数返回字符串str2在字符串str1中第⼀次出现的位置)。
  • The matching process does not include the terminating null-characters, but it stops there.(字符串的⽐较匹配不包含 \0 字符,以 \0 作为结束标志)。
int main()
{
	char arr1[] = "abbbbcdebbehig";
	char arr2[] = "bbe";
	char* ret = strstr(arr1, arr2);
	if (ret != NULL)
		printf("%s\n", ret);
	else
		printf("找不到\0");
	return 0;
}

strstr函数的模拟实现:


//暴力求解 

char* my_strstr(const char* str1, const char* str2)
{
	
	const char* cur = str1;
	char* s1 = NULL;
	char* s2 = NULL;
	assert(str1 && str2);
	//特殊规定的处理:
	if (*str2 == '\0')
		return (char *)str1;
	while (*cur)
	{
		s1 = cur;
		s2 = str2;
		while (*s1&&*s2&&*s1 == *s2)
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
		{
			return (char*)cur;
		}
		cur++;
	}
	return NULL;
}


//测试用例1
//abbbbcdebbehig
//bbe

//测试用例2
//abbbbcdebbehig
//abb

//测试用例3
//abbbbcdebbehig
//bbf

//测试用例4
//abbbbcdebbehig
//abbbbcdebbehig

//测试用例越多,功能越齐全,不容易漏掉其他的情况
//bug也不容易出现

int main()
{
	char arr1[] = "abbbbcdebbehig";
	char arr2[] = "bbe";
	char* ret = my_strstr(arr1, arr2);
	if (ret != NULL)
		printf("%s\n", ret);
	else
		printf("找不到\0");
	return 0;
}

 11.strtok 函数的使用

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

 

 

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>
#include<string.h>
//strtok 函数
int main()
{
	char arr1[] = "zhangsan@163.com#hehhe";
	char arr2[30] = {0};
	strcpy(arr2, arr1);
	const char* p = "@.#";

	char* s = NULL;
	//for循环优点:初始化部分只执行一次
	for (s = strtok(arr2, p); s != NULL; s = strtok(NULL, p))
	{
		printf("%s\n", s);
	}

	//char* s = strtok(arr2, p);
	//printf("%s\n", s);
	//s = strtok(NULL, p);
	//printf("%s\n", s);
	//s = strtok(NULL, p);
	//printf("%s\n", s);
	//s = strtok(NULL, p);
	//printf("%s\n", s);
	//繁琐、冗余
	return 0;
}

12.strerror 函数的使用

  • strerror 函数可以把参数部分错误码对应的错误信息的字符串地址返回来。
  • 在不同的系统和C语⾔标准库的实现中都规定了⼀些错误码,⼀般是放在 errno.h 这个头⽂件中说明的,C语⾔程序启动的时候就会使⽤⼀个全局的变量errno来记录程序的当前错误码,只不过程序启动 的时候errno是0,表⽰没有错误,当我们在使⽤标准库中的函数的时候发⽣了某种错误,就会将对应 的错误码,存放在errno中,⽽⼀个错误码的数字是整数很难理解是什么意思,所以每⼀个错误码都是 有对应的错误信息的。strerror函数就可以将错误对应的错误信息字符串的地址回。
int main()
{
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d:%s\n", i, strerror(i));
	}
	return 0;
}

在vs下输出结果为:

 

 

#include<errno.h>

//C语言是可以进行文件操作的
//打开文件:
//FILE* pf=fopen(...)
//如果文件打开成功,则返回一个地址
//如果文件打开失败,则返回一个NULL
int main()
{
	FILE* pFile;
	pFile = fopen("unexist.ent", "r");
	if (pFile == NULL)
		//printf("Error opening file unexist.ent: %s\n", strerror(errno));
	//strerror    头文件:<string.h>
	//errno       头文件:<errno.h>
		perror("Error opening file unexist.ent");
	//perror 函数自动加上:和空一格
	return 0;
}

输出结果:


网站公告

今日签到

点亮在社区的每一天
去签到