凡人视角C++之string(上)
好久没有更新博客了,这段时间一直在忙图像处理的项目,近期空了下来。也是时候整合C++的相关内容,静心感受下编程语言的魅力。和大家共同探讨学习。我将以头文件的形式展开学习,且仅仅讲述相关接口的应用,至于内部详细的实现,鉴于本人水平有限。不敢献丑。经过考虑,决定先从和数据结构相关的头文件開始,由于这些头文件中的内容在OJ里经常要用到。今天要学习的是string头文件。这里的string是C++里的string,而C里的string在C++里仍然保留,头文件名称为cstring。这里不做展开。在此说明:以下的代码都是在VS 2015编译环境下执行。
Some Details
basic_string
实际上,string头文件中并不仅仅有string这个类型,这个头文件中最基本的是一个叫basic_string的类模板,这个类模板的声明例如以下:
template < class charT,
class traits = char_traits<charT>,
class Alloc = allocator<charT>
> class basic_string;
上面的类模板构造有点复杂。我们没有必要深究。仅仅须要知道我们能够在basic_string这个类中自己定义三种类型作为member type即可了。
当中的charT (character type)是最重要的模板參数,它直接说明了字符串中的元素类型,另外两个类型均採用默认參数(以charT为參数构建的类)即可。
为什么要提basic_string这玩意儿呢。由于string类型正是basic_string的special type,在实际操作中,最常使用的是char类型(字符型)。故仅仅需将上面的charT转换为char便是string类型了。string类型的构造例如以下:
typedef basic_string<char> string; //元素为8bits字符类型
相似的,在c++内置类型中,还有wstring、u16string和u32string(后两个是在c++11标准下),我们能够依据实际须要选取字符串类型。它们的构造例如以下:
typedef basic_string<wchar_t> wstring; //16位或32位
typedef basic_string<char16_t> u16string; //16位
typedef basic_string<char32_t> u32string; //32位
String versus Character Array
之前看到过一篇文章。讲到了string和char*,我在此做个总结。
- string内存由系统进行管理,自己主动实现内存的申请和释放;而char* 则须要自己管理。
假设你要使用的内存较大,则string系统自己主动申请的内存可能不够使用。
因此,在使用内存大小知道的情况下,建议使用char* ,而当使用内存详细大小未知,但内存不大时能够使用string。
string相比char* 有一个长处,c++标准库对string类进行了封装,里面的各种成员函数处理字符串相当方便。这也是我经常使用string的一个原因。
至于string和char类型的vector有什么差别。我倒还没有深究过。大概是成员函数不同吧,知道的小伙伴能够在以下留言下。
Elaboration
Member Functions
string::string
string(); //(1)默认构造函数,构造一个空字符串。字符串长度为0
string(const string& str); //(2)拷贝构造函数
string(const string& str, size_t pos, size_t len = npos);
//(3)复制str一部分,pos是起始位置。len是复制的字符串长度(默认值是到字符串底部)这里要注意str的第一个字符pos=0
string(const char* s); //(4)复制C模式下s指针指向的字符数组(字符串)
string(const char* s, size_t n); //(5)复制前n个字符数组元素
string(size_t n,char c); //(6)复制n个连续的字符c
template <class InputIterator>
string(InputIterator first, InputIterator last);
//(7)利用iterator复制字符序列。范围为[first,last),注意最后一个不包含
string(initializer_list<char> il); //(8)将初始化列表il转换为string
string(string&& str) noexcept; //(9)右值引用str,并且不抛出异常信息。
关于右值引用和move语义这块内容。是C++11的新特性,我当时琢磨了非常久也还是云里雾里,预计是自己悟性不够高,我认为有两篇文章写得还不错,贴在这里。另外,不知右值和暂时变量有何不同,知道的小伙伴也能够在以下留言。
https://www.ibm.com/developerworks/cn/aix/library/1307_lisl_c11/
https://my.oschina.net/letiantian/blog/470921
Demonstration: //为简略。今后代码将省略cout,自己操作时应加上
#include<iostream>
#include<string> //调用string头文件
#include<initializer_list> //(8)中要用到
using namespace std;
string test(const string& x) //(9)的測试函数,产生右值
{
return x;
}
int main()
{
string s4("string now"); //(4)
string s1; //(1)
string s2(s4); //(2)
string s3a(s4, 7, 3); //(3)设置长度
string s3b(s4, 7); //(3)默认长度,也就是究竟部
string s5("string now", 6); //(5)
string s6(3, '6'); //(6)
string s7(s4.begin(), s4.begin() + 6);
//(7)begin函数后面会提到。能够生成iterator
initializer_list<char> s0 = {'s', 't', 'r', 'i', 'n', 'g'};
//生成initializer_list
string s8(s0); //(8)
string s9(test(s4)); //(9)
}
//自行将凝视中的序号与上面的序号对比进行学习
结果例如以下。看看是不是和你们想象中的一样呢。
string::operator=
string& operator= (const string& str); //(1)赋值string类型变量
string& operator= (const char* s); //(2)赋值c风格字符串
string& operator= (char c); //(3)赋值一个字符,字符串长度为1
string& operator= (initializer_list<char> il); //(4)赋值初始化列表il
string& operator= (string&& str) noexcept; //(5)利用右值引用赋值
Demonstration:
#include<iostream>
#include<string> //调用string头文件
#include<initializer_list> //(4)中要用到
using namespace std;
string test(const string& x) //(5)的測试函数,产生右值
{
return x;
}
int main()
{
string s1, s2, s3, s4, s5;
//为把operator=和构造函数分开,使用默认构造函数
s2 = "string now"; //(2)
s1 = s2; //(1)
s3 = '6'; //(3)
initializer_list<char> s0 = {'s', 't', 'r', 'i', 'n', 'g'};
s4 = s0; //(4)
s5 = test(s2); //(5)
}
Some More Details
string类型对象是以’\0’结尾的嘛?
预计非常多人跟我一样都想过这个问题,由于在C语言中,系统默认字符串都是以’\0’截尾的。我们最好还是今天来编个小程序验证一下。
#include<iostream>
#include<string>
using namespace std;
int main()
{
string s0 = "string now"; //初始化s0
if (s0[10] == '\0')
cout << "Yes." << endl; //假设末尾是'\0',则输出Yes.
else cout << "No." << endl; //假设末尾不是'\0',则输出No.
return 0;
}
在这里,我们得到了一个令人惬意的答案,说明C++风格的string仍然是以’\0’结尾的,通常情况下,末尾的’\0’我们能够忽略不计。
编码类型对string的影响
提到这个问题。是由于我注意到了这么一句话,我在这里引用一下。
Note that this class handles bytes independently of the encoding used: If used to handle sequences of multi-byte or variable-length characters (such as UTF-8), all members of this class (such as length or size), as well as its iterators, will still operate in terms of bytes (not actual encoded characters).
这句话的意思概括起来就是说,无论你使用哪种类型的编码。string类型的操作都将按一个字节的方式来处理。我们不禁想到了中文,由于中文是在GB2312中编码的。并且一个中文字符占用两个字节。这样会引起什么问题呢?我们也来測试一下。
#include<iostream>
#include<string>
using namespace std;
int main()
{
string s0 = "測试"; //用中文初始化s0
cout << s0 << endl << endl; //查看是否能输出中文
for (int i = 0; i < 2; ++i) //输出前2个字节,看看是否会输出測试两个字
cout << s0[i] << endl;
return 0;
}
刚開始,我们将整个字符串输出,看看是否会显示“測试”这两个字,结果是这两个字显示了,说明c++是能够识别GB2312编码的。而当我们尝试将字符串按单个字节输出的时候。就发现了问题,由于输出台输出的是空白,这就说明string类型并不能直接辨别这个是什么编码。它仅仅能按单个字节进行读取,这就会导致该字节没有默认的ASCII编码能够相应,因此也就不会有内容输出了。
string的内容实在有点多,为了保持页面的精简,方便浏览,我将把下半部分内容放到下篇博文中。如有错误,欢迎指正。
凡人视角C++之string(上)的更多相关文章
- java基础面试题:switch语句能否作用在byte上,能否作用在long上,能否作用在String上?
package com.swift; public class Switch_Test { public static void main(String[] args) { /* * switch语句 ...
- python学习(二十二) String(上)
str1 = "This is a 'test'" print(str1) str1 = 'This is a "test"' print(str1) str1 ...
- switch语句能否作用在byte,long,string上
switch是java中的多分支结构.在switch(expr)中,expr只能是一个整数表达式,或者是枚举常量,整数表达式可以是int基本类型也可以是Integer包装类型,由于byte,short ...
- switch语句能否作用在byte上,能否作用在long上,能否作用在String上?
在Java 7以前,在switch(expr1)中,expr1只能是一个整数表达式(但不包括long和Long)或者枚举常量,整数表达式可以是int基本类型或Integer包装类型,byte.shor ...
- switch 是否能作用在byte 上,是否能作用在long 上,是否能作用在String上?
答:在Java 5以前,switch(expr)中,expr只能是byte.short.char.int.从Java 5开始,Java中引入了枚举类型,expr也可以是enum类型,从Java 7开始 ...
- switch 是否能作用在 byte 上,是否能作用在 long 上, 是否能作用在 String 上?
在 Java 5 以前,switch(expr)中,expr 只能是 byte.short.char.int.从 Java 5 开始,Java 中引入了枚举类型,expr 也可以是 enum 类型,从 ...
- 11、Struts2 的文件上传和下载
文件上传 表单准备 要想使用 HTML 表单上传一个或多个文件 须把 HTML 表单的 enctype 属性设置为 multipart/form-data 须把 HTML 表单的method 属性设置 ...
- commons-fileupload.jar实现文件上传
标签: uploadfileimportexceptionstringmyeclipse 2012-09-06 19:55 1497人阅读 评论(0) 收藏 举报 分类: 好东东(2) Jav ...
- Servlet异步上传文件
这里需要用到插件ajaxfileupload.js,jar包:commons-fileupload-1.3.2.jar,commons-io-2.5.jar 注意红色部分的字!!!! 1.创建一个we ...
随机推荐
- JQuery为textarea添加maxlength
<html> <head> <title>JQuery为textarea添加maxlength</title> <script type=&quo ...
- mysql加减时间-函数-时间加减
select timediff('23:40:00', ' 18:30:00'); -- 两时间相减 SELECT substring( timediff(,) ----“:”相减返回小时:分钟 -- ...
- 算法笔记_214:第六届蓝桥杯软件类校赛真题(Java语言A组)
目录 1 题目一 2 题目二 3 题目三 4 题目四 5 题目五 6 题目六 7 题目七 前言:以下代码仅供参考,若有错误欢迎指正哦~ 1 题目一 一个串的子串是指该串的一个连续的局部.如果不要求连续 ...
- python之tcp自动重连
操作系统: CentOS 6.9_x64 python语言版本: 2.7.13 问题描述 现有一个tcp客户端程序,需定期从服务器取数据,但由于种种原因(网络不稳定等)需要自动重连. 测试服务器示例代 ...
- 关于gitblit在Windows中无法Start的问题
前期配置/data/defaults.properties文件,请自行百度 首先:找到该目录下的该文件 右键打开,找到SET ARCH=xx,将xx替换成x86 将该处的默认修改成配置环境变量的jvm ...
- 〖Android〗sshd for android, 及映射根文件系统至本地盘符
严重问题: 若移植失败将可能直接导致手机***无法开机***,导入相关文件需慎重! 达成效果: 1. ssh 远程登录 Android 终端: 2. sftp 挂载/映射 Android 根文件系统至 ...
- SpringMVC 参数中接收数组、List写法
本文使用SpringMVC版本: org.springframework:spring-web:4.3.9.RELEASE 写法及说明(示例代码的类上的注解是@RestController,所以不需要 ...
- 微信小程序云端解决方案探索之路
小程序刚推出的时候,很多人都觉得它就是 H5,因为开发小程序的三大语言和 HTML.CSS.JS 是一脉相承的,即使改变了扩展名也改不了其实质. 那么小程序的实质到底是不是 H5 呢?经过我们的论证分 ...
- 无限极分类php实现—查子孙树、家谱树
1.本文更新日期:2018/05/20 , 亲测可用,在原有基础上进行增强和 详细化 . 2.面包屑导航 和 子孙树 效果图如下: 3.代码: <?php // 无限级分类中,查家谱树(面包屑导 ...
- QQ登录整合/oauth2.0认证-04-调整到QQ互联进行QQ登录
---------------------------------目录------------------------------------- QQ登录整合/oauth2.0认证-03-对第二节的代 ...