C语言——字符函数和字符串函数

C语言——字符函数和字符串函数

1.字符分类函数

2.字符转换函数

3.strlen的使用和模拟实现

4.strcpy的使用和模拟实现

5.strcat的使用和模拟实现

6.strcmp的使用和模拟实现

7.strncpy的使用和模拟实现

8.strncat的使用和模拟实现

9.strncmp的使用

10.strstr的使用

11.strtok的使用

12.strerror的使用

1.字符分类函数

在C语言中有一系列的函数是专门做字符分类的

这些函数的头文件都是ctype.h

iscntrl : 任何控制字符

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

isdigit :十进制数字0到9

isxdigit :十六进制数字,包括0到9,小写字母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 :任何可打印字符,包括图形字符和空白字符

在上面的函数中,如果符合后面的条件,就返回真

我们现在通过讲解一个函数,通过这个函数,我们同时也可以知道别的函数的用法

int islower(int c);

这个部分是用来判断参数部分c是否是小写字母

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

接下来我们来写一个练习

练习:写一个代码,将字符串中的小写字母改为大写,其他字母不变

#include<stdio.h>
#include<ctype.h>

int main()
{
	char str[] = "i am a Student\n";
	int i = 0;
	char c = 0;
	while (str[i])
	{
		c = str[i];
		if (islower(c))
		{
			c -= 32;
		}
		putchar(c);
		i++;
	}
	return 0;
}

2.字符转换函数

C语言提供了2个字符转换函数:

is tolower(int c);//将大写字母改为小写
is toupper(int c);//将小写字母改为大写

通过前面我们学习的知识可知,小写字母和大写字母之间相差32,所以我们将小写字母转为大写字母时,需要-32,反之+32;

例如上面的代码

3. strlen的使用和模拟实现

size_t strlen(const char *str)
  • 字符串以’\0’作为结束标志,strlen函数返回的是字符串中’\0’前面的字符个数(不包含‘\0’)

  • 参数指向的字符串必须要以’ \0’结束

  • 注意函数的返回值是size_t,是无符号的

  • strlen的使用必须要包含头文件

  • 学会strlen的模拟实现

strlen的使用

#include<stdio.h>
#include<string.h>

int main()
{
    const char *str1 = "abcdef";
    const char *str2 = "bbb";
    if(strlen(str2)-strlen(str1))
    {
        printf("str2>str1\n");
    }
    else
    {
        printf("str1>str2\n");
    }
    return 0;
}

strlen的模拟实现

方式1:计数器方式
int my_strlen(const char *str)
{
    int count = 0;
    assert(str);//断言检查指针是否有效(防止空指针)
    while(*str)
    {
        count++; //计数器增加
        str++;//指针移动到下一个字符
    }
    return count;
}
方式2:
//不能创建临时变量计数器,递归形式
int my_strlen(const char *str)
{
    assert(str);
    if(*str=='\0')
        return 0;
    else
        return 1+my_strlen(str+1);
}
方式3//指针——指针的方式
int my_strlen(char *str)
{
    assert(str != NULL);
    char *p=str;
    while(*p != '\0')
        p++;
    return p-str;
}

4. strcpy的使用和模拟实现

char *strcpy(char *destination,const cahr *source)
//简化为char *my_strcpy(char *dest, const char *src);  
  • 将源字符串(source 所指向的字符串)复制到目标数组(destination 所指向的数组)中,包括终止的空字符(\0),并在复制到该字符时停止。

  • 源字符串必须以’\0’结束

  • 会将源字符串中的’\0’拷贝到目标空间

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

  • 目标空间必须可修改

  • 学会模拟实现

strcpy的模拟实现

#include<stdio.h>

char* my_strcpy(char* dest, const char* src)
{
	//1.保存目标字符串的起始地址
	char* ret = dest;
	//2.对字符进行逐个复制,直到碰到'\0'字符
	while(1)
	{
		*dest = *src;
		if (*dest == '\0')
			break;
		dest++;
		src++;
	}
	//3.返回目标字符串的起始地址
	return ret;
}
int main()
{
	char str1[] = "hello,world!";
	char str2[50];
	my_strcpy(str2,str1);
	printf("%s\n", str2);
	return 0;
}

5. strcat的使用和模拟实现

char *strcpy(char *destination,const cahr *source)
  • 将源字符串添加到目标字符串的末尾,目标字符串的’\0’字符会被源字符串的首字符的第一个字符覆盖,并且在两个合并起来的新字符串后面添加’\0’

  • 源字符必须以’\0’结束

  • 目标字符串中也得有’\0’,否则没办法知道追加从哪里开始

  • 目标空间必须足够大,能容纳下源字符串的内容

  • 目标空间必须可以修改

  • 字符串自己给自己追加

模拟实现strcat函数

#include<stdio.h>

char* my_strcat(char* dest, const char* src)
{
	//1.保存目标字符串的起始地址
	char* ret = dest;
	//2.找到目标字符串的末尾('\0'的位置)
	while (*dest != '\0')
	{
		dest++;
	}
	//3.将原字符串的内容追加到目标字符串末尾
	while (*src != '\0')
	{
		*dest++ = *src++;
	}
	//4.添加新的字符串终止符
	*dest = '\0';
	//5.返回目标字符串的起始地址
	return ret;
}
int main()
{
	char str1[50] = "hello,";
	char str2[] = "world!";
	my_strcat(str1, str2);
	printf("%s\n", str1);
	return 0;
}

6. strcmp的使用和模拟实现

int my_strcmp(const char* str1, const char* str2)
  • 从两个字符串的首字符开始比较,如果相同,则继续比较,知道遇到不相等的字符串或者某个字符串遇到’\0’字符
  • 第一个字符串大于第二个字符串的话,返回大于0的数字
  • 第一个字符串小于第二个字符串的话,返回小于0的数字
  • 第一个字符串等于第二个字符串的话,返回0
  • 要想判断两个字符串的大小,我们可以两个字符串对应的ASCIII码值的大小
#include<stdio.h>

int my_strcmp(const char* str1, const char* str2)
{
	while (*str1 != '\0' && *str2 != '\0')
	{
		if (*str1 != *str2)
		{
			return *str1 - *str2;
		}
		str1++;
		str2++;
	}
	return *str1-*str2;
}
int main()
{
	char str1[] = "jackwojskf";
	char str2[] = "kdhgebjfs";
	int ret = my_strcmp(str1, str2);
	printf("%d\n",ret);
	return 0;
}

7. strncpy的使用和模拟实现

char *strncpy(char *destination, const char *source,size_t num)
  • 将源字符串的前num个字符复制到目标缓冲区,如果在复制完num个字符之前遇到了源字符串的结束字符(“\0”),则目标缓冲区会用’\0’填充,直到总共写入num个字符为止
  • 拷贝num个字符从源字符串到目标空间
  • 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后面追加0,直到num个
#include<stdio.h>

char* my_strncpy(char* dest, const char* src, size_t n) 
{
    char* original_dest = dest;
    size_t i;
    //复制最多n个字符
    for (i = 0; i < n && src[i] != '\0'; i++) 
    {
        dest[i] = src[i];
    }
    //如果src长度小于n,用'\0'填充剩余空间
    for (; i < n; i++) 
    {
        dest[i] = '\0';
    }
    return original_dest;
}
int main() 
{
    char dest[20];
    const char* src = "Hello, World!";
    // 复制前5个字符
    my_strncpy(dest, src, 5);
    dest[5] = '\0'; // 确保字符串正确终止
    printf("复制5个字符: %s\n", dest); // 输出: Hello
    // 复制超过源字符串长度的字符
    my_strncpy(dest, "Hi", 10);
    printf("复制2个字符但n=10: '%s'\n", dest); // 输出: 'Hi'后面跟着8个'\0'
    return 0;
}

8. strncat的使用和模拟实现

char *strncat(char *destination, const char *source, size_t num );
  • 将source指向字符串的前num个字符追加到destination指向的字符串末尾,再追加⼀个’\0’字符
  • 如果source指向的字符串的长度小于num的时候,只会将字符串中到\0的内容追加到destination指向的字符串末尾
#include<stdio.h>

char* my_strncat(char* dest, const char* src, size_t n) 
 {
    char* ret = dest;
    // 1. 找到 dest 的末尾
    while (*dest != '\0') 
    {
        dest++;
    }
    // 2. 从 src 复制最多 n 个字符到 dest 末尾
    size_t i;
    for (i = 0; i < n && src[i] != '\0'; i++) 
    {
        *dest++ = src[i];
    }
    // 3. 添加终止空字符
    *dest = '\0';
    return ret;
}
int main() 
{
    char dest[20] = "Hello";
    const char* src = ", World!";
    my_strncat(dest, src, 5); // 只追加 ", Wo"
    printf("%s\n", dest);    // 输出: Hello, Wo
    return 0;
}

9. strncmp的使用

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

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

#include <stdio.h>
#include <string.h>

int main() 
{
    const char* str1 = "Hello, World!";
    const char* str2 = "Hello, C!";
    int result = strncmp(str1, str2, 5);//只比较前5个字符
    if (result == 0) 
    {
        printf("前5个字符相同\n");
    }
    else if (result < 0) 
    {
        printf("str1 < str2\n");
    }
    else 
    {
        printf("str1 > str2\n");
    }
    return 0;
}

10. strstr的使用

char *strstr( const char *str1, const char *str2);
  • 函数返回字符串str2在字符串str1中第⼀次出现的位置
  • 字符串的比较匹配不包括’\0’字符,以’\0’作为结束标志
#include <stdio.h>
#include <string.h>

int main() 
{
    const char* text = "Hello, world! Welcome to C programming.";
    const char* substring = "world";
    // 在 text 中查找 substring
    char* result = strstr(text, substring);//调用strstr函数
    if (result != NULL) 
    {
        printf("找到子串: %s\n", result);  // 输出从 "world" 开始的剩余部分
        printf("位置偏移: %ld\n", result - text);  // 计算偏移量
    }
    else 
    {
        printf("未找到子串\n");
    }
    return 0;
}

11. strtok的使用

char *strtok ( char *str, const char * sep);
  • sep参数指向一个字符串,定义了用作分隔符的字符集合

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

  • strtok函数找到str中的下⼀个标记,并将其用 ‘\0’ 结尾,返回⼀个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串⼀般都是临时拷贝的内容 并且可修改。)

  • strtok函数的第⼀个参数不为NULL,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置

  • strtok函数的第一个参数为NULL,函数将在同一个字符串中将被保存的位置开始,查找下一个标记

  • 如果字符串中不存在更多的标记,则返回NULL指针

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

int main() 
{
    char str[] = "Hello,world!This is,a test.";  // 必须用可修改的字符数组(不能是字符串常量)
    const char* delimiters = ",.! ";  // 分隔符:逗号、句号、感叹号、空格
    // 第一次调用:传入原字符串
    char* token = strtok(str, delimiters);//调用strtok函数
    while (token != NULL) 
    {
        printf("找到子串: %s\n", token);
        // 后续调用:传入 NULL
        token = strtok(NULL, delimiters);
    }
    return 0;
}

12. strerror的使用

char * strerror(int errnum );

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

在不同的系统和C语言标准库的实现中都规定了⼀些错误码,⼀般是放在 errno.h 这个头文件中说明的,C语言程序启动的时候就会使用⼀个全面的变量errno来记录程序的当前错误码,只不过程序启动的时候errno是0,表示没有错误,当我们在使用标准库中的函数的时候发生了某种错误,就会讲对应的错误码,存放在errno中,而⼀个错误码的数字是整数很难理解是什么意思,所以每⼀个错误码都是有对应的错误信息的。strerror函数就可以将错误对应的错误信息字符串的地址返回。

#define _CRT_SECURE_NO_WARNINGS
#include<errno.h>
#include<stdio.h>
#include<string.h>

int main()
{
	int i = 0;
	for (i = 0; i <= 10; i++)//循环
	{
			printf("%s\n", strerror(i));//打印每个错误码对应的描述
	}
	return 0;
}

在VS2022的环境下输出结果为

在这里插入图片描述

举例:

#define _CRT_SECURE_NO_WARNINGS
#include<errno.h>
#include<stdio.h>
#include<string.h>

int main()
{
	FILE* pFile;//声明文件指针
	pFile = fopen("unexist.ent", "r");//尝试以只读模式打开文件
	if (pFile == NULL)//检查文件是否成功打开
		printf("Error opening file unexist.ent:%s\n", strerror(errno));
	return 0;
}

输出结果

在这里插入图片描述
我们也可以了解perror函数,perror函数相当于一次就将上述代码中的第9行完成了,直接将错误信息打印出来。perror函数打印完参数部分的字符串后,再打印一个冒号和一个

#define _CRT_SECURE_NO_WARNINGS
#include<errno.h>
#include<stdio.h>
#include<string.h>

int main()
{
	FILE* pFile;
	pFile = fopen("unexist.ent", "r");
	if (pFile == NULL)
		perror("Error opening file unexist.ent");
	return 0;
}

输出结果
在这里插入图片描述

内容概要:本文针对传统三电平并网逆变器在谐波抑制、电网不平衡适应性及动态响应方面的不足,提出一种基于有源中点箝位(ANPC)三电平拓扑的高性能并网控制策略。该策略深度融合双极性倍频脉宽调制(DPWMA)、正负序分离锁相技术与电网电压前馈控制,构建了“精准同步—扰动补偿—优质调制”三位一体的一体化控制体系。依托ANPC拓扑在开关损耗均衡、中点电位稳定低谐波输出方面的硬件优势,结合DPWMA调制提升等效开关频率、正负序分离实现不平衡电网下的精确锁相、前馈控制克服闭环滞后等先进控制手段,显著改善了系统的稳态电能质量、动态响应速度与复杂工况适应能力。通过多工况仿真验证,该复合策略在稳态运行时可大幅降低总谐波畸变率,在电网不平衡与动态扰动工况下仍能维持并网电流对称、功率平稳及快速恢复能力,展现出优异的综合性能与工程应用潜力。; 适合人群:具备电力电子与电力系统基础知识,从事新能源并网、逆变器控制、微电网或相关领域研究的研发人员及研究生。; 使用场景及目标:① 提升高功率并网逆变器的电能质量与运行稳定性;② 解决电网电压不平衡、畸变等复杂工况下的并网难题;③ 优化动态响应性能,提升系统抗扰能力;④ 为ANPC拓扑与先进控制策略的工程化应用提供技术参考。; 阅读建议:建议结合仿真模型深入理解DPWMA调制、正负序分离锁相与前馈控制的实现细节,重点关注多工况下的性能对比分析,以掌握复合控制策略的设计逻辑与优化效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值