从零开始学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 相关的知识 ...
随机推荐
- javascript中slipt()分割
slipt()分割取长度 例子1: n变量其实只有两个1,结果分割成数组有3个,所以结果页取1长度的话要减去1 l 异步请求data数据输出是html,当要获取数据长度的时候, 用解析html获取长度 ...
- Legal High
不让任何人承担责任,不想看的东西就回避, 但是,如果想夺回值得夸耀的生存方式,就必须看那些不愿意看的现实,必须带着身负重伤的觉悟前进,这才叫做战斗. 有怨言的话去坟墓里说,钱不是全部,钱就是你们向对手 ...
- [蓝桥杯2016初赛]卡片换位 BFS
题目描述 你玩过华容道的游戏吗?这是个类似的,但更简单的游戏.看下面 3 x 2 的格子 +---+---+---+ | A | * | * | +---+---+---+ | B | | * | + ...
- 最优矩阵连乘问题 区间DP
最优矩阵连乘积 Accepted: 10 Total Submit: 18Time Limit: 1000ms Memony Limit: 32768KB Description 在科学计算中经常要计 ...
- tcp连接建立和断开
TCP协议作为传输层主要协议之一,具有面向连接,端到端,可靠的全双工通信,面向字节流的数据传输协议. 1.TCP报文段 虽然TCP面试字节流,但TCP传输的数据单元却是报文段.TCP报文段分为TCP首 ...
- 【PAT甲级】1005 Spell It Right (20 分)
题意: 给出一个非零整数N(<=10^100),计算每位之和并用英文输出. AAAAAccepted code: #include<bits/stdc++.h> using name ...
- 《java核心技术:卷1》PDF版 和 Word版下载
链接:https://pan.baidu.com/s/1OcpdZ4wfeo55xeJQQBHXRg 提取码:hds0
- windows下安装redis并部署服务
下载地址: windows版本: https://github.com/MSOpenTech/redis/releases Linux版本: 官网下载: http://www.redis.cn/ gi ...
- 使用element-ui组件el-table时需要修改某一行或列的样式(包含解决选择器无效问题)
在后台管理系统项目中,经常会使用element-ui中的组件el-table(表格)来展示列表数据. 当展示数据的时候,可能就需要给给某一行或者列设置特殊的样式,在查询文档是我遇到了一些问题:包括设置 ...
- 【剑指Offer面试编程题】题目1524:复杂链表的复制--九度OJ
题目描述: 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点). 输入: 输入可能包含多个测试样例,输入以EOF结束. 对于每个测试案例,输入的第 ...