参考书籍:c++primer
string对象上的操作
读写string对象
int main()
{
string s;
cin >> s;
cout << s << endl;
return 0;
}
如果程序输入的是“Hello World!”,则输出是“Hello”,输出中没有任何空格。因为string对象会自动忽略开头的空白并从第一个真正的字符开始读起,直到遇到下一处空白为止。
另外,多个输入或者多个输出可以连写在一起:
int main()
{
string s1,s2;
cin >> s1>>s2;
cout << s1<<s2<< endl;
return 0;
}
输入"Hello World",则输出"helloWorld"
读取未知数量的string对象
当然我们不止可以读入两个对象,我们也可以读入未知数量的对象
int main()
{
string word;
while (cin >> word)
cout << word << endl;
}
如果流有效,也就是没遇到文件结束标记或非法输入,那么执行while语句内部的操作。此时循环体将刚刚从标准输入读取的内容。重复若干次后,一旦遇到文件结束标记或非法输入循环也就结束了。
使用getline读取一整行
有时我们希望能在最终得到的字符串中保留输入时的空白符,这时应该用getline函数代替原来的>>运算符。getline函数的参数时一个输入流和一个string对象,函数从给定的输入流中读入内容,直到遇到换行符为止(注意换行符也被读进来了)
int main()
{
string line;
while (getline(cin, line))
cout << line << endl;
}
string的empty和size操作
empty函数根据string对象是否为空返回一个对应的布尔值(0或1)
int main()
{
string line;
while (getline(cin, line))
if (!line.empty())
cout << line << endl;
}
通过改写之前的程序,可以做到只输出非空行
size函数返回string对象的长度,可以使用size函数只输出长度超过4个字符的行:
int main()
{
string line;
while (getline(cin, line))
if (line.size()>4)
cout << line << endl;
}
在这里需要注意的是:
对于size函数返回的是一个string::size_type类型的值,string类及其他大多数标准库类型都定义了几种配套的类型,类型size_type即是其中的一种:它是一个无符号的值,而且能够足够存放下任何string的大小。所有用于存放string类的size函数返回值的变量,都应该是string::size_type类型的。
比较string对象
相等性运算符(==和!=)分别检验两个string对象相等不相等,string对象相等意味着它们的长度而且所包含的字符也全都相同。其他关系运算符参照字典顺序进行比较。
1.如果两个string对象的长度不同,而且较短string对象的每个字符都与较长string对象对应位置上的字符相同,就说较短string对象小于较长string对象
2.如果两个string对象在某些对应的位置上不一致在,则string对象比较的结果其实string对象中第一对相异字符比较的结果。
例子:
string str = "Hello"
string phase = "Hello World"
string slang = "Hiya"
根据规则1可判断,对象str小于对象phase;根据规则2可判断,对象slang既大于对象phase也大于对象slang
为string对象赋值
string st1(10,'c'),st2; //st1的内容是cccccccccc;st2是一个空的字符串
st1 = st2//赋值:用st2的副本替换st1的内容 //此时st1和st2都是空字符串
两个string对象相加
其内容是把左侧的运算对象与右侧的运算对象串接而成
int main()
{
string s1 = "hello,", s2 = "world\n";
string s3 = s1 + s2;
cout << s3 << endl;
}
运行结果是“hello,world"
字面值和string对象相加
即使一种类型并非所需,我们也可以使用它,不过前提是该种类型可以自动转换成所需的类型。因为标准库允许把字符字面值和字符串字面值转换成string对象,所以在需要string对象的地方就可以使用这两种字面值来替代。例如:
string s1 = "hello", s2 = "world";
string s3 = s1 +","+ s2+'\n';
cout << s3 << endl;
运行结果是”hello,world"
注意:当把string对象和字符串及字面值混在一条语句种使用时,必须确保每个加法运算符(+)两侧的运算对象至少有一个是string:
string s4 = s1 + ","; //正确:把一个string对象和一个字面值相加
string s5 = "hello" + ","; //错误:两个运算符都不是string
string s5 = s1 + "," + "world"; //正确
string s6 = "hello" + "," + s2; //错误
处理string对象中的字符
如果想对string对象中的每个字符做点什么操作,目前最好的办法就是使用C++11新标准提供的一种语句:范围for语句。这种语句遍历给定序列中的每个元素并对序列中的每个值执行某种操作,其语法形式为:
for(declaration:expression)
statement
其中,expression部分是一个对象,用于表示一个序列。declaration部分负责定义一个变量,该变量将被用于访问序列的基础元素。每次迭代,declaration部分的变量会被初始化为expression部分的下一个元素值。我们可以使用范围语句for语句把string对象的中的字符每行一个输出出来:
string str("some string");
for (auto c : str) //对于str中的每一个字符
cout << c << endl;
每次迭代,str的下一个字符被拷贝给c,因此该循环可以读作“对于字符串str中的每个字符串str中的每个字符c”
还有个复杂一点的例子:使用范围for语句和ispunct函数来统计string对象中标点符号的个数
string s =("Hello World!!!");
decltype(s.size()) //decltype用来推测并返回括号内类型
punct_cnt = 0; //统计s中标点符号的个数
for (auto c : s) //对于s中的所有字符
if (ispunct(c))
++punct_cnt;
cout << punct_cnt << endl;
如果想改变string对象中的字符值,必须把循环变量定义成引用类型
例如,我们想把字符串中的所有小写字符变为大写形式:
string s("Hello World!!!");
for (auto& c : s)
c = toupper(c); //toupper函数接受一个字符,然后输出其大写形式
cout << s << endl;
return 0;
输出结果为:HELLO WORLD!!!
若想仅仅改变指定位置的字符,则需要添加下标:
string s("Hello World!!!");
if (!s.empty())
s[1] = toupper(s[1]);
cout << s<<endl;
return 0;
输出结果为:HEllo World!!!
将第一个词大写:
string s("Hello World!!!");
for (decltype(s.size())index = 0;
index != s.size() && !isspace(s[index]); index++) //isspace函数检测字符是否为空白
{
s[index] = toupper(s[index]);
}
cout << s << endl;
return 0;