标准库String类型

来源:互联网 发布:java web文件管理系统 编辑:程序博客网 时间:2024/06/17 00:03

引入

string类型支持长度可变的字符串,C++标准库将负责管理与存储字符相关的内存,以及提供各种有用的操作。标准库String类型的目的就是满足对字符串的一般应用。
用户要是用string类型,应包含的相关头文件:

  • #include < string >
  • using std::string;

string 对象的定义和初始化

string 对象的定义和初始化 strings1; 默认构造函数 s1 为空串 strings2(s1); 将 s2 初始化为 s1 的一个副本 strings3(“value”); 将 s3 初始化为一个字符串字面值副本 strings4(n, ‘c’); 将 s4 初始化为字符 ‘c’ 的 n 个副本

注:字符串字面值和标准库string类型不是同一种类型。

string 对象的读写

string 类型的输入操作符:

Readsand discards any leading whitespace (e.g., spaces, newlines, tabs)
读取并忽略开头所有的空白字符(如空格,换行符,制表符)。

reads characters until the next whitespace character isencountered
读取字符直至再次遇到空白字符,读取终止。

// Note: #include and using declarations must be added to compile this code     int main()     {         string s;          // empty string         cin >> s;          // read whitespace-separated string into s         cout << s << endl; // write s to the output         return 0;     }

读入未知数目的string 对象

int main()     {         string word;         // read until end-of-file, writing each word to a new line         while (cin >> word)             cout << word << endl;         return 0;     }

上例中,用输入操作符来读取 string 对象。该操作符返回所读的 istream 对象,并在读取结束后,作为 while 的判断条件。如果输入流是有效的,即还未到达文件尾且未遇到无效输入,则执行 while 循环体,并将读取到的字符串输出到标准输出。如果到达了文件尾,则跳出 while 循环。

用getline 读取整行文本

这个函数接受两个参数:一个输入流对象和一个 string 对象。getline 函数从输入流的下一行读取,并保存读取的内容到不包括换行符。和输入操作符不一样的是,getline 并不忽略行开头的换行符。只要 getline 遇到换行符,即便它是输入的第一个字符,getline 也将停止读入并返回。如果第一个字符就是换行符,则 string 参数将被置为空 string。

int main()     {         string line;         // read line at time until end-of-file         while (getline(cin, line))             cout << line << endl;         return 0;     }

由于 line 不含换行符,若要逐行输出需要自行添加。照常,我们用 endl 来输出一个换行符并刷新输出缓冲区。

由于 getline 函数返回时丢弃换行符,换行符将不会存储在 string 对象中。

string对象的操作

string对象的操作 s.empty() 如果 s 为空串,则返回 true,否则返回 false。 s.size() 返回 s 中字符的个数 s[n] 返回 s 中位置为 n 的字符,位置从 0 开始计数 s1+ s2 把 s1 和s2 连接成一个新字符串,返回新生成的字符串 s1= s2 把 s1 内容替换为 s2 的副本 v1== v2 比较 v1 与 v2的内容,相等则返回 true,否则返回 false !=,<, <=, >, and >= 保持这些操作符惯有的含义

string 的 size 和 empty 操作

int main()     {         string st("The expense of spirit\n");         cout << "The size of " << st << "is " << st.size()              << " characters, including the newline" << endl;         return 0;     }

编译并运行这个程序,得到的结果为:

 The size of The expense of spirit is 22 characters, including the newline

了解 string 对象是否空是有用的。empty() 可以更直接地回答这个问题:

     if (st.empty())          // ok: empty

如果 string 对象为空则返回 true 否则返回 false。

string::size_type 类型

string 类类型和许多其他库类型都定义了一些配套类型(companiontype)。通过这些配套类型,库类型的使用就能与机器无关(machine-independent)。size_type 就是这些配套类型中的一种。它定义为与 unsigned 型(unsignedint 或 unsignedlong)具有相同的含义,而且可以保证足够大能够存储任意 string 对象的长度。为了使用由 string 类型定义的 size_type 类型是由 string 类定义。

任何存储 string 的 size 操作结果的变量必须为 string::size_type 类型。特别重要的是,不要把 size 的返回值赋给一个 int 变量。

虽然我们不知道 string::size_type 的确切类型,但可以知道它是 unsigned 型(2.1.1 节)。对于任意一种给定的数据类型,它的 unsigned 型所能表示的最大正数值比对应的 signed 型要大倍。这个事实表明 size_type 存储的 string 长度是 int 所能存储的两倍。

因此,为了避免溢出,保存一个 stirng 对象 size 的最安全的方法就是使用标准库类型 string::size_type。

string 关系操作符

string 对象比较操作是区分大小写的,即同一个字符的大小写形式被认为是两个不同的字符。在多数计算机上,大写的字母位于小写之前:任何一个大写之母都小于任意的小写字母。

string 对象的赋值

大多数 string 库类型的赋值等操作的实现都会遇到一些效率上的问题,但值得注意的是,从概念上讲,赋值操作确实需要做一些工作。它必须先把 st1 占用的相关内存释放掉,然后再分配给 st2 足够存放 st2 副本的内存空间,最后把 st2 中的所有字符复制到新分配的内存空间。

两个 string 对象相加

string 对象的加法被定义为连接(concatenation)。也就是说,两个(或多个)string 对象可以通过使用加操作符 + 或者复合赋值操作符 +=连接起来。

和字符串字面值的连接

当进行 string 对象和字符串字面值混合连接操作时,+ 操作符的左右操作数必须至少有一个是 string 类型的:

string s1 = "hello";   // no punctuation     string s2 = "world";     string s3 = s1 + ", ";           // ok: adding a string and a literal     string s4 = "hello" + ", ";      // error: no string operand     string s5 = s1 + ", " + "world"; // ok: each + has string operand     string s6 = "hello" + ", " + s2; // error: can't add string literals

s5 的初始化方法显得有点不可思议,但这种用法和标准输入输出的串联效果是一样的(1.2 节)。本例中,string 标准库定义加操作返回一个 string 对象。这样,在对 s5 进行初始化时,子表达式 s1+ “, ” 将返回一个新 string 对象,后者再和字面值 “world\n”连接。整个初始化过程可以改写为:

string tmp = s1 + ", "; // ok: + has a string operands5 = tmp + "world";     // ok: + has a string operand

而 s6 的初始化是非法的。依次来看每个子表达式,则第一个子表达式试图把两个字符串字面值连接起来。这是不允许的,因此这个语句是错误的。

从 string 对象获取字符

string 类型通过下标操作符([])来访问 string 对象中的单个字符。下标操作符需要取一个 size_type 类型的值,来标明要访问字符的位置。这个下标中的值通常被称为“下标”或“索引”(index)。

string 对象的下标从 0 开始。如果 s 是一个 string 对象且 s 不空,则 s[0] 就是字符串的第一个字符, s[1] 就表示第二个字符(如果有的话),而 s[s.size()- 1] 则表示 s 的最后一个字符。
引用下标时如果超出下标作用范围就会引起溢出错误。

string str("some string");     for (string::size_type ix = 0; ix != str.size(); ++ix)         cout << str[ix] << endl;

下标操作可用作左值

for (string::size_type ix = 0; ix != str.size(); ++ix)         str[ix] = '*';

计算下标值

任何可产生整型值的表达式可用作下标操作符的索引。例如,假设 someval 和 someotherval 是两个整形对象,可以这样写:

str[someotherval * someval] = someval;

虽然任何整型数值都可作为索引,但索引的实际数据类型却是类型 unsigned 类型 string::size_type。

前面讲过,应该用 string::size_type 类型的变量接受 size 函数的返回值。在定义用作索引的变量时,出于同样的道理,string 对象的索引变量最好也用 string::size_type 类型。

在使用下标索引 string 对象时,必须保证索引值“在上下界范围内”。“在上下界范围内”就是指索引值是一个赋值为 size_type 类型的值,其取值范围在 0 到 string 对象长度减 1 之间。使用 string::size_type 类型或其他 unsigned 类型,就只需要检测它是否小于 string 对象的长度。

标准库不要求检查索引值,所用索引的下标越界是没有定义的,这样往往会导致严重的运行时错误。

string对象中字符的处理

string对象中字符的处理 isalnum(c) 如果 c 是字母或数字,则为 True。 isalpha(c) 如果 c 是字母,则为 true。 iscntrl(c) 如果 c 是控制字符,则为 true isdigit(c) 如果 c 是数字,则为 true。 isgraph(c) 如果 c 不是空格,但可打印,则为 true。 islower(c) 如果 c 是小写字母,则为 true。 isprint(c) 如果 c 是可打印的字符,则为 true。 ispunct(c) 如果 c 是标点符号,则 true。 isspace(c) 如果 c 是空白字符,则为 true。 isupper(c) 如果 c 是大写字母,则 true。 isxdigit(c) 如果是 c 十六进制数,则为 true。 tolower(c) 如果 c 大写字母,返回其小写字母形式,否则直接返回 c。 toupper(c) 如果 c 是小写字母,则返回其大写字母形式,否则直接返回 c。

表中的大部分函数是测试一个给定的字符是否符合条件,并返回一个 int 作为真值。如果测试失败,则该函数返回 0 ,否则返回一个(无意义的)非 0 ,表示被测字符符合条件。

表中的这些函数,可打印的字符是指那些可以表示的字符,空白字符则是空格、制表符、垂直制表符、回车符、换行符和进纸符中的任意一种;标点符号则是除了数字、字母或(可打印的)空白字符(如空格)以外的其他可打印字符。

这里给出一个例子,运用这些函数输出一给定 string 对象中标点符号的个数:

string s("Hello World!!!");     string::size_type punct_cnt = 0;     // count number of punctuation characters in s     for (string::size_type index = 0; index != s.size(); ++index)         if (ispunct(s[index]))             ++punct_cnt;     cout << punct_cnt          << " punctuation characters in " << s << endl;

这个程序的输出结果是:

 3 punctuation characters in Hello World!!!

和返回真值的函数不同的是,tolower 和 toupper 函数返回的是字符,返回实参字符本身或返回该字符相应的大小写字符。我们可以用 tolower 函数把 string 对象 s 中的字母改为小写字母,程序如下:

// convert s to lowercase     for (string::size_type index = 0; index != s.size(); ++index)         s[index] = tolower(s[index]);     cout << s << endl;

得到的结果为:

 hello world!!!

建议:采用 C 标准库头文件的 C++ 版本
C++ 标准库除了定义了一些选定于 C++ 的设施外,还包括 C 标准库。C++ 中的头文件 cctype 其实就是利用了 C 标准库函数,这些库函数就定义在 C 标准库的 ctype.h 头文件中。
C 标准库头文件命名形式为 name 而 C++ 版本则命名为 cname ,少了后缀,.h 而在头文件名前加了 c 表示这个头文件源自 C 标准库。因此,cctype 与 ctype.h 文件的内容是一样的,只是采用了更适合 C++程序的形式。特别地,cname 头文件中定义的名字都定义在命名空间 std 内,而 .h 版本中的名字却不是这样。
通常,C++ 程序中应采用 cname 这种头文件的版本,而不采用 name.h 版本,这样,标准库中的名字在命名空间 std 中保持一致。使用 .h 版本会给程序员带来负担,因为他们必须记得哪些标准库名字是从 C 继承来的,而哪些是 C++ 所特有的。

原创粉丝点击