文章目录
一、定义和初始化string对象
如果提供一个字符串字面值,则该字面值中除了最后的那个空字符外其他所有的字符都被拷贝到新创建的string对象中去。
string s1; //默认初始化,s1是一个空字符串
string s2 = s1; //s2是s1的副本
string s3 = "hiya"; //s3是该字符串字面值的副本
string s4(10, 'c'); //s4的内容是cccccccccc
直接初始化和拷贝初始化
拷贝初始化:使用等号(=)初始化一个变量
直接初始化:不使用等号
当初始值只有一个时,直接初始化和拷贝初始化都课可;
当初始化要用到的值有多个,建议使用直接初始化
二、string对象上的操作
string的操作 | |
---|---|
os << s | 将s写到输出流os当中,返回os |
is >> s | 从is中读取字符串赋给s,字符串以空白分隔,返回is |
getline(is, s) | 从is中读取一行赋给 s,返回is |
s.empty() | s为空返回true,否则返回false |
s.size() | 返回s中字符的个数 |
s[n] | 返回s中第n个字符的引用,位置n从0记起 |
s1 + s2 | 返回s1和s2连接的结果 |
s1 = s2 | 用s2的副本代替s1中原来的字符 |
s1 == s2 | 如果s1和s2中所含的字符完全一样,则他们相等 |
s1 != s2 | |
<, <=, >, >= | 利用字符在字典中的顺序进行比较,且对字母的大小写敏感 |
读写string对象
使用IO操作符读写string对象:
int main() {
string s; //空字符串
cin >> s; //将string对象读入s,遇到空白停止
cout << s << endl;
return 0;
}
在执行读取操作时,string对象会自动忽略开头的空白(即空格符、换行符、制表符等)并从第一个真正的字符开始读起,直到遇见下一处空白为止。
string类对象的输入输出操作也是返回运算符左侧的运算对象作为其结果。因此,多个输入或者多个输出可以连写一起:
int main() {
string s1, s2; //把第一个输入读入到s1中,第二个输入读到s2中
cin >> s1 >> s2;
cout << s1 << s2 << endl;
return 0;
}
读取未知数量的string对象
int main() {
string s;
while (cin >> s) { //反复读取,直至达到文件末尾
cout << s << endl;
}
return 0;
}
while中的条件负责在读取时检测流的情况,如果流有效,也就是说没遇到文件结束标记或非法输入,那么执行while语句内部操作。
使用getline读取一整行
若希望能在最终得到的字符串中保留输入时的空白符,此时用getline运算符。getline函数的参数是一个输入流和一个string类对象,函数从给定的输入流中读入内容,直到遇见换行符为止(注意换行符也被读进来了),然后把所读入的内容存入那个string对象中去(注意不存换行符)。getline只要一遇到换行符就结束读取操作并返回结果。
int main() {
string s;
while (getline(cin, s)) { //反复读取,直至达到文件末尾
cout << s << endl;
}
return 0;
}
string 的 empty 和 size 操作
empty是string的一个成员函数,调用方法:使用点操作符指明是哪个对象执行了empty函数
//每次读入一整行,遇到空行直接跳过
while (getline(cin, line))
if (!line.empty())
cout << line << endl;
size函数返回string对象的长度
string line;
//每次读入一整行,输出其中超过80个字符的行
while (getline(cin, line))
if (line.size() > 80)
cout << line << endl;
string::size_type 类型
string 类及其他大多数标准库类型都定义了一些配套类型。通过这些配套类型,库类型的使用就能与机器无关。size_type 就是这些配套类型中的一种。
string::size_type是一个 unsigned 类型的值,而且可以保证足够大,能够存储任意 string 对象的长度。任何存储string的size操作结果的变量必须为string::size_type 类型。特别重要的是,不要把size的返回值赋给一个 int 变量。
string str("some string");
for (string::size_type index = 0; index != str.size(); index++)
cout << str[index] << endl;
对于任意一种给定的数据类型,它的 unsigned 型所能表示的最大正数值比对应的 signed 型要大一倍。这个事实表明 size_type 存储的 string 长度是 int 所能存储的两倍。为了避免溢出,保存一个 stirng 对象 size 的最安全的方法就是使用标准库类型 string::size_type。
比较string对象
相等性运算符(==和!=)分别检验两个string对象相等或不相等;
关系运算符< 、<=、 >、 >=分别检验一个string对象是否< 、<=、 >、 >=另外一个string对象。
1.如果两个string对象的长度不同,而较短string对象的每个字符都与较长string对象对应位置上的字符相同,就说较短string对象小于较长string对象。
2.如果两个string对象在某些对应的位置上不一致,则string对象比较的结果其实是string对象中第一对相异字符比较的结果。
为string对象赋值
对于string类而言,允许把一个对象的值赋给另外一个对象:
string st11(10, 'c'), str2; //str1的内容是cccccccccc;str2是一个空字符串
str1 = str2; //赋值:此时str1和str2都是空字符串
两个string对象相加
两个string对象相加得到一个新的string对象,其内容是把左侧的运算符对象与右侧的运算符对象串接而成。
string s1 = " hello, ", s2 = "world\n";
string s3 = s1 + s2; //s3的内容是hello, world\n
s1 += s2; //等价于s1 = s1 + s2
字面值和string对象相加
字面值:是一个不能改变的值,如数字、字符、字符串等。单引号内的是字符字面值,双引号内的是字符字面值。
因为标准库允许把字符字面值和字符串字面值转换成string对象,所以在需要string对象的地方就可以使用这两种字面值来替代。
string s1 = "hello", s2 = "world";
string s3 = s1 + "," + s2 + '\n';
当把string对象和字符字面值及字符串字面值混在一条语句中使用时,必须确保每个加法运算符的两侧的运算对象至少有一个是string
string s4 = s1 + ","; //正确:string对象+字面值
string s5 = "hello" + ","; //错误:字面值+字面值
string s6 = s1 + "," + "world";
//正确:等价于(s1 + ",") + "world",s1 + ","结果是string对象
string s7 = "hello" + "," + s2; //错误
三、处理string对象中的字符
我们需要单独处理string对象中的字符,
关键问题1 :如何获取字符本身。
关键问题2 :要知道能改变某个字符的特性。在cctype头文件中定义了一组标准库处理这部分工作。
cctype头文件中的函数 | |
---|---|
isalnum ( c ) | 当c是字母或数字时为真 |
isalpha ( c ) | 当c是字母时为真 |
iscntrl ( c ) | 当c是控制符时为真 |
isdigit ( c ) | 当c是数字时为真 |
isgraph ( c ) | 当c是不是空格但可打印时为真 |
islower ( c ) | 当c是小写字母时为真 |
isprint ( c ) | 当c是可打印字符时为真 |
ispunct ( c ) | 当c是标点字符时为真 |
isspace ( c ) | 当c是空白时为真 |
isupper ( c ) | 当c是大写字母时为真 |
isxdigit ( c ) | 当c是十六进制数字时为真 |
tolower ( c ) | 如果c是大写字母,输出对应的小写字母;否则原样输出c |
toupper ( c ) | 如果c是小写字母,输出对应的大写字母;否则原样输出c |
如何处理每个字符
方法:使用c++11新标准提供的一种语句:范围for语句
范围for语句:遍历给定序列的每个元素并对序列中的每个值执行某种操作,语法形式:
for (declaration : expression)
statement
expression:用于表示一个序列
declaration:定义一个变量,用于访问序列中的基础元素。每次迭代,变量会被初始化为expression部分的下一个元素值
举个栗子1:
//使用范围for语句把string对象中的每一行输出
string str("some string");
for (auto c : str) //通过使用auto关键字让编译器来决定变量c的类型
cout << c << endl;
举个栗子2:
//使用范围for语句和ispunct函数来统计string对象中标点符号的个数
int main() {
string s("Hello World!!!");
//使用decltype关键字声明计数变量punct_cnt,类型是s.size函数返回值的类型
decltype(s.size()) punct_cnt = 0;
for (auto c : s)
if (ispunct(c))
punct_cnt++;
cout << punct_cnt << " punctuation characters in " << s << endl;
return 0;
}
输出结果:3 punctuation characters in Hello World!!!
使用范围for语句改变字符串中的字符
想要改变string对象中字符的值,必须把循环变量定义成引用类型。
//把字符串改写为大写字母的形式
string s("Hello World!!!");
for(auto &c : s)
c = toupper(c); //c是一个引用,因此赋值语句将改变s中字符的值
cout << s << endl;
输出结果:HELLO WORLD!!!
只处理一部分字符
访问string对象中的单个字符有两种方式:
①使用下标
②使用迭代器
下标运算符([ ]):接收的输入参数是string :: size_type类型的值,这个参数表示要访问的字符的位置;返回值是该位置上字符的引用。
如果某个下标是带符号类型的值,将自动转换为由string :: size_type表达的无符号类型。
string对象的下标必须大于等于0而小于是,s.size()。
c++标准并不要求标准库检查下标是否合法,一旦使用了一个超出范围的下标,就会产生不可预知的后果。
举例:
//只要字符串不是常量,就能为下标运算符返回的字符赋新值
//将字符串的首字符改成大写形式
string s("some string");
if (!s.empty()) //在访问指定字符前,首先要进行判空操作
s[0] = toupper(s[0]);
输出结果:Some string
使用下标执行迭代
举例:
//把s的第一个词改为大写形式
//依次处理s中的字符直至我们处理完全部字符或者遇到一个空白
for (decltype(s.size()) index = 0;
index != s.size() && !isspace(s[index]); index++)
s[index] = toupper(s[index]);
注意检查下标的合法性
使用下标时必须确保其在合理范围内。一种简便易行的方法是:总是设下标的类型为string :: size_type,因为此类型是无符号数,确保下标不会小于0。此时,代码只需确保下标小于size()的值就可以了。
使用下标执行随机访问
//把0到15之间的十进制数转换为对应的十六进制形式
const string s = "0123456789ABCDEF";
cout << "Enter a series of numbers between 0 and 15"
<< " seperated by spaces. Hit ENTER when finished:" << endl;
string result;
string :: size_type n; //用于保存从输入流读取的数
while (cin >> n) { //在循环内部使用n作为s的下标
if (n < s.size())
result += s[n];
}
cout << "Your hex number is: " << result << endl;
运行结果:注意:
cin>>a 当输入所有数据后,通过输入EOF的方法,可以退出while(cin>>a)循环
详见(转载)
while(cin >> s)如何退出循环
https://blog.csdn.net/momo_mo520/article/details/80777221