相信学习过计算机编程的人,基本应该都接触过C语言,在C语言中处理字符串大家一定多遇到过,

也都知道处理字符串非常麻烦,而在C++里面,由标准库string类提供对可变长的字符串的支持。下面

来看看string类的特性。

1、使用的先决条件

  在使用标准库之前必须包含相应的头文件, 要使用string类型,就需要包含相应的头文件,如下所示:

#include <string>

  在使用iostream的时候,我们未来引用iostream里面的类,前面需要加上  std::  来表示引用的是标准

IO库提供的功能,同样在使用string类的时候,需要加上一个表示作用域的限制修饰的说明,如下所示:

std::string  str;    //定义一个string的对象str

  在每一次定义的时候都要这样使用 std:: 很麻烦,C++提供了一种更方便的机制,如下:

using std::string;

  在源文件里面加上上面这一句, 在使用的时候,就可以直接使用 string来定义对象,如下所示:

string  str;

2、string类的初始化

  string类提供了多种初始化方法:

  1)  string   str;  //初始化为空字符串, 调用默认构造函数,

  2)   string   str2="volcanol";  // 赋值初始化,复制str2为"volcanol"的一个副本,

  3) string str1("volcanol");     //直接初始化,调用初始化函,

  4) string str1="volcanol"

    string str2(str1);   //利用 string对象初始化string str对象

  5) string  str1(3,'c');  //初始化str1为"ccc",

3、string对象的读写

  可以利用iostream提供的输入和输出机制来对string对象进行操作。

  输入:

string str;
cin>>str;

  这样就可以通过标准输入来输入字符到string对象中, 要注意的是:

  A)  cin在输入的的时候会忽略开始的空白符(空格,制表符,换行符),然后从非空白字符开始读入

  B)  cin在输入的时候,会在再次遇到空白字符后结束输入。

    这里的意思就是:  通过 cin>>str读入的字符流不会包含 endl 换行符,因此如果要换行的话,就

需要自己添加换行符。

  同样可以利用cout<<来输出string对象,如下所示:

cout<<str<<endl;

下面是一段例子代码:

#include <iostream>
#include <string> using std::cin;
using std::cout;
using std::endl;
using std::string; int main(int argc,char *argv[])
{
string str;
while(cin>>str)
cout<<str<<endl; return ;
}

执行情况如下所示:

[root@localhost cpp_src]# g++ test.cpp
[root@localhost cpp_src]# ./a.out
a //输入a 然后按回车键
a
ab //输入ab,然后按下回车键
ab aaa bbb ccc //输入aaa bbb ccc 按下回车键
aaa
bbb
ccc

  按下 ctrl+d 就会退出上面的程序,  这里while循环判断 cin>>str 是否遇到 end-of-file 结束符,

当按下ctrl+d后, cin>>str 返回 false, 结束循环。

4、getline函数的使用

  通过调用 getline函数可以一次输入一行, 这里需要注意的是:getline不会忽略开始的换行符,而是会

忽略最后的换行符,而且getline在遇到 空格、制表符的时候,不会结束一行的输入,直到遇到endl换行符。

  getline()接受两个参数:  getline(cin, str);

Exp:

[root@localhost cpp_src]# cat test.cpp
#include <iostream>
#include <string> using std::cin;
using std::cout;
using std::endl;
using std::string; int main(int argc,char *argv[])
{
string str;
while(getline(cin,str))
cout<<str<<endl; return ;
}

执行结果如下:

[root@localhost cpp_src]# g++ test.cpp
[root@localhost cpp_src]# ./a.out
aaa bbb ccc ddd //输入aaa bbb ccc ddd按下换行
aaa bbb ccc ddd
//直接输入换行 //直接输入换行 //输入12345 按下换行

  这里需要注意的是: getline不会忽略一行开头的换行符,而且输入后在string对象最后不会加上endl换行符。

5、string的操作

  string类型提供了很多的操作, 下面我们来看一下:

  string  str;

  str.size();  返回str对象的长度

  str.empty(); 判断str是否是空字符串

  str[n];  下标操作,取其中的一个字符

  str1 + str2;

  str2 =str1;

  str1 == str2

  还有 != ,  <, <=,  >,>= 这些比较操作,这些操作与整数型的操作的意义一样,但是string的

比较是按照字典序,同时区分大小写,  满足下面的关系:A < a

  

Exp:  关于str.size() 函数计算的长度,

[root@localhost cpp_src]# cat test.cpp
#include <iostream>
#include <string> using std::cin;
using std::cout;
using std::endl;
using std::string; int main()
{
string str1;
string str2; cout<<str1.size()<<endl;
cout<<sizeof("")<<endl; return ;
}

执行结果如下所示:

[root@localhost cpp_src]# g++ test.cpp
[root@localhost cpp_src]# ./a.out

  通过上面的例子可见, str.size()函数计算长度的时候并不包括最后的null字符'\0', 这一点需要注意。

  还有一个特殊的地方: 就是 sizeof对 str对象的计算,得到的结果,与str.size 得到的结果不一样,

因此需要注意。如下代码所示:

[root@localhost cpp_src]# cat test.cpp
#include <iostream>
#include <string> using std::cin;
using std::cout;
using std::endl;
using std::string; int main()
{
string str1;
string str2; cout<<str1.size()<<endl;
cout<<sizeof("")<<endl;
cout<<sizeof(str1)<<endl;
return ;
}

  上面代码的执行结果如下所示:

[root@localhost cpp_src]# g++ test.cpp
[root@localhost cpp_src]# ./a.out

  这里是因为 string对象会保留4个字节来存储string对象的长度。

Exp: 关于 str.empty()函数的使用

[root@localhost cpp_src]# cat test.cpp
#include <iostream>
#include <string> using std::cin;
using std::cout;
using std::endl;
using std::string; int main()
{
string str1;
string str2; if(str1.empty())
{
cout<<"str1 is a empty string"<<endl;
}
else
{
cout<<"str1 is not a empty string"<<endl;
} return ;
}

  执行结果如下:

[root@localhost cpp_src]# g++ test.cpp
[root@localhost cpp_src]# ./a.out
str1 is a empty string

  这里可以知道的是,如果string对象是一个空字符串,那么 str.empty()函数返回true。

其实也可以通过 str.size( )==0 来判断string对象是不是为空。因为 str.size()不会计算最后的 ‘\0'.

Exp: 关于 str[n] 的使用

[root@localhost cpp_src]# cat test.cpp
#include <iostream>
#include <string> using std::cin;
using std::cout;
using std::endl;
using std::string; int main()
{
string str1;
str1="volanol"; for(string::size_type i=; i != str1.size(); i++)
{
cout<<str1[i]<<endl;
}
return ;
}

执行结果如下:

[root@localhost cpp_src]# ./a.out
v
o
l
a
n
o
l

  这个代码使用了上面说的:  str1 = 字符串字面值的赋值方法, 同时使用了 str[n]的下标引用方法。

这里有一点需要说明:  string::size_type 是定义在string库中的类型,这个类型专门用来计算string的长度

的。  同时还有一点: string对象的下标从0开始,到 str.size - 1 结束,就是说:   0<= n <= str.size() - 1

  str[n]的下标还可以作为左值。如下所示:

[root@localhost cpp_src]# cat test.cpp
#include <iostream>
#include <string> using std::cin;
using std::cout;
using std::endl;
using std::string; int main()
{
string str("volcanol");
cout<<"str is:"<<str<<endl; cout<<"after str[3]='y' the str is:";
str[]='y';
cout<<str<<endl; return ;
}

执行结果如下:

[root@localhost cpp_src]# ./a.out
str is:volcanol
after str[]='y' the str is:volyanol

Exp:  关于字符串的相加  str1 + str2

[root@localhost cpp_src]# cat test.cpp
#include <iostream>
#include <string> using std::cin;
using std::cout;
using std::endl;
using std::string; int main()
{
string str1;
string str2("hi,"); str1="volanol"; string str3= str2+ str1;
cout<<str3<<endl; return ;
}

执行结果如下所示:

[root@localhost cpp_src]# g++ test.cpp
[root@localhost cpp_src]# ./a.out
hi,volanol

这段代码,演示了  string类型的 str1 + str2 的效果,同时演示了  string str("volcanol"); 这样的直接初始化

方式。

  string对象的 + 操作可以与字符串字面值进行操作,如下:

Exp:

[root@localhost cpp_src]# cat test.cpp
#include <iostream>
#include <string> using std::cin;
using std::cout;
using std::endl;
using std::string; int main()
{
string str1;
string str2("hi,"); str1="volanol"; string str3= str2+ str1;
cout<<str3<<endl; string str4= str3 + "nice to meet you"; //字符串字面值 + 运算
cout<<str4<<endl; return ;
}

执行结果如下:

[root@localhost cpp_src]# g++ test.cpp
[root@localhost cpp_src]# ./a.out
hi,volanol
hi,volanolnice to meet you

  同时需要注意的是:  + 操作符使用的时候,其左、右操作必须有一个是 string对象,否则是错误的。

例如:

 #include <iostream>
#include <string> using std::cin;
using std::cout;
using std::endl;
using std::string; int main()
{
string str1;
string str2("hi,"); str1="volanol"; str1 = "hi," + str1; str2= "hi,"+"volcanol"; cout<<str1<<endl;
cout<<str2<<endl; return ;
}

编译的情况如下所示:

[root@localhost cpp_src]# g++ test.cpp
test.cpp: In function ‘int main()’:
test.cpp:: 错误:操作数类型 ‘const char []’ 和 ‘const char []’ 对双目 ‘operator+’ 而言无效
[root@localhost cpp_src]#

  可以发现 18 行出现错误了, 说 const char[4] 和 const char [9] 不能用双目运算符进行计算,

原因上面的提示信息已经说的很明白了,const char类型不支持+ 操作。

关于书中的习题:

1、什么是默认构造函数

  默认构造函数是类构造对象是默认调用的构造函数,如果用户不编写用户自定义的构造函数,则系统

默认会提供一个默认的构造函数。

2、例举三种初始化string对象的方法

  A:  string  str;  默认构造函数

B :   string   str("volcnaol");   利用字符串字面值直接初始化

    string   str1(str);   利用string对象直接初始化

  C   string  str = "volcanol";  利用字符串字面值复制初始化

    string  str1 = str;  利用string对象复制初始化

  D:  string  str(3,  'c');

方法D的例子如下:

[root@localhost cpp_src]# cat test.cpp
#include <iostream>
#include <string> using std::cin;
using std::cout;
using std::endl;
using std::string; int main()
{
string str(,'');
cout<<str<<endl; return ;
}

执行结果如下:

[root@localhost cpp_src]# g++ test.cpp
[root@localhost cpp_src]# ./a.out

3、 下面 s和s1的值分别是什么

     string  s;  

  int main()

  {

    string s1;
}

这里 s和s1 都是空字符串,  这个地方考察了一个知识点未初始化的对象的初值是什么。  string对象

不初始化就是空字符串。

     int   a;

     int main()

  {

       int  b;

     }

   如上面所示, 则 a = 0;   而b将会是一个随机值。 这是因为全局的内置类型如果不初始化,则系统默认会

初始化为0,  而局部变量的内置类型就会是一个随机值。因此变量在定义的时候最好要初始化一下,保证在使用

之前就是有一个值,可以避免一些莫名其妙的错误。

习题4、编写程序实现从标准输入每次读入一行文本, 然后改下程序每次读入一个单词。

读入一行的程序:

[root@localhost cpp_src]# cat test.cpp
#include <iostream>
#include <string> using std::cin;
using std::cout;
using std::endl;
using std::string; int main()
{
string str;
getline(cin,str);
cout<<str<<endl; return ;
}

修改为读入一个单词:

#include <iostream>
#include <string> using std::cin;
using std::cout;
using std::endl;
using std::string; int main()
{
string str;
//getline(cin,str);
cin>>str;
cout<<str<<endl; return ;
}

习题5: 编写一个程序读入两个字符串,测试是否相等,如果不相等,则指出哪一个较大; 测试两个是否等长,

如果不等长,则指出哪一个较长。

[root@localhost cpp_src]# cat test.cpp
#include <iostream>
#include <string> using std::cin;
using std::cout;
using std::endl;
using std::string; int main()
{
string str1;
string str2; cin>>str1>>str2;
cout<<"str1 is:"<<str1<<endl;
cout<<"str2 is:"<<str2<<endl; if(str1==str2)
cout<<"str1 == str2"<<endl;
else if(str1 > str2)
cout<<"str1 > str"<<endl;
else
cout<<"str1 < str2"<<endl; if(str1.size() == str2.size())
cout<<"str1 and str2 have same length"<<endl;
else if(str1.size() > str2.size())
cout<<"str1 is longger than str2"<<endl;
else
cout<<"str1 is shorter than strw"<<endl; return ;
}

习题6: 编写一个程序读入多个string对象,然后连接成1个更大的string对象输出; 然后改下程序,将相邻的string对象

用空格隔开。

[root@localhost cpp_src]# cat test.cpp
#include <iostream>
#include <string> using std::cin;
using std::cout;
using std::endl;
using std::string; int main()
{
string str1;
string str2;
string str3;
string str4; cin>>str1>>str2>>str3>>str4; string str5;
str5=str1 + str2 + str3 + str4;
cout<<str5<<endl; return ;
}

修改后的程序:

[root@localhost cpp_src]# cat test.cpp
#include <iostream>
#include <string> using std::cin;
using std::cout;
using std::endl;
using std::string; int main()
{
string str1;
string str2;
string str3;
string str4; cin>>str1>>str2>>str3>>str4; string str5;
str5=str1 +" "+ str2+" " + str3+" " + str4;
cout<<str5<<endl; return ;
}

7、下面的程序合法吗,实现什么功能

string s;
cout<<s[]<<endl;

  合法,这个程序最终会输出一个换行号。

    这个地方尤其要注意,我开始的时候也做错啦,经过测试才知道是对的。

最后一个题目不做啦,下次补上。

C++_系列自学课程_第_4_课_string_《C++ Primer 第四版》的更多相关文章

  1. C++_系列自学课程_第_7_课_数组_《C++ Primer 第四版》

    说到数组,大家应该都很熟悉,在C.Pascal.Java等语言中,都有数组的概念.在C++中也提供了对数组的支持.数组简单来说就是一堆相同 数据类型对象的集合. 这里要把握住两个要点: 相同的数据类型 ...

  2. C++_系列自学课程_第_6_课_bitset集_《C++ Primer 第四版》

    在C语言中要对一个整数的某一个位进行操作需要用到很多的技巧.这种情况在C++里面通过标准库提供的一个抽象数据类型 bitset得到了改善. 一.标准库bitset类型 1.bitset的作用 bits ...

  3. C++_系列自学课程_第_5_课_vector容器_《C++ Primer 第四版》

    再一次遇到 vector 这个单词; 每一次见到这个单词都感觉这个单词非常的 "高大上"; 数字遇到vector马上就可以360度旋转: 当 "电" 遇到vec ...

  4. C++_系列自学课程_第_3_课_变量和基本类型_《C++ Primer 第四版》

    最近复习C++相关内容,决定在这里记录自己复习的过程. 以前写过部分文字,但是没有坚持连续写,因此学完后 基本又忘光啦,主要是没有实践,这一次决定自学完后,在这里在复习一遍增强自己的记忆和理解程度. ...

  5. C++_系列自学课程_第_12_课_结构体

    #include <iostream> #include <string> using namespace std; struct CDAccount { double bal ...

  6. C++_系列自学课程_第_12_课_语句_《C++ Primer 第四版》

    前面的文章说完了表达式和类型转换的部分内容,在我参考的书里面,接下来讨论的是各种语句,包括:顺序语句.声明语句.复合语句(块语句).语句作用域 .if语句.while语句.for语句.do...whi ...

  7. C++_系列自学课程_第_11_课_类型转换_《C++ Primer 第四版》

    上次说了关于表达式的一些内容,说到还有一些关于数据类型转换的内容,今天我们接着八一八C++中的数据类型转换. 一.隐式类型转换 在表达式中,有些操作符可以对多种类型的操作数进行操作, 例如 + 操作符 ...

  8. C++_系列自学课程_第_10_课_表达式_《C++ Primer 第四版》

    程序设计语言中大部分程序都在进行表达式的求值操作, 例如求两个数的和,求一个表达式的逻辑结果,或者通过输入输出表达式语句进行输入和输出. 这里我们对表达式进行讨论. 一.表达式 1.表达式 表达式由一 ...

  9. C++_系列自学课程_第_9_课_C语言风格字符串_《C++ Primer 第四版》

    前面说了写关于数组和指针的内容,这次在这里讨论一下字符串,讨论一下C语言风格的字符串. 在C语言里面我们利用字符数组来对字符串进行处理, 在C++里面我们前面说过一种类类型string可以对字符串进行 ...

随机推荐

  1. Got the Best Employee of the year 2015 Star Award

    Got "The Best Employee of the year 2015 Star Award" from the company, thanks to all that h ...

  2. char varchar nchar nvarcharar到底有多大区别

    首先说明下,ASP.NET MVC系列还在龟速翻译中. 工作好多年,基础知识甚是薄弱,决定以后在coding(cv操作)的时候尽量多google下,然后总结下来,目的有三:     1. 加深自己的理 ...

  3. JS获取剪贴板图片之后的格式选择与压缩问题

    前言 某年某月的某一天,突然发现博客服务器上上传的图片都比较大,一些很小的截图都有几百kb,本来服务器带宽就慢,不优化一下说不过去. 问题细述 特别说明:本文代码因为只是用于我自己后台写markdow ...

  4. Appium的安装-MAC平台

    其实Appium的安装方式主要有两种: 1)自己安装配置nodejs的环境,然后通过npm进行appium的安装 2)直接下载官网提供的dmg进行安装,dmg里面已经有nodejs的环境和appium ...

  5. 2013 duilib入门简明教程 -- 自绘控件 (15)

        在[2013 duilib入门简明教程 -- 复杂控件介绍 (13)]中虽然介绍了界面设计器上的所有控件,但是还有一些控件并没有被放到界面设计器上,还有一些常用控件duilib并没有提供(比如 ...

  6. SQL Server 默认跟踪(Default Trace)

    一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 基础知识(Rudimentary Knowledge) 查看默认跟踪信息(Default Tr ...

  7. Sql Server系列:数据类型转换函数

    T-SQL提供了两个显示转换的函数:CAST函数和CONVERT函数. 1. CAST函数 语法: CAST ( expression AS data_type [ ( length ) ] ) 示例 ...

  8. WPF MVVM框架下,VM界面写控件

    MVVM正常就是在View页面写样式,ViewModel页面写逻辑,但是有的时候纯在View页面写样式并不能满足需求.我最近的这个项目就遇到了,因此只能在VM页面去写样式控件,然后绑定到View页面. ...

  9. Hawk 3.1 动态页面,ajax,瀑布流

    不少朋友反映,Hawk的手气不错,好像没法处理动态页面.其实很容易,比其他软件都容易,让我慢慢道来. 1. 什么是动态页面 很多网站,在刷新的时候会返回页面的全部内容,但实际上只需要更新一部分,这样可 ...

  10. linux下遍历目录

    遍历目录的主要思想 由于目录就是一颗树,所以遍历目录就转换为遍历一棵树.谈到树的遍历就再熟悉不过了,有树的前序.层次和后序遍历,我使用的是前序遍历,后序遍历和前序遍历本质上一样,而层次遍历要比前两个麻 ...