目录
1.字符串
1.1简单介绍
1.2简化操作
1.3注意事项
1.4易错点的辨析
1.5字符串输入面纱
1.6面向行的输入getline
1.7面向行的输入get
1.8浅浅总结getline和get
1.9数字混合字符串的问题
1.字符串
1.1简单介绍
C++里面处理这个字符串的方式有两种,一种就是我们的这个C风格的字符串,典型特征就是以斜杠0作为结尾,另外一种就是我们的string类型;
下面的这个实例里面,cat就是打印输出前面的7个字符,遇到斜杠0就会停止输出,但是对于这个dog字符串而言,因为这个里面没有斜杠0,因此这个就会一直打印,直到遇到斜杠0为止;
1.2简化操作
简化操作:不是使用上面的大括号的方式,而是使用的引号的方式,因为使用这个大括号的时候里面的每一个数组元素都是一个字符,这个时候需要我们自己手动的添加上这个斜杠0,但是我们很容易忘记,使用下面的这个引号的方式,这样进行编译的时候这个字符串的后面默认就是有这个斜杠0的标志的,不需要我们进行手动的添加,这样的方式叫做字符串常量或者是字符串字面值;
1.3注意事项
我们下面介绍了几种这个注意事项,就是我们的这个单引号里面的这个字符叫做字符常量和我们上面的这个字符串常量又是有区别的;
字符常量实际上就是一个单引号表示的,表示的一个ASCII数值;
字符串常量表示的是这个字符串,里面有多个字符,且默认就是使用的这个斜杠0结尾的;
双引号里面只有一个字符,这个表示的一个字符串的地址,这个字符串是有这个字符和\0组成,表示的这个地址是我们的这个字符串所在的内存地址;
1.4易错点的辨析
我们下面的这个其实是有一个程序的,但是这个我们直接看结论:
就是这个Basicman这个字符串,我们使用这个sizeof计算的是这个整个数组的长度,包括这个空字符的个数,遇到\0停止,类似于这个数组的capacity的意思,显示的是这个数组的空间大小;
strlen计算的只是这个数组的有效的字符的个数,像这个空字符是不会被计算进去的,因此使用strlen计算这个字符串的长度就是8;
1.5字符串输入面纱
下面的一个程序里面有一个隐藏的问题,我们也将通过下面的这个案例揭露这个字符串的输入的技巧:我们定义了两个数组,一个数组name,一个数组dessert就是甜点的意思;
我们首先输入的就是这个Alistair Dreeb这个长字符串,我们原本是想要把这个字符串存储到这个name这个数组里面的,我们输入完成之后这个时候系统就会提示我们去输入我们最喜欢的甜点dessert,但是我们一旦按下这个回车键,这个时候我们还没有输入任何内容,系统就会打印输出,相当于这个过程里面,我们的这个cin只进行了一次输入,cout输入是没有问题的,但是我们没有进行这个cin 的第二次输入,为什么编译器就会执行到这个cout的第二次输出呢?
对于上处出现的问题的解释说明:这个就是一个隐藏的缺陷问题,就是关于这个cin的读取问题,就是我们第一次输入这个Alistair Dred之后,这个字符串存储到了这个缓冲区域里面去,我们首先要明白一组概念:
空字符:空字符指的就是我们的这个斜杠0,代表一个字符串的结束标志;
空白:这个包括了空格,制表符和换行符这三部分内容,这个是和空字符不同的,要明白;
我们首先要知道,我们的这个键盘输入是没有办法输入这个\0的,但是这个字符串的结束标志就是\0,我们没有办法输入这个\0,那么这个cin如何判断这个字符串是不是结束了呢?这个时候cin就是通过这个空白判断的,因此这个cin在获得这个字符数组的时候,实际上第一次只会读取到这个第一个空格前面的位置,然后在这个末尾加上\0存储到我们的这个name数组里面去,因为这个数组里面的内容是一个字符串,以\0结束,所以这个存储的时候会加上这个\0的;
这个时候只有这个dreed留在了我们的这个输入队列里面,当cin在这个输入队列里面进行搜索的时候,他发现了这个Dreed,因此这个dreed被存储到了dessert这个数组里面去;
1.6面向行的输入getline
上面我们输入一个类似于这个Alistair Dreeb字符串,这个时候cin只会读取这个空白前面的字符串,无法进行这一整行的字符串的读入;
我们可以使用这个getline这个函数,getlien(name,20)就是我们想要把这个20个大小的字符串存储到我们的name数组里面去,getlien读取的时候,只会读取19个字符,然后会加上这个\0,就是我们的这个函数参数里面的20个字符;
同样是上面的那个案例,我们再进行这个输入的时候,面对这个字符串,getline就会跳过这个空白,因为这个我们输入之后,缓存区里面的内容就是我们的这个字符串加上换行符,因为我们输入之后按下了这个enter,因此这个缓存区里面是会有这个换行符的;
这个时候getline进行读取,读取到这个换行符的时候,这个就会认为这个字符串全部读取完成了,这个换行符就会被丢弃掉,因此这个时候我们的缓存区是没有内容的,我们第二次使用这个函数getline的时候我们就可以进行这个正常的输入了;
1.7面向行的输入get
这个同时和这个getline很像的就是这个get了,这个getline实际上只是这个get里面的一个形式而已
还是上面得这个程序,我们如果使用这个get函数作为读取操作,这个时候,当这个get读取到我们的输入的这个字符串的时候,和getline一样是会继续读下去的,遇到这个换行符之后也会认为这个字符串读取结束了,但是这个get函数不会丢弃这个换行符,而是继续把这个换行符留到我们的这个缓存区里面去,这个时候我们再次使用这个get函数的时候,这个缓存区里面是有内容的,就是这个换行符,因此这个时候还会引发异常:即我们没进行第二次输入,这个就会打印这个输出的结果,就是因为这个时候的输出队列里面保留了这个换行符,get读取到这个换行符,使得我们没有办法进行这个第二次输入的操作;
想要解决这个问题也很简单,下面是两个方案:
其实想要解决这个问题,我们就要知道这个问题的根源是在哪里,这个get读取两次的时候,就是因为这个缓存区里面有这个换行符,因此我们只需要解决掉这个换行符就可以了;
第一个操作就是,使用这个get调用之后,后面接上一个这个cin.get函数,把这个换行符吞掉,第一次添加这个get是为了吞掉这个换行符,第二次加其实就是一个好的习惯,因为我们没有第三次输入了,但是为了这个编程习惯,我们建议加上去;
第二种就是这个cin.get()函数的返回值就是这个cin,因此我们可以连续的对于这个函数进行调用,只需要写一行就可以完成这个效果,如下图所示:
1.8浅浅总结getline和get
其实上面已经说的很清楚了,就是这个get读取的时候不会丢起这个换行符,但是这个getline在读取的时候会丢掉这个换行符,因此这个getline可以进行多次的输入;
当使用这个get函数的时候,会出现问题,但是我们也给除了这个解决的方案:就是可以加上这个额外的cin.get就是为了吞掉这个换行符,也可以根据这个cin.get返回值就是cin对于这个get进行链式调用,只需要一行代码就解决这个问题;
其实这个cin.getline函数的返回值也是一个cin,这个也是可以连续调用的,这个不会有问题;
1.9数字混合字符串的问题
我们输入这个1966之后,getline进行读取的时候,读取的是这个剩下的换行符,因此这个时候,我们可以总结这个getline会丢弃这个换行符,get和cin都不会丢弃这个换行符的;
读取这个换行符之后,第二次的这个cin.getline就没有等待我们的输入直接打印输出了;
想要解决这个问题也是有方法的:其实还是上面老方法,就是把这个换行符吞掉,或者是链式调用,两个的本质都是一样的;