博客:http://blog.youkuaiyun.com/qianxin_dh
邮箱:qianxin_dh@163.com
c++处理字符串的方式有两种:
- 来自c语言,即c风格字符串。
- 基于string类库。
本篇博客主要归纳c风格字符串的常规用法,关于string类库的一些内容将在后续博客中进行总结。
c-风格字符串
存储在连续字节中的一系列字符意味着可以将字符串存储在char数组中。c-风格字符串具有一种特殊的性质:以空字符结尾,空字符被写为\0,其ASCII码为0,用来标记字符串的结尾。
例如下面两个声明:
char str1[] = {'q','i','a','n','x','i','n'}; //不是字符串
char str2[] = {'q','i','a','n','x','i','n','\0'}; //是字符串
上面两个数组都是char数组,但是只有第二个数组是字符串。空字符对c-风格字符串而言至关重要。在c++中有很多处理字符串的函数,其中包括大家最熟悉的cin等函数,它们都逐个地处理字符串中的字符,直至达到空字符为止。
上述将数组初始化为字符串的工作需要使用大量的单引号,且必须加上空字符,这显得十分费力。因此,我们常使用一个用引号括起来的字符串即可,如:
char animal[10] = "tiger";
char fruit[] = "apple";
用引号括起的字符串隐式地包括结尾的空字符。将字符串读入到char数组中时,将自动加上结尾的空字符,当然,这里我们应确保数组足够大,能够存储字符串中的所有字符,也包括空字符。
note:
1)字符串常量(使用双引号)不能与字符常量(使用单引号)互换,因为字符串常量还隐含了一个字符’\0’。
2)strlen(animal)的值为5。(不是6,因为strlen只计算可见的字符)
字符串输入
首先定义一个数组:
const int Size = 20;
char name[Size];
之后我们输入字符串到name:cin>>name;
比如,我们输入的字符串为:”Qian xin”;
接着,我们输出字符串name的内容:cout<<name;
发现输出的结果为”Qian”,而并非我们想要的结果”Qian xin”;
这是由于cin使用空白(空格,制表符和换行符)来确定字符串的结束位置,这意味着cin在获取字符数组输入时只读取了一个单词。读取该单词后,cin将该字符串放到数组中,并自动在结尾添加空字符。
那么我们如何实现讲”Qian xin”成功读取至数组name中呢?
读取一行字符串输入
istream中的类提供了一些面向行的类成员函数:getline()和get()。这两个函数都可以读取一行输入,直至换行符。不同的是,getline()将丢弃换行符,而get()将换行符保留在输入序列中。
getline()
getline()函数读取整行,它使用通过回车键输入的换行符来确定输入结尾。该函数有两个参数,第一个参数是用来存储输入行的数组的名称,第二个参数是要读取的字符数。如这个参数为10,则函数最多只能读取9个字符,余下的空间用于存储自动在结尾处添加的空字符。 如:cin.getline(name,10);
get()
该函数有几种变体,其中一种与getline()相似,他们接受的参数相同,并且都读取到行尾。但get并不再读取并丢弃换行符,而是将其留在输入队列中。假设我们连续两次调用get():
cin.get(animal,20);
cin.get(fruit,20); //此处有问题
第一次调用后,换行符留在了输入队列中,因此第二次调用时看到的第一个字符便是换行符,get()认为已到达行尾,因此,fruit无法成功读取内容。
get()还有另一种变体,不带任何参数的get()函数,它可读取下一个字符(即使是换行符)。因此,可以如下解决上诉代码产生的问题:
cin.get(animal,20);
cin.get();
cin.get(fruit,20);
除了连续向两个数组输入字符串可能会出现这类错误时,混合输入数字和字符串也会导致问题,看如下代码:
int main (int argc, char const *argv[])
{
using namespace std;
const int Arsize = 20;
int age;
char name[Arsize];
cin>>age;
cin.getline(name, Arsize);
cout<<"age= "<<age<<endl;
cout<<"name= "<<name<<endl;
return 0;
}
此时发现name输出为空;问题在于,当cin读取年龄时,将回车键生成的换行符留在了输入队列中,后面的getline看到换行符后,将认为是一个空行,并将一个空字符串赋给name数组。这里我们依然可以使用不带有参数的get先读取并丢弃换行符。