0
点赞
收藏
分享

微信扫一扫

字符串操作函数使用及实现

幸福的无所谓 2022-03-25 阅读 76

文章目录

1.gets

char* gets(char*str)
作用:从标准输入(stdin)读入一个字符串,保存在str指向的内存空间里面
返回值:如果读入成功,返回一个char *类型的指针,指向读入字符串的的首元素
注意gets可以读入空格,scanf不能

#include<stdio.h>
#include<stdlib.h>
int main()
{
	char* p = (char*)malloc(10 * sizeof(char));
	gets(p);
	printf("%s", p);
	free(p);
	p = NULL;
	return 0;
}

可以读入空格在这里插入图片描述
gets函数的返回值是读入的字符串首元素的地址

int main()
{
	char* p = (char*)malloc(10 * sizeof(char));
	char*tmp=gets(p);//输入abc def
	printf("%s", tmp);//输出abc def
	free(p);
	p = NULL;
	return 0;
}

在这里插入图片描述

2.fgets

char * fgets(char *str,size_t size,FILE *stream)
作用:从stream指定的文件中获取字符,读入到str指向的内存中,读取一行或者读到文件末尾或者读取了size-1个字符就结束
参数:可以理解为第一个参数是目的地,stream指向的文件是源头,把源头的内容复制到目的地,但是源头的内容还在,没有丢失。size_t size是一次最多能够从源头搬运的字符个数
返回值:读取成功返回读取的字符串,读取失败返回空指针。

#include<stdio.h>
#include<string.h>
#include<errno.h>
int main()
{
	FILE*p=fopen("123.txt", "r");
	char arr[100] = { 0 };
	if (!p)
	{
		printf("%s", strerror(errno));
	}
	else
	{
		fgets(arr, 100, p);
		printf("%s", arr);
	}
	fclose(p);
	p = NULL;
	return 0;
}

在这里插入图片描述

可以看到,fgets只能从文件中读取一行放到字符串中,如果文件有多行,还会读取换行
fgets不仅可以从文件中读取,还可以从键盘(stdin)中读取

int main()
{
	char arr[20] = { 0 };
	fgets(arr, 19, stdin);
	printf("%s", arr);
	return 0;
}

在这里插入图片描述
从键盘中读取的时候,会读取空格和换行
在这里插入图片描述
这里定义arr[20],但是最多只能读取19个字符,准确来说是从键盘读取18个字符,因为我们通常意识不到’\n’ ,最多只能读取19个字符的原因是arr的第20个空间要存放’\0’ ,所以把size_t size 设置为19

3.puts

int puts(const char*str)
作用:将str指向的字符串打印在标准输出流(屏幕,stdout)上。
参数:参数中的 *str被const修饰,这个const的作用是防止str指向的内容被更改,我们只是想要打印str指向的内容,并不想让str指向的内容更改,所以使用了const修饰
返回值:puts()函数若输出失败会返回-1,输出成功随机返回一个非负数,即输出成功会返回0或者正数

int main()
{
	char arr[20] ="asdfg";
	puts(arr);
	return 0;
}

在这里插入图片描述
puts(arr)在输出的时候,会在后面自动加上一个’\n’换行

int main()
{
	char arr[20] ="asdfg";
	int a=puts(arr);
	printf("%d", a);
	return 0;
}

输出成功,返回0或者正数
在这里插入图片描述

4.fputs

int fputs(const char*str,FILE *stream )
作用:将str指向的字符串写到stream指向的文件中
这里将fputs与fgets做对比,fputs是把字符串写到文件中去,而且没有写入的数量限制。而fgets是把文件中的字符串读出来,读到一个数组中,有数量限制,fgets函数的第二个参数限制读出的数量,这是因为数组的空间是有限的,如果把文件中的内容全部fgets读到数组中,数组有可能存不下,所以我们要用第二个参数限制从文件中读出来的字符的数量。但是对于fputs而言,是把数组中的字符往文件里面放,不会出现把文件放满的情况,所以fputs只有2个参数,不必对字符数量作出限制
在这里插入图片描述

#include<stdio.h>
#include<string.h>
#include<errno.h>
int main()
{
	FILE*p=fopen("test.txt", "w");
	char arr[15] = "asdfghjkl";
	fputs(arr,p);
	fclose(p);
	p = NULL;
	return 0;
}

在这里插入图片描述
fputs将字符串中的内容写入了文件,如果想要分2行写入,只需要在字符串中添加’\n’

#include<stdio.h>
#include<string.h>
#include<errno.h>
int main()
{
	FILE*p=fopen("test.txt", "w");
	char arr[30] = "asdfghjkl\nasdfghjkl";
	fputs(arr,p);
	fclose(p);
	p = NULL;
	return 0;
}

在这里插入图片描述
注意如果多次使用fputs向文件中写入的话,后一次写入的内容会覆盖前面一次写入的内容
fputs也可以直接把字符串写入屏幕

#include<stdio.h>
#include<string.h>
#include<errno.h>
int main()
{
	char arr[30] = "asdfghjkl\nasdfghjkl";
	fputs(arr,stdout);
	return 0;
}

在这里插入图片描述
fputs的返回值:成功写入返回0,失败返回-1

int main()
{
	FILE*p=fopen("test.txt", "w");
	char arr[30] = "asdfghjkl\nasdfghjkl";
	int a=fputs(arr,p);
	fclose(p);
	p = NULL;
	printf("a=%d", a);
	return 0;
}

在这里插入图片描述
这些字符串操作相关的函数,如果返回值是int,那么操作失败的话貌似都是返回-1;如果返回值是char* ,那么操作失败的话返回NULL

5.strcpy

char* strcpy(char *dest ,const char * src)
作用:把源头的字符串拷贝到目的地里面去,注意这里的src用const修饰

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[15] = "############";
	char arr2[10] = "asdfg";
	strcpy(arr1, arr2);
	printf("%s", arr1);
	return 0;
}

在这里插入图片描述
在这里插入图片描述
我们看到arr2在strcpy到arr1的时候,把’\0’也复制了过去,还要注意一点,arr2后面应该是有5个’\0’ ,但是只复制了一个过去
在这里插入图片描述
使用strcpy时 ,要注意目的地的长度大于源头的长度,不能出现把源头复制到了目的地以后,dest中没有位置可以放’\0’了。
strcpy函数的实现:

#include<stdio.h>
#include<string.h>
#include<assert.h>
char* mystrcpy(char* dest, const char* src)
{
	assert(dest != NULL && src != NULL);
	char* tmp = dest;
	while (*dest++ = *src++)
	{
		;
	}
	return tmp;
}
int main()
{
	char arr1[15] = "############";
	char arr2[10] = "asdfg";
	mystrcpy(arr1, arr2);
	printf("%s", arr1);
	return 0;
}

6.strncpy

char* strncpy(char* dest ,char *src,size_t n)
作用:把src中的n个字符复制到dest中,任然要保证dest的大小大于src

int main()
{
	char arr1[15] = "############";
	char arr2[10] = "asdfg";
	strncpy(arr1, arr2,3);
	printf("%s", arr1);
	return 0;
}

在这里插入图片描述

int main()
{
	char arr1[15] = "############";
	char arr2[10] = "asdfg";
	strncpy(arr1, arr2,7);
	printf("%s", arr1);
	return 0;
}

在这里插入图片描述
注意拷贝了2个’\0’到str1中
在这里插入图片描述

int main()
{
	char arr1[20] = "#################";
	char arr2[10] = "asdfg";
	strncpy(arr1,arr2,12);
	printf("%s", arr1);
	return 0;
}

在这里插入图片描述
在这里插入图片描述
arr2里面只有10个字符,强行拷贝12个字符给arr1,发现arr1的第10个元素和第11个元素都变成了’\0’ ,说明在使用strncpy时,如果size_t n大于src中原有的元素个数,那么strncpy不仅会把src中的内容拷贝到dest,还会在补上n-sizeof(src)/sizeof(src[1])个’\0’

strncpy函数的实现

#include<stdio.h>
#include<string.h>
#include<assert.h>
char* mystrncpy(char* dest, const char* src, size_t n)
{
	assert(dest && src);
	int i = 0;
	char* tmp = dest;
	for (i = 0;i<n; i++)
	{
		if (*src)
		{
			*dest = *src;
			src++;
			dest++;
		}
		else
		{
			*dest = '\0';
			dest++;
		}
	}
	return tmp;
}
int main()
{
	char arr1[20] = "#################";
	char arr2[10] = "asdfg";
	mystrncpy(arr1,arr2,12);
	printf("%s", arr1);
	return 0;

这是一种实现方法,但是这个方法有一个bug,如果char arr2[10] = { ‘a’,‘s’,’\0’,‘d’,‘f’,‘g’,’\0’,’\0’,’\0’,’\0’ };的话,后面的"dfg"就不能拷贝到arr1中.而且这个实现方法并没有考虑到拷贝失败返回NULL的问题
如图:

#include<stdio.h>
#include<string.h>
#include<assert.h>
char* mystrncpy(char* dest, const char* src, size_t n)
{
	assert(dest && src);
	int i = 0;
	char* tmp = dest;
	for (i = 0;i<n; i++)
	{
		if (*src)
		{
			*dest = *src;
			src++;
			dest++;
		}
		else
		{
			*dest = '\0';
			dest++;
		}
	}
	return tmp;
}
int main()
{
	char arr1[20] = "#################";
	char arr2[10] = { 'a','s','\0','d','f','g','\0','\0','\0','\0' };
	mystrncpy(arr1,arr2,12);
	printf("%s", arr1);
	return 0;
}

在这里插入图片描述
在这里插入图片描述

来看一下标准的strcpy函数能不能解决这个问题

int main()
{
	char arr1[20] = "#################";
	char arr2[10] = { 'a','s','\0','d','f','g','\0','\0','\0','\0' };
	strncpy(arr1,arr2,12);
	printf("%s", arr1);
	return 0;
}

在这里插入图片描述
貌似也不行。
原因在于strncpy的参数只有dest ,src和size_t n .没有传字符串的长度进去,strncpy认为只要src指到’\0’了,那么就到终点了,所以也就不能把’dfg’拷贝过去

7.strcat

字符串追加函数
char* strcat(char* dest ,const char* src)
作用:把src字符串追加到dest后面

int main()
{
	char arr1[11] = "asdfg";
	char arr2[10] = "12345";
	printf("%s", strcat(arr1, arr2));
	return 0;
}

在这里插入图片描述
arr2追加到arr1中,是到arr2中的第一个’\0’就停止了,并不会把arr2后面的所有的’\0’都追加到arr1中,否则上例中arr1[11]就溢出了。具体如下:

int main()
{
	char arr1[11] = "asd";
	char arr2[5] = { 'w','e','\0','r','\0' };
	strcat(arr1, arr2);
	return 0;
}

上面例子中arr2中的’r’就没有被追加到arr1中去
在这里插入图片描述

一般这种字符串操作函数,只认第一个’\0’ ,第一个’\0’后面是什么,这些函数都不会考虑

strcat函数的实现:

#include<stdio.h>
#include<string.h>
#include<assert.h>
char* mystrcat(char* dest, const char* src)
{
	assert(dest && src);
	char* tmp = dest;
	while (*dest)
	{
		dest++;
	}
	while (*dest++ = *src++)
	{
		;
	}
	return tmp;
}
int main()
{
	char arr1[11] = "asd";
	char arr2[5] = "wert";
	printf("%s", mystrcat(arr1, arr2));
	return 0;
}
举报

相关推荐

0 条评论