字符函数和字符串函数

一、字符分类函数

                                                      头文件是#include 

字符函数和字符串函数_第1张图片

下面是函数的使用条件,有x的就代表只要符合体条件就返回真

字符函数和字符串函数_第2张图片

我们以islower为例写一段代码实现一下功能:将小写字符改成大写字符

#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
int main() {
	int i = 0;
	char arr[20] = { "aJsfjsJsfH" };
	while (arr[i] != '\0') {
		if (islower(arr[i]))
			arr[i] -= 32;
		i++;
	}
	printf("%s", arr);
	return 0;
}

二、字符转换函数

我们以tolower为例用代码实现将大写字符转化为小写字符 

#include 
#include 
int main() {
	char a = 'H';		//我们将h字符放在a里面
	char b = tolower(a);		//我们将小写h转换为大写H后放入b里面
	printf("%c", b);
	return 0;
}

三、strlen的使用和模拟实现

函数原型

size_t strlen ( const char * str );

头文件: 

#include 
#include 
int main() {
	if (strlen("abc")-strlen("abcde")>0)
	{
		printf(">\n");
	}
	else
	{
		printf("<=\n");
	}
	return 0;
}

 很多人会以为会打印出<=其实不然,由于strlen的返回值是无符号整型,无符号整型-无符号整型的结果也会是无符号整型。所以应该是打印出>号。(有符号减无符号结果也是无符号)

前面我们用计数器的方式,和指针减指针的方式模拟过strlen,下面我们用递归的方式来模拟

#include 
size_t mystrlen(const char *str)
{
	if (*str!='\0')
	{
		return 1 + mystrlen(str+1);
	}
	else
	{
		return 0;
	}
}
int main() {
	char arr[] = { "asjkldjgl" };
	size_t lenght = mystrlen(arr);
	printf("%zu", lenght);
	return 0;
}

四、strcpy的使用和模拟实现

函数原型


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

 头文件:

 作用是将source指向的字符复制到destination指向的数组中,包括终止字符\0。

注意事项:

1.源字符串必须以‘\0’结束

2.将源字符串中的‘\0’拷贝到目标空间。

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

4.目标空间必须可修改。(就像常量字符串,不能修改或者是用const限定的)。

#include 
#include 
int main() {
	char arrs[] = { "hasdfklj" };
	char arrd[20] = {};
	strcpy(arrd, arrs);
	printf("%s", arrd);
	return 0;
}

 现在我们来模拟实现strcpy

#include 
char my_strcpy(char* p1, const char* p2) {
	do
	{
		*p1 =* p2;
		p1++;
		p2++;
	} while (*p2!='\0');
	*p1 = *p2;
	return 0;
}
int main() {
	char arrs[10] = { "hasdfklj" };
	char arrd[10] = {};
	my_strcpy(arrd, arrs);
	printf("%s", arrd);
	return 0;
}

 其实还能将这段代码进行化简(加升级改造)

#include 
#include 
char* my_strcpy(char* p1,const char* p2) {
    char*p=p1;        //之所以要在创一个新指针将p1的首地址复制给它,那是因为经过循环后的p1指向的不是首地址,这会对我们模拟实现返回时要返回char*造成影响
    assert(p1&&p2);        //作用是避免指针为空指针
	do
	{			//后置++先运算后赋值
	} while (*p1++ =* p2++);		//这个执行原理其实和上面的一样,从第一个开始一个一个往后赋值,当赋值到\0时,它的ascll码值为0,所以退出循环
	*p1 = *p2;
	return p1;        //由于是模拟实现strcpy的返回类型是char*
}
int main() {
	char arrs[10] = { "hasdfklj" };
	char arrd[10] = {};
	my_strcpy(arrd, arrs);
	printf("%s", arrd);
	return 0;
}

五、strcat的使用和模拟实现

 函数原型

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

头文件:

作用是将源字符串的副本附加到目标字符串,destination中终止的\0字符被source中的第一个字符覆盖,并且\0字符包含在destination中由两者串联形成的新字符串的末尾。

#include 
#include 
int main() {
	char arr1[20] = { "aakld" };
	char arr2[20] = { "asskj"};
	strcat(arr1, arr2);
	printf("%s", arr1);
	return 0;
}

注意事项:

1.源字符串必须以‘\0’结束

2.将源字符串中的‘\0’拷贝到目标空间。

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

4.目标空间必须可修改。(就像常量字符串,不能修改或者是用const限定的)。

 下面模拟实现strcat(我们自己写的strcat无法实现自己给自己追加字符,但是strcat可以(有风险))

#include 
#include 
void my_strcat(char* p1, const char* p2) {
    assert(p1&&p2);
    while (*p1) {
        p1++;
    }
    while (*p2) {
        *p1++ = *p2++;
    }
    *p1 = '\0';
}

int main() {
    char arrd[30] = "hasdfklj";
    char arrs[15] = "sdseds";
    my_strcat(arrd, arrs);
    printf("%s\n", arrd);
    return 0;
}

六、strcmp的使用和模拟实现

函数原型

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

头文件

作用是将字符串str1和str2进行比较,从第一个字符开始,比较他们的ascll码值,如果相等,则继续处理,直到字符不同,或到\0为止

字符函数和字符串函数_第3张图片

#include 
#include 
int main() {
	char arr1[] = { "asdslfkj" };
	char arr2[] = { "asdeiwl" };
	int r = strcmp(arr1, arr2);        //要注意strcmp在vs环境中返回的值是1,-1,0,但是在其他环境中返回的值可能不是,所以判断条件一定要按照下面来写,而不是写成r==1,r==-1
	if (r>0)
	{
		printf("arr1中字符的ascll码值大于arr2");
	}
	else if (r<0)
	{
		printf("arr1中字符的ascll码值小于arr2");
	}
	else if(r==0)
	{
		printf("arr1中字符的ascll码值等于arr2");
	}
	return 0;
}

现在我们用代码来实现自己的strcmp函数

#include 
#include 
int my_strcmp(const char* p1,const char* p2) {
    assert(p1&&p2);
	while (*p1++ == *p2++)
	{
		if (*p1 == '\0' && *p2 == '\0')        //这个条件非常重要,如果两串字符串完全相同比完\0之后回一直比下去。直到出现不同的为止
			return 0;
		}
	}
	if (*p1 > *p2)
	{
		return 1;
	}
	else if (*p1 < *p2)
	{
		return -1;
	}

}
int main() {
	char arr1[] = { "asdf" };
	char arr2[] = { "asdf" };
	int r = my_strcmp(arr1, arr2);
	if (r > 0)
	{
		printf("arr1中字符的ascll码值大于arr2");
	}
	else if (r < 0)
	{
		printf("arr1中字符的ascll码值小于arr2");
	}
	else if (r == 0)
	{
		printf("arr1中字符的ascll码值等于arr2");
	}
	return 0;
}

 注意:前面三个函数是长度不受限制的字符串函数(strcpy strcmp strcpy)下面三个则是长度受限的字符串函数

七、strncpy函数的使用 

函数原型:

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

头文件 

 将源字符串的num个字符复制到目标字符串中,如果复制num个字符之前遇到源字符串的结束符,则用0填充目标字符串(这里的用0填充的意思是将\0换成0,防止在复制时遇到\0停止。而不是在复制完成后将源字符串原本是\0的地方用0填充),直到总共写入num个字符。(如果源字符串的长度大于num,则不会在目标字符串的末尾添加\0,这种情况下读取目标字符串可能会导致越界)

下面只演示越界的情况

#include
#include
int main() {    
	char dest[8] = { "xxxxx" };
	char sour[20] = { "lsdkjflsdj" };
	printf("%s", strncpy(dest, sour,8));        //这里就是源字符串大于num,在复制给目标字符串时无法给目标字符串填充\0。
	return 0;
}

八、strncat函数的使用

函数原型:

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

 头文件

从源字符串中最多复制num个字符串到目标字符串的末尾,过程中函数会先找到目标字符串的末尾(也就是\0所在的位置),然后从源字符串中复制最多num个字符串的末尾,覆盖原来的目标字符串的\0,最后,会在追加后的字符串末尾添加\0。

#include 
#include 
int main() {
	char dest[14] = { "xxxxx" };
	char sour[20] = { "lsdkjflsdj" };
	printf("%s", strncat(dest, sour,8));
	return 0;
	return 0;
}

九、strncmp函数的使用

函数原型:

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

 头文件

strncmp函数会逐个字符比较str1和str2的前n个字符,直到出现以下情况

比较了n个字符

遇到了不同字符

其中一个字符串遇到了\0

字符函数和字符串函数_第4张图片

代码实例就省略了

十、strstr的使用和模拟实现

函数原型:

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

 头文件

strstr函数会在str1中查找str2子字符串首次出现的位置。它会从str1的开头开始逐字符地进行比较,直到找到与str2完全匹配的子字符串,或者达到str1结尾结束。

指向 str2 中指定的整个字符序列在 str1 中首次出现的指针,如果 str1 中不存在该序列,则指向 null 指针。

注意

str1指向要被搜索的主字符串的指针,该字符串需要是以\0结尾的有效字符串。

str2指向要搜索的子字符串的指针,同样需要是以\0结尾的有效字符串。

#include 
#include 
int main()
{
	char arr1[30] = { "how are you,i'm fine thankyou" };
	char arr2[10] = { "fine" };
	char* p = strstr(arr1, arr2);
	if (p==NULL)
	{
		printf("找不到");
	}
	else
	{
		printf("找到了");
	}
	return 0;
}

下面我们来进行模拟strstr实现

#include 
#include 
char* my_strstr(const char* str1,const char* str2) {
    assert(str1&&str2);
	if (*str2=='\0')
	{
		return str1;
	}
	while (*str1)
	{
		char* p1 = str1;		//这里设置p1p2,是为了防止在查找字符时轻易改变str1str2,各自的初始位置,同时在最外层进行一次循环后将str2的首地址赋值给p2,str1++后的地址赋值给p1
		char* p2 = str2;
		while (*p1&&*p2&&*p1==*p2)		//情况1;如果其中p1p2有一个字符串已经历遍或者同时历遍,则跳出循环
		{								//情况2:如果p1p2一直相等直到p2历遍找到\0,也跳出循环
			p1++;
			p2++;
		}
		if (*p2=='\0')		//找到了
		{
			return str1;
		}
		str1++;		//在最外层循环中,作用是用str1中的第一个字符与str2中第一个字符比较,如果不同,则str1++,用第2个与str2第一个来比较,直到找到为止(或找不到)
	}
	return NULL;
}
int main()
{
	char arr1[40] = { "this is a sample string" };
	char arr2[10] = { "sample" };
	char* result = my_strstr(arr1,arr2);
	if (result!=NULL)
	{
		printf("子字符串 '%s' 在主字符串中首次出现的位置是: %#X\n", arr2, result);
	}
	else 
	{
		printf("未在主字符串中找到子字符串 '%s'\n",arr2);
	}
	return 0;
}

十一、strtok函数的使用

函数原型:

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

头文件 

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

第一个参数指定一个字符串,塔波扩了0个或多个由sep字符串中一个或多个分隔符分割的标记。

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

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

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

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

#include 
#include 
int main()
{
	char str[] = { "192.168.023.431" };
	char cpy[50] = { 0 };		//这个就是要分割的临时拷贝
	strcpy(cpy, str);
	char sep[] = { "." };
	char* r = strtok(cpy,sep);
	for (r;r!=NULL;r=strtok(NULL,sep))
	{
		printf("%s\n", r);
	}
	return 0;
}

十二、strerror函数的使用

函数原型:

char * strerror ( int errnum );

头文件

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

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

#include
#include
#include		//这个头文件的作用是调用错误信息库
int main() {
	FILE* pf = fopen("test.txt", "r");		//以读的形式打开test.txt文件,如果文件不存在,则打开失败
	if (pf==NULL)
	{
		printf("错误信息是: %s", strerror(errno));		//这里的strerror的作用就是返回错误信息的字符串首地址
	}
	return 0;
}

拓展:

其实还可以用perror函数(就不用strerror函数了)

函数原型:

void perror(const char *s);

perror 函数会根据全局变量 errno 的值,将对应的错误信息输出到标准错误流。errno 是一个整数类型的全局变量,当系统调用或库函数执行出错时,会将相应的错误号赋值给 errno。perror 函数会将 s(如果不为 NULL)和错误信息一起输出,格式为:s: 错误信息。

#include
#include
#include		//这个头文件的作用是调用错误信息库
int main() {
	FILE* pf = fopen("test.txt", "r");		//以读的形式打开test.txt文件,如果文件不存在,则打开失败
	if (pf==NULL)
	{
		perror("错误信息是");        //这个括号内如果不填字符则会直接输出错误信息
	}
	return 0;
}

你可能感兴趣的:(算法)