【C语言】字符串处理函数及典例

下一篇:字符串处理函数及典例(2)


目录

1.字符串长度测试函数strlen

2.字符串比较函数strcmp

3.字符串复制函数strcpy

4.字符串连接函数strcat

5.大小写转换函数strupr,strlwr

6.字符串应用举例 

//不用strcpy函数,编程实现复制字符串

//不用strlen函数,编程测试字符串长度

//不用strcat函数,编程实现连接输入的两个字符串

//编程实现将一个输入的十进制整数转换为二进制数字字符串

atoi函数和itoa函数

//编程实现将一个输入的小写字母口令字符串加密

//已知10名同学的姓名和考试成绩,编程实现按姓名的字典顺序将其递增排序


头文件#include<string.h>

1.字符串长度测试函数strlen

格式:unsigned int strlen (char *string)

功能:测试并返回字符串的实际长度(读取到字符串结束符 '\0' 停止)。

注意:如果就想表达 '\0' 这个字符串,加上反斜杠变成 '\\0' 即可。

这里要熟练掌握转义字符的应用。其实编译器都为你做好了,仔细看字体的颜色是不是不一样? 

2.字符串比较函数strcmp

格式:int strcmp(char *string1,char *string2)

功能:从左向右逐个字符比较两个字符串队对应的ASCII码值(不是比较长度),直到遇到不同字符或NULL(即 '\0' )为止,并由函数返回值返回一个比较结果的整数(正数/负数/0),VS环境下返回1、0、-1。

实现strcmp函数功能的代码段:

for (i = 0; strint1[i] == string2[i]; i++);
    if (string[i] == '\0');
        break;
return string1[i] - string2[i];

注意:

1)C语言中必须用strcmp函数比较两个字符串,不能用 > < == 等关系运算符比较;

2)string1,string2可以是字符串常量,一维字符数组名或一级字符指针,代表了两个字符串起始字符的地址

3)由于字符的ASCII码值与词典的字母一致,所以利用strcmp比较字符串可以实现按字典顺序排序

3.字符串复制函数strcpy

格式:char *strcpy(char *string1,char *string2)

功能:将string2指向的源字符串复制到string1中。字符串结束符NULL(即 '\0' )也一同复制到目标字符串中。遇到 ' \0 ' 即停止复制,可用于字符串的交换

 实现strcpy函数功能的代码段:

int i = 0;
while (str2[i] != '\0')//注意这里最后一个'\0'没有复制过去
{
	str1[i] = str2[i];
	i++;
}
str1[i] = '\0';//加上字符串结束符,否则目标字符串后面会出现乱码


int i = 0;
while (str1[i] = str2[i])
	i++;  //这样写就不需要加'\0',因为这里直接将'\0'也复制过来了

 注意:

1)str1 = " hello world " ;             错     

     strcpy ( str1," hello world ");    对

2)strcpy函数要求目标字符串有足够的空间,否则在复制源字符串时会溢出,越界;

3)string2代表了源字符串起始字符的地址,可以是字符串常量,一维字符数组名,一级字符指针。但代表了目标字符串起始字符的地址string1只能是一维字符数组名或一级字符指针,不能是字符串常量,因为字符串常量的值不能改变。

4.字符串连接函数strcat

格式:char *strcat(char *string1,char *string2)

功能:将string2指向的字符串连接到string1指向的字符串后面。可以通过函数返回的地址string1访问连接后的新串。

注意:不能自己给自己追加,要用strncat(详见字符串处理函数即典例(2))

 注意:

调用时注意事项同strcpy函数,定义string1时,数组的长度要大于等于strlen(string1) + strlen(string2) + 1,否则会出现溢出和越界。

5.大小写转换函数strupr,strlwr

格式:char *strupr(char *str)

           char *strlwr(char *str)

功能:strupr()将str指向的字符串中的字符转换为大写,strlwr()将str指向的字符串中的字符转换为小写。

这里直接用strupr和strlwr编译器会报错,根据错误提示改为_strupr和_strlwr即可。(啥?你问我为啥,我也布吉岛啊,对我来说超纲了呜呜呜,哪位小可爱知道的话可以在评论区里留言哦,这里先谢过大家了哈~)

注意:

strupr()和strlwr()不会创建新串,而是改变原有字符串大小写。所以str只能是一维字符数组名或一级字符指针,不能是字符串常量,因为字符串常量的值不能改变。 

6.字符串应用举例 

//不用strcpy函数,编程实现复制字符串

简单点如下:

int main()
{
	char arr1[20];
	char arr2[] = "hello world";
	int i = 0;
	while (arr2[i] != '\0')
	{
		arr1[i] = arr2[i];
		i++;
	}
	arr1[i] = '\0';//给最后一个赋'\0',否则会出现乱码(such as 烫烫烫烫烫烫蘉簖蜩鴾)
	printf("%s\n", arr1);
	return 0;
}

想要高级点??那就要指针和函数出马了: 

void my_strlen(char* dest, char* src)
{
    assert (dest && src);
	while (*src != '\0')
	{
		*dest = *src;
		dest++;
		src++;
	}
	*dest = *src;//拷贝最后一个字符'\0'
}

//魔法1来了!!!
//以上代码可以等价为:
//void my_strlen(char* dest, char* src) 
//{
//  assert (dest && src);
//	while (*dest++ = *src++)
//	{
//		;
//	}
//}
//至于为啥,相信聪明的你肯定知道的吧~~

//魔法2来了!!!
//根据之前的知识我们知道strcpy本质上返回char*
//这里就用char*来写个函数
//char* my_strlen(char* dest, char* src)
//{
//  assert (dest && src);
//  char* ret = dest;//只需传入数组首地址即可
//  while (*dest++ = *src++);
//  return ret;
//}

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

这里再插入一个小知识:assert 

assert(statement); ——  表达式为真啥事都不发生,表达式为假则报错

注意:assert在release版本中自动优化了

就拿上面的题来举例,如果dest或者src为NULL怎么办?程序会崩溃的,而程序员自己不知道咋错了。怎么让程序员晓得有Bug呢?

void my_strlen(char* dest, char* src) 
{
	//此处assert断言指针有效性,假(有一个为NULL或都是NULL)则会报错
	assert(dest != NULL);
	assert(src != NULL);
	//或者直接简单点assert(dest&&src);
	while (*dest++ = *src++)
	{
		;
	}
}

这样就OK啦,可以准确提醒程序员哪有错误,精确到line哦~

//不用strlen函数,编程测试字符串长度

//函数
int my_strlen(const char* str)
{
	assert(str != NULL);//断言指针有效性
	int count = 0;
	if (*str != '\0')
	{
		count++;
		str++;
	}
	return count;
}
//递归
int my_strlen(const char* str)
{
	assert(str != NULL);
	if (*str != '\0')
		return 1 + my_strlen(str + 1);
	else
		return 0;
}
//指针-指针
int my_strlen(const char* str)
{
	assert(str != NULL);
	const char* start = str;
	while (*str)
		str++;
	return str - start;
}

 //不用strcmp函数,比较两个字符串

int my_strcmp(const char* str1, const char* str2)
{
	assert(str1 && str2);
	while(*str1==*str2)
	{
		if (*str1 == '\0')
			return 0;
		str1++;
		str2++;
    }
//	if (*str1 > *str2)
//		return 1;
//	else
//		return -1;
    return *str1 - *str2;
}

//不用strcat函数,编程实现连接输入的两个字符串

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
	char arr1[20];
	char arr2[10];
	printf("请输入两个数组:");
	gets(arr1);//接收输入的数组arr1
	gets(arr2);//接收输入的数组arr2
	int i = 0;
	int j = 0;
	while (arr1[i] != '\0')//这一步是为了找到arr1中的'\0'对应的下标,
	{                      //作为arr2接入arr1的起始位置
		i++;
	}
	for (j = 0 ; arr2[j] != '\0'; j++)//只要arr2没有到'\0',
	{                                 //
		arr1[i+j] = arr2[j];          //就循环将arr2[j]放入arr1[i+j]中对应的位置上去
	}
	arr1[i + j] = '\0';//将arr1结尾放一个'\0',否则会出现乱码
	printf("%s\n", arr1);
	return 0;
}

//编程实现将一个输入的十进制整数转换为二进制数字字符串

atoi函数和itoa函数

小Tips:库函数 atoi(头文件#include<stdlib.h>)可以把一个数字字符串转换成对应整数,格式:int atoi(const char *str)

库函数 itoa(头文件#include<stdio.h>)可以把一个输入的整数转换为字符串

格式:char *itoa(int value,char *string,int radix),其中value为欲转换的数据;string为目标字符串的地址;radix为转换后的进制数。

 这是借助函数的方法,那么不使用这两个库函数,我们能不能编程实现答案呢?

 当然可以啦,不过注意是转换为字符串,不是单纯的转换为二进制数字哦~

这里用的是do-while循环,之前用的是while循环,道理都是一样的,就看你哪个用的更顺手啦~  具体内容详见 进制转换专题

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
	char arr[30];
	int n = 0;
	int i = 0;
	printf("请输入一个整数:");
	scanf("%d", &n);
	do                                            
	{                        //这里是转换为十进制字符                   
		arr[i] = n % 2 + '0';//与转换为十进制数字只差了一个 +'\0'                      
		i++;  
		n = n / 2;
	} while (n != 0);//出循环时i为最大下标加一!
	arr[i] = '\0';//将最后一个字符赋为'\0',否则会出现乱码
	int l = 0;
	int r = i - 1;
	for (l = 0, r = i - 1; l < r; l++, r--)//生成的字符是逆序的,所以要先两两交换
	{
		char tmp = arr[l];
		arr[l] = arr[r];
		arr[r] = tmp;
	}
	printf("%s\n", arr);
	return 0;
}

//编程实现将一个输入的小写字母口令字符串加密

字符串加密,解密的方法有很多,简单一点就是直接对字符加上或减去一个数从而变成另一个数;更进一步是将这个数换成一串复杂的密文;或干脆使用一张字符变换对照表……

这里我们就不深究了,只使用一种简单的加密思路:找出每个小写字母在26个字母中的序号,转换为从z开始计数的逆序号。将来只需再运行一遍本程序即可得到原始口令。

小写字母逆序转换(e.g.'a'--->'z','b'--->'y'……):

换后 = ' z ' - 换前 + ' a ' 

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
	char arr1[20];
	char arr2[20];
	int i = 0;
	printf("请输入密码:");
	gets(arr1);
	while (arr1[i] != '\0')
	{
		arr2[i] = 'z' - arr1[i] + 'a';//重点!!!
		i++;
	}
	arr2[i] = '\0';
	printf("转换后的密码是:%s\n", arr2);
	return 0;
}

再将转换后的密码输入即可得到原始密码。 

//已知10名同学的姓名和考试成绩,编程实现按姓名的字典顺序将其递增排序

为什么多个名字要用多维数组存储名字是字符串,一个字符串需要一个一维数组存储,多个名字就需要多维数组。如name[10][10]={"张三","李四","王五",……};相当于"张三"占用整个多维数组的第一行,"李四"占第二行,"王五"占第三行……

int main()
{
	char name[10][10] = { "张三","李四","王五","赵一","周五","钱二","孙三","冯九","吴六","郑七" };
	char nametmp[10];//交换的中间值
	int score[10] = { 95,74,83,90,66,89,70,92,73,86 };
	int scoretmp;//交换的中间值
	int i = 0;
	int j = 0;

	//这里的思路很像冒泡排序,两两相邻比较,边比边换

	for (i = 0; i < 10; i++)//外层决定趟数,一趟解决一个姓名的位置
	{
		for (j = 0; j < 10 - 1 - i; j++)//内层决定每一趟比的次数
		{
			if (strcmp(name[j], name[j + 1]) > 0)//这里的arr[]指的是一个数组中的起始字符,也正因为这一特点我们才能根据 姓 来排序
			{                                    //两个姓对应的ASCII码值比较,
				strcpy(nametmp, name[j]);        //将大的与小的交换放在后面
				strcpy(name[j], name[j+1]);      //注意strcpy可用于字符串的交换,这也进一步说明了每个姓名都是一个字符串,都占用一个数组
				strcpy(name[j+1], nametmp);
				scoretmp = score[j];             //成绩也跟着名字交换
				score[j] = score[j+1];
				score[j+1] = scoretmp;
			}
		}
	}
	printf("排序后的名单为:\n");
	for (i = 0; i < 10; i++)
	{
		printf("%s\t%d\n", name[i], score[i]);
	}
	return 0;
}


呼  ~  终于完成了,还是有点小成就感的哈哈哈。

有志者事竟成,破釜沉舟,百二秦关终属楚;

苦心人天不负,卧薪尝胆,三千越甲可吞吴。

要继续加油鸭!!!

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值