可以说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 字符串、向量和数组)的更多相关文章

  1. <<C++ Primer>> 第三章 字符串, 向量和数组 术语表

    术语表 第 3 章 字符串, 向量和数组 begin: 是 string 和 vector 的成员,返回指向第一个元素的迭代器.也是一个标准库函数,输入一个数字,返回指向该数字首元素的指针.    缓 ...

  2. 从零开始学安全(十九)●PHP数组函数

    $temp= array(1,2,3,,,,) 创建一个数组赋值给temp $id=range(1,6,2);     成长值   1到6  跨度为2  就是3个长度数组 也可以是字符“a” &quo ...

  3. [C++ Primer] 第3章: 字符串, 向量和数组

    标准库类型string string初始化 string s2(s1); string s2 = s1; string s3("value"); string s3 = " ...

  4. Java从零开始学十(Arrays类对数组的常用方法)

    一.Arrays类常用方法 二.简单例子 package com.pb.demo1; import java.util.Arrays; /* * Arrays工具类的中的几个常用方法 * 1.copy ...

  5. C++ Primer 第3章 字符串、向量和数组

    C++ Primer 第3章 字符串.向量和数组 C Primer 第3章 字符串向量和数组 1 命名空间的using声明 2 标准库类型string 3 标准库类型vector 4 迭代器介绍 5 ...

  6. 从零开始学 Web 之 JavaScript(四)数组

    大家好,这里是「 Daotin的梦呓 」从零开始学 Web 系列教程.此文首发于「 Daotin的梦呓 」公众号,欢迎大家订阅关注.在这里我会从 Web 前端零基础开始,一步步学习 Web 相关的知识 ...

  7. C++ Primer 5th 第3章 字符串、向量和数组

    *****代码在Debian g++ 5.40 / clang++ 3.8(C++11)下编写调试***** 本章主要是关于字符串.数组的内容,以及一些简单的容器知识. 1.using的声明 usin ...

  8. 57. Spring 自定义properties升级篇【从零开始学Spring Boot】

    之前在两篇文章中都有简单介绍或者提到过 自定义属性的用法: 25.Spring Boot使用自定义的properties[从零开始学Spring Boot] 51. spring boot属性文件之多 ...

  9. 从零开始学 Web 系列教程

    大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新…… github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:http:/ ...

  10. 从零开始学 Web 之 DOM(一)DOM的概念,对标签操作

    大家好,这里是「 Daotin的梦呓 」从零开始学 Web 系列教程.此文首发于「 Daotin的梦呓 」公众号,欢迎大家订阅关注.在这里我会从 Web 前端零基础开始,一步步学习 Web 相关的知识 ...

随机推荐

  1. Ubuntu将Python3软连接到Python

    sudo ln -s /usr/bin/python3 /usr/bin/python

  2. python面试题手动总结答案锦集

    数据类型 字符串 1.列举python中的基本数据类型 数字:int 布尔值:bool 字符串:str 列表:list 元组:tuple 字典:dict 集合:set 然后我们需要了解一些运算符,应为 ...

  3. PAT T1017 The Best Peak Shape

    动态规划找最长上升子序列,正反遍历一遍序列即可~ #include<bits/stdc++.h> using namespace std; ; int N; int a[maxn]; in ...

  4. PAT T1011 Cut Rectangles

    大模拟题,按要求建立多边形,先定位斜边的位置,再分类讨论~ #include<bits/stdc++.h> using namespace std; ; struct node { dou ...

  5. oracle SQL 练习

    COURSE 表 DROP TABLE "SCOTT"."course"; CREATE TABLE "SCOTT"."cours ...

  6. Mate Linux 桌面的什么受GNOME 2 粉丝喜欢 ?

    导读 如果你以前听过这个传闻:当 GNOME3 第一次发布时,很多 GNOME 用户还没有准备好放弃 GNOME 2. Mate(以马黛茶yerba mate植物命名)项目的开始是为了延续 GNOME ...

  7. 支持USB4的Linux 5.6,有望在今年4月份推出

    导读 根据外媒Phoronix的报道,Linux 5.6将支持USB4,. USB4的规范在去年9月份发布,基于雷电3,并与之向后兼容.英特尔的开源部门在去年10月份添加了USB4的初始补丁. 据报道 ...

  8. android传递数据bundle封装传递map对象

    android开发默认情况下,通过Bundle bundle=new Bundle();传递值是不能直接传递map对象的,解决办法: 第一步:封装自己的map,实现序列化即可 ? 1 2 3 4 5 ...

  9. Django 学习 之ORM聚合查询分组查询与F查询与Q查询

    一.聚合查询和分组查询 1.聚合查询aggregate 关于数据表的数据请见上一篇:Django 学习 之ORM多表操作(点我) aggregate(*args, **kwargs),只对一个组进行聚 ...

  10. NXP TJA1040, TJA1042, TJA1050 TJA1051, TJA1057, TJA1044, TJA1055区别

    历史关系 PCA82C250和PCA82C251是属于NXP第一代 CAN PHY(CAN物理层收发器): TJA1050, TJA1040和TJA1041是属于NXP第二代CAN PHY: TJA1 ...