【C语言】:字符串函数超详解(10个最重要函数)

目录

一、strlen函数

1.strlen函数的使用

2.⚠strlen函数使用时的注意事项

3.strlen函数的模拟实现

二、strcpy函数

1.strcpy函数的使用

2.⚠strcpy函数使用时的注意事项

3.strcpy函数的模拟实现

三、strcat函数

1.strcat函数的使用

2.⚠strcat函数使用时的注意事项

3.strcat函数的模拟实现

四、strcmp函数

1.strcmp函数的使用

2.strcmp函数的模拟实现

五、strncpy函数

1.strncpy函数的使用

2.strcpy函数与strncpy函数比较

3.strncpy函数的模拟实现

六、strncat函数

1.strncat函数的使用

2.strncat函数与strcat函数比较

3.strncat函数使用时的注意事项

4. strncat函数的模拟实现

七、strncmp函数

1.strncmp函数的使用

 2.strncmp函数与strcmp函数比较

八、strstr函数

1.strstr函数的使用

2.strstr函数的模拟实现

九、strtok函数

1.strtok函数的使用

2.strtok函数的改进 

3.⚠strtok函数使用时的注意事项 

十、strerror函数

1.strerror函数的使用

2.附加:perror函数


一、strlen函数

1.strlen函数的使用

size_t strlen ( const char * str );

  • 字符串以 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包 含 '\0' )。
  • 参数指向的字符串必须要以 '\0' 结束。
  • 注意函数的返回值为size_t,是无符号的( 易错 )
  • strlen函数使用时需要包含头文件 <string.h>

下面给大家展示一下最简单的strlen函数的实现

//strlen函数的使用
#include<string.h>
int main()
{
	char arr[] = "abcdef";
	size_t len = strlen(arr);
	printf("%zu", len);

	return 0;
}

解释:arr数组里存放的是字符串“abcdef\0”,strlen计算的是‘\0’之前的字符的个数,所以strlen计算出来的结果就是6.

2.⚠strlen函数使用时的注意事项

1.返回值类型:size_t

size_t是无符号整型,这里要注意的是不能使用%d来打印strlen返回值,否则可能报警告

我们可以看到如果我们这里使用%d来打印它就报警告显示size_t转换到int可能丢失数据

2.strlen与sizeof的比较

函数作用示例
strlen计算‘\0’之前字符的个数(不包含‘\0’)

strlen(“abcde”)

输出结果:5

sizeof计算数组(字节)/字符串个数(包含‘\0’)

sizeof(“abcde”)

输出结果:6

strlen函数使用时的误区:

这里给大家一段代码,大家思考一下它的输出结果是什么?

//strlen函数使用时的误区
#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = "abcd";
	char arr2[] = "abcdef";

	if (strlen(arr1) - strlen(arr2) > 0)
		printf("arr1>arr2\n");
	else
		printf("arr1<arr2\n");

	return 0;
}

这里我们明显看到arr1数组的元素个数要比arr2数组的元素个数要少,那么打印结果就是arr1<arr2咯?实践出真知,我们运行来看一下

这与我们分析的结果恰恰相反,可这是为什么呢?大家可以回归到上面的strlen函数使用时的注意事项,strlen函数的返回值类型是size_t,是一个无符号整型,那这里strlen(arr1)-strlen(arr2)可能是一个负数吗?很显然是不可能的,这里给大家解释一下:

按照正常逻辑 strlen(arr1)-strlen(arr2)计算出的结果是-2,而strlen的返回值类型是无符号整型,那么这里的-2要被当作无符号整型来处理,那怎么处理呢?

-2的二进制原码:10000000 00000000 00000000 00000010

-2的二进制反码:111111111 111111111 111111111 111111101

-2的二进制补码:111111111 111111111 111111111 111111110

这里编译器要把-2当作无符号整型时,就会把-2的二级制的补码当作它的原码,所以这里strlen(arr1)-strlen(arr2)的二进制值为111111111 111111111 111111111 111111110可见是一个非常大的数,所以这里打印出来的结果恰恰与我们分析的相反

那如果我们非要通过作差来写这个代码呢?我们应该如何去写?

//改善后
#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = "abcd";
	char arr2[] = "abcdef";

	if ((int)strlen(arr1) - (int)strlen(arr2) > 0)
		printf("arr1>arr2\n");
	else
		printf("arr1<arr2\n");

	return 0;
}

这里我就是通过强制类型转换来实现的,我们把size_t强制转化为int类型,而int是有符号整型,这里就不会出现上面一样的错误了,但是这里还是要强调一下,我们尽量不要去强制类型转化,因为又是强制类型转化可能导致数据的丢失。

3.strlen函数的模拟实现

方法一:计数器

//strlen函数的模拟实现
//方法一:计数器
//int my_strlen(const char*str)
//{
//	int count = 0;
//	while (*str)
//	{
//		count++;
//		str++;
//	}
//	return count;
//}

//int main()
//{
//	char str[] = "abcdef";
//	int r = my_strlen(str);
//	printf("%d", r);
//	return 0;
//}

方法二:指针-指针

//方法二:指针-指针
//int my_strlen(char* str)
//{
//	assert(str);
//	char* p = str;
//	while (*p != '\0')
//	{
//		p++;
//	}
//	return p - str;
//}

//int main()
//{
//	char str[] = "abcdef";
//	int r = my_strlen(str);
//	printf("%d", r);
//	return 0;
//}

方法三:递归(不创建临时变量的前提下):

//方法四:递归
//不能在函数内部创建临时变量,求字符串的长度
//size_t my_strlen(const char* str)
//{
//	assert(str);
//	if (*str != '\0')
//		return 1 + my_strlen(str + 1);
//	else
//		return 0;
//}

//int main()
//{
//	char str[] = "abcdef";
//	size_t r = my_strlen(str);
//	printf("%zu", r);
//	return 0;
//}

二、strcpy函数

1.strcpy函数的使用

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

  •  源字符串必须以 '\0' 结束。
  • 会将源字符串中的 '\0' 拷贝到目标空间。
  • 目标空间必须足够大,以确保能存放源字符串。
  • 目标空间必须可修改。
  • strcpy函数使用时需要包含头文件<string.h>

参数说明: char * destination是目标地址,const char * source是源头地址,strcpy函数的返回值类型是一个地址(指针)

 下面给大家展示一下最简单的strcpy函数的实现

//strcpy
#include<string.h>
int main()
{
	char arr1[] = "abcdef";
	char arr2[20] = { 0 };
	strcpy(arr2, arr1);
	printf("%s\n", arr2);
	return 0;
}

解释:strcpy(arr2,arr1)就是要把arr1数组里面的内容(包含‘\0’)拷贝到arr2里面.

2.⚠strcpy函数使用时的注意事项

1.源字符串里必须以‘\0’结尾:

如果源头数组里都没有‘\0’,那么到底要拷贝多少元素到数组arr2里面呢?

2.源字符串中的‘\0’也会拷贝到arr2数组里。

3.目标空间足够大:

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

4.目标空间必须可修改:

目标空间肯定是会被修改的,因为要把arr1数组里的内容拷贝进去,所以不能用const修饰arr2,但是可以用const来修饰arr1,来确保arr1数组里的内容不被修改。

3.strcpy函数的模拟实现

#include<stdio.h>
#include<assert.h>
#include<string.h>
char* my_strcpy(char* des, const char* src)
{
	char* ret = des;
	assert(des && src);
	while (*des++=*src++)
	{
		;
	}
	return ret;
}

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

补充:assert断言,它的作用是用来检测是否有误,如果有错误,就会报错,并且会把错误的地方和原因呈现出来,如果没有错误,则这句语句就跳过。assert需要包含头文件<assert.h>


三、strcat函数

1.strcat函数的使用

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

  • 源字符串必须以 '\0' 结束。
  • 目标字符串中也得有 \0 ,否则没办法知道追加从哪里开始。
  • 目标空间必须有足够的大,能容纳下源字符串的内容。
  • 目标空间必须可修改。
  • strcat函数使用时需要包含头文件<string.h>

参数说明: char * destination是目标地址,const char * source是源头地址,strcat函数的返回值类型是一个地址(指针)

 下面给大家展示一下最简单的strcat函数的实现 

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[20] = "Hello";
	char arr2[] = "world";
	char*r=strcat(arr1, arr2);
	printf("%s\n", arr1);
	printf("%s\n", r);
	return 0;
}

 

2.⚠strcat函数使用时的注意事项

 1.源字符串必须以 '\0' 结束:不然拼接接到哪里为止不知道

 2.目标字符串中也得有 \0:否则没办法知道追加从哪里开始拼接

 3.目标空间必须有足够的大:这样目标字符串才能容得下拼接过后两个字符串长度的和

 4.目标字符串必须为可修改的:这样strcat才有效果,源字符串可以添加const修饰

#include<stdio.h>
#include<string.h>
#include<assert.h>
char* mystrcat(char* arr1, const char* arr2)
{
    assert(arr1 && arr2);
    char* p = arr1;
    while (*arr1)
    {
        arr1++;
    }

    while ((*arr1++ = *arr2++))
    {
        ; 
    }
    return p;
}

int main()
{
    char arr1[20] = "hello";
    char arr2[] = "world";
    char* ret = mystrcat(arr1, arr2);
    printf("%s", ret);

    return 0;
}

3.strcat函数的模拟实现

#include<stdio.h>
#include<assert.h>
 
char* mystrcat(char* arr1, const char* arr2)
{
	assert(arr1 && arr2);
	char* p = arr1;
	while (*arr1)
	{
		arr1++;
	}//找到目标字符串中的\0,明确从那里开始追加。
	while ((*arr1++ = *arr2++))
	{
		;
	}
	return p;
}
int main()
{
	char arr1[20] = "hello";
	char arr2[] = "world";
	char* ret = mystrcat(arr1, arr2);
	printf("%s", ret);
	return 0;
}

四、strcmp函数

1.strcmp函数的使用

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

 参数说明和标准规定以及功能

const char*str1代表第一个字符串

const char*str2代表第二个字符串

返回值及规定:

返回值为int(整型)

如果第一个字符串大于第二个字符串,则返回值为大于0的数字

如果第一个字符串小于第二个字符串,则返回值为小于0的数字

如果第一个字符串等于第二个字符串,则返回值为等于0的数字

功能:用来比较str1和str2指向的字符串,从两个字符串的第一个字符开始比较,如果两个字符串的ASCALL码值相等,就继续比较下一个字符,直到遇到不相等的两个字符,或者字符串结束。

下面给大家展示一下最简单的strcmp函数的实现:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abq";
	int r = strcmp(arr1, arr2);
	if (r > 0)
		printf("arr1>arr2\n");
	else if(r<0)
		printf("arr1<arr2\n");
	else
		printf("arr1=arr2\n");
	return 0;
}

 

2.strcmp函数的模拟实现

#include<assert.h>
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;
}
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abc";
	int r = my_strcmp(arr1, arr2);
	if (r > 0)
		printf("arr1>arr2\n");
	else if (r < 0)
		printf("arr1<arr2\n");
	else
		printf("arr1=arr2\n");
	return 0;
}

五、strncpy函数

1.strncpy函数的使用

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

我们观察发现strncpy函数strcpy 函数的返回值一模一样,但是strncpy函数的函数参数比strcpy 函数参数多了一个,那这个参数的意义是什么呢?

  • 拷贝num个字符从源字符串到目标空间,最多拷num个。
  • 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。

这下大家应该对num参数的意义有了一定的了解了吧,那接下来我给大家展示一下最简单的strncpy函数的实现:

//strncpy
#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = "abcdefg";
	char arr2[20] = { 0 };
	strncpy(arr2, arr1, 5);
	printf("%s", arr2);
	return 0;
}

 那我们再思考一下如果拷贝时源字符串个数不够的话会怎么样呢?我们来做一个简单的测试

//strncpy
int main()
{
	char arr1[] = "abc";
	char arr2[] = "xxxxxxxxxxxxxxx";
	strncpy(arr2, arr1, 5);
	printf("%s", arr2);
	return 0;
}

我们打开监视窗口发现当源字符串不够5个元素时,这里他就会自动把‘\0’补充直到5个为止,那如果提前遇到‘\0’又会是怎样的?我们再来做个简单的测试,监视它看一下结果:

//strncpy
int main()
{
	char arr1[] = "abc\0def";
	char arr2[] = "xxxxxxxxxxxxxxx";
	strncpy(arr2, arr1, 5);
	printf("%s", arr2);
	return 0;
}

当提前遇到‘\0’时,strcpy就会当作源字符串已经结束了,就不会再拷贝'\0'后面的元素了,并且,不够的用'\0'来补充。

2.strcpy函数与strncpy函数比较

  • strcpy函数拷贝到'\0'为止,如果目标空间不够的话,容易出现越界行为
  • strncpy指定了拷贝元素的个数,源字符串不一定要有'\0',同时在设计参数的时候就会多一层思考:目标空间的大小是否够用。

总结: strncpy相对于strcpy函数更加安全

3.strncpy函数的模拟实现

#include<stdio.h>
#include<string.h>
#include<assert.h>
 
char* my_strncpy(char* arr1, const char* arr2, size_t num)
{
	assert(arr1 && arr2);
	char* p = arr1;
	int i = 0;
	for (i = 0;i < num && arr2[i];i++)
	{
		arr1[i] = arr2[i];
	}
	if (i < num)
	{
		arr1[i] = 0;
	}
	return p;
 
}
 
int main()
{
	char arr1[20] = { 0 };
	char arr2[] = "abcdefg";
	char* ret = my_strncpy(arr1, arr2, 3);
	printf("%s", ret);
	return 0;
}

六、strncat函数

1.strncat函数的使用

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

 我们这里通过比较strncat函数发现strncat函数又只是比strcat多了一个参数,那我们通过类比猜测这个参数是不是也是限制它所要拼接的长度呢?

  •  将source指向字符串的前num个字符追加到destination指向的字符串末尾,再追加一个 \0 字 符
  • 如果source指向的字符串的长度小于num的时候,只会将字符串中到 \0 的内容追加到destination指向的字符串末尾
  • 目标空间大小必须足够大

我们来看一个最简单的例子:

//strncat
int main()
{
	char arr1[] = "abcdefgh";
	char arr2[30] = "xxxxx";
	strncat(arr2, arr1, 3);
	printf("%s", arr2);
	return 0;
}

 

这是时候我们思考一下,源头的字符串中的'\0'会被拼接过来吗?这时候我们做个简单的测试来看一下:

//strncat
int main()
{
	char arr1[] = "abc";
	char arr2[30] = "xxxxx\0xxxxxxx";
	strncat(arr2, arr1, 3);
	printf("%s", arr2);
	return 0;
}

 通过监视窗口,我们发现源字符串中的‘\0’确实被拷贝过来了,但是如果我们拼接两个字符的话,那‘\0’还会被拼接过来了吗?

//strncat
int main()
{
	char arr1[] = "abc";
	char arr2[30] = "xxxxx\0xxxxxxx";
	strncat(arr2, arr1, 2);
	printf("%s", arr2);
	return 0;
}

 

通过监视窗口,我们发现当num的个数少于源头字符串元素个数时'\0'还是会被拼接过来。

那如果num>源字符串的个数时,会补更多的‘\0’吗?我们再来举个简单的例子:

//strncat
int main()
{
	char arr1[] = "abc";
	char arr2[30] = "xxxxx\0xxxxxxx";
	strncat(arr2, arr1, 5);
	printf("%s", arr2);
	return 0;
}

我们通过监视窗口可以看到, 当num>源字符串的个数时,它并不会补两个‘\0’,那么我们总结一下吧。

2.strncat函数与strcat函数比较

  • 参数不同,strnact多了一个参数,这个参数用来限制拼接的元素个数
  • 相对strcat函数而言,strnact更加灵活,也更加安全

3.strncat函数使用时的注意事项

总结:

  • 当num<源字符串个数时,末尾都会拼接个‘\0’
  •  当目标字符串中间有‘\0’,那么strncat就会从中间遇到的那个‘\0’开始拼接 
  • 当num>源字符串的个数时,它并不会补剩下空余的‘\0’,只会补一个‘\0’来结尾

4. strncat函数的模拟实现

#include<stdio.h>
#include<assert.h>
 
char* mystrncat(char* arr1, const char*arr2 , size_t num)
{
	assert(arr1 && arr2);
	char* p = arr1;
	while (*arr1)
	{
		arr1++;
	}

	for (int i = 0;arr2[i] && i < num;i++)
	{
		arr1[i] = arr2[i];
	}
	if (num < 0)
	{
		arr1[i] = 0;
	}
	return p;
}
int main()
{
	char arr1[20] = "hello";
	char arr2[] = "world";
	char* ret = mystrncat(arr1, arr2,3);
	printf("%s", ret);
	return 0;
}

七、strncmp函数

1.strncmp函数的使用

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

我们通过类比strncmp函数,发现strncmp函数返回值类型与strcmp函数返回值类型相同,但是strncmp函数的参数比strcmp函数参数多一个,我们类比上面两个函数,就可以知道这个num参数的作用就是限制字符串的个数 

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

规则:

如果第一个字符串大于第二个字符串,则返回值为大于0的数字

如果第一个字符串小于第二个字符串,则返回值为小于0的数字

如果第一个字符串等于第二个字符串,则返回值为等于0的数字

给大家展示一下最简单的strncmp函数的实现:

//strncmp
#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = "abcdefgh";
	char arr2[] = "abcdew";
	int r = strncmp(arr2, arr1, 6);
	if (r > 0)
		printf(">");
	else if(r<0)
		printf("<");
	else
		printf("=");
	return 0;
}

 

 2.strncmp函数与strcmp函数比较

  • 参数不同,可以比较任意长度了
  • 相对于strcmp函数,strncmp函数更加灵活,更加安全

八、strstr函数

1.strstr函数的使用

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

功能:strstr函数,查找str2指向的字符串在str1指针的字符串中第一次出现的位置。如果找到返回地址,找不到返回NULL

参数:str1指针,指向的被查找的字符串;str2指针,指向了要查找的字符串。

返回值:

  • 如果str1指向的字符串中存在str2指向的字符串,那么返回第一次出现位置的指针
  • 如果str1指向的字符串中不存在str2指向的字符串,那么返回NULL

strstr函数最简单的实现:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = "heheabcdefabcedf";
	char arr2[] = "def";
	char* p = strstr(arr1, arr2);
	if (p != NULL)
		printf("找到了,%s\n", p);
	else
		printf("没找到\n");
	return 0;
}

2.strstr函数的模拟实现

#include<stdio.h>
#include<string.h>
char* my_strstr(const char* str1, const char* str2)
{
	const char* p = str1;
	const char* s1 = NULL;
	const char* s2 = NULL;
	if (*str2 == '\0')
		return (char* )str1;
	while (*p)
	{
		s1 = p;
		s2 = str2;
		while (*s1 && *s1 && *s1 == *s2)
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
			return (char*)p;
		p++;
	}
	return NULL;
}
int main()
{
	char arr1[] = "heheabcdefabcedf";
	char arr2[] = "def";
	char* p = my_strstr(arr1, arr2);
	if (p != NULL)
		printf("找到了,%s\n", p);
	else
		printf("没找到\n");
	return 0;
}


九、strtok函数

1.strtok函数的使用

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

参数说明:

  • str:首次调用时传入带分割的字符串;后续调用传入NULL,表示继续分割同一个字符串。
  • sep:包含所有分隔符的字符串(例如:char sep[]="@*%",@ * %分别为3个分隔符符)

功能: 

  • 分割str字符串:根据sep字符串中特定的分隔符,分割str字符串为多个子字符串
  • 修改str字符串:strtok会直接在原始字符串中插入'\0'终止符,替换分隔符的位置,原始字符串就会被修改为多个子字符串。

使用规则:

  • 首次调用:传入待分割字符串和分隔符
  • 后续调用:传入NULL和相同的分隔符,继续分割
  • 结束条件:当返回NULL时,表示分割完成

strtok函数的最简单实现:

//strtok-->分割
#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = "asdfghjkl@qq.com";
	char del[] = "@.";
	char buf[20] = { 0 };
	strcpy(buf, arr);
	char* p = strtok(buf, del);
	printf("%s\n", p);            //asdfghjkl
	p = strtok(NULL, del);
	printf("%s\n", p);            //qq
	p = strtok(NULL, del);
	printf("%s\n", p);            //com
	p = strtok(NULL, del);
	printf("%s\n", p);            //(null)
	return 0;                   
}

 我们如果这样写代码的话,如果字符串中有1000个分隔符,那我们是不是就要写1000行这种代码?是不是有点太“傻”了,那怎么样改进一下这个代码呢?

2.strtok函数的改进 

//高级版
#include<stdio.h>
#include<string.h>
int main()
{

	char arr[] = "asdfghjkl@qq.com";
	char del[] = "@.";

	char buf[20] = { 0 };
	strcpy(buf, arr);

	char* p = NULL;
	for (p = strtok(buf, del); p != NULL; p = strtok(NULL, del))
	{
		printf("%s\n", p);
	}
	return 0;
}

大家看打印结果是不是一模一样的啊?

3.⚠strtok函数使用时的注意事项 

  • 在分割字符串的时候,会把字符串破坏,如果有的题目需要保留原字符串的话,我们就可以先用strcpy函数拷贝一份原字符串,在拷贝的那一份字符串中进行分割,这样更安全。
  • 当字符串中出现多个连在一起的分割符,系统会把这多个分隔符视为一个分隔符进行分割

十、strerror函数

1.strerror函数的使用

char* strerror ( int errnum );  

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

参数: 这个错误码一般传递的是error这个变量的值,在C语言中有一个全局变量叫:errno,当库函数的调用发生错误的时候,就会将本次错误的错误码存放在errno这个变量中。

返回值:函数返回通过错误码得到的错误信息字符串的首字符的地址。

#include <errno.h>
#include <string.h>
#include <stdio.h>
int main()
{
 int i = 0;
 for (i = 0; i <= 10; i++) {
 printf("%s\n", strerror(i));
 }
 return 0;
}

 

在Windows11+VS2022环境下输出的结果如下:

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

 strerror也可以打开文件,如果文件不存在的话就会显示错误信息:

#include<stdio.h>
#include<string.h>
#include<errno.h>
int main()
{
	//C语言可以打开文件
	//fopen
	//如果以已读的形式打开文件,文件是必须要存在的,如果文件不存在,则打开文件失败
	//fopen函数就会把错误码放在errno里
	//同时函数会返回NULL
	FILE* p = fopen("尺寸换米.exe", "r");
	if (p == NULL)
	{
		printf("%s\n", strerror(errno));
		return 1;
	}
	//读文件

	//关闭文件
	fclose(p);
	p = NULL;
	return 0;
}

这里就可以看到,当文件不存在的时候,编译器就会输出 No such file or directory表示文件不存在

2.附加:perror函数

也可以了解⼀下perror函数,perror函数相当于⼀次将上述代码中的第9行完成了,直接将错误信息 打印出来。perror函数打印完参数部分的字符串后,再打印一个冒号和一个空格,再打印错误信息。

//perror
#include<stdio.h>
#include<string.h>
#include<errno.h>
int main()
{
	//C语言可以打开文件
	//fopen
	//如果以已读的形式打开文件,文件是必须要存在的,如果文件不存在,则打开文件失败
	//fopen函数就会把错误码放在errno里
	//同时函数会返回NULL
	FILE* p = fopen("尺寸换米.exe", "r");
	if (p == NULL)
	{
		perror("exe");
		//exe:错误信息
	}
	//读文件

	//关闭文件
	fclose(p);
	p = NULL;
	return 0;
}

最终的输出结果和桑面的其实是一样的 

总结:到这里我给大家总结了10个最重要的字符串函数包括:strlen函数以及模拟实现、strcpy函数以及模拟实现、strcat函数以及模拟实现、strncpy函数以及模拟实现、strncat函数以及模拟实现、strncmp函数、strstr函数以及模拟实现、strtok函数以及改进、strerror函数,相信大家看了这篇文章能够有所收获,后续我还会分享更多的知识点,也欢迎大家能够进入我的主页浏览我写的文章,也欢迎在评论区留下你的问题,如果这篇文章对你有帮助的话,请给这篇文章点赞、收藏加关注,文章制作不易,谢谢大家的支持🌹🌹🌹

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值