认识C++字符串复合类型

简介: 认识C++字符串复合类型

前言:


 C++与C语言在内容上有些是一样的,也许正是因为如此,博主讲得细一点的话内容就会偏多啦,在学习的时候,因为知识很杂,所以知识点或内容排布不是很妥当的地方望指出!那我们就开始学习C++中的字符串复合类型,go!


1.数组


1.1C++的数组

 数组是一种数据格式,能够存储多个同类型的值,每个值都存储在一个独立的数组元素中,计算机在内存中依次存储数组的各个元素。


 创建数组的新知识:元素个数只能是常数表达式或const值



 补充:C语言不支持使用 const int ArraySize = 10来成为数组的元素个数,int arr[ArraySize]是错误的。


 数组是复合类型的原因是,数组是使用其它类型来创建的,我通常说arr是整型数组,浮点型数组,就是在强调数组是由什么其它类型创建的。我们并没有说arr是数组类型这一说法。


 有效下标值的重要性:编译器并不会检查下标的正确性,当我们下标因计算错误,超出了数组的范围后,并不会显性的提示错误,但我们运行时就会因破坏数据或代码而导致终止。


1.2C++数组初始化


 补充:"这并不是一个很好的做法"-----根据情况做就OK; "而这样就很轻松的向内存";


 补充:C++11将使用大括号{}的初始化(初始化列表)作为一种通用的初始化方式,可用于所有类型,前面也说过,也可以用{}给单值变量初始化。int a = {0};



*2.字符串


2.1字符串与数组

 先看一下下面的代码吧!



 补充:"直到到达空字符";"会将数组外的解释为";


 看完后你就开始进入字符串的思维了(doge)


字符串常量和字符常量表示什么?



拼接字符串的详细过程补充:



  事实上,任何两个由空白(空格、制表符和换行符)分隔的字符串常量都将自动拼接成一个字符串。


2.2字符数组的存储

 字符串常量在数组初始化的时候存进去或者通过cin对象输入字符串存到字符数组里去



 看到name2[3] = '\0';的时候,我们接下来cout<<name2;的时候,只显示出来前三个字符,因为索引值位3对应数组的第四个元素,我们在第四个元素主动放进斜杠0,提前结束了该字符串,而name2后面的其它字符oy是被我们忽略了的。



 注意:我在这个编译器的首行是有引用头文件#include <iostream>,我是有引才能用的cout和cin。不要因为我截图没截进来就以为不用引哈。


2.3字符串输入cin

 字符串输入cin有一个缺陷,在上面的一个代码中巧妙的避开了,我们接下来的代码来了解cin的脾气。



  理解一个点:cin在遇到空白后会停止读取,空白也给拿走了,空白并不是存在字符数组dessert里,而是丢弃掉了。随后把读取到的字符放进数组里并在结尾添了个'\0'。(第一种)



 我们看到a数组里的元素是bb和末尾的一个斜杆零,Ali bb中间的空白被丢弃掉了,空白的ASCCI码值是32。(cin)、scanf。



 用一个字符c来接收也是一样,只得到字符b的ASCII码值。 (cin)、scanf。



 而cin.get(c)就不一样了,它把空格给吸收给了字符变量c。 (cin.get(ch))、getchar。


 这说明空格还是有在输入缓冲区里的。所以对于两次连续的cin来说,空格是被忽视的。(第三种)



  再看到这个,我们连续给ch字符数组输入两次,第一次的Ali被后面的aaaaa覆盖掉了,这时候结合前面的种种情况会有两种想象----第二种、第三种这两个现象。


第一种:第一次读取的时候,把空格也给读取了,但被丢掉了。但我们使用cin.(get)读到了空格,说明这种并不是很可靠。(不可靠);


第二种:空格留在了输入缓冲区里面,cin读取的时候,因为是空格就意味着读取结束,cin的内部实现里有一种,在第一次读到空格的时候,会进行再一次的读取。用这里的例子说就是,Alistair Dreeb,空格被读了,触动"开关",再读一次,读到的Dreeb覆盖掉了空格。(可行);


第三种:就是cin一上来看到是空格,就直接跳过了这个字符,从下一个开始读(可行);


 总结:C++中的cin很像C里的scanf,表现在为字符数组输入字符的时候,结尾会为我们自动添加斜杆0,对于空格、制表符等空白就会使读取停止。但接下来再用cin或scanf读取的时候,若第一个遇到的是空白等,对于cin和scanf来说都是直接抛弃(要么被覆盖,要么被忽视)掉的。为什么能这么说,因为我们使用cin.get(c)来接收的时候,是能妥妥接收到空格这个字符的,和C语言的getchar的用法和特征是一样的。


  还有一个问题存在的,这里的数组大小是20个,那最多只能存放19个,最后一个是'\0'才能保证是字符串,但,假如我们输入了一个30个字符的字符串,这能防止吗?答案是必须使用cin的较高级特性,就像是strncat限制一样。一个程序员心想写bug是拦不住的(doge)。


  那如何解决问题那,我的名字中间就是有空格呀,那我们就看到能读取一行的成员函数cin.getline()和cin.get(),这两个函数都读取一行输入,直到到达换行符。而getline()将丢弃换行符,get()保留换行符在输入序列中。


2.4cin.getline()

每次读取一行字符串输入


 例如:假设要使用getline()将姓名读入到一个包含20个元素的name数组中,可以使用这样的函数调用。eg:cin.getline(name, 20);


 这将把一行不超过19个字符(不包括换行符)的字符串存到name字符数组中,加上换行符最多20个字符。



 补充:"getline遇到换行符(回车)结尾";想表达的是,换行符是getline的结尾。


 这里面名字有空格对于cin.getline()来说,不是行尾,只是一个字符' '(空格字符)而已。


 注意:它这里不需要>>来指明插入到哪个地方,在第一个参数的地方就说明了,所以cin.getline(name, 20);就可以啦


2.5cin.get()

面向行的输入:get()


 get()该函数有几种变体,其中一种变体的工作方式和getline()类似,它们接收的参数相同,解释参数的方式也相同,并且都读取到行尾,但与getline()不同的是get()并没有读取换行符而是留在了输入队列。


上面的代码输入如果用成cin.get(name, ArSize);


                                       cin.get(dessert, ArSize);


 我们会发现dessert里啥内容都没有,因为第一个里换行符留在了输入队列,第二个get()上来一读就是换行符,都到行尾了,一个内容都没有,所以dessert里啥也没有。那有解决办法吗?


 幸好get()还有一整变体,使用不带任何参数的cin.get()调用可读取下一个字符,和C语言里的getchar()读取一个字符一样,把输入缓冲区里的换行符给读走,让第二个cin.get(dessert, ArSize)停留在我们要输入的环节。


 所以把输入部分换成cin.get(name, ArSize); cin.get();cin.getline(dessert, ArSize);则与上面的代码一模一样。


 另一种使用方式:cin.get(name, ArSize).get(); 将两个类成员函数拼接起来,之所以可以这样做,是因为cin.get(name, ArSize)返回一个cin对象,该对象再次被用来调用成员函数。


 同样,cin.getline(name, ArSize).getline(dessert, ArSize)是一个整体;连续接收两行字符串输入,与两次调用getline()效果一样。


2.6函数重载例子

 C++允许函数有多个版本的,条件是这些函数的参数列表不一样,cin.get()编译器就知道是要读取一个字符,cin.get(字符数组, Size);编译器知道要读取Size个字符到数组中,相同函数,根据参数不同,功能不同,这就是函数重载


 get()和getline()使用哪个好?:首先,老式实现没有getline(),第二get()使输入结果更清晰,什么意思呢?当我们用get()来输入一行字符串后,我们再get()一次后,用一个字符变量接收第二次get()的内容,如果这个字符是换行符,那就说明读取了一整行后最后只剩下了一个换行,get()完整的读取了一行,若不是换行符,则说明该行还有其它输入内容,没有读取一整行。


2.7混合输入数字和字符串


 在输入数值时,换行符会留下的。


 总结getline()和get()对于空字符的赋予:getline读掉换行符,将换行符替换成空字符赋给数组;


get()留下换行符,并直接为数组添上空字符,它们的读取结束标志是换行符。


 string类请见下回!!


 希望大家看完有所收获,也希望大家能喜欢我的博客。你的点赞是我更新的动力,欢迎指出文章描述不正确的或排版或内容分布的问题,博主会根据情况更改,一起努力把!


 求点赞,求点赞,求点赞!(flower)

相关文章
|
8天前
|
存储 C++
C++(五)String 字符串类
本文档详细介绍了C++中的`string`类,包括定义、初始化、字符串比较及数值与字符串之间的转换方法。`string`类简化了字符串处理,提供了丰富的功能如字符串查找、比较、拼接和替换等。文档通过示例代码展示了如何使用这些功能,并介绍了如何将数值转换为字符串以及反之亦然的方法。此外,还展示了如何使用`string`数组存储和遍历多个字符串。
|
8天前
|
安全 程序员 C语言
C++(四)类型强转
本文详细介绍了C++中的四种类型强制转换:`static_cast`、`reinterpret_cast`、`const_cast`和`dynamic_cast`。每种转换都有其特定用途和适用场景,如`static_cast`用于相关类型间的显式转换,`reinterpret_cast`用于低层内存布局操作,`const_cast`用于添加或移除`const`限定符,而`dynamic_cast`则用于运行时的类型检查和转换。通过具体示例展示了如何正确使用这四种转换操作符,帮助开发者更好地理解和掌握C++中的类型转换机制。
|
14天前
|
C++
使用 QML 类型系统注册 C++ 类型
使用 QML 类型系统注册 C++ 类型
19 0
|
22天前
|
存储 C++
【C/C++学习笔记】string 类型的输入操作符和 getline 函数分别如何处理空白字符
【C/C++学习笔记】string 类型的输入操作符和 getline 函数分别如何处理空白字符
29 0
|
2月前
|
编译器 C++ 运维
开发与运维函数问题之函数的返回类型如何解决
开发与运维函数问题之函数的返回类型如何解决
29 6
|
2月前
|
安全 编译器 C++
C++一分钟之-模板元编程实例:类型 traits
【7月更文挑战第15天】C++的模板元编程利用编译时计算提升性能,类型traits是其中的关键,用于查询和修改类型信息。文章探讨了如何使用和避免过度复杂化、误用模板特化及依赖特定编译器的问题。示例展示了`is_same`类型trait的实现,用于检查类型相等。通过`add_pointer`和`remove_reference`等traits,可以构建更复杂的类型转换逻辑。类型traits增强了代码效率和安全性,是深入C++编程的必备工具。
47 11
|
2月前
|
C++
C++一分钟之-类型别名与using声明
【7月更文挑战第20天】在C++中,类型别名和`using`声明提升代码清晰度与管理。类型别名简化复杂类型,如`using ComplexType = std::vector&lt;std::shared_ptr&lt;int&gt;&gt;;`,需注意命名清晰与适度使用。`using`声明引入命名空间成员,避免`using namespace std;`全局污染,宜局部与具体引入,如`using math::pi;`。恰当应用增强代码质量,规避常见陷阱。
51 5
|
29天前
|
设计模式 安全 IDE
C++从静态类型到单例模式
C++从静态类型到单例模式
23 0
|
2月前
|
算法 C++
2730. 找到最长的半重复子字符串(c++,滑动窗口)
2730. 找到最长的半重复子字符串(c++,滑动窗口)
|
2月前
|
C++
567. 字符串的排列(c++)滑动窗口
567. 字符串的排列(c++)滑动窗口