从零开始学C++(2 字符串、向量和数组)
可以说string和vector是C++标准库中最重要的两种类型,string支持可变长字符串,而vector表示可变长的集合。
string
头文件:<string>
定义在命名空间 std 中,using std::string;
string s1; // 默认初始化,s1是一个空串
string s2(s1); // s2是s1的副本
string s3 = s1; // s3是s1的副本
string s4("value"); // s4是字面值"value"的副本,除了字面值最后的那个空字符外
string s5 = "value"; // 等价于上面的括号初始化
string s6(n, 'c'); // 把s6初始化为由连续n个字符c组成的串
这里需要区分直接初始化和拷贝初始化(后面学了类相关的知识就会知道,这两种初始化调用分别调用的是构造函数和拷贝控制的某种构造函数)。
使用等号(=)初始化一个变量,实际上执行的就是拷贝初始化(copy initialization),编译器把等号右侧的初始值拷贝到新创建的对象中去。反之,不使用等号,则执行的就是直接初始化(direct initialization)。
string的操作
os << s 将s写到输出流os中,返回os
is >> s 从is中读取字符串赋给s,字符串以空白分隔,返回is
getline(is, s) 从is中读取一行赋给s,返回is
s[n] 返回s中第n个字符的引用,位置n从0计起
s1 + s2 返回s1和s2连接后的结果
// 读取未知数量的string对象 int main()
{
string word;
while (cin >> word)
cout << word << endl;
return ;
}
string的size()函数返回类型为string::size_type,它是一个无符号类型的值,而且能足够存放下任何string对象的大小。
string对象与字符字面值或者字符串字面值相加时,必须确保每个加法运算符(+)的两侧的运算对象至少有一个是string对象:
int main()
{
string str1("hell");
string str2 = str1 + 'o' + " world";
cout << str2 << endl;
return ;
}
如何处理string对象中的字符呢?
头文件cctype中定义了一组标准库函数
isalnum(c) 当c是字母或数字时为真
isalpha(c) 当c是字母时为真
iscntrl(c) 当c是控制字符时为真
isdigit(c) 当c是数字时为真
isgraph(c) 当c不是空格但可打印时为真
islower(c) 当c是小写字母时为真
isprint(c) 当c是可打印字符时为真
ispunct(c) 当c是标点符号时为真
isspace(c) 当c时空白时为真(即c是空格、横向制表符、纵向制表符、回车、换行、进纸符)
isupper(c) 当c是大写字母时为真
isxdigit(c) 当c是十六进制数字时为真
tolower(c) 如果c是大写字母,输出对应的小写字母;否则原样输出c
toupper(c) 如果c是小写字母,输出对应的大写字母;否则原样输出c
string str3("abcdefgh0123");
for (auto c : str3) {
if (isxdigit(c)) {
cout << "0x" << c << endl;
} else {
cout << c << endl;
}
}
vector
也被称为容器(container),头文件<vector>,using std::vector;
vector是一个类模板(class template)。模板本身不是类或函数,可以将模板看作为编译器生成类或函数编写的一份说明。编译器根据模板创建类或函数的过程称为实例化(instantiation),当使用模板时,需要指出编译器应该把类或函数实例化成何种类型。
vector的使用
vector<int> ivec; // ivec保存int类型的对象
vector<ClassObj> co_vec; // co_vec保存ClassObj类类型的对象
vector<vector<string>> files; // files保存的元素是vector对象
定义和初始化
vector<T> v1; // v1是一个空vector,它潜在的元素是T类型的,执行默认初始化
vector<T> v2(v1); // v2中包含有v1所有元素的副本
vector<T> v2 = v1; // 等价于v2(v1)
vector<T> v3(n, val); // v3包含了n个重复的元素,每个元素的值都是val
vector<T> v4(n); // v4包含了n个重复地执行了值初始化的对象
vector<T> v5{a,b,c...}; // 列表初始化,包含了{}中的元素
vector<T> v6={a,b,c...}; // 同上
使用列表初始化时,注意:
vector<int> v1{10}; // v1只有一个元素
vector<int> v2(10); // v2有10个元素
vector<int> v3{10, 1}; // 2个元素,10、1
vector<int> v4(10, 1); // 10个元素,值都是1
用圆括号:提供的值用来构造(construct)vector对象
用花括号:列表初始化该vector对象,也就是说,初始化过程会尽可能地把花括号内的值当成是元素初始值的列表来处理,只有在无法执行列表初始化时才会考虑其他初始化方式。
vector<string> v5{10}; // v5有10个默认初始化的元素
vector<string> v6{10, "hi"}; // v6有10个值为"hi"的元素
上面两条语句尽管使用了花括号,但是花括号中的值(10)与元素类型(string)不匹配,不能作为元素的初始值,编译器会尝试使用构造函数去初始化对象。
vector<string> v7{10, "hi", "hello"}; // 错误
使用push_back向vector对象中添加元素
vector<int> ivec;
for (int i = 0; i != 10; ++i) {
ivec.push_back(i);
}
迭代器(iterator)
提供迭代器的类型,拥有begin和end成员函数,begin返回指向第一个元素(或第一个字符)的迭代器;end返回容器(或string对象)“尾元素的下一位置”的迭代器。
auto b = ivec.begin(), e = ivec.end();
如果容器为空,则begin和end返回的是同一个迭代器,都是尾后迭代器。
拥有迭代器的标准库类型使用iterator和const_iterator来表示迭代器的类型:
vector<int>::iterator iter1; // iter1能读写vector<int>的元素
string::iterator iter2;
vector<int>::const_iterator iter3; // iter3 只能读元素,不能写元素
vector和string迭代器支持的运算
iter + n iter - n iter += n iter -= n
iter1 - iter2 两个迭代器相减的结果是它们之间的距离,参与元素的两个迭代器必须指向的是同一个容器中的元素或尾元素的下一位置
>、>=、<、<=
注意:两个迭代器不能相加!!!(没有意义)
数组
在C++代码中,尽可能地使用vector,而不使用数组。
数组的声明:a[d],其中a是数组的名字,d是数组的维度。维度说明了数组中元素的个数,因此必须大于0。数组中元素的个数也属于数组类型的一部分,编译的时候维度必须是已知的,因此,维度必须是一个常量表达式:
unsigned cnt = 10;
constexpr unsigned sz = 10;
int arr[10]; // 正确
int *parr[sz]; // 含有10个整型指针的数组
string err[cnt]; // 错误:cnt不是常量表达式
string strs[GetSize()]; // 当GetSize()是constexpr时正确,否则错误
数组下标的类型为size_t,size_t是一种机器相关的无符号类型,被设计得足够大以便能表示内存中任意对象的大小,在头文件<cstddef>中。
在很多用到数组名字的地方,编译器都会自动地将其替换为一个指向数组首元素的指针:
string nums[] = {"a", "b", "c"};
string *p = &nums[0]; // 指向nums的第一个元素
string *ps = nums; // 等价
在一些情况下,数组的操作实际上是指针的操作,所以当使用数组作为一个auto变量的初始值时,推断得到的类型是指针而非数组:
int ia[] = {0,1,2,3,4,5};
auto ia2(ia); // ia2是一个整型指针,指向ia的第一个元素
当使用decltype关键字时上述转换不会发生:
decltype(ia) ia3 = {0,1,2,3,4,5};
ia3[4] = 10;
标准库函数begin和end,与容器中的两个同名成员功能类似,作用于数组。
C风格字符串
它不是一种类型,而是为了表达和使用字符串而形成的一种约定俗成的写法。按此习惯书写的字符串存放在字符数组中并以空字符结束。
strlen(p) 返回p的长度,空字符不计算在内
strcmp(p1, p2) 比较p1和p2,如果p1==p2,返回0,如果p1>p2,返回正值,否则返回一个负值
strcat(p1, p2) 将p2附加到p1之后,返回p1
strcpy(p1, p2) 将p2拷贝给p1,返回p1
string对象转换为C风格字符串:str.c_str();
本来想把《STL源码剖析》中的vector实现写出来,但是内容就太多了,所以现阶段就只写C++的基础知识,后面再单独写其他深入的内容。
从零开始学C++(2 字符串、向量和数组)的更多相关文章
- <<C++ Primer>> 第三章 字符串, 向量和数组 术语表
术语表 第 3 章 字符串, 向量和数组 begin: 是 string 和 vector 的成员,返回指向第一个元素的迭代器.也是一个标准库函数,输入一个数字,返回指向该数字首元素的指针. 缓 ...
- 从零开始学安全(十九)●PHP数组函数
$temp= array(1,2,3,,,,) 创建一个数组赋值给temp $id=range(1,6,2); 成长值 1到6 跨度为2 就是3个长度数组 也可以是字符“a” &quo ...
- [C++ Primer] 第3章: 字符串, 向量和数组
标准库类型string string初始化 string s2(s1); string s2 = s1; string s3("value"); string s3 = " ...
- Java从零开始学十(Arrays类对数组的常用方法)
一.Arrays类常用方法 二.简单例子 package com.pb.demo1; import java.util.Arrays; /* * Arrays工具类的中的几个常用方法 * 1.copy ...
- C++ Primer 第3章 字符串、向量和数组
C++ Primer 第3章 字符串.向量和数组 C Primer 第3章 字符串向量和数组 1 命名空间的using声明 2 标准库类型string 3 标准库类型vector 4 迭代器介绍 5 ...
- 从零开始学 Web 之 JavaScript(四)数组
大家好,这里是「 Daotin的梦呓 」从零开始学 Web 系列教程.此文首发于「 Daotin的梦呓 」公众号,欢迎大家订阅关注.在这里我会从 Web 前端零基础开始,一步步学习 Web 相关的知识 ...
- C++ Primer 5th 第3章 字符串、向量和数组
*****代码在Debian g++ 5.40 / clang++ 3.8(C++11)下编写调试***** 本章主要是关于字符串.数组的内容,以及一些简单的容器知识. 1.using的声明 usin ...
- 57. Spring 自定义properties升级篇【从零开始学Spring Boot】
之前在两篇文章中都有简单介绍或者提到过 自定义属性的用法: 25.Spring Boot使用自定义的properties[从零开始学Spring Boot] 51. spring boot属性文件之多 ...
- 从零开始学 Web 系列教程
大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新…… github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:http:/ ...
- 从零开始学 Web 之 DOM(一)DOM的概念,对标签操作
大家好,这里是「 Daotin的梦呓 」从零开始学 Web 系列教程.此文首发于「 Daotin的梦呓 」公众号,欢迎大家订阅关注.在这里我会从 Web 前端零基础开始,一步步学习 Web 相关的知识 ...
随机推荐
- 第九届蓝桥杯B组决赛 调手表(完全背包)
问题描述 M78 星云的一个小时有 n 分钟. 大家都知道,手表只有一个按钮可以把当前的数加一.在调分钟的时候,如果当前显示的数是 0 ,那么按一下按钮就会变成 1,再按一次变成 2 .如果当前的数是 ...
- 重新理解《务实创业》---HHR计划--以太一堂第三课
第一节:开始学习 1,面对创业和融资,我们应该如何从底层,理解他们的本质呢?(实事求是) 2,假设你现在要出来融资,通常你需要告诉投资人三件事:我的市场空间很大,我的用户需求很疼,我的商业模式能跑通. ...
- tensorflow文本分类实战——卷积神经网络CNN
首先说明使用的工具和环境:python3.6.8 tensorflow1.14.0 centos7.0(最好用Ubuntu) 关于环境的搭建只做简单说明,我这边是使用pip搭建了python的 ...
- macOS 10.14+ 安装LTP
LTP是哈尔滨工业大学(HIT,窝工)出品的一个自然语言处理工具包.其功能包括中文分词(“分词效果好于jieba分词”[引用自学长]).词性标注.实体识别等. 对于macOS来说,现有的版本可能不多, ...
- Eclipse中java代码注释变成乱码的问题
今天在查看曾经写过的代码时发生了一件很是让人头疼的事: 我写的所有注释全部都变成了了乱码,曾经刚入门时也是经常遇到类似的问题,解决起来很快,每天可能都会在工作空间里看到,但是随着时间的推移,写代码的规 ...
- Linux centosVMware apache 限定某个目录禁止解析php、限制user_agent、php相关配置
一.限定某个目录禁止解析php 核心配置文件内容 vim /usr/local/apache2.4/conf/extra/httpd-vhosts.conf 先创建.编辑一个php 配置 vim /u ...
- 莫烦 - Pytorch学习笔记 [ 二 ] CNN ( 1 )
CNN原理和结构 观点提出 关于照片的三种观点引出了CNN的作用. 局部性:某一特征只出现在一张image的局部位置中. 相同性: 同一特征重复出现.例如鸟的羽毛. 不变性:subsampling下图 ...
- 「CF126B」Password
题目描述 给定一个字符串 \(S\),我们规定一个字符串 \(P\) 是可行解,\(P\) 需要满足: \(P\) 是 \(S\) 的前缀 \(P\) 是 \(S\) 的后缀 \(P\) 出现在 \( ...
- Python 之网络编程之进程总体概要
一: 进程的概念:(Process) 进程就是正在运行的程序,它是操作系统中,资源分配的最小单位. 资源分配:分配的是cpu和内存等物理资源 进程号是进程的唯一标识 同一个程序执行两次之后是两个进程 ...
- Ideone:在线多语言编程执行器工具
Ideone:在线多语言编程执行器工具此网站提供40种编程语言以上, 能在线直接做编译和执行的动作,该工具是一款简易的编程测试工具,虽然不能替代专业版的工具,但是其功能非常全面. Ideone,一款在 ...