c++字符串与c字符串
c++字符串与c风格字符串
- 1. C风格的字符串
- 2. 字符串字面量
- 3.C++ std::string 类
- 3.1 C风格字符串的优势和劣势
- 3.2 使用string类
- 3.2.1 std::string 字面量
- 3.2.2 c++字符串的数值转换
- (1)字符串转数值
- (2)数值转字符串
- 3.2.3 c++常用字符串函数
- 3.2.4 原始字符串字面量
你编写的每个应用程序都会使用某种类型的字符串。使用老式C语言时,没有太多的选择,只
能使用普通的以null结尾的字符数组来表示字符串。遗憾的是,这种表示方式会导致很多问题,例 如会导致安全攻击的缓冲区溢出。C++ STL包含了一个安全易用的std::string类,这个类没有这些 缺点。
1. C风格的字符串
在C语言中,字符串表示为字符的数组。字符串中的最后一个字符是空字符(\0’)
C++包含一些来自C语言的字符串操作函数,它们在< cstring >头文件中定义。
函数名称 | 说明 |
---|---|
strlen() | 返回字符串长度,不包含空字符‘\0’的一字节,字符串长度不等于字符个数 |
strcpy() | 字符串拷贝 |
C和C++中的sizeof操作符可用于获得给定数据类型或变量的大小。例如,sizeof(char)返回1,
因为char的大小是1字节。但是,在C风格的字符串中,sizeof()和strlen()是不同的。绝对不要通过 sizeof()获得字符串的大小。如果C风格的字符串存储为char[],则sizeof()返回字符串使用的实际内存,包括‘\0’字符。例如:
char text[]= "abcdef";
size_t s1= sizeof(text); // is 7
size_t s2 = strlen(text); // is 6
但是,如果C风格的字符串存储为char*, sizeof()就返回指针的大小!例如:
const char* text2 = "abcdef";
size_t s3 = sizeof(text2); // is platform-dependent
size_t s4 = strlen(text2); // is 6
在32位模式编译时,s3的值为4,而在64位编译时,s3的值为8,因为这返回的是指针const char*
的大小。可在<cstring>头文件中找到操作字符串的C函数的完整列表。
在Microsoft Visual Studio中使用C风格的字符串函数时,编译器可能会给 出安全相关的警告甚或错误,说明这些函数已经被废弃了。使用其他C标准库函数可以避免这些警告,例如
strcpy_s()和strcat_s(),这些函数是“安全C库” (ISO/IEC TR 24731)标准的一部分。然而,最好的解决方案是切换到C++的 string 类。
2. 字符串字面量
注意,C++程序中编写的字符串要用引号包围。例如,下面的代码输出字符串"hello",这段代码
包含这个字符串本身,而不是一个包含这个字符串的变量:
cout <<"hello" << endl;
在上面的代码中,"hello”是一个字符串字面量(string literal),因为这个字符串以值的形式写出,
而不是一个变量。与字符串字面量关联的真正内存在内存的只读部分中。通过这种方式,编译器可 以重用等价字符串字面量的引用,来优化内存的使用。也就是说,即使一个程序使用了 500次"hello"字符串字面量,编译器也只在内存中创建一个hello实例。这种技术称为字面量池
(literal pooling)。
字符串字面量可以赋值给变量,但因为字符串字面量位于内存的只读部分,且使用了字面量池,
所以这样做会产生风险。C++标准正式指出:字符串字面量的类型为“n个const char的数组”,然而为了向后兼容较老的不支持const的代码,大部分编译器不会强制程序将字符串字面量赋值给 const char类型的变量。这些编译器允许将字符串赋值给不带有const的char,而且整个程序可以 正常运行,除非试图修改字符串。一般情况下,试图修改字符串的行为是没有定义的。它可能会导 致程序崩溃;可能使程序继续执行,看起来没有什么莫名其妙的副作用;可能不加通告地忽略修改 行为;可能修改行为是有效的,这完全取决于编译器。例如,下面的代码展示了未定义的行为:
char* ptr = "hello"; // Assign the string literal to a variable.
ptr[1] = 'a '; // Undefined behavior!
一种更安全的编码方法是在引用字符串常量时,使用指向 const 字符的指针。下面的代码包含
同样的 bug,但由于这段代码将字符串字面量赋值给 const char* 所以编译器会捕捉到任何写入只 读内存的企图。
const char* ptr = "hello"; // Assign the string literal to a variable.
ptr[ 1] = 'a'; // Error! Attempts to write to read-only memory
还可以将字符串字面量用作字符数组(char®的初始值。这种情况下,编译器会创建一个足以放 下这个字符串的数组,然后将字符串复制到这个数组。因此,编译器不会将字面量放在只读的内存中,也不会进行字面量的池操作。
char arr [] = "hello"; // Compiler takes care of creating appropriate sized // character array arr.
arr[ 1] = 'a '; // The contents can be modified.
3.C++ std::string 类
C++提供了一个得到极大改善的字符串概念,并作为标准库的一部分提供了这个字符串的实现。 在C++中,std::string是一个类(实际上是basic string模板类的一个实例),这个类支持
<cstring >中提 供的许多功能,还能自动管理内存分配。string类在std名称空间的< string >头文件中定义。
3.1 C风格字符串的优势和劣势
优势 | 劣势 |
---|---|
很简单,底层使用了基本的字符类型和数组结构 | 为了模拟一等字符串数据类型,需要付出很多努力 |
量级轻,如果使用得当,只会占用所需的内存 | 使用难度大,而且很容易产生难以找到的内存bug |
很低级,因此可以按操作原始内存的方式轻松操作和复制字符串 | 没有利用C++的面向对象特性 |
能够很好地被C语言程序员理解 | 要求程序员了解底层的表示方式 |
3.2 使用string类
尽管string是一个类,但是几乎总是可以把string当做内建类型使用。事实上,把string想象为
简单类型更容易发挥string的作用。通过运算符重载的神奇作用,C++的string使用起来比C字符串容易得多。
3.2.1 std::string 字面量
源代码中的字符串字面量通常解释为const char*。使用用户定义的标准字面量”s”可以把字符串
字面量解释为std::string。例如:
auto stringl = "Hello World"; // stringl will be a const char*
auto string2 = "Hello World"s; // string2 will be an std::string
3.2.2 c++字符串的数值转换
数值转字符串 | 字符串转数值 |
---|---|
to_string(int val) | int stoi(const string& str, size_t *idx=0, int base=10) |
to_string(unsigned val) | long stol(const string& str, size_t *idx=0, int base=10) |
to_string(long val) | unsigned long stoul(const string& str, size_t *idx=0, int base=10) |
(1)字符串转数值
int stoi(const string& str, size_t *idx=0, int base=10)
stoi
将n进制字符串转为十进制,第二个参数是字符串起始位置,第三个参数表示n进制
也可以直接用重载的 int stoi(const string& str)
,默认字符串为十进制,起始位置为0,制
#include<string>
#include <iostream>
#include <exception>
using namespace std;
int main()
{int i=0;try{i = stoi("FEEF", 0, 16);//int i = stoi("我的"); 输入非法时,可以捕获异常"invalid stoi argument"}catch (exception e){cout << e.what() << endl;}system("pause");return 0;
}
输出结果:
(2)数值转字符串
转十进制可以用to_string
,但是低版本的编译器可能不支持
转多进制可以用_itoa_s
,但似乎没有安全机制,导致无法捕获异常
char cstr[20];_itoa_s(100,cstr,2);cout << cstr << endl;
转多进制还可以用 stringstream
#include<string>
#include <iostream>
#include <sstream>
#include <bitset>
using namespace std;
int main()
{int num = 1234;stringstream stream;//转二进制stream << bitset<16>(num);cout << stream.str() <<endl;stream.str(""); //清空缓存,如果注释掉,那么会输出所有的历史结果//转8进制stream << oct << num;cout << stream.str() << endl;stream.str("");//转十六进制stream << hex << num;cout << stream.str() << endl;stream.str("");system("pause");return 0;
}
结果:
如果需要把格式化后的字符串通过>>输出到字符串, 必须每次都调用clear()方法
3.2.3 c++常用字符串函数
函数 | 功能 |
---|---|
append | 将字符添加到字符串的末尾 |
at | 返回字符串中的指定位置处的元素的引用 |
c_str | 将字符串的内容转换为 C 样式空终止字符串 |
data | 转换为字符数组的字符串的内容 |
empty | 测试是否该字符串包含的字符 |
erase | 从指定位置字符串中移除元素或某个范围的元素 |
find | 与指定的字符序列匹配的子字符串的第一个匹配项的向前搜索字符串 |
find_first_not_of | 搜索与指定任何的字符串元素相匹配的第一个字符的字符串 |
find_first_of | 搜索与指定任何的字符串元素相匹配的第一个字符的字符串 |
rfind | 向后方向中的首次出现的与指定的字符序列匹配的子字符串搜索字符串 |
pop_back | 清除该字符串的最后一个元素 |
push_back | 该字符串的末尾添加一个元素 |
insert | 将某个元素的数目或某个范围的元素插入到指定位置的字符串 |
length | 返回字符串中的元素的当前数目 |
replace | 替换指定的字符或从其他区域或字符串或 C 字符串复制的字符在字符串中位于指定位置处的元素 |
substr | 从指定位置的字符串开头的复制的子字符串的最大字符数 |
3.2.4 原始字符串字面量
原始字符串字面量(raw string literal)是可以横跨多行代码的字符串字面量,不需要转义嵌入的双引号,像\t和\1!这种转义序列不按照转义序列的方式处理,而是按照普通文本的方式处理。如果像下面这样编写普通的字符串字面量,那么会收到一个编译器错误,因为 字符串包含了未转义的引号:
string str = "Hello "World"!// Error!
对于普通的字符串,必须转义双引号,如下所示:
string str = "Hello \"World\"!";
对于原始字符串字面量,就不需要转义引号了。
原始字符串字面量的写法:
string str = R"(Hello "World"!)";
原始字符串字面量可以跨越多行代码。例如,如果像下面这样编写普通的字符串字面量,那么会收到一个编译器错误,因为普通的字符串字面量不能跨越多行:
string str = "Line 1
Line 2 with \t"; // Error!
可使用如下原始字符串字面量来替代:
string str = R"(Line 1
Line 2 with \t)";
这也说明,使用原始字符串字面量时,\t转义字符没有替换为实际的制表符字符,而是按照字面形式保存。将str写入控制台得到的输出如下所示:
Line 1
Line 2 with \t
因为原始字符串字面量以)“结尾,所以使用这个语法时,不能在字符串中嵌入)”。例如,下面的 字符串是不合法的,因为在这个字符串中间包含了一个)”:
string str = R"(The characters )"n are embedded in this string)" // Error!
如果需要嵌入)",则需要使用扩展的原始字符串字面量语法,如下所示:
R"d-char-sequence(r-char-sequence)d-char-sequence"
r-char-sequence
是实际的原始字符串。d-char-sequence
是可选的分隔符序列,原始字符串首尾的分隔符序列应该一致。分隔符序列最多能有16个字符。应选择未出现在原始字符串字面量中的序列作为分隔符序列。上面的例子可以改用唯一的分隔符序列:
string str = R"-(The characters )" are embedded in this string)-";
在操作数据库查询字符串和正则表达式等字符串时,原始字符串字面量可以令程序的编写更加方便。
c++字符串与c字符串相关推荐
- Go 学习笔记(51)— Go 标准库之 strings(字符串比较、字符串前后缀、字符串统计、字符串索引、字符串包含、字符串转换、字符串复制、字符串替换、字符串去除、字符串分割和连接)
1. 概述说明 import "strings" strings 包实现了用于操作字符的简单函数. strings 包与 bytes 包中的函数用法基本一样. 2. 主要函数 2. ...
- python字符串基本形式_python字符串常用方式
class str(basestring): """ str(object='') -> string Return a nice string represent ...
- Java案例——统计字符串中每个字符串出现的次数
统计字符串中每个字符串出现的次数 需求: 1.键盘录入一个字符串,要求统计字符串中每个字符串出现的次数 举例:键盘录入"aababcabcdabcde" 在控制台输出:" ...
- 如何在Python中对字符串进行子字符串化
Python offers many ways to substring a string. It is often called 'slicing'. Python提供了许多对字符串进行子字符串化的 ...
- java代码中fastjson生成字符串和解析字符串的方法和javascript文件中字符串和json数组之间的转换方法...
1.java代码中fastjson生成字符串和解析字符串的方法 List<TemplateFull> templateFulls = new ArrayList<TemplateFu ...
- c语言将字母存入字符串,C语言把资料读入字符串以及将字符串写入文件
C语言把文件读入字符串以及将字符串写入文件 1.纯C实现 FILE *fp; if ((fp = fopen("example.txt", "rb")) == ...
- oracle 数据有引号,oracle插入字符串数据时字符串中有'单引号问题
使用insert into(field1,field2...) values('val1','val2'...)时,若值中有单引号时会报错. 处理方法:判断一下val1,val2中是否含有单引号,若含 ...
- R语言使用str_locate函数和str_locate_all函数来定位特定字符串或者字符串模式在字符串中的位置:str_locate函数第一个位置、str_locate_all函数定位所有位置
R语言使用str_locate函数和str_locate_all函数来定位特定字符串或者字符串模式在字符串中的位置:str_locate函数第一个位置.str_locate_all函数定位所有位置 目 ...
- 写一个函数,2 个参数,1 个字符串,1 个字节数,返回截取的字符串,要求字符串中的中文不能出现乱码
题目要求: 写一个函数,2 个参数,1 个字符串,1 个字节数,返回截取的字符串,要求字符串中的中文不能出现乱码. 如("我ABC",4)应该截为"我AB", ...
- 字符串留用与字符串池
1.关于字符串操作对应用程序性能的影响 字符串相等性检查是应用程序常见的操作,于此同时,这也是一种严重损害性能的操作.执行序号(字符串的二进制)相等行检查时,CLR会进行以下操作: 1.判断字符串的长 ...
最新文章
- C++之匿名对象与析构函数的关系
- 九度 1408 寻找表达式 (中缀转后缀)
- qt 解决中文乱码问题
- nginx反向代理和rewrite进行解决跨域问题、去掉url中的一部分字符串,通过nginx正则生成新的url
- 玩转异步 JS :async/await 简明教程(附视频下载)
- 题目1452:搬寝室(dp题目)
- centos 7 一键安装gitlab
- gdb coredump oracle,GDB + CoreDump 调试记录
- 开源容器云openshift pdf_OpenShift和Kubernetes的10个最重要的区别
- 802.11无线WIFI协议学习笔记(一)
- AI 医生“战疫”在前线
- 流落在帝都的那些80后北漂IT人,你们的未来在哪儿
- Vue脚手架热更新技术探秘
- 英文视频添加中英双语字幕(基于Whisper语音识别和Google翻译)
- 男生和女生的十个瞬间 (温馨啊)【转载】
- html下拉复选框联动,HTML : CheckBox 复选框成组联动(JavaScript)
- Matlab读取shp文件及存储形式
- 如何将电脑文件自动备份到u盘?
- RK平台之AI组件例程使用说明
- android培训课程