【C语言进阶】字符函数和字符串函数

【C语言进阶】字符函数和字符串函数


本章目标:

学会并掌握处理字符和字符串的库函数的使用方法和注意事项,并能模拟实现它们。

本章重点:

1.求字符串长度

strlen()

2.长度不受限制的字符串函数

strcpy()

strcat()

strcmp()

3.长度受限制的字符串函数

strncpy()

strncat()

strncmp()

4.字符串查找

strstr()

strtok()

5.错误信息报告

strerror()

6.字符操作函数

​ 字符分类函数

​ 字符转换函数

7.内存操作函数

memcpy()

memmove()

memset()

memcmp()


0 前言

C语言对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,而字符串通常是放在 常量字符串 中或者 字符数组 中的。

字符串常量 适用于那些对它不做修改的字符串函数。


一、函数介绍

1 strlen()

1.1 函数原型

求字符串长度。

size_t strlen (const char* str);

1.2 介绍

1.字符串以 \0 作为结束标志,strlen 函数返回的是在字符串中 \0 之前出现的字符个数(但不包括 \0

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

3.函数的返回值类型为 size_t ,是无符号整型( unsigned int )。

4.学会 strlen 函数的模拟实现。

1.3 示例

代码示例

#include<stdio.h>

#include<string.h>
int main()
{
	//strlen()的应用

	const char* str1 = "abcdef";
	const char* str2 = "bbb";

	if (strlen(str2) - strlen(str1) > 0)
	{
		printf("str2 > str1\n");//输出结果
	}
	else
	{
		printf("str1 > str2\n");
	}

	return 0;
}

解释说明

1.if (strlen(str2) - strlen(str1) > 0)两个无符号数相减,结果也是无符号数

2 if 语句的修改:

1.if (strlen(str2) > strlen(str1))
2.if ((int)strlen(str2) - (int)strlen(str1) > 0)
3.int ret = strlen(str2) - strlen(str1);
  if (ret > 0)	


2 strcpy()

2.1 函数原型

拷贝源字符串到目标字符串中。

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

2.2 介绍

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

2.该函数会将源字符串中的 \0 拷贝到目标空间中

3.目标字符串的空间必须足够大(至少等于源字符串的大小),以确保能够存放源字符串。

4.目标空间必须可变(能够修改)

5.学会 strcpy 函数的模拟实现。

2.3 示例

代码示例

#include<stdio.h>

#include<string.h>
int main()
{
	//strcpy()的应用

	char str1[20] = "XXXXXXXXXXXXXXXXX";
	char str2[] = "hello pokemon.";

	printf("%s\n", str1);
	strcpy(str1, str2);
	printf("%s\n", str1);

	return 0;
}

解释说明

1 该函数会将源字符串中的 \0 拷贝到目标空间中


3 strcat()

3.1 函数原型

将源字符串追加到目标字符串后面。

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

3.2 介绍

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

2.目标空间必须足够大能容纳下源字符串(追加的字符串)的内容

3.目标空间必须可变(能够修改)

4.最好不要自己给自己追加

5.学会 strcat 函数的模拟实现。

3.3 示例

代码示例

#include<stdio.h>

#include<string.h>
int main()
{
	//strcat()的应用

	char arr1[20] = "hello ";
	char arr2[] = "pokemon.";

	strcat(arr1, arr2);
	printf("%s\n", arr1);


	char arr3[20] = "hello";
	//strcat(arr3, arr3);//error;最好不要自己给自己追加
	printf("%s\n", arr3);

	return 0;
}

解释说明

1 最好不要自己给自己追加,不然的话字符串末尾的 \0 会被覆盖strcat() 就会一直追加,直到填满目标空间,最终会引发异常,程序崩溃


4 strcmp()

4.1函数原型

比较两个字符串。

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

4.2 介绍

1.将两个字符串进行比较

2.从起始位置开始比较每一对字符如果两个字符相等,则进行下一对字符的比较,直到有一对字符不同或遇到 \0 就结束比较

3.该函数会返回一个整型值,用来指示字符串之间的关系

4.标准规定:

return valueindicates
>0str1大于str2
=0str1等于str2
<0str1小于str2

4.3 示例

代码示例

#include<stdio.h>

#include<string.h>
int main()
{
	//strcmp()的应用

	char str1[] = "abcdef";
	char str2[] = "abq";
	char str3[] = "abc";
	char* pc = "abc";

	//str1/str2
	int ret = strcmp(str1, str2);
	if (ret > 0)
		printf("str1 > str2\n");
	else if (ret == 0)
		printf("str1 == str2\n");
	else if (ret < 0)
		printf("str1 < str2\n");

	//str1/str3
	ret = strcmp(str1, str3);
	if (ret > 0)
		printf("str1 > str3\n");
	else if (ret == 0)
		printf("str1 == str3\n");
	else if (ret < 0)
		printf("str1 < str3\n");

	//str3/pc
	ret = strcmp(str3, pc);
	if (ret > 0)
		printf("str3 > pc\n");
	else if (ret == 0)
		printf("str3 == pc\n");
	else if (ret < 0)
		printf("str3 < pc\n");

	return 0;
}

解释说明

1 字符串比较函数,比较的是对应位置字符对的 ASCII 值的大小;哪个字符大,那么其所在的字符串就大。


5 strncpy()

5.1 函数原型

从源字符串 source 中拷贝 num 个字符到目的字符串 destination 中。

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

5.2 介绍

1.拷贝 num 个字符从源字符串到目的空间

2.如果源字符串的长度小于 num ,则拷贝完源字符之后,在目标字符串后补充 \0 ,直到所有拷贝字符数够 num

3.如果源字符串的长度大于 num,则不会在目标空间末尾隐式追加 \0 字符

5.3 示例

代码示例

#include<stdio.h>

#include<string.h>
int main()
{
	//strncpy()的应用

	char arr1[20] = "abcdef";
	char arr2[] = "xxx";

	strncpy(arr1, arr2, 5);
	printf("%s\n", arr1);//xxx

	return 0;
}

解释说明

1 如果源字符串的长度小于 num ,则拷贝完源字符之后,在目标字符串后补充 \0 ,直到所有拷贝字符数够 num。但是待拷贝的字符个数 num 不能超过目标空间的大小。


6 strncat()

6.1 函数原型

追加 num 个字符,不够则只追加到源字符串的结尾 \0 处。

char* strncat(cagr* destination, const cahr* source);

6.2 介绍

1.从源字符串中向目标字符串后追加 num 个字符

2.如果源字符串的长度小于 num ,则只追加到源字符串的末尾 \0

3.如果源字符串的长度大于 num ,则只追加 num 个字符,并在结尾补充 \0

6.3 示例

6.3.1 示例1

代码示例

#include<stdio.h>

#include<string.h>
int main()
{
	//strncat()的应用

	char str1[20];
	char str2[20];

	strcpy(str1, "To be ");
	strcpy(str2, "or not to be");

	strncat(str1, str2, 6);
	puts(str1);//To be or not

	return 0;
}

解释说明

1 将源字符串 str2 中前6个字符追加到 str1 中,追加完成后并在末尾补上 \0

2 puts() 用来打印字符串并换行。


6.3.2 示例2

代码示例

#include<stdio.h>

#include<string.h>
int main()
{
	//strncat()的应用2

	char arr1[20] = "abcdef\0XXXXXXXX";
	char arr2[] = "aaa";

	strncat(arr1, arr2, 5);
	puts(arr1);//"abcdefaaa"

	return 0;
}

解释说明

1 如果源字符串的长度小于 num ,则只追加到源字符串的末尾 \0 处。

  即不够追加时只追加到源字符串的 \0 处就停止


7 strncmp()

7.1 函数原型

比较两个字符串前 num 个字符。

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

7.2 介绍

1.比较到出现不相同的字符或者其中一个字符串结束或者 num 对字符全部比较完

2.该函数会返回一个整型值,用来指示字符串之间的关系

3.标准规定:

return valueindicates
>0str1大于str2
=0str1等于str2
<0str1小于str2

7.3 示例

代码示例

#include<stdio.h>

#include<string.h>
int main()
{
	//strncmp()的应用

	char str[][5] = { "R2D2","C3P0", "R2A6" };

	puts("Looking for R2 astromech droids...");

	int i;
	for (i = 0; i < 3; i++)
	{
		if (strncmp(str[i], "R2xx", 2) == 0)//如果下标i位置的字符串前两个字符为R2则打印
		{
			printf("found %s\n", str[i]);
		}
	}

	return 0;
}

解释说明

1 比较源字符串 str[i] 与目标字符串 "R2xx"num 个字符。


8 strstr()

8.1 函数原型

寻找一个字符串中的子串。

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

8.2 介绍

1.从字符串 str1 中找第一次出现字符串 str2 的位置,然后返回该位置

2.如果没找到子串,返回空指针 NULL

8.3 示例

代码示例

#include<stdio.h>

#include<string.h>
int main()
{
	//strstr()的应用

	char str[] = "This is a simple string.";
	char* pch;
	pch = strstr(str, "simple");//找子串,然后返回目标位置的地址

	strncpy(pch, "sample", 6);//相当于是修改simple为sample
	puts(str);//打印输出字符串

	return 0;
}

解释说明

1 通过 strstr() 找到 str 中的子串 "simple" ,然后通过 strncpy() 修改为 "sample"


9 strtok()

9.1 函数原型

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

9.2 介绍

1.sep 参数是一个字符串,定义了用作分隔符的字符集合

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

3.strtok 函数找到 str 中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针

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

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

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


9.3 示例

9.3.1 示例1

代码示例

#include<stdio.h>

#include<string.h>
int main()
{
	//strtok()的应用

	char str[] = "- This, a sample string.";
	char* pch;
	printf("Splitting string \"%s\" into tokens:\n", str);

	pch = strtok(str, " ,.-");
	while (pch != NULL)
	{
		printf("%s\n", pch);
		pch = strtok(NULL, " ,.-");
	}

	/*	
	*	This
	*	a
	*	sample
	*	string
	*/

	return 0;
}

解释说明

1 用作分隔符的字符集合:" ,.-"


9.3.2 示例2

代码示例

#include<stdio.h>

#include<string.h>
int main()
{
	//strtok()的应用2

	const char* p = "xxx_yyy@163.com";
	const char* sep = "_@.";

	char arr[30];
	char* str = NULL;

	strcpy(arr, p);
	for (str = strtok(arr, sep); str != NULL; str = strtok(NULL, sep))
	{
		printf("%s\n", str);
	}

	/*
	*	xxx
	*	yyy
	*	163
	*	com
	*/

	return 0;
}

解释说明

1 str = strtok(arr, sep)arr 的位置开始向后查找标记字符,找到后会将该字符置为 \0 并记录其地址,然后返回该地址

2 str = strtok(NULL, sep)从上一个标记位置开始向后查找下一个标记字符,如果不存在则返回 NULL 指针,否则将重复这一过程


10 strerror()

10.1 函数原型

返回错误码所对应的错误信息首字符的地址。

char* strerror(int errnum);

10.2 介绍

1.库函数在执行的过程中如果发生了错误会将一个错误码存放在 errno 这个变量中。(运行时错误)

2.errno 是C语言提供的一个全局变量

3.错误码的可读性差,应该将其翻译成错误信息。


10.3 示例

10.3.1 示例1

代码示例

#include<stdio.h>

#include<string.h>
int main()
{
	//strerror()的应用1

	FILE* pFile;
	pFile = fopen("unexist.ent", "r");
	//如果调用fopen函数失败,则会将会产生的错误码放入errno变量中

	if (pFile == NULL)//如果打开失败,显示错误信息
	{
		printf("Error opening file unexist.ent:\n%s\n", strerror(errno));
		//perror("str");//显示输出:No such file or directory
		//errno: Last error number
	}

	return 0;
}

解释说明

1 strerror(errno) :将错误码翻译成错误信息,并返回错误信息首字符的地址。

2 perror("str"); 找到并打印错误信息。


10.3.2 示例2

代码示例

#include<stdio.h>

#include<string.h>
int main()
{
	//strerror()的应用2

	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d:%s\n", i, strerror(i));//打印错误码为0~9的错误信息
	}

	/*
	*	0:No error
	*	1:Operation not permitted
	*	2:No such file or directory
	*	3:No such process
	*	4:Interrupted function call
	*	5:Input/output error
	*	6:No such device or address
	*	7:Arg list too long
	*	8:Exec format error
	*	9:Bad file descriptor
	*/

	return 0;
}

解释说明

1 打印错误码为0~9的错误信息。


11 其他字符函数

11.1 字符分类函数

介绍

函数如果它的参数符合下列条件就返回真
iscntrl()任何控制字符(不可打印字符)
isspace()空白字符:空格 ’ '、换页 ‘\f’、换行 ‘\n’、回车 ‘\r’、制表符 ‘\t’、垂直制表符 ‘\v’
isdigit()十进制数字:0~9
isxdigit()十六进制数字:包括所有十进制数字,小写字母af,大写字母AF
islower()小写字母:a~z
isupper()大写字母:A~Z
isalpha()字母: a~z 或 A~Z
isalnum()字母或数字,az,AZ,0~9
ispunct()标点符号,任何不属于数字或者字母的图形字符(可打印)
isgraph()任何图形字符
isprint()任何可打印字符,包括图形字符和空白字符

说明:此处仅作简单介绍。


11.1.1 示例

代码示例

#include<stdio.h>

#include<ctype.h>
int main()
{
	//isupper()、tolower()

	char str[] = "Test string.\n";
	char c;
	int i = 0;

	while (str[i])//将大写字符转换为小写字符
	{
		c = str[i];
		if (isupper(c))
		{
			c = tolower(c);
		}
		putchar(c);
		i++;
	}

	/*
	*	test string.
	*/

	return 0;
}

解释说明

1 如果字符数组中有大写字母,就将其转换为小写字母并输出,其他字符原样输出。


11.2 字符转换函数

11.2.1 tolower()
① 函数原型:

将大写字母转换为小写字母。

int tolower ( int c );
② 介绍:

1.传入的参数如果是大写字母,就将其转换成小写字母否则就不进行任何转换

2.返回值以 int 值的形式返回,该值可以隐式转换为 char

3.该函数定义在 <ctype.h> 头文件中。

③ 示例:

代码示例tolower() 的应用1

#include<stdio.h>

#include<ctype.h>
int main()
{
	//tolower()的应用1

	char ch1 = '1';
	char ch2 = 'A';
	char ch3 = 'm';
	char ch4 = 65;//'A'
	char ch5 = 109;//'m'
	putchar(tolower(ch1));//1
	putchar(tolower(ch2));//a
	putchar(tolower(ch3));//m
	putchar(tolower(ch4));//a
	putchar(tolower(ch5));//m

	return 0;
}

解释说明

1 tolower 传入的参数如果是大写字母( 值为对应的ASCII码值 ),就将其转换成小写字母如果是其他字符就不进行任何转换

2 putchar 用来打印字符


代码示例tolower() 的应用2

#include<stdio.h>

#include<ctype.h>
int main()
{
    //tolower()的应用2

    int i = 0;
    char str[] = "Test String.\n";
    char c;
    while (str[i])
    {
        c = str[i];
        putchar(tolower(c));
        i++;
    }
    
    /*
    *   test string.
    */

	return 0;
}


11.2.2 toupper()
① 函数原型:

将小写字母转换为大写字母。

int toupper ( int c );
② 介绍:

1.传入的参数如果是小写字母( 值为对应的ASCII码值 ),就将其转换成大写字母否则就不进行任何转换

2.返回值以 int 值的形式返回,该值可以隐式转换为 char

3.该函数定义在 <ctype.h> 头文件中。

③ 示例:

代码示例

#include<stdio.h>

#include<ctype.h>
int main()
{
	//toupper()的应用

	int i = 0;
	char str[] = "Test String.\n";
	char c;
	while (str[i])
	{
		c = str[i];
		putchar(toupper(c));
		i++;
	}

	/*
	*	TEST STRING.
	*/

	return;
}

解释说明

1 传入的参数如果是小写字母( 值为对应的ASCII码值 ),就将其转换成大写字母如果是其他字符就不进行任何转换

2 putchar 用来打印字符


12 memcpy()

12.1 函数原型

用来处理不重叠的内存拷贝。

void* memcpy(void* destination, const void* source, size_t num);

12.2 介绍

1.函数 memcpysource 的位置开始向后复制 num 个字节的数据到 destination 的内存位置。

2.这个函数在遇到 \0 的时候并不会停下来

3.如果 sourcedestination 有任何的重叠,复制的结果都是都是未定义的。(用来处理不重叠的内存拷贝)

4.函数返回目标空间的起始地址

12.3 示例

代码示例

#include<stdio.h>

#include<string.h>
struct
{
	char name[40];
	int age;
}person, person_copy;
int main()
{
	//memcpy()的应用
    
	char my_name[] = "Pierre de Fermat";

	//using memcpy to copy string:
	memcpy(person.name, my_name, strlen(my_name) + 1);
	person.age = 46;

	//using memcpy to copy structure:
	memcpy(&person_copy, &person, sizeof(person));

	printf("person_copy: %s, %d\n", person_copy.name, person_copy.age);
	//person_copy: Pierre de Fermat, 46

	return 0;
}


13 memmove()

13.1 函数原型

内存移动,可处理重叠的内存拷贝。

void* memmove(void* destination, const void* source, size_t num);

13.2 介绍

1.该函数与 memove 的差别就是本函数处理的源内存块和目标内存块可以是重叠的

2.如果源空间和目标空间出现重叠,就得使用 memove 函数处理

13.3 示例

代码示例

#include<stdio.h>

#include<string.h>
int main()
{
	//memmove()的应用

	char str[] = "memmove can be very useful......";
	memmove(str + 20, str + 15, 11);//str[15] = v(very),str[20] = u(useful);

	puts(str);//memmove can be very very useful.

	return 0;
}


14 memcmp()

14.1 函数原型

比较两个内存块

int memcmp(const void* ptr1, const void* ptr2, size_t num);

14.2 介绍

1.比较从 ptr1ptr2 指针开始的 num 个字节。

2.返回值:

return valueindicates
>0ptr1大于ptr2
=0ptr1等于ptr2
<0ptr1小于ptr2

14.3 示例

代码示例

#include<stdio.h>

#include<string.h>
int main()
{
	//memcmp()的应用

	char buffer1[] = "DWgaotP12df0";
	char buffer2[] = "DWGAOTP12DF0";

	int n = memcmp(buffer1, buffer2, sizeof(buffer1));

	if (n > 0)
	{
		printf("'%s' is greater than '%s'.\n", buffer1, buffer2);//g>G
	}
	else if (n < 0)
	{
		printf("'%s' is less than '%s'.\n", buffer1, buffer2);
	}
	else
	{
		printf("'%s' is the same as '%s'.\n", buffer1, buffer2);
	}

	return 0;
}


总结:

  本节介绍了C语言中常见的字符函数与字符串函数;同时给出了使用示例。


感谢您的阅读!如有任何错误,欢迎您的批评指正!

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言进阶高级编程PDF》是一本以C语言为主题的进阶级别编程书籍,旨在帮助读者提升C语言编程水平并掌握更高级的编程技巧和思维方式。 该PDF书籍的内容包括但不限于以下几个方面: 1. 数据结构与算法:介绍了常用数据结构(如链表、栈、队列、树等)的实现原理和使用方法,以及一些常见算法(如排序、查找等)的实现。 2. 指针与内存管理:探讨了指针的概念、指针和数组、指针和函数等相关内容,以及如何进行动态内存管理和资源释放。 3. 文件操作:介绍了C语言中对文件的读写操作方法,包括文件的打开、写入、读取和关闭等。 4. 高级函数和宏:介绍了C语言中的函数指针、回调函数、宏定义等高级编程技巧,以及如何利用宏定义提高代码的可读性和可维护性。 5. 库函数和系统调用:详细介绍了C语言标准库函数和一些系统调用的使用方法,如字符串处理函数、数学函数、时间函数等。 6. 多线程和进程:探讨了C语言中多线程和进程的概念和使用方法,包括线程的创建与同步、进程的创建与间通信等。 通过阅读《C语言进阶高级编程PDF》,读者可以拓宽自己的C语言知识面,学习更高级和更复杂的编程技巧,提升自己在C语言编程方面的能力和应用水平。无论是对于初学者还是有一定经验的C语言开发者来说,这本书都是一本很有价值的参考资料。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值