C语言指针操作(七)通过指针引用字符串

这篇具有很好参考价值的文章主要介绍了C语言指针操作(七)通过指针引用字符串。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

通过指针引用字符串详解,以及字符指针变量和字符数组的比较、

在平常的案例中已大量地使用了字符串,如在 printf函数中输出一个字符串。这些字符串都是以直接形式 (字面形式) 给出的,在一对双引号中包含若干个合法的字符。在本节中将介绍使用字符串的更加灵活方便的方法:通过指针引用字符串

目录

一、字符串的引用方式

1.1引入

二、字符指针作函数参数

2.1举例说明

2.2程序改进

三、使用字符指针变量和字符数组的比较


一、字符串的引用方式

1.1引入

在 C 程序中,字符串是存放在字符数组中的。想引用一个字符串,可以用以下两种方法。

(1)用字符数组存放一个字符串,可以通过数组名和下标引用字符串中一个字符,也可以通过数组名和格式声明 “ %s ” 输出该字符串。

举例:定义一个字符数组,在其中存放字符串 " I love China! " ,输出该字符串和第8个字符。

#include <stdio.h>
int main()
{
	char string[] = "1 love China!";	//定义字符数组string
	printf("%s\n", string);				//用%s格式声明输出string,可以输出整个字符串
	printf("%c\n", string[7]);			//用%c格式输出一个字符数组元素
	return 0;
}

运行结果:

用指针输入字符串,C语言,c语言,c++,数据结构,算法,指针

程序分析:

用指针输入字符串,C语言,c语言,c++,数据结构,算法,指针

在定义字符数组 string 时未指定长度,由于对它初始化,因此它的长度是确定的,长度应为14,其中 13 个字节存放 " l love China! " 13个字符,最后一个字节存放字符串结束符 '\0'。数组名 string  代表字符数组首元素的地址。题目要求输出该字符串第 8 个字符,由于数组元素的序号从 0 起算,所以应当输出 string[7],它代表数组中序号 7 的元素的值(它的值是字母 C )。实际上 string[7] 就是 *(string+7),string+7 是一个地址,它指向字符 “ C ”。

(2)用字符指针变量指向一个字符串常量,通过字符指针变量引用字符串常量。

举例:通过字符指针变量输出一个字符串。

#include <stdio.h>
int main()
{
	char* string = "1 love China!";		//定义指针变量string
	printf("%s\n", string);				//用%s格式输出整个字符串
	printf("%c\n", *(string + 7));		//用%c格式输出一个元素
	return 0;
}

运行结果:

用指针输入字符串,C语言,c语言,c++,数据结构,算法,指针

程序分析:

用指针输入字符串,C语言,c语言,c++,数据结构,算法,指针

在程序中没有定义字符数组,只定义了一个 char* 型的指针变量(字符指针变量) string,用字符串常量 " I love China! " 对它初始化。C 语言对字符串常量是按字符数组处理的,在内存中开辟了一个字符数组用来存放该字符串常量,但是这个字符数组是没有名字的,因此不能通过数组名来引用,只能通过指针变量来引用。

对字符指针变量 string 初始化,实际上是把字符串第 1 个元素的地址(即存放字符串的字符数组的首元素地址)赋给指针变量 string,使 string 指向字符串的第 1 个字符,由于字符串常量 " I love China! " 已由系统分配在内存中连续的 14 个字节中,因此,string 就指向了该字符串的第一个字符。在不致引起误解的情况下,为了简便,有时也可说 string 指向字符串 " I love China! " ,但应当理解为 “ 指向字符串的第 1 个字符 ”。

注意:

string 被定义为一个指针变量,基类型为字符型。请注意它只能指向一个字符类型数据,而不能同时指向多个字符数据,更不是把 " I love China! " 这些字符存放到 string 中(指针变量只能存放地址),也不是把字符串赋给 *string。只是把 " I love China! " 的第 1 个字符的地址赋给指针变量。

%s 是输出字符串时所用的格式符,在输出项中给出字符指针变量名 string,则系统会输出 string 所指向的字符串第 1 个字符,然后自动使 string 加 1,使之指向下一个字符,再输出该字符……如此直到遇到字符串结束标志 '\0' 为止。在内存中,字符串的最后被自动加了一个 '\0' ,因此在输出时能确定输出的字符到何时结束。

说明:

通过字符数组名或字符指针变量可以输出一个字符串,而对一个数值型数组,是不能企图用数组名输出它的全部元素的。

例如:

int a[10];
...
printf("%d\n",a);

是不行的,它输出的是数组首元素的地址。对于数值型数组的元素值只能逐个输出。

举例:将字符串 a 复制为字符串 b,然后输出字符串b。

#include <stdio.h>
int main()
{
	char a[] = "I am a student.", b[20];//定义字符数组
	int i;
	for (i = 0; *(a + i) != '\0'; i++)
		*(b + i) = *(a + i);			//将a[i的值赋给b[i
	*(b + i) = '\0';					//在b数组的有效字符之后加'\0'
	printf("string a is:%s\n", a);	    //输出a数组中全部有效字符
	printf("string b is:");
	for (i = 0; b[i] != '\0'; i++)
		printf("%c", b[i]);				//逐个输出b数组中全部有效字符
	printf("\n");
	return 0;
}

运行结果:

用指针输入字符串,C语言,c语言,c++,数据结构,算法,指针

程序分析:

程序中 a 和 b 都定义为字符数组,今通过地址访问其数组元素。在 for 语句中,先检查 a[i] 是否为 '\0' ( a[i] 是以 *(a+i) 形式表示的)。如果不等于 '\0',表示字符串尚未处理完,就将 a[i] 的值赋给b[i],即复制一个字符。在 for 循环中将 a 串中的有效字符全部复制给了 b 数组。最后还应将 '\0' 复制过去,作为字符串结束标志。

在第 2 个 for 循环中输出 b 数组中的元素,在 printf 函数中用下标法表示一个数组元素(即一个字符)。也可以用输出 a 数组的方法输出b数组。用以下一行代替程序的10-13行。

printf("string b is:%s\n”,b);

程序中用逐个字符输出的方法只是为了表示可以用不同的方法输出字符串。

也可以用另一种方法:用指针变量访问字符串。通过改变指针变量的值使它指向字符串中的不同字符。

举例:用指针变量来处理问题。

#include<stdio.h>
int main()
{
	char a[] = "I am a boy.", b[20], * pl, * p2;
	pl = a; p2 = b;					//pl, p2分别指向a数组和b数组中的第一个元素
	for (; *pl != '\0'; pl++, p2++)	//pl,p2每次自加1
		*p2 = *pl;					//将pl所指向的元素的值赋给p2所指向的元素
	*p2 = '\0';						//在复制完全部有效字符后加'\0'
	printf("string a is:%s\n", a);	//输出a数组中的字符
	printf("string b is:%s\n", b);	//输出b数组中的字符
	return 0;
}

运行结果:

用指针输入字符串,C语言,c语言,c++,数据结构,算法,指针

程序分析:

p1 和 p2 是指向字符型数据的指针变量。先使 p1 和 p2 分别指向字符串 a 和 b 的第1个字符。*p1 最初的值是字母 'I'。赋值语句 “ *p2 = *p1; ” 的作用是将字符 'I' ( a 串中第 1 个字符)赋给 p2 所指向的元素,即 b[0]。然后 p1 和 p2 分别加 1,分别指向其下面的一个元素,直到 *p1 的值为 '\0' 止。

二、字符指针作函数参数

如果想把一个字符串从一个函数 “传递” 到另一个函数,可以用地址传递的办法,即用字符数组名作参数,也可以用字符指针变量作参数。在被调用的函数中可以改变字符串的内容,在主调函数中可以引用改变后的字符串。

2.1举例说明

举例:用函数调用实现字符串的复制。

(1)用字符数组名作为函数参数

#include <stdio.h>
int main()
{
	void copy_string(char from[], char to[]);
	char a[] = "I am a teacher.";
	char b[] = "You are a student.";
	printf("string a=%s\nstring b=%s\n", a, b);
	printf("\ncopy string a to string b:\n");
	copy_string(a, b);		                 //用字符数组名作为函数实参
	printf("string a = % s\nstring b = % s\n", a, b);
	return 0;
}
void copy_string(char from[], char to[])	//形参为字符数组
{
	int i = 0;
	while (from[i] != '\0')
	{
		to[i] = from[i];
		i++;
	}
	to[i] = '\0';
}

运行结果:

用指针输入字符串,C语言,c语言,c++,数据结构,算法,指针

程序分析:

用指针输入字符串,C语言,c语言,c++,数据结构,算法,指针

a 和 b 是字符数组。copy_string() 函数的作用是将 from[i] 赋给 to[i],直到 from[i] 的值等于 '\0' 为止。在调用 copy_string() 函数时,将 a 和 b 第 1 个字符的地址分别传递给形参数组名 from 和  to 。因此 from[i] 和 a[i] 是同一个单元,to[i] 和 b[i] 是同一个单元。程序执行完以后,由于 b 数组原来的长度大于 a 数组,因此在将 a 数组复制到 b 数组后,未能全部覆盖 b 数组原有内容。b 数组最后 3 个元素仍保留原状。在输出 b 时由于按 %s (字符串)输出,遇 '\0' 即告结束,因此第一个 '\0' 后的字符不输出。如果用 %c 逐个字符输出是可以输出后面这些字符的。

(2)用字符型指针变量作实参

#include <stdio.h>
int main()
{
	void copy_string(char from[], char to[]);	//函数声明
	char a[] = "I am a teacher.";				//定义字符数组a并初始化
	char b[] = "You are a student.";			//定义字符数组b并初始化
	char* from = a, * to = b;					//from指向a数组首元素,to指向b数组首元素
	printf("string a=%s\nstring b=%s\n", a, b);
	printf("\ncopy string a to string b:\n");
	copy_string(from, to);						//实参为字符指针变量
	printf("string a=%s\nstring b=%s\n", a, b);
	return 0;
}
void copy_string(char from[], char to[])		//形参为字符数组
{
	int i = 0;
	while (from[i] != '\0')
	{
		to[i] = from[i];
		i++;
	}
	to[i] = '\0';
}

运行结果:

用指针输入字符串,C语言,c语言,c++,数据结构,算法,指针

程序分析:

指针变量 from 的值是 a 数组首元素的地址,指针变量 to 的值是 b 数组首元素的地址。它们作为实参,把 a 数组首元素的地址和 b 数组首元素的地址传递给形参数组名 from 和 to (它们实质上也是指针变量)。

(3)用字符指针变量作形参和实参

#include <stdio.h>
int main()
{
	void copy_string(char* from, char* to);
	char* a = "I am a teacher. ";				//a是 char *型指针变量
	char b[] = "You are a student. ";			//b是字符数组
	char* p = b;								//使指针变量p指向b数组首元素
	printf("string a=%s\nstring b=%s\n", a, b);	//输出a串和b串
	printf("\ncopy string a to string b : \n");
	copy_string(a, p);							//调用copy_string函数,实参为指针变量
	printf("string a=%s\nstring b=%s\n", a, b);//输出改变后的a串和b串
	return 0;
}
void copy_string(char* from, char* to)			//定义函数,形参为字符指针变量
{

	for (; *from != '\0'; from++, to++)
	{
		*to = *from;
	}
	*to = '\0';
}

运行结果:

用指针输入字符串,C语言,c语言,c++,数据结构,算法,指针

程序分析:

形参改用 char* 型变量(即字符指针变量)。在程序(1)和(2)中 copy_string 函数的形参用字符数组名,其实编译系统是把字符数组名按指针变量处理的,只是表示形式不同。copy_string 函数中不是用下标法引用数组元素,而是通过移动指针变量的指向,找到并引用数组元素。

main 函数中的 a 是字符指针变量,指向字符串 "I am a teacher." 的首字符。b 是字符数组,在其中存放了字符串 "You are a student." 。p 是字符指针变量,它的值是 b 数组第一个元素的地址,因此也指向字符串 "You are a student.” 的首字符。copy_string 函数的形参 from 和 to 是字符指针变量。在调用 copy_string 时,将数组 a 首元素的地址传给 from,把指针变量 p 的值(即数组 b 首元素的地址)传给 to。因此 from 指向 a 串的第一个字符 a[0],to 指向 b[0]。在 for 循环中,先检查 from 当前所指向的字符是否为' \0',如果不是,表示需要复制此字符,就执行 “ *to = *from ”,每次将 *from 的值赋给 *to,第 1 次就是将 a 串中第 1 个字符赋给 b 数组的第 1 个字符。每次循环中都执行 “from++” 和 “to++”,使 from 和 to 分别指向 a 串和 b 数组的下一个元素。下次再执行 “ *to = *from ” 时,就将 a 串中第 2 个字符赋给b[1]……最后将 '\0' 赋给 *to,注意此时 to 指向哪个单元。

2.2程序改进

对 copy_string 函数还可以改写得更精练一些,可以作以下一些改动:

(1)将 copy_string 函数改写为

void copy_string(char* from, char* to)
{
	while ((*to = *from) != '\0')
	{
		to++; from++;
	}
}

在本程序中将 “ *to = *from ” 的操作放在 while 语句括号内的表达式中,而且把赋值运算和判断是否为 '\0' 的运算放在一个表达式中,先赋值后判断。在循环体中使 to 和 form 增值,指向下一个元素……直到 *from 的值为 '\0' 为止。

(2)copy_string 函数的函数体还可以改为

{
	while ((*to++ = *from++) != '\0');
}

把上面程序的 to++和 from++ 运算与 *to = *from合并,它的执行过程是,先将 *from 赋给 *to,然后使 to 和 from 增值。显然这又简化了。

(3)copy_string 函数的函数体还可以改为

{
	while (*from!='\0')
	{
		*to++ = *from++;
	}
	*to != '\0';
}

当 *from 不等于 '\0' 时,将 *from 赋给 *to,然后使 to 和 from 增值。

(4)由于字符可以用其ASCII码来代替

例如,“ ch=' a' ”可用 “ ch= 97 ”代替,“ while(ch!='a') ” 可以用 “ while(ch!=97) ”代替。因此,“ while(*from!='\0') ” 可以用 “ while(*from!=0) ” 代替( '\0' 的 ASCII 代码为 0 )。而关系表达式 “ *from!=0 ” 又可简化为 “ *from ”,这是因为若 *from 的值不等于0,则表达式 “ *from ” 为真,同时 “ *from!=0 ” 也为真。因此 “ while(*from!=0) ” 和 “ while(*from) ”是等价的。

所以函数体可简化为

{
	while (*from)
	{
		*to++ = *from++;
	}
	*to != '\0';
}

(5)上面的 while 语句还可以进一步简化为

	while (*to++ = *from++);

它与下面的语句等价

	while ((*to++ = *from++) != '\0');

(6)函数体中也可以改为只用一个 for 语句

	for (; (*to++ = *from++) != '\0'; );

	for (; *to++ = *from++; );

(7)也可以用字符数组名做函数形参,在函数中另定义两个指针变量p1,p2。函数 copy_string 可写为

void copy_string(char from[], char to[])
{
	char* pl, * p2;
	pl = from; p2 = to;
	while ((*p2++ = *pl++) != '\0');
}

以上各种用法,使用十分灵活,程序精练,比较专业,初学者看起来不太习惯,觉得含义不直观。初学者要很快地写出它们可能会有些困难,也容易出错。但应能看懂以上的用法。在对C熟练后,以上形式的使用是比较多的。

归纳起来,用字符指针作为函数参数时,实参与形参的类型有以下几种对应关系

实参 形参
字符数组名 字符数组名
字符数组名 字符指针变量
字符指针变量 字符指针变量
字符指针变量 字符数组名

三、使用字符指针变量和字符数组的比较

用字符数组和字符指针变量都能实现字符串的存储和运算,但它们二者之间是有区别的,不应混为一谈,主要有以下几点。

(1)字符数组由若干个元素组成,每个元素中放一个字符,而字符指针变量中存放的是地址(字符串第 1 个字符的地址),绝不是将字符串放到字符指针变量中。

(2)赋值方式。可以对字符指针变量赋值,但不能对数组名赋值。

(3)初始化含义。数组可以在定义时对各元素赋初值,但不能用赋值语句对字符数组中全部元素整体赋值。

	char str[14] = "1 love China!";

不等价于

	char str[14];
	str[] = "1 love China!";	//把字符串赋给数组中的各元素,错误

(4)存储单元的内容。编译时为字符数组分配若干存储单元,以存放各元素的值,而对字符指针变量,只分配一个存储单元( Visual C++为指针变量分配 4 个字节)。

如果定义了字符数组,但未对它赋值,这时数组中的元素的值是不可预料的。可以引用(如输出)这些值,结果显然是无意义的,但不会造成严重的后果,容易发现和改正。

(5)指针变量的值是可以改变的,而字符数组名代表一个固定的值(数组首元素的地址),不能改变。

(6)字符数组中各元素的值是可以改变的(可以对它们再赋值),但字符指针变量指向的字符串常量中的内容是不可以被取代的(不能对它们再赋值)。

(7)引用数组元素。对字符数组可以用下标法(用数组名和下标)引用一个数组元素(如 a[5] ),也可以用地址法 ( 如 *(a+5) ) 引用数组元素 a[5]。如果定义了字符指针变量 p,并使它指向数组 a 的首元素,则可以用指针变量带下标的形式引用数组元素 ( 如 p[5] ),同样,可以用地址法(如 *(p+5) )引用数组元素 a[5]。

(8)用指针变量指向一个格式字符串,可以用它代替 printf 函数中的格式字符串。

	char* format;
	format = "a=%d,b=%f\n";		//使format指向一个字符串
	printf(format, a, b);

它相当于

	printf("a= %d,b=%f\n", a, b);

因此只要改变指针变量 format 所指向的字符串,就可以改变输入输出的格式。这种 printf 函数称为可变格式输出函数。

C语言指针操作系列文章:

C语言指针操作(一)地址,指针,指针变量是什么

C语言指针操作(二)指针变量作为函数参数

C语言指针操作(三)通过指针引用数组

C语言指针操作(四)用数组名作函数参数

C语言指针操作(五)通过指针引用多维数组

C语言指针操作(六)指向函数的指针

C语言指针操作(七)通过指针引用字符串

C语言指针操作(八)返回指针值的函数

C语言指针操作(九)指针数组和多重指针

C语言指针操作(十)动态内存分配与指向它的指针变量

C语言指针操作(十一)有关指针的小结文章来源地址https://www.toymoban.com/news/detail-769766.html

到了这里,关于C语言指针操作(七)通过指针引用字符串的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 对输入的字符串通过空格分隔

    场景:想要对输入的字符串通过空格分隔,但是不同字符串之间的空格个数不一样,因此可以使用正则表达式进行分隔。 str.trim().split(/\\\\s+/) 这行代码可以分解成两部分: str.trim() : 这个调用会移除字符串 str 的两端空格,并返回处理后的字符串。例如,对于字符串 \\\" hello wor

    2024年02月08日
    浏览(40)
  • C语言字符和字符串的输入与输出

    1、scanf函数输入单个字符 C语言scanf输入时缓冲区问题 scanf函数是标准输入流(从键盘接收数据),接收的数据放入输入缓冲区中,其中就包括在键盘输入的空格、回车这类字符,当你用%d接收时是不会影响的,但是用%c就会产生错误,这是因为在\\\"%c\\\"输入时,空格和转义字符均作

    2023年04月09日
    浏览(62)
  • C语言学习:输入一行字符串,输出字符串中最长的单词。

    输入一行字符,编写一个函数,将此字符串中最长的单词输出。 代码示例如下: 一、输出字符串中第一个最长单词 测试结果:  二、输出字符串中所有最长单词 评论区指出上述程序不能输出同样最长的两个单词,修改后该程序能输出所有最长单词,即如果有多个同样最长的

    2024年02月05日
    浏览(38)
  • C语言如何输入一个字符串?

    在 scanf() 和 printf() 函数中, %s 指的就是字符串 所以我们就可以使用 scanf(\\\"%s\\\",str) 和 printf(\\\"%s\\\",str) 从键盘处读取字符串并将字符串打印出来 代码如下: 这里要注意的一点是:在 scanf 函数中,后面的参数必须是一个地址,如输入一个整形变量: scamf(\\\"%d\\\",a) ,都需要进行 取地址操

    2024年02月04日
    浏览(43)
  • C语言-字符串与输入输出

    在 C 语言中,字符串实际上是使用空字符 \\0 结尾的一维字符数组。因此,\\0 是用于标记字符串的结束。 空字符(Null character)又称结束符,缩写 NUL,是一个数值为 0 的控制字符,\\0 是转义字符,意思是告诉编译器,这不是字符 0,而是空字符。 比如:下面声明和初始化创建

    2024年02月02日
    浏览(37)
  • C语言指针操作(三)通过指针引用数组

    通过指针引用数组的几种方法的原理和差异;以及利用指针引用数组元素的技巧 关于地址,指针,指针变量可以参考这篇文章: C语言指针操作(一)地址,指针,指针变量是什么 关于指针变量作为函数参数可以参考这篇文章: C语言指针操作(二)指针变量作为函数参数

    2024年02月04日
    浏览(36)
  • 将输入的字符串反向输出(c语言)

    2024年02月05日
    浏览(45)
  • C语言指针操作(五)通过指针引用多维数组

    多维数组的地址,通过指针引用多维数组详解。 通过指针引用一维数组可以参考这篇文章: C语言指针操作(三)通过指针引用数组 目录 一、多维数组的地址 1.1引入 1.2地址举例说明 1.3地址类型详解 1.4实例说明 二、指向多维数组元素的指针变量 2.1指向数组元素的指针变量

    2024年02月03日
    浏览(35)
  • 如何用C语言读取不定长字符串输入

    上述代码中,我们使用了一个字符数组 str 来存储用户输入的字符串,数组大小为 MAX_STR_LEN 。然后,我们使用 getchar() 函数逐个读取字符,并将其存储到数组中,直到读取到换行符为止。在读取过程中,我们还需要检查字符数是否超过了数组的长度,以防止内存溢出。 最后,

    2024年02月08日
    浏览(33)
  • 【C语言_题库】C语言:编写一个程序,输入一组字符串,将字符串中的小写字母转换为大写字母,其它字符不变,并输出。

    【问题描述】 从键盘输入一行英文字符串,把所有小写字母变成大写字母,其他字母和字符保持不变。 【输入形式】 输入一行字符串,含大小写。 【输出形式】 输出大写字母形式。 【样例输入①】 hello,world. 【样例输出①】 result:HELLO,WORLD. 【样例输入②】 hello,China. 【样例

    2024年02月07日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包