字符函数和字符串函数

1. 字符分类函数

C语言中有一系列的函数是专门做字符分类的,也就是一个字符是属于什么类型的字符的。
这些函数的使用都需要包含⼀个头文件是 < ctype.h>.

以islower为例: 

islower 是能够判断参数部分的 c 是否是小写字母的。通过返回值来说明是否是小写字母,如果是就返回非0的整数,如果不是小写字母,则返回0。

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

int main()
{
	char arr[30] = " i Am a STUdent. ";
	int i = 0;
	while (arr[i])
	{
		if (islower(arr[i]))
		{
			arr[i] = arr[i] - 32;
		}
		i++;
	}
	printf("%s", arr);
	return 0;
}

2. 字符转换函数  

C语言提供了2个字符转换函数:
int tolower ( int c ); //将参数传进去的⼤写字⺟转⼩写 
int toupper ( int c ); //将参数传进去的⼩写字⺟转⼤写

由此,我们可以改良一下上述代码

int main()
{
	char arr[30] = " i Am a STUdent. ";
	int i = 0;
	while (arr[i])
	{
		if (islower(arr[i]))
		{
			arr[i] = toupper(arr[i]);
		}
		i++;
	}
	printf("%s", arr);
	return 0;
}

3. strlen 的使用和模拟实现

size_t strlen ( const char * str );
字符串以 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包
  含 '\0' )。
参数指向的字符串必须要以 '\0' 结束。
注意函数的返回值为 size_t,是无符号的( 易错 )
strlen的使用需要包含头文件
补充:1.无符号数减无符号数答案还是无符号数
           2.无符号数的原、反、补码相同

3.1比较两个字符串的长度

strlen的应用:
int main()
{
	char arr1[] = "abc";
	char arr2[] = "abcdef";
	if ((strlen(arr1)) - (strlen(arr2)) > 0)
	{
		printf("arr1>arr2");
	}
	else
	{
		printf("arr1<arr2");
	}
	return 0;
}

3.2strlen的模拟实现:

 
1.计数器的方式
#include<assert.h>
int my_strlen(const char* str)
{
	assert(str != NULL);
	int count = 0;
	while (*str)
	{
		count++;
		str++;
	}
	return count;
}
int main()
{
	char arr[] = "abcdefghi";
	int r = my_strlen(arr);
	printf("%d", r);
	return 0;
}

2.指针-指针

int my_strlen(const char* str)
{
	assert(str != NULL);
	char* start = str;
	while (*str)
	{
		
		str++;
	}
	return str-start;
}
int main()
{
	char arr[] = "abcdefghi";
	int r = my_strlen(arr);
	printf("%d", r);
	return 0;
}

3.递归的写法

int my_strlen(const char* str)
{
	if (*str == 0)
		return 0;
	else
		return 1 + my_strlen(str + 1);
}
int main()
{
	char arr[] = "abd";
	int r = my_strlen(arr);
	printf("%d", r);
}

4. strcpy 的使用和模拟实现

Copies the C string pointed by source into the array pointed by destination, including the
terminating null character (and stopping at that point).
源字符串必须以 '\0' 结束。
会将源字符串中的 '\0' 拷贝到目标空间。
• 目 标空间必须足够大,以确保能存放源字符串。
• 目 标空间必须可修改。
学会模拟实现。

 常见错误(目标空间不够大)

常见错误2(destination为常量)

4.1 strcpy的应用:

int main()
{
	char arr1[] = "hello bit.";
	char arr2[20] = { 0 };
	strcpy(arr2, arr1);
	printf("%s", arr2);
	return 0;
}

4.2 strcpy模拟实现my_strcpy

void my_strcpy( char* dest,const char* sour)   //我们不希望sour被改动掉
{
	assert(dest && sour);//这里要保证dest和sour都不为空指针,只要他俩有一个空指针(即0),则报警
	while (*sour != '\0')
	{
		*dest = *sour;
		dest++;
		sour++;
	}
	*dest = *sour;
}

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

注意,不得这样写!!不得投机取巧!!

void my_strcpy( char* dest,  char* sour)
{

	*dest = *sour;     //不能这样写,strcpy是一个字符一个字符拷贝的,这样写arr2只会得到a!
}
int main()
{
	char arr1[] = "abcdef";
	char arr2[20] = { 0 };
	my_strcpy(arr2, arr1);
	printf("%s\n", arr2);
	return 0;
}

4.3my_strcpy的调整优化 

但是,我们真的模拟实现了strcpy吗?strcpy的返回地址为目标空间的起始地址,但是我们的dest指针都跑到最后面去了,感觉不太合适,故应该做出如下调整:

char* my_strcpy( char* dest,const char* sour)   //我们不希望sour被改动掉
{
	assert(dest && sour);//这里要保证dest和sour都不为空指针,只要他俩有一个空指针(即0),则报警
	char* ret = dest;
	while (*sour != '\0')
	{
		*dest = *sour;
		dest++;
		sour++;
	}
	*dest = *sour;
}

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

5. strcat 的使用和模拟实现

5.1strcat的应用

Appends a copy of the source string to the destination string. The terminating null character
in destination is overwritten by the first character of source, and a null-character is included
at the end of the new string formed by the concatenation of both in destination.
作用方式:
                1.找到目标空间的第一个\0;
                2.从这个\0的位置开始追加源头字符串;
                3.源头字符串的内容,包括\0都会追加到目标空间。
简述一下就是:
源字符串必须以 '\0' 结束。
目标 字符串中也得有 \0 ,否则没办法知道追加从哪里开始。
目标空间必须有足够的大,能容纳下源字符串的内容。
目标空间必须可修改。
试用一下:
int main()
{
	char arr[20] = "hello ";
	strcat(arr, "world");
	printf("%s", arr);
	return 0;
}

5.2strcat的模拟实现

#include<assert.h>
char* my_strcat(char* dest, const char* sour)
{
	assert(dest && sour);
	char* ret = dest;
	while (*dest != '\0')        //寻找第一个\0
		dest++;
	while (*sour != '\0')
	{
		*dest = *sour;
		dest++;
		sour++;
	}
	*dest = *sour;             //把最后一个\0也考过来
	return ret;
}
int main()
{
	char arr[20] = "hello ";
	my_strcat(arr, "world");
	printf("%s", arr);
	return 0;
}

5.3自己追加自己可行吗?

自己追加自己时,会造成死循环 ,因为这样会把标志结束的\0覆盖掉,导致其一直在循环。若想自己给自己追加,用strncat函数。

6. strcmp 的使用和模拟实现

6.1strcmp的应用

This function starts comparing the first character of each string. If they are equal to each
other, it continues with the following pairs until the characters differ or until a terminating
null-character is reached.

 简而言之,就是比较两个字符串大小(不是长度strlen),对应位置上的字符进行比较,ASCII码值   的大小。

第⼀个字符串大于第二个字符串,则返回大于0的数字
第⼀个字符串等于第二个字符串,则返回0
第⼀个字符串小于第二个字符串,则返回小于0的数字

试用一下:

int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abcq";
	int ret = strcmp(arr1, arr2);
	if (ret > 0)
	{
		printf(">\n");
	}
	else if (ret < 0)
	{
		printf("<\n");
	}
	else
	{
		printf("=\n");
	}
	return 0;
}

6.2strcmp模拟实现

#include<assert.h>
#include<string.h>
int my_strcmp(const char* arr1, const char* arr2)
{
	assert(arr1 && arr2);
	while (*arr1 == *arr2)
	{
		if (*arr1 == "\0")
		{
			return 0;
		}
		arr1++;
		arr2++;
	}
	return *arr1 - *arr2;
}

int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abcq";
	int ret = my_strcmp(arr1, arr2);
	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 terminating
null-character is copied.(如果source 指向的字符串的长度小于num的时候,只会将字符串中到
\0 的内容追加到destination指向的字符串末尾)。

9. strncmp函数的使用

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

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

10. strstr 的使用

char * strstr ( const char * str1, const char * str2);

在一个字符串中,找一个子字符串,找出第一次出现的位置,如果找到了,就返回第一次出现的地址,如果找不到,就返回NULL

10.1strstr的应用

#include<string.h>

int main()
{
	char arr1[] = "abcdefabcdef";
	char arr2[] = "def";
	char* ret = strstr(arr1, arr2);
	if (ret == NULL)
	{
		printf("没找到");
	}
	else
	{
		printf("找到了:%s\n", ret);
	}
	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 1
#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = "192#168.6.11@1";
	char sep[] = "#.@";
	char* str = NULL;
	for (str = strtok(arr, sep); str != NULL; str = strtok(NULL, sep))
	{
		printf("%s\n", str);     //字符串是连续存储的,%s会自动识别字符串指针并解读到\0结束,把 
                                   他指向的内容用Printf打印出来(类比数组)
	}
	return 0;
}

12. strerror 函数的使用

char* strerror ( int errnum );
strerror 函数可以把参数部分错误码对应的错误信息的字符串地址返回来。
在不同的系统和C语言标准库的实现中都规定了⼀些错误码,⼀般是放在 errno.h 这个头头件中说明的,C语⾔程序启动的时候就会使⽤⼀个全局的变量errno来记录程序的当前错误码,只不过程序启动
的时候errno是0,表示没有错误,当我们在使⽤标准库中的函数的时候发生了某种错误,就会将对应
的错误码,存放在errno中,而一个错误码的数字是整数很难理解是什么意思,所以每⼀个错误码都是
有对应的错误信息的。strerror函数就可以将错误对应的错误信息字符串的地址返回。
也可以了解⼀下 perror 函数,perror函数直接将错误信息打印出来。perror函数打印完参数部分的字符串后,再打印⼀个冒号和⼀个空格,再打印错误信息。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值