C语言进阶指南(13)(字符串与指针)

news2024/11/28 10:57:14

欢迎来到博主的专栏——C语言进阶指南
博主id:reverie_ly

文章目录

    • 字符串
    • 字符串与字符数组
    • 字符串与指针
    • 常量字符串
    • 字符串的输入与输出
      • 字符串的输出
      • 字符串的输入
    • 实现存放字符串的数组

字符串

字符串是由一连串字符组成的字符数据,C语言中并没有给字符串设置一个字符串的数据类型。所以字符串通常都是存放在字符数组中或者由字符指针指向这个字符串

由一个字符为起始位置,‘\0’为结束标志的字符集合称为字符串,字符串的元素个数是字符数加上字符的结束标志’\0’.

以最常见的“hello,world”为例,该字符串的存储形式为
在这里插入图片描述

字符串与字符数组

由于C语言并没有给字符串设定一个数据类型。所以不能用变量的形式来存储字符串。但是可以将字符串中的每个字符单独的存放到字符数组上

char str[12]="hello,world";

或者

char str[12] = { 'h','e','l','l','o',',', 'w','o','r','l','d','\0' };

这两个字符数组的存储形式如下:
在这里插入图片描述
需要注意的一点是,字符串一定是由‘\0’结尾的字符集合,如果字符数组中的元素不足够存放‘\0’的话,那么这个字符数组不能当做字符串使用。

通常来说,字符数组的元素多于存放字符串中,除了‘\0’以外的字符的话,字符数组会自动在末尾加上‘\0’。

以下是字符数组不能存放‘\0’的情况。

char str1[11]={“hello,world”};
char str2[11] = { 'h','e','l','l','o',',', 'w','o','r','l','d' };

由于字符数组的元素个数不能放下\0,所以不会在字符数组中的字符串末尾加上\0.
在这里插入图片描述
在str中的字符集合不能当做字符串使用

字符串与指针

字符串除了可以使用数组存放以外,也可以使用指针来指向字符串。

当使用指针指向字符串的时候,内存会开辟一段空间专门存放这段字符串,指针指向的是字符串的首元素

char*p="hello,world";

在这里插入图片描述

注意当使用指针来指向字符串时,字符串一定会有\0,不需要像字符数组留出一个位置来存放

常量字符串

当使用指针指向字符串时,该字符串在内存开辟的空间是不可以修改的,所以我们将这种指针指向的字符串成为字符串常量。

int main()
{
	char* p = "hello,world";
	*(p + 2) = 'a';//error
	return 0;
}

运行这段代码可以发现程序崩溃。
在这里插入图片描述

由于常量字符串是没有访问权限的,所以为了提高程序的安全性,常常使用const来限至指针的取值,避免出现修改常量字符串的情况

const char*p="hello,world";

限定以后就能放心使用指针p来指向常量字符串了。此时对指针p进行访问操作时编译器会发生警告,方便我们定位程序中的bug。
在这里插入图片描述
那么常量字符串与字符数组的字符串的区别在于

对于常量字符串来说,重点在于字符串而不是字符串常量的指针,对于同一个常量字符串,他们的不同指针指向的地址都是该字符串的第一个元素。
而字符组会开辟两组不一样的内存空间来存放元素,因此即使这两个字符组的元素一致。也不会存放在相同的地址。

上面的概念有些绕,我们以一个代码来分析。

int main()
{
	char str1[] = "hello,world";
	char str2[] = "hello,world";
	char* pstr1 = "hello,world";
	char* pstr2 = "hello,world";
	if (str1 == str2)
		printf("str1=str2\n");
	else
		printf("str1!=str2\n");
	if (pstr1 == pstr2)
		printf("pstr1=pstr2\n");
	else
		printf("pstr1!=pstr2\n");
	return 0;
}

运行可以发现
在这里插入图片描述
那么也就是说用字符数组存储的字符串,是将字符串存放到字符数组中,所以即使存放的是相同的字符串,str1与str2也不会是相同的字符数组的字符串。
而用字符指针指向的字符串是常量字符串,而常量字符串是单独存放在内存的某一块当中的,当两个指针指向相同的常量字符串时,指向的都是同一个地方。
在这里插入图片描述

字符串的输入与输出

字符串的输出

在格式串中,字符串的格式转换是%s,所以当使用输入/输出函数来输入/输出字符串时,使用%s来进行转换

int main()
{
	char str1[12] = "hello,world";
	printf("%s", str1);//向屏幕输出字符hello,world
	return 0;
}

需要注意的是,%s对应的参数必须是字符类型的指针,在前面也提到过,数组名可以作为指向数组中首元素的地址的指针使用,所以(“%s”,str1)的str1是字符串“hello,world”中字符‘h’的地址。

还记得前面提到的字符串结束标志‘\0’吗,此时‘\0’的作用就体现出来了,当我们将字符串进行输入与输出时,当输出/读取到‘\0’时,停止对字符串的输入/输出操作。

int main()
{
	char str1[] = { "hello,world\0reverie_ly" };
	printf("%s", str1);
	return 0;
}

运行程序发现,对str1中的字符串只读取到了“hello,world”。
在这里插入图片描述
由此发现,对字符串进行输出时,如果输出到了\0,就会停止输出。

字符串的输入

与字符串的输出格式类似,但是读入字符串时,还会由于读取到了‘\n’而停止读入。

char str1[20];
scanf("%s",str1);

实现存放字符串的数组

如果想要将多个字符串组合到一个数组当中,那么二维数组是一个很好的选择。

int main()
{
	char str1[4][20] = { {"hello,world"},
		{"reverie"},
		{"cowboybebop"},
		{"C programing"}
	};
	for (int i = 0; i < 4; i++)
	{
		printf("%s\n", str1[i]);
	}
	return 0;
}

在这里插入图片描述

可以发现用二维数组来存放字符串有两个问题
(1)数组当中的字符个数被限定住了,想要存储更多字符的字符串,就需要创建一个更多元素的二维数组
(2)可以发现,二维数组中的数据是很难填满的,这就导致了二维字符数组存放字符串会造成内存空间的浪费

如果想解决这些问题,我们就需要声明一个数组元素可大可小,能存储任意字符串,而且数组中的元素可以不用对齐的二维数组。
但是很可惜,C语言并没有规定这种二维数组的声明。

那么我们只能用另外一种方式来将这些字符串存储在一个数组当中

回顾上一个文章提到的,指针数组使用存放指针的数组,在这个文章中也提到了字符串可以作为指向字符串元素的指针来使用,那么就可以将字符串当做指针,存放在指针数组当中。

	char *pstr1[4] = { {"hello,world"},
		{"reverie"},
		{"cowboybebop"},
		{"C programing"}
	};

在这里插入图片描述

如此使用指针数组就能实现存放字符串时,既可以不限定字符串的元素个数,又可以节省内存空间。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1266720.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Kafka 保证消息消费全局顺序性

当有消息被生产出来的时候&#xff0c;如果没有指定分区或者指定 key &#xff0c;那么消费会按照【轮询】的方式均匀地分配到所有可用分区中&#xff0c;但不一定按照分区顺序来分配 我们知道&#xff0c;在 Kafka 中消费者可以订阅一个或多个主题&#xff0c;并被分配一个或多…

【预测爆款不用愁,有服饰RFID小助手】

时尚服饰行业库存成本高&#xff0c;数据不精准&#xff0c;爆款服饰一直抓不住&#xff0c;增加库存滞销风险难脱逃&#xff0c;给服饰零售企业带来极大困扰。 帮您提前预测爆款服饰小塔服饰RFID系统 小塔RFID系统作为服饰新零售小助手&#xff0c;通过RFID系统与硬件结合&a…

Vue3 Teleport

假设情景 以下面截图为例&#xff0c;A组件中可以操控数字的加减&#xff0c;想把这个功能放到B组件中使用&#xff0c;AB两个组件非父子组件&#xff0c;甚至可能被嵌套了其他组件&#xff0c;一般办法可能是将A组件数据传给AB组件的父组件&#xff0c;然后在相办法给B&#…

贝叶斯Sklearn实践

贝叶斯统计学是一种基于贝叶斯定理的概率推理方法&#xff0c;它提供了一种对概率进行建模和更新的框架。贝叶斯方法在机器学习中得到了广泛的应用&#xff0c;特别是在分类问题中&#xff0c;如垃圾邮件过滤、文本分类等。与传统的频率主义方法相比&#xff0c;贝叶斯方法具有…

【PyQt】QPixmap与numpy.array互转

这里给出QPixmap→numpy.ndarray的两条转换(一个是使用PIL.Image而另一个不用)&#xff0c; 以及numpy.ndarray→QPixmap两条转换(同样也是用不用PIL.Image的区别)。 代码运行结果&#xff1a; from PyQt5.QtCore import QPoint,QRect,Qt from PyQt5.QtWidgets import QLabel …

如何拥有免费的docker镜像仓库

shigen日更文章的博客写手&#xff0c;擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长&#xff0c;分享认知&#xff0c;留住感动。 hello&#xff0c;伙伴们&#xff0c;最近在研究devops的事情&#xff0c;发现了很有意思的东西。 就是我们所有…

springboot整合redis+自定义注解+反射+aop实现分布式锁

1.定义注解 import java.lang.annotation.*; import java.util.concurrent.TimeUnit;/** Author: best_liu* Description:* Date: 16:13 2023/9/4* Param * return **/ Retention(RetentionPolicy.RUNTIME) Target({ElementType.METHOD}) Documented public interface RedisLo…

怎么把dwg格式转换pdf?

怎么把dwg格式转换pdf&#xff1f;DWG是一种由AutoCAD开发的二维和三维计算机辅助设计&#xff08;CAD&#xff09;文件格式&#xff0c;它的名称是“绘图&#xff08;Drawing&#xff09;”的缩写。DWG文件通常包含了设计图纸、模型和元数据等信息&#xff0c;并且被广泛用于工…

工艺系统所管理数字化实践

摘要 本文介绍了上海核工程设计研究院在数字化转型方面的实践&#xff0c;包括业务数字化和管理数字化两个方面。业务数字化方面&#xff0c;该院通过开发小工具改进工作流程。管理数字化方面&#xff0c;该院采用零代码平台集中管理管道力学信息相关模型和数据&#xff0c;并…

Martin Fowler:数字化时代,远程与本地协同工作孰优孰劣?(2)| IDCF

作者&#xff1a;Martin Fowler 译者&#xff1a;冬哥 原文&#xff1a;https://martinfowler.com/articles/remote-or-co-located.html &#xff08;接上篇 &#xff09; 二、大多数人在同地办公时工作效率更高 与软件开发中的许多主题一样&#xff0c;我不能拿 100 个软…

Sectigo通配符证书

Sectigo通配符证书&#xff08;Wildcard SSL Certificate&#xff09;是一种特殊类型的SSL证书&#xff0c;它适用于一个主域名及其所有子域名。这意味着&#xff0c;只要子域名在主域名下&#xff0c;就可以使用同一张通配符证书进行加密保护。这为拥有多个子域名的网站提供了…

探究Kafka原理-7.exactly once semantics 和 性能测试

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring源码、JUC源码、Kafka原理&#x1f525;如果感觉博主的文章还不错的话&#xff0c;请&#x1f44…

方差分析汇总

一文整理了方差分析的全部内容&#xff0c;包括方差分析的定义&#xff08;基本思想、检验统计量的计算、前提条件&#xff09;、方差分析分类&#xff08;单因素、双因素、多因素、事后多重比较、协方差分析、重复测量方差分析&#xff09;、方差分析流程&#xff08;数据格式…

四川天蝶电子商务有限公司真实可靠吗?

随着数字经济的不断发展&#xff0c;抖音电商服务日益成为企业拓展销售渠道、提升品牌影响力的关键一环。在这样的大背景下&#xff0c;四川天蝶电子商务有限公司凭借其专业的服务能力和创新的技术手段&#xff0c;迅速崛起为抖音电商服务领域的领军企业。 四川天蝶电子商务有限…

使用 ZFPlayer 播放视频的注意点

一 静音功能 通过调用系统的AVPlayer.muted来实现的 - (void)setMuted:(BOOL)muted {_muted muted;self.player.muted muted;if (self.audioMuteChange) {self.audioMuteChange(self, muted);}... }播放进度条 /// 滑杆 property (nonatomic, strong, readonly) ZFSliderV…

04、基于高斯分布的异常检测算法

04、基于高斯分布的异常检测算法原理与实践 开始学习机器学习啦&#xff0c;已经把吴恩达的课全部刷完了&#xff0c;现在开始熟悉一下复现代码。对这个手写数字实部比较感兴趣&#xff0c;作为入门的素材非常合适。 数据的严重偏斜往往会导致监督学习算法面临巨大的挑战——…

亚马逊云科技 re:Invent 2023:引领科技前沿,探索未来云计算之窗

文章目录 一、前言二、什么是亚马逊云科技 re:Invent&#xff1f;三、亚马逊云科技 re:Invent 2023 将于何时何地举行四、亚马逊云科技 re:Invent 2023 有什么内容&#xff1f;4.1 亚马逊云科技 re:Invent 2023 主题演讲4.2 亚马逊云科技行业专家探实战 五、更多亚马逊云科技活…

发牌洗牌的简单逻辑

1. 需求分析 1.1 要求实现&#xff1a; 我们能使用一副牌&#xff0c;基本的实现多人炸金花小游戏。 1.2 实现分析&#xff1a; 1、有一副牌&#xff1a; 首先自定义card类&#xff0c;来定义每一张牌&#xff1b;&#xff08;牌上由花色和数字&#xff08;1~13&#xff09;&…

第二十章多线程

线程简介 java语言提供了并发机制&#xff0c;程序员可以在程序中执行多个线程&#xff0c;每一个线程完成一个功能&#xff0c;并与其他线程并发运行。 一个进程是一个包含有自身地址的程序&#xff0c;每个独立执行的程序都称为进程。也就是说每个正在执行的程序都是一个进…