标准库string类基本用法

1 基本介绍与头文件

标准库类型string表示可变长的字符序列,使用string类型必须首先包含string头文件。string定义在命名空间std中。

// 头文件以及命名空间
#include <string>
using std::string;

2 string对象的定义和初始化

string s1;				// 默认初始化,s1是一个空串
string s2(s1);			// s2是s1的副本
string s2 = s1;			// 等价于s2(s1),s2是s1的副本
string s3("value");		// s3是字面值“value"的副本,除了字面值最后的空字符外
string s3 = "value";	// 等价于s3("value"),s3是字面值”value“的副本
string s4(n,'c');		// 把s4初始化为连续n个字符c组成的串

2.1 拷贝初始化

string s5 = "hello";	// 使用=号初始化一个变量,实际为拷贝初始化

2.2 直接初始化

string s6("hello");		// 不使用=号初始化一个变量,为直接初始化
string s7(5, 'c');		// 直接初始化,s7内容为ccccc

对于多个值进行初始化的情况,一般使用直接初始化,当然也可以使用拷贝初始化的方式,需要显示的创建一个(临时)对象用户拷贝

string s8 = string(5,'c');	// 拷贝初始化,s8的内容是ccccc
// 本质上等价于
string temp(5,'c');			// temp的内容是ccccc
string s8 = temp;			// 将temp拷贝给s8

可以看到,尽管初始化s8的语句合法,但是和初始化s7的方式比价可读性更差,也没有任何补偿优势,不建议使用。

3 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如果s1和s2所含的字符不完全 一样,则他们不相等;对大小写敏感
<, <=, >, >=利用字符在字典中的顺序进行比较,且对字母大小写敏感

4 string操作实例

4.1 is >> s 和 os << s

** 4.1.1 读写string对象**

/*
 * function: 演示读取string对象
 * 
 * 2020-11-26
 */

#include <iostream>
#include <string>

using std::string;

int main(int argc, char *argv[])
{
    string s1, s2;                          // 默认初始化,s1,s2是空串

    std::cin >> s1 >> s2;                   // 从标准输入给s1, s2赋值,以空格分隔

    std::cout << s1 << s2 << std::endl;     // 将s1, s2输出到标准输出

    return 0;
}       

读取string对象
注意:1.在执行读取操作时,string对象会自动忽略开头的空白(即空格符、换行符、制表符等)并从第一个真正的字符开始读起,直到遇见下一处空白。2.和内置类型的输入输出操作一样,string对象的此类操作也是返回运算符左侧的运算对象作为结果。因此,多个输入或者多个输出可以连写在一起。

4.1.2 读取未知数量的string对象

/*
 * function: 演示读取未知数量的string对象
 *
 * 2020-11-26
 */

#include <iostream>
#include <string>

using std::string;

int main(int argc, char *argv[])
{
    string word;               // 默认初始化,s为空串

    while (std::cin >> word)   // 反复读取,直到文件末尾
    {   
        std::cout << word << std::endl;     // 逐个输出单词,每个单词后面紧跟一个换行符
    }   

    return 0;
}

读取位置数量的string对象
注意:最后使用ctrl+d表文件结尾,在linux中ctrl+d 不是发送信号,而是表示一个特殊的二进制值,表示 EOF。

4.3 getline(is, s)

/*
 * function: 演示使用getline读取string对象的一整行
 *
 * 2020-11-26
 */

#include <iostream>
#include <string>

using std::string;

int main(int argc, char *argv[])
{
    string line;

    while (getline(std::cin, line))     // 每次读取一行,直到文件结尾
    {   
        std::cout << line << std::endl; 
    }   

    return 0;
}

使用getlin读取一整行

4.4 s.empty()和s.size()

4.4.1 empty()的基本用法

/*
 * function: 演示s.empty()的一般用法
 *
 * 2020-11-27
 */

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main(int argc, char *argv[])
{
    ifstream in("test.txt");

    string line;

    while (getline(in, line))   // 从test.txt文件中,依次读取一行,直到文件末尾
    {   
        if (!line.empty())      // 如果为空行,则不打印
        {   
            std::cout << line << std::endl;
        }   
    }   

    return 0;
}

empty()
4.4.2 s.size()的基本用法

/*
 * function: 演示s.size()的一般用法
 *
 * 2020-11-27
 */

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main(int argc, char *argv[])
{
    ifstream in("test.txt");

    string line;

    while (getline(in, line))   // 从test.txt文件中,依次读取一行,直到文件末尾
    {   
        if (line.size() > 6)    // 一行大于6个字符才打印
        {   
            std::cout << line << std::endl;
        }   
    }   

    return 0;
}

size()

4.5 比较string对象

string类定义了几种用于比较字符串的运算符。这些比较运算符逐一比较string对象中字符,并且对大小写敏感。

1.如果两个string对象的长度不同,而且较短的string对象的每个字符都与较长的string对象对应位置上的字符形同,就说较短的string对象小于较长string对象。
2.如果两个string对象在某些对应的位置上不一致,则string对象比较的结构其实是string对象中第一对相异字符的比较结果。

4.6 string对象相加

/*
 * function: 演示两个string相加以及字面值与string对象相加操作
 *
 * 2020-11-29
 */

#include <iostream>
#include <string>

using std::string;

int main(int argc, char *argv[])
{
    string s1("hello");
    string s2("world");

    std::cout << "s1+s2=" << s1 + s2 << std::endl;

    string s3 = s1 + "," + "world";

    std::cout << "s3=" << s3 << std::endl;

    //string s4 = "," + "world" + s1;   // 错误两个运算对象都不是string
    
    return 0;
}

s1+s2

5 处理string对象中的字符

在cctype头文件中定义了一组标准库函数处理这部分工作

函数名意义
isalnum( c )当c是字母或数字时为真
isalpha( c )当c是字母时为真
isdigit( c )当c是数字时为真
islower( c )当c是小写字母时为真
isupper( c )当c是大写字母时为真
isxdigit( c )当c是十六进制数子时为真
tolower( c )如果c是大写字母,输出对应的小写字母;否则原样输出c
toupper( c )如果c是小写字母,输出对应的大写字母;否则原样输出c
iscntrl( c )当c是控制字符时为真
isprint( c )当c是可打印字符时为真(即c是空格或c具有有可视形式)
ispunct( c )当c是标点符号时为真(即c不是控制字符、数字、字母、可打印空白中的一种)
isspace( c )当c是空白时时为真(即c是空格、横向制表符、纵向制表符、回车符、换行符、进纸符中的一种)
isgraph( c )当c不是空格但可以打印时为真

5.1 处理每个字符

处理每个字符?使用基于范围的for 语句
如果想对string对象中的每个字符做点儿什么操作,目前最好的办法是使用C++11新标准提供的一种语句:范围for(range for)语句。这种语句遍历给定序列中的每个元素并对序列中的每个值执行某种操作,其语法形式是:

for(declaration:expression)
	statement
	/*
	expression部分是一个对象,用于表示一个序列。
 	declaration部分负责定义一个变量,该变量将被用于访问序列中的基础元素。
	每次迭代,declaration部分的变量会被初始化为expression部分的下一个元素值。
	*/
/*
 * function: 演示使用范围for语句遍历string对象的每个字符
 *
 * 2020-11-30
 */

#include <iostream>
#include <string>

using std::string;

int main(int argc, char *argv[])
{
    string str("hello world");

    for (auto c : str)  // 对于str中的每个字符
    {   
        std::cout << c << std::endl;    // 输出当前字符,后面紧跟一个换行符
    }   

    return 0;
}

string_c

/*
 * function: 演示使用范围for语句遍历string对象的每个字符并且修改
 *
 * 2020-11-30
 */

#include <iostream>
#include <string>
#include <cctype>

using std::string;

int main(int argc, char *argv[])
{
    string str("hello world");

    std::cout << str <<std:: endl;
    for (auto &c : str)  // 对于str中的每个字符(需要修改字符c,注意:c是引用)
    {   
        c = toupper(c);  // 判断是不是小写字母,如果是小写字母改为大写

        std::cout << c;
    }   
    std::cout << std::endl;

    return 0;
}

string_c

5.2 处理部分字符

只处理一部分字符?
如果要处理string对象中的每一个字符,使用范围for语句是个好主意。然而,有时我们需要访问的只是其中一个字符,或者访问多个字符但遇到某个条件就要停下来。例如,同样是将字符改为大写形式,不过新的要求不再是对整个字符串都这样做,而仅仅把string对象中的第一个字母或第一个单词大写化。
要想访问string对象中的单个字符有两种方式:一种是使用下标,另外一种是使用迭代器,这个方法以后在介绍。

下标运算符([])接收的输入参数是string::size_type类型的值,这个参数表示要访问的字符的位置:返回值是该位置上字符的引用。

注意:string的下标必须大于等于0而小于s.size().
使用超出此范围的下标将引发不可预知的结果,依次类推,使用下标访问空string也会引发不可预知的结果。

/*
 * function: 演示使用下标运算符修改第一个字符
 *
 * 2020-11-30
 */

#include <iostream>
#include <string>
#include <cctype>

using std::string;

int main(int argc, char *argv[])
{
    string str("hello world");

    std::cout << str <<std:: endl;

    if (!str.empty())   // 注意判断string是否为空
    {   
        str[0] = toupper(str[0]);  // 修改第一个字符
    }   

    std::cout << str << std::endl;

    return 0;
}

string_c

/*
 * function: 演示使用下标运算符修改第一个单词
 *
 * 2020-11-30
 */

#include <iostream>
#include <string>
#include <cctype>

using std::string;

int main(int argc, char *argv[])
{
    string str("hello world");

    std::cout << str <<std:: endl;

    // 判断sting对象不为空
    if (!str.empty())
    {   
        // 依次处理str中的字符直到处理完所用字符或者遇到第一个空白
        for (decltype(str.size()) ii = 0; ii != str.size() && !isspace(str[ii]); ++ii)
        {   
            str[ii] = toupper(str[ii]);
        }   
    }   

    std::cout << str << std::endl;

    return 0;
}

string_c

扩展阅读

1 string::size_type类型介绍

string类及其他大多数标准库类型都定义了几种配套的类型。这些配套类型体现了标准库类型与机器无关的特性,类型size_type 即是其中的一种。在具体使用的时候,通过作用域操作符来表明名字size_type是在类string中定义的。
尽管我们不太清楚string::size_type类型的细节,但有一点是可以肯定的:它是一个无符号类型的值,而且能足够存放下任何string对象的大小。所有用于存放string类的size函数返回值的变量,都应该是string::size_type类型的。
在c++11新标准中,允许编译器通过auto类型说明符或者decltype类型指示符来推断变量的类型:

	// len的类型是string::size_typelen
	auto len = s.size();	
	decltype(s.size()) len = s.size();	

注意:如果一条表达式中已经有了size()函数就不要再使用int了,这样可以避免混用int和unsigned可能带来的问题。

例如:假设n是一个具有负值的int,则表达式s.size()<n的判断结果几乎肯定是true。因为负值n会自动的转换成一个比较大的无符号值。

已标记关键词 清除标记
课程简介: 历经半个多月的时间,Debug亲自撸的 “企业员工角色权限管理平台” 终于完成了。正如字面意思,本课程讲解的是一个真正意义上的、企业级的项目实战,主要介绍了企业级应用系统中后端应用权限的管理,其中主要涵盖了六大核心业务模块、十几张数据库表。 其中的核心业务模块主要包括用户模块、部门模块、岗位模块、角色模块、菜单模块和系统日志模块;与此同时,Debug还亲自撸了额外的附属模块,包括字典管理模块、商品分模块以及考勤管理模块等等,主要是为了更好地巩固相应的技术栈以及企业应用系统业务模块的开发流程! 核心技术栈列表: 值得介绍的是,本课程在技术栈层面涵盖了前端和后端的大部分常用技术,包括Spring Boot、Spring MVC、Mybatis、Mybatis-Plus、Shiro(身份认证与资源授权跟会话等等)、Spring AOP、防止XSS攻击、防止SQL注入攻击、过滤器Filter、验证码Kaptcha、热部署插件Devtools、POI、Vue、LayUI、ElementUI、JQuery、HTML、Bootstrap、Freemarker、一键打包部署运行工具Wagon等等,如下图所示: 课程内容与收益: 总的来说,本课程是一门具有很强实践性质的“项目实战”课程,即“企业应用员工角色权限管理平台”,主要介绍了当前企业级应用系统中员工、部门、岗位、角色、权限、菜单以及其他实体模块的管理;其中,还重点讲解了如何基于Shiro的资源授权实现员工-角色-操作权限、员工-角色-数据权限的管理;在课程的最后,还介绍了如何实现一键打包上传部署运行项目等等。如下图所示为本权限管理平台的数据库设计图: 以下为项目整体的运行效果截图: 值得一提的是,在本课程中,Debug也向各位小伙伴介绍了如何在企业级应用系统业务模块的开发中,前端到后端再到数据库,最后再到服务器的上线部署运行等流程,如下图所示:
©️2020 CSDN 皮肤主题: 游动-白 设计师:上身试试 返回首页