(九十五)函数与C-风格字符串

简介:

当传递给函数的是C-风格字符串时,和将数组传递给函数类似。

但传递C-风格字符串给函数时,首先是代码:

char a[10] = "abcdef";

char *b = a;

函数原型:char abc(char* a,int m); //m是字符串长度,非必须

这个时候,将字符串传递给函数的时候,

参数有三种形式:

①abc(a); //这种方式是将字符串作为参数

abc(b); //这种方式是将指向字符串的指针作为参数

③abc("abcdef"); //这种方式是将字符串常量作为参数

 

①和②优点,是可以通过指针或字符串(此时字符串是地址)作为参数,然后直接修改字符串内容。

③的优点,是直接传递的常量(注意,这个时候传递的不是字符串a)。

 

其中①和②是可以修改的,③是不能修改字符串的。假如要禁止字符串的修改,那么在函数原型和函数头加上const关键字,并相应在其他地方加上const关键字。

 

字符串作为地址时,实际上是字符串第一个字符的内存地址。

 

如代码:

#include<iostream>
using namespace std;
char abc(char* a);		//函数abc,返回值为char类型

int main()
{
	char a[10] = "abcdef";	//创建字符串a
	char *b = a;	//创建指针b指向数组a
	char c=abc(b);	//调用函数b,实参为指针b,返回值赋值给char变量c
	cout << a << endl;	//打印字符串a
	cout << c << endl;	//打印字符c(是abc函数返回值)
	system("pause");
	return 0;
}

char abc(char* a)
{
	for (; *a!=0;a++)	//指针不断偏移,直到遇见空字符0。也可以写为*a !='\0'
		*a = 'h';	//给指针指向的地址赋值字符h
	a--;	//因为这个时候指针指向的是空字符,所以往回偏移一个char距离
	return *a;
}

输出:


hhhhhh
h
请按任意键继续. . .

字符串和char数组的区别:

字符串和char数组的最大区别是,字符串的最后有结束字符(“\0”,ASCII值为0),而不以其为结尾的,则是char数组。

 

假如不写完,就容易导致有问题,例如:输出字符串的时候,输出的是烫(貌似烫是因为乱码)。

 

用函数返回字符串:

用函数返回字符串的方法,是将函数制作为指针函数。

例如函数头:char *abc(int*m,int n);

这个时候,abc是函数名,int*m是实参传递的字符串地址,int n是字符串的宽度。如代码:

#include<iostream>
using namespace std;

char *hanshu(char*m, const int n);

int main()
{
	char m[4] = "mab";
	char *f = hanshu(m, 4);	//调用函数hanshu,参数分别为字符串m的第一个字符的地址,和字符串长度4
	cout << m << endl;	//输出第一个字符串
	cout << f << endl;	//输出第二个字符串
	system("pause");
	return 0;
}

char *hanshu(char*m, const int n)	//char指针函数
{
	char *x = new char[n];	//new一个字符串x,长度为传递的参数n
	char a = m[0];	//字符a为传递的地址m所指向地址(char类型)的值,是参数指向地址(字符串mab)的第一个字符,即m
	for (int i = 0;i < n - 1;x++,i++)
		*x = a;	//偏移指针,并赋值为字符变量a的值(m)
	*x = '\0';	//最后一个位置填上'\0'字符
	x = x - n + 1;	//再把指针移回去
	return x;	//返回指针位置,即字符串第一个字符的位置
}

输出:


mab
mmm
请按任意键继续. . .

总结:

①函数可以返回地址(像声明指针那样)。

 

②函数不能在返回地址的时候同时返回字符串的长度(但可以通过给字符串指定位置赋值'\0'字符)

 

③也可以在new字符串之后,不能忘记字符串的结尾是\0,否则会出问题。

可以这样,如代码:

char *hanshu(char*m, int n)	//char指针函数
{
	char c = *m;
	char *a = new char[n+1];	//+1是空字符,不然下面的都要相应-1
	a[n] = '\0';	//n=4时,n+1=5个成员,a[4]是第五个成员,是空字符
	while (n-- >0)
		a[n] = c;	//这里是上面已经n-1之后的值,例如上面n=1时,n-->0,然后n=0,于是a[n]是a[0]
	return a;	//返回指针位置,即字符串第一个字符的位置
}

函数与字符串总结:

①字符串的结尾是" \"

 

②假如是void 变量名(char*指针, int 字符串长度);

传递的参数是指针,不能直接通过指针修改字符串,只能通过例如:指针名[0]这样,逐个修改字符。

如代码:

char word[4] = "mab";
hanshu(word);
void hanshu(char*m)	//char指针函数
{
	m[0] = 'c';
	m[1] = 'c';
	m[2] = 'c';
}

这样来修改字符串。或者使用wihle或者for循环,循环更新使用例如m++这样来移动指针。

因为需要逐个修改字符,所以有必要引入字符串长度,正如②的第一行那么写。在函数内,可以像以上代码那样逐个修改,也可以使用循环for或者while进行修改。

至于为什么需要逐个修改字符,不能一次直接修改,不知道……猜测是因为指针类型是char*,所以不能一次修改。

 

③假如是有返回值的字符串变量,返回值通常为指针地址——非指针地址情况参照(4);

注意,字符串应以空字符结尾。

有几种情况:

1)在函数内使用char 变量名[字符串长度]

由于字符串长度要求是常量,即使函数头传递的参数被const所限定,也是不能使用的,只能直接输入数字。所以这个办法——×

 

2)在函数内使用char *指针名 = new char[字符串长度]

这种情况下,字符串长度可以为函数头传递的参数,并且,不需要一定使用const进行限定。如函数头:char *指针名(int 变量名) 这样的。当然,也可以是char *指针名(const int 变量名)  这样的,这个办法——√

 

④函数头:void开头——无返回值;

char *开头,有返回值,返回值为 指针 或 函数内被static限定的字符串名;

 

⑤函数头传递的参数:

通常有(1int类型的字符串长度;(2char*类型的指针名/字符串名等;

 

需要函数读取传递的参数(如字符,或者指针),来作为新字符串的字符的话,在函数头使用 指针、字符串名、或者字符 作为参数。

如:char *指针名( char 变量名, int 字符串长度) ;

也可以将char 变量名改为char*指针名 或 char 字符串名[] 等。

 

⑥返回值,有以下几种情况:

无返回值——函数头使用void,函数往往是通过传递的指针地址来修改字符串。

有返回值——函数头使用char*字符串(传递的参数),返回值为指针名 或 被static限定的字符串名。通过返回值的地址,来修改字符串。

 

⑦函数本身:

修改原有字符串:需要让指针/字符串名作为传递的参数,然后逐个修改字符串的每个成员。

创建新字符串:需要传递字符串长度(除非默认字符串长度为固定值),返回值为指针名(因为函数头不能为字符串名,即char 字符串名[字符串长度](传递的参数)——应该吧),因此,函数内部也不能把字符串名作为返回值(因为函数执行完后,临时变量会被删除,而new指针指向的地址不会被删除)。

——但是若用static关键字 限定 字符串名,则可以用字符串名作为新字符串的返回值。如代码:

#include<iostream>
using namespace std;
 
char *abc(int);

int main()
{
	int a = 5;
	char *b = abc(a);
	cout << b << endl;
	system("pause");
	return 0;
}

char *abc(int m)
{
	char *a = new char[m];
	a[--m] = '\0';
	while (m-- > 0)
		a[m] = 'a';
	static char c[4];
	for (int i = 0;i < 3;i++)
		c[i] = a[i];
	c[3] = '\0';
	return c;
}


输出:


aaa
请按任意键继续. . .


目录
相关文章
|
5月前
|
程序员 编译器 C语言
C++风格与C风格类型强转异同
C++风格的强转: C++强制类型转换 C风格的强制类型转换很容易理解,不管什么类型都可以直接进行转换,使用格式如下: 目标类型 b = (目标类型) a; C++也是支持C风格的强制类型转换,但是C风格的强制类型转换可能会带来一些隐患,出现一些难以察觉的问题,所以C++又推出了四种新的强制类型转换来替代C风格的强制类型转换,降低使用风险。 在C++中,新增了四个关键字static_cast、const_cast、reinterpret_cast和dynamic_cast,用于支持C++风格的强制类型转换。 C++风格的强制类型转换能更清晰的表明它们要干什么,程序员只要看一眼这样的代码,立即
66 0
|
2月前
|
C++ 索引
C++系列十五:字符串
C++系列十五:字符串
|
4月前
|
IDE 程序员 开发工具
Python 进阶指南(编程轻松进阶):十一、注释、文档字符串和类型提示
Python 进阶指南(编程轻松进阶):十一、注释、文档字符串和类型提示
32 0
|
9月前
|
JavaScript 前端开发
js正则表达式的作用及使用方法
js正则表达式的作用及使用方法
77 1
|
4月前
|
XML JavaScript 前端开发
使用 doscify 将文章写成文档一般丝滑
使用 doscify 将文章写成文档一般丝滑
56 0
|
5月前
|
前端开发
【前端学习】—箭头函数和普通函数的区别(十四)
【前端学习】—箭头函数和普通函数的区别(十四)
|
11月前
|
机器学习/深度学习 搜索推荐 算法
编程艺术 - 第二章 、俩个字符串是否包含问题以及扩展
编程艺术 - 第二章 、俩个字符串是否包含问题以及扩展
47 0
语法着色控件使用典型范例
语法着色控件使用典型范例
58 0
|
JavaScript
细读 ES6 | 模板字符串进阶用法
细读 ES6 | 模板字符串进阶用法
350 0
|
设计模式 JSON 运维
代码荣辱观-以运用风格为荣,以随意编码为耻
代码荣辱观-以运用风格为荣,以随意编码为耻