字符串是存储在内存的连续字节中的一系列字符。C++语言中有两种风格的字符串,分别是C风格的字符串和 string 类型的字符串。
C风格的字符串就是一个特殊的字符数组,以空字符('\0')表示字符串的结束。要将字符串存储到数组中,最常用的方法有两种——将数组初始化为字符串常量(字符串字面值)、将键盘或文件输入读入到数组中,如下面程序所示:
//string.cpp -- storing strings in an array 在数组中存储字符串
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
const int Size = 15; //定义符号常量来指定数组的长度
char name1[Size]; //创建数组name1
char name2[Size] = "C++owboy"; //创建数组name2并初始化
cout << "Howdy! I'm " << name2;
cout << "! what's your name?\n";
cin >> name1; //将用户输入的字符串存储到name1中
cout << "Well, " << name1 << ",your name has ";
cout << strlen(name1) << " letters and is stored\n"; //返回储存在数组中的字符串的长度
cout << "in an array of " << sizeof name1 << " bytes.\n"; //返回整个数组的长度
cout << "Your initial is " << name1[0] << ".\n"; //提取数组第一个元素
name2[3] = '\0'; //将数组name2的第四个元素设置为空字符
cout << "Here are the first 3 characters of my name: "; //使得字符串在第三个字符之后即结束
cout << name2 << endl;
return 0;
}
上面的程序存在一个缺陷,即当用户输入中间用空格隔开的多个单词的字符串时,无法正常读取,如下面程序所示:
//instr1.cpp -- reading more than one string 读取多个字符串
#include <iostream>
using namespace std;
int main()
{
const int ArSize = 20;
char name[ArSize];
char dessert[ArSize];
cout << "Enter your name:\n";
cin >> name;
cout << "Enter your favorite food:\n";
cin >> dessert;
cout << "I have some delicious " << dessert;
cout << " for you, " << name << ".\n";
return 0;
}
上述程序运行后,当第一次需要用户输入名字的时候,如果用户输入了不连续的多个字符串,例如Jason Gao,则程序将直接运行完毕,不进行下一个问题的询问和等待用户输入,因为cin使用空白(空格、制表符和换行符)来确定字符串的结束位置,这意味着cin在获取字符数组输入时只读取一个单词,读取单词后,cin将该字符串放到数组中,并自动在结尾添加空字符。为实现整行取,可使用getline()和get()这两个面向行的类成员函数。 getline()函数读取整行,它使用通过回车键输入的换行符来确定输入结尾(在保存字符串时,用空字符来替换换行符)。完整程序示例:
#include <iostream>
using namespace std;
int main()
{
const int ArSize = 20;
char name[ArSize];
char dessert[ArSize];
cout << "Enter your name:\n";
cin.getline(name, ArSize); //调用方法:cin.getline(param1,param2)
cout << "Enter your favorite food:\n"; //param1--用来存储输入行的数组的名称
cin.getline(dessert, ArSize); //param2--要读取的字符数
cout << "I have some delicious " << dessert;
cout << " for you, " << name << ".\n";
return 0;
}
get()函数读取整行,与getline()接受的参数相同,解释参数的方式相同,也读取到行尾,但get将换行符保留在输入队列中。所以如果连续调用: cin.get(name,ArSize); cin.get(dessert,ArSize); 由于第一次调用后,换行符将留在输入队列中,因此第二次调用时看到的第一个字符便是换行符,则get()认为已到达行尾,而没有发现任何可读取的内容。可利用get的两种变体来解决: 一、使用不带任何参数的cin.get()调用可读取下一个字符(即使是换行符),如: cin.get(name,ArSize); cin.get(); cin.get(dessert,ArSize); 二、使用get()的方式将两个类成员函数拼接起来(合并),如: cin.get(name,ArSize).get(); 完整程序示例:
#include <iostream>
using namespace std;
int main()
{
const int ArSize = 20;
char name[ArSize];
char dessert[ArSize];
cout << "Enter your name:\n";
cin.get(name, ArSize).get();
cout << "Enter your favorite food:\n";
cin.get(dessert, ArSize);
cin.get();
cout << "I have some delicious " << dessert;
cout << " for you, " << name << ".\n";
return 0;
}
string 类型的字符串是通过 string 类型的变量而不是字符数组来存储字符串。要使用 string 类,必须在程序中包含头文件 string。string 类位于名称空间 std 中,因此必须提供一条 using 编译指令、或 using 声明、或使用 std::string 来引用它。下面程序说明了 string 对象和字符数组之间的一些相同点和不同点。
//strtype1.cpp -- using the C++ string class
#include <iostream>
#include <string>
using namespace std;
int main()
{
char char1[20];
char char2[20] = "jaguar";
string str1;
string str2 = "panther";
cout << "Enter a kind of feline: ";
cin >> char1;
cout << "Enter another kind of feline: ";
cin >> str1;
cout << "Here are some felines:\n";
cout << char1 << " " << char2 << " " << str1 << " " << str2 << endl;
cout << "The third letter in " << char2 << " is " << char2[2] << endl;
cout << "The third leeter in " << str2 << " is " << str2[2] << endl;
return 0;
}
从这个示例可知,在很多方面,使用 string 对象的方式与使用字符数组相同。
- 可以使用C风格字符串来初始化 string 对象。
- 可以使用 cin 来将键盘输入存储到 string 对象中。
- 可以使用 cout 来显示 string 对象。
- 可以使用数组表示法来访问存储在 string 对象中的字符。
在数组中提到过,不能将一个数组赋给另一个数组,但使用 string 类时,可以将一个 string 对象赋给另一个 string 对象,还可以使用运算符 + 将两个 string 对象合并起来(对于字符数组,需要使用 strcpy() 和 strcat() 函数),以及使用运算符 += 将字符串附加到 string 对象的末尾。示例程序如下:
//strtype2.cpp -- assigning,adding,and appending
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s1 = "penguin";
string s2, s3;
cout << "You can assign one string object to another: s2 = s1\n"; //赋值
s2 = s1;
cout << "s1: " << s1 << ", s2: " << s2 << endl;
cout << "You can assign a C-style string to a string object.\n";
cout << "s2 = \"buzzard\"\n";
s2 = "buzzard";
cout << "s2: " << s2 << endl;
cout << "You can concatenate strings: s3 = s1 + s2\n";
s3 = s1 + s2;
cout << "s3: " << s3 << endl;
cout << "You can append strings.\n";
s1 += s2;
cout << "s1 += s2 yields s1 = " << s1 << endl;
s2 += " for a day";
cout << "s2 += \" for a day\" yields s2 = " << s2 << endl;
return 0;
}
下面的程序示例对用于 string 对象的技术和用于字符数组的技术进行了比较。(注意: strcpy() 和 strcat() 函数在win10的VS2015中编译时会报错,可在项目→属性→C/C++→预处理器→预处理器定义中加入语句:_CRT_SECURE_NO_WARNINGS)
//strtype3.cpp -- more string class features
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
int main()
{
char charr1[20];
char charr2[20] = "jaguar";
string str1;
string str2 = "panther";
//assignment for string objects and character arrays
str1 = str2; //copy str2 to str1
strcpy(charr1, charr2); //copy char2 to char1
//appending for string objects and character arrays
str1 += " paste"; //add paste to end of str1
strcat(charr1, " juice"); //add juice to end of char1
//finding the length of a string object and a C-style string
int len1 = str1.size(); //obtain length of str1
int len2 = strlen(charr1); //obtain length of char1
cout << "The string " << str1 << " contains " << len1 << " characters.\n";
cout << "The string " << charr1 << " contains " << len2 << " characters.\n";
return 0;
}
对于 string 对象,面向行的读取时,使用的句法不同,示例程序如下:
//strtype4.cpp -- line input 整行读取
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
int main()
{
char charr[20];
string str;
cout << "Length of string in charr before input: " //未输入内容之前,数组内容未定义,函数strlen()从数组的第一个元素开始计算字节数,直到遇到
<< strlen(charr) << endl; //空字符,对于未被初始化的数据,第一个空字符出现的位置是随机的,所以数组长度不一定是0。
cout << "Length of string in str before input: "
<< str.size() << endl; //未输入内容之前,string对象的长度被自动设置为0
cout << "Enter a line of text:\n";
cin.getline(charr, 20); //数组读取整行内容
cout << "You entered: " << charr << endl;
cout << "Enter another line of text:\n";
getline(cin, str); //string读取整行内容
cout << "You entered: " << str << endl;
cout << "Length of string in charr after input: "
<< strlen(charr) << endl;
cout << "Length of string in str after input: "
<< str.size() << endl;
return 0;
}
|