很多应用程序都需要处理字符串。C语言在string.h(C++中为cstring)中提供了一系列的字符串函数,很多早期的C++实现为处理字符串提供了自己的类。

string类是由头文件string支持的(注意,头文件string.h和cstring支持对C-风格字符串进行操纵的C库字符串函数,但不支持string类)。

要使用类,关键在于知道它的公有接口,而string类包含大量的方法,其中包括了若干构造函数,用于将字符串赋给变量、合并字符串、

比较字符串和访问各个元素的重载运算符以及用于在字符串中查找字符和子字符串的工具等。

简而言之,string类包含的内容很多。

========================================= 

一、构造字符串

首先看string的构造函数。

毕竟对于类而言,最重要的内容之一是,有哪些方法可以用于创建其对象

ctor用于标识构造函数。

实际上string是模板具体化basic_string<char>的一个typedef。同时省略了与内存管理相关的参数。

size_type是一个依赖于实现的整型,是在头文件string中定义的。

string类讲string::npos定义为字符串的最大长度,通常为unsigned int的最大值。

NBTSNull-terminated string 表示以空字符结束的字符串——传统字符串;

接下来看一下一个关于string类的demo程序:

 //str1.cpp -- introducing the string class
#include <iostream>
#include <string>
//using string constructors int main()
{
using namespace std;
string one("Lottery Winner!"); //ctor #1
cout<<one<<endl; //overloaded << string two(, '$'); //ctor #2
cout<<two<<endl; string three(one); //ctor #3
cout<<three<<endl; one +="Oops!"; //overloaded +=
cout<<one<<endl; two = "Sorry! That was";
three[]='p'; string four; //ctor #4
four = two + three; //overloaded + , =
cout << four << endl; char alls[] = "All's well that ends well";
string five(alls,); //ctor #5
cout<<five<<"!\n"; string sixe(alls+, alls+); //ctor #6
cout<<six<<", "; string seven(&five[], &five[]); //ctor #6 again
cout<<seven<<"...\n"; sting eight(four, , ); //ctor #7
cout<<eight<<" in motion!"<<endl;
return ;
}

程序说明:

可以将string对象初始化为常规的C-风格字符串,然后使用<<重载运算符来显示它。

string one("Lottery Winner!"); //ctor #1

cout<<one<<endl; //overloaded <<

接下来的构造函数将string对象two初始化为由20个$字符组成的字符串:

string two(20, '$');     //ctor #2

复制构造函数将string对象three初始化为string对象one:

string three(one);    //ctor #3

重载+=运算符将字符串"Oops!"附加到字符串one的后面:

one += "Oops!";    //overloaded +=

这里是将一个C-风格字符串附加到一个string对象后面。但+=运算符被多次重载,以便能够附加string对象和单个字符;

同样,=运算符也被重载,以便可以将string对象、C-风格字符串或char值赋给string对象:

two = "Sorry! That was";

two = one;

two = '?';

重载[ ]运算符,使得可以用数组表示法访问string对象中的各个字符:

three[0] = 'P';

默认构造函数创建一个以后可以对其进行赋值的空字符串:

string four;

four = two + three;  //该行使用了+运算符创建了一个临时string对象,然后使用重载=运算符将它赋给对象four。

第5个构造函数将一个C-风格字符串和一个整数作为参数,其中的整数参数表示要复制多少个字符:

char alls[] = "All's well that ends well";

string five(alls,20);   # ctor #5

第6个构造函数有一个模板参数:

template<class Iter> string(Iter begin, Iter end);

begin和end像指针那样,指向内存中两个位置。构造函数将使用begin和end指向的位置之间的值,对string对象进行初始化。

[begin, end)来自数学中,意味着包括begin,但不包括end在内的区间。

也就是说,end指向被使用的最后一个值后面的一个位置。

string six(alls+6, alls+10);  //ctor #6

数组名相当于指针,alls+6和alls+10的类型都是char* 。因此使用模板时,将用类型char *替换Iter。

第一个参数指向了数组alls中的第一个w,第二个参数指向了第一个well后面的空格。

因此,six将被初始化为字符串“well”。

第7个构造函数将一个string对象的部分内容复制到构造的对象中:

string eight(four, 7, 16);   //ctor #7

上述语句从four的第8个字符开始,将16个字符复制到eight中。

接下来讨论两个C++11新增的构造函数

构造函数string(string && str)类似于复制构造函数,导致新创建的string为str的副本。但与复制构造函数不同的是,它不保证将str视为const。

这种构造函数是移动构造函数(move constructor)。在有些情况下,编译器可以使用它而不是复制构造函数,以优化性能。

构造函数string(initializer_list<char>il)让您能够将列表初始化语法用于string类。也就是说,它使得下面这样的声明是合法的:

string piano_man = {'L', 'i', 's', 'z', 't'};

string comp_land {'L', 'i', 's', 'p'};

这个构造函数确实实现了让列表初始化语法普遍实用的意图;

========================================= 

二、string类输入

对于类,很有帮助的一点,知道有哪些输入方式可用。

对于C-风格字符串,有3种方式

char info[100];

cin >> info;                     //读word,一段字符串

cin.getline(info, 100);    //读一行,丢弃末尾换行符\n;

cin.get(info, 100);         //读一行,包括末尾换行符\n;

对于string对象,有两种方式:

string stuff;

cin>>stuff;                // read a word

getline(cin, stuff)      //read a line, discard \n

两个版本的getline()都有一个可选参数,用于指定使用哪个字符来确定输入的边界:

cin.getline(info, 100, ':')    //read up to :   discard :

getline(stuff, ':')               //read up to :    discard :

在功能上一个主要的区别在于,string版本的getline()将自动调整string对象的大小,使之刚好能够存储输入的字符

char fname[10];

string lname;

cin >> fname;                  //如果超过9个字符长度的词,会出现问题;

cin >> lname;                   //可以读取很长很长的词

cin.getline(fname, 10);     //可能缩短字符串

getline(cin, fname);           //没有缩短字符串

自动调整大小的功能,让string版本的getline()不需要指定读取多少个字符的数值参数。

另外我们发现对于string版本而言,cin是作为getline函数的参数。如下:

// lname作为string对象

getline(cin, lname);

这种规则也适用于>>,如下:

operator>>(cin, lname);    //等效于 cin>> lname;

读取C-风格字符串的函数是istream类的方法;所以对于C-风格字符串而言,cin是调用对象;所以有:

cin.getline(fname, 10);   //cin对象调用了getline方法

cin >> info;                     //cin对象重载了>>运算符;如果info是string对象,则可以自动调整对象大小以满足输入的实际情况;如果info是字符数组,则要注意输入的字符串长度不要超过字符数组的长度。

string类的输入函数会自动调整目标string的大小,使之与输入匹配。但也存在一些限制

第一个限制是string对象的最大允许长度;由常量string::npos指定。这通常是最大的unsigned int值。//对于普通的交互式输入,这不会带来实际的限制;但如果试图将整个文件的内容读取到单个string对象中,这可能成为一种限制因素;

第二个限制是程序可以使用的内存量

string版本的getline()函数从输入中读取字符,并将其存储到目标string中,直到发生下列三种情况:

1、到达文件尾;在这种情况下,输入流的eofbit将被设置,这意味着方法fail()和eof()都将返回true;

2、遇到分界符(默认为\n);在这种情况下,将把分界字符从输入流中删除,但不存储它;

3、读取的字符数达到最大允许值;string::npos和可供分配的内存字节数中较小的一个,在这种情况下,将设置输入流的failbit,这意味着方法fail()将返回true。

输入流对象有一个统计系统,用于跟踪流的错误状态。在这个系统中,检测到文件尾后将设置eofbit寄存器,检测到输入错误时将设置failbit寄存器,出现无法识别的故障时将设置badbit寄存器,一切顺利时将设置goodbit寄存器。后续会深入讨论这一点。

string版本的operator>>()函数的行为:它不断读取,直到遇到空白字符,并将其留在输入队列中;

空白字符:空格、换行符、制表符;更普遍地说,任何将其作为参数调用isspace(),该函数返回true的字符。

========================================= 

三、使用字符串

String类对全部6个关系运算符都进行了重载。

对于每个关系运算符都以3种方式进行重载;以便能够将string对象与另一个string对象、C-风格字符串进行比较、C-风格字符串与string对象进行比较;

string snake1("cobra");

string snake2("coral");

char snake3[20] = "anaconda";

if(snake2 <snake1)             //operator < (const string &, const string &)

..

if(snake1 == snake3)       // operator == (const string &, const char *)

...

if(snake3 != snake2)          //operator != (const char *, const string &)

...

可以确定字符串的长度。size()和length()成员函数都返回字符串中的字符数:

if (snake1.length() == snake2.size())

cout<<"Both strings have the same length.\n"

为什么这两个函数完成相同的任务呢?length()成员来自较早版本的string类,而size()则是为提供STL兼容性而添加的。

find()方法:可以以多种不同的方式在字符串中搜索给定的子字符串或字符。

========================================= 

四、string还提供了哪些功能

string库提供了很多其他工具,包括完成下述功能的函数:

1、删除字符串的部分或全部内容;

2、用一个字符串的部分或全部内容替换另一个字符串的部分或全部内容;

3、将数据插入到字符串中或删除字符串中的数据;

4、从字符串中提取子字符串;

5、将一个字符串中的内容复制到另一个字符串中;

6、交换两个字符串的内容;

7、将一个字符串的部分或全部内容与另一个字符串的部分或全部内容进行比较;

这些函数大多数都被重载,以便能够同时处理C-风格字符串和string对象;

============================================== 

五、字符串种类

事实上string库实际上是基于一个模板类的:

template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>>

basic_string{...};

模板basic_string有4个具体化,每个具体化都有一个typedef名称:

typedef basic_string<char> string;

typedef basic_string<wchar_t> wstring;

typedef basic_string<char16_t> u16string;

typedef basic_string<char32_t> u32string;

这让您能够使用基于类型wchar_t,char16_t,char32_t,char的字符串。

C++_类入门4-String类的更多相关文章

  1. String类比较,String类运算比较,String运算

    String类比较,String类运算比较 >>>>>>>>>>>>>>>>>>>&g ...

  2. C++程序设计入门(上) string类的基本用法

    string类中的函数 1. 构造 2. 追加 3. 赋值 4. 位置与清除 5. 长度与容量 6. 比较 7. 子串 8. 搜索 9. 运算符 追加字符串 string s1("Welc ...

  3. C++_类入门3-嵌套类

    可以将类B声明在另一个类中.在另一个类A中声明的类B被称为嵌套类(nested class). 类A的成员函数可以创建和使用嵌套类B的对象. 当且仅当声明为公有部分时,才能在类A的外面使用嵌套类.而且 ...

  4. 常用类Object,String类详解

    -------------------- String -----------------------1.求字符串长度 public int length()//返回该字符串的长度 String st ...

  5. Unicode与ASCiI之间有什么区别?java当中的转义字符 Character类的使用 String类的使用

    ASCII码 称为 美国标准信息交换码 (American standard code of Information Interchange) 其中一共有多少个码?2的7次幂 128个 Unicode ...

  6. java自学第4期——:Scanner类、匿名对象介绍、Random类、ArrayList集合、标准类格式、String类、static静态、Arrays工具类、Math类(1)

    一.Scanner类 1.api简介: 应用程序编程接口 2.Scanner类: 作用:获取键盘输入的数据 位置: java.util.Scanner. 使用:使用成员方法nextInt() 和 ne ...

  7. C++_类入门2-使用类

    进一步探讨类的特征,重点是类设计技术,而不是通用原理.一些特性很容易,一些特性很微妙. 运算符重载 目的是使C++操作更美观,更接近于内置类型的操作. 隐藏了内部的实现机理,并强调了实质. 格式:op ...

  8. C#中是否可以继承String类

    C#中是否可以继承String类? 答:String类是sealed类故不可以继承. 当对一个类应用 sealed 修饰符时,此修饰符会阻止其他类从该类继承. 在下面的示例中,类 HoverTree ...

  9. 【Java 进阶篇】【第一课】String类

    引用 String类包含在java.lang包中.这个包会在Java启动的时候自动import,所以可以当做一个内置类(built-in class).我们不需要显式的使用import引入String ...

  10. Java基础(30):String对象的常用方法与实例(String类)

    Java 中 String 类的常用方法 Ⅰ String 类提供了许多用来处理字符串的方法,例如,获取字符串长度.对字符串进行截取.将字符串转换为大写或小写.字符串分割等,下面我们就来领略它的强大之 ...

随机推荐

  1. MySQL日期数据类型总结

    MySQL:MySQL日期数据类型.MySQL时间类型使用总结 MySQL 日期类型:日期格式.所占存储空间.日期范围 比较. 日期类型        存储空间      日期格式           ...

  2. SaeMysql操作示例

    新浪sae的官方说明文档:http://apidoc.sinaapp.com/sae/SaeMysql.html Class SaeMysql 具体实现:http://apidoc.sinaapp.c ...

  3. 717. 1-bit and 2-bit Characters最后一位数是否为0

    [抄题]: We have two special characters. The first character can be represented by one bit 0. The secon ...

  4. 3-No resource found that matches the given name 'Theme.AppCompat.Light 的完美解决方案

    转载:http://www.360doc.com/content/15/0316/15/9200790_455576135.shtml 由于我在配置安卓环境时也碰到了类似问题,用这篇博客解决了主要问题 ...

  5. R dataframe 遗忘, which 矩阵搜索

    A data frame is used for storing data tables. It is a list of vectors of equal length. For example, ...

  6. Luogu 1580 [NOIP2016] 换教室

    先用Floyed做亮点之间的最短路,设计dp,记dp[i][j][0]为到第i节课,换了j次课,当前有没有换课达到的期望耗费体力最小值 方程(太长了还是看代码吧):dp[i][j][0]<-dp ...

  7. vue.js的一些模板指令简述

    1.模板指令都是写在<template></template>html里面   v-text : value是什么就显示什么,如果value里面有html的标签,也会直接显示出 ...

  8. Tomcat与Web.xml配置

    1.编码配置 <Connector acceptCount=”100″ connectionTimeout=”20000″ disableUploadTimeout=”true” enableL ...

  9. Invoke()的使用

    (最近在看协程) Invoke()方法是一种委托机制 Invoke ( "SendMsg", 3 ), 意思是3秒之后调用 SendMsg() 方法 使用时应该注意以下几点: 1. ...

  10. Vue vue-resource发送Http请求

    vue-resource 1.cnpm install vue-resource --save 2.在main.js中import VueResource from 'vue-resource' 3. ...