C++_系列自学课程_第_4_课_string_《C++ Primer 第四版》

  相信学习过计算机编程的人,基本应该都接触过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 0;
}

执行情况如下所示:

[[email protected] cpp_src]# g++ test.cpp
[[email protected] 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[email protected] 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 0;
}

执行结果如下:

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

//直接输入换行

12345 //输入12345 按下换行
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() 函数计算的长度,

[[email protected] 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 0;
}

执行结果如下所示:

[[email protected] cpp_src]# g++ test.cpp
[[email protected] cpp_src]# ./a.out
0
1

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

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

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

[[email protected] 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 0;
}

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

[[email protected] cpp_src]# g++ test.cpp
[[email protected] cpp_src]# ./a.out
0
1
4

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

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

[[email protected] 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 0;
}

  执行结果如下:

[[email protected] cpp_src]# g++ test.cpp
[[email protected] cpp_src]# ./a.out
str1 is a empty string

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

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

Exp: 关于 str[n] 的使用

[[email protected] 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=0; i != str1.size(); i++)
    {
        cout<<str1[i]<<endl;
    }
    return 0;
}

执行结果如下:

[[email protected] 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]的下标还可以作为左值。如下所示:

[[email protected] 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[3]=‘y‘;
    cout<<str<<endl;

    return 0;
}

执行结果如下:

[[email protected] cpp_src]# ./a.out
str is:volcanol
after str[3]=‘y‘ the str is:volyanol

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

[[email protected] 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 0;
}

执行结果如下所示:

[[email protected] cpp_src]# g++ test.cpp
[[email protected] cpp_src]# ./a.out
hi,volanol

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

方式。

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

Exp:

[[email protected] 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 0;
}

执行结果如下:

[[email protected] cpp_src]# g++ test.cpp
[[email protected] cpp_src]# ./a.out
hi,volanol
hi,volanolnice to meet you

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

例如:

 1 #include <iostream>
 2 #include <string>
 3
 4 using std::cin;
 5 using std::cout;
 6 using std::endl;
 7 using std::string;
 8
 9 int main()
10 {
11     string str1;
12     string str2("hi,");
13
14     str1="volanol";
15
16     str1 = "hi," + str1;
17
18     str2= "hi,"+"volcanol";
19
20     cout<<str1<<endl;
21     cout<<str2<<endl;
22
23     return 0;
24 }

编译的情况如下所示:

[[email protected] cpp_src]# g++ test.cpp
test.cpp: In function ‘int main()’:
test.cpp:18: 错误:操作数类型 ‘const char [4]’ 和 ‘const char [9]’ 对双目 ‘operator+’ 而言无效
[[email protected] 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的例子如下:

[[email protected] 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(3,‘9‘);
    cout<<str<<endl;

    return 0;
}

执行结果如下:

[[email protected] cpp_src]# g++ test.cpp
[[email protected] cpp_src]# ./a.out
999

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

     string  s;  

  int main()

  {

    string s1;
      }

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

不初始化就是空字符串。

     int   a;

     int main()

  {

       int  b;

     }

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

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

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

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

读入一行的程序:

[[email protected] 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 0;
}

修改为读入一个单词:

#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 0;
}

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

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

[[email protected] 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 0;
}

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

用空格隔开。

[[email protected] 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 0;
}

修改后的程序:

[[email protected] 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 0;
}

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

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

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

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

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

时间: 2024-08-24 03:37:54

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

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

说到数组,大家应该都很熟悉,在C.Pascal.Java等语言中,都有数组的概念.在C++中也提供了对数组的支持.数组简单来说就是一堆相同 数据类型对象的集合. 这里要把握住两个要点: 相同的数据类型.集合. 一.数组 1.定义 数组是由数组存储的对象的类型名.标识符和数组维数组成一种复合数据类型. 类型名规定了可以存储在数组中的对象的类型, 标识符用来标识 数组,用来在程序中引用数组元素, 维数用来规定数组可以存放多少数组元素. 数组的定义如下所示: 类型名 数组标识符[n]; 下面是一些数组

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

在C语言中要对一个整数的某一个位进行操作需要用到很多的技巧.这种情况在C++里面通过标准库提供的一个抽象数据类型 bitset得到了改善. 一.标准库bitset类型 1.bitset的作用 bitset可以看成bit的集合,可以单独的访问集合中的某一位,访问的结果可以作为逻辑的判断的条件.使用bitset的时候可以 不关心这些bit的存储方式,而通过bitset类型提供的一套接口进行操作. 和string和vector一样,要使用bitset类型,需要报备,如下所示: #include <bi

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

最近复习C++相关内容,决定在这里记录自己复习的过程. 以前写过部分文字,但是没有坚持连续写,因此学完后 基本又忘光啦,主要是没有实践,这一次决定自学完后,在这里在复习一遍增强自己的记忆和理解程度. 一.基本内置类型 C++语言内置了一些数据类型,主要有两大类: 整型和浮点型. 整型又有:  bool型.char型.wchar_t型.short型,int型,long int型. 浮点型有: float型, double型.long double型(扩展双精度型). 我们知道不同的数据类型决定了不

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

再一次遇到 vector 这个单词; 每一次见到这个单词都感觉这个单词非常的 "高大上"; 数字遇到vector马上就可以360度旋转: 当 "电" 遇到vector,马上让交流可以变得和直流一样进行控制(德国电气工程师的矢量控制理论,目前在工控界对电机控制应用 非常广泛,是变频器控制的基础理论,可惜的是中国目前没有这方面的真正的专家, 就是IT行业中的TI公司的TMS320LF24xx系列 DSP做的事,中国的基础理论的研究真的是落后于西方发达国家很多年),而在C

C++_系列自学课程_第_8_课_指针和引用_《C++ Primer 第四版》

C语言最富有迷幻色彩的部分当属指针部分,无论是指针的定义还是指针的意义都可算是C语言中最复杂的内容.指针不但提供给了程序员直接操作硬件部分的操作接口,还提供给了程序员更多灵活的用法.C++继承这一高效的机制,同时引入了另一个与指针相似但不相同的机制: 引用. 一.引用 简单的来说,引用就是变量的别名(alias), 通过别名我们可以操作引用代表的变量. 定义一个引用的语法如下所示: 变量类型   &引用标识符 = 变量名. Exp: int iVar=10; int &iRef = iVa

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

上次说了关于表达式的一些内容,说到还有一些关于数据类型转换的内容,今天我们接着八一八C++中的数据类型转换. 一.隐式类型转换 在表达式中,有些操作符可以对多种类型的操作数进行操作, 例如 + 操作符的操作数可以同时有int型,也可以有float型, 这就引入了一个问题到底应该由什么 决定表达式的值的类型. 例如: 3.1415926 + 5; //double类型 + 整型, 结果为什么类型呢?? 3.1415926 * 2 * 3 ; //double类型 * 整型 * 整型: 得到的表达式

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

程序设计语言中大部分程序都在进行表达式的求值操作, 例如求两个数的和,求一个表达式的逻辑结果,或者通过输入输出表达式语句进行输入和输出. 这里我们对表达式进行讨论. 一.表达式 1.表达式 表达式由一个操作数或者多个操作数同操作符组合而成: 字面值是一个最简单的表达式.  表达式都会产生一个结果,如果表达式中没有操作符,则表达式 的值是操作数本身, 如果表达式中有操作符,则表达式的结果是操作符对操作数进行操作后的结果. 一般而言表达式的返回的是右值,不能给表达式赋值, 但可以获取表达式的值. E

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

前面的文章说完了表达式和类型转换的部分内容,在我参考的书里面,接下来讨论的是各种语句,包括:顺序语句.声明语句.复合语句(块语句).语句作用域 .if语句.while语句.for语句.do...while语句.break语句.continue语句.goto语句.try语句. 这里我们来讨论这些语句,为了方便讨论和记忆,我们可以将这些语句可以分为五大类:   简单语句.条件语句.循环语句.流程控制语句.异常处理.当然也可以 不这么分类,我这么说就是为了自己好理解和记忆. 一.简单语句 我将顺序语句

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

1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 struct CDAccount 7 { 8 double balance; //余额 9 double rate; //利息 10 int term; //存期 11 }; 12 13 struct Date 14 { 15 int year; 16 int month; 17 int day; 18 }; 19 20 struct Per