可以说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. Airless Pump Bottle For The Rise Of Cosmetic Packaging Solutions

    Airless Pump Bottle    are used in the rise of cosmetic packaging solutions. According to the suppli ...

  2. 关于java自学的内容以及感受(7.28)

    这一周学习了关于一些算法运算,我进行了程序的编写与运行,代码如下: public class TestSign{ public static void main(String[] args){ int ...

  3. SpringBoot报错笔记

    异常一: 1.访问所有方法路径都返回一个page: 截图: 出错原因:不知道 解决方法:新建项目 异常二: 提交表单信息报错 原因:映射文件和和表单的提交方式不统一 解决方法:统一方式即可: 错误三: ...

  4. mysql之魔鬼训练营

    普通 + 中等 难度练习题 测试数据: --建表 --学生表 CREATE TABLE `Student`( `s_id` VARCHAR(20), `s_name` VARCHAR(20) NOT ...

  5. luogu P2704 炮兵阵地(经典状态压缩DP)

    方格有m*n个格子,一共有2^(m+n)种排列,很显然不能使用暴力法,因而选用动态规划求解. 求解DP问题一般有3步,即定义出一个状态 求出状态转移方程 再用算法实现.多数DP题难youguan点在于 ...

  6. mysql mvcc 的理解

    mvcc 全称 multiple version concurrency control 多版本并发控制,是数据库领域比较常用的一种非锁并发技术. mysql 的innodb中,在RR.RC级别会使用 ...

  7. express框架开发接口部署线上环境PM2

    1.PM2介绍 PM2是一个线上环境下,用于启动nodejs进程守护的工具,用来保证服务的稳定及分摊服务器进程和压力. 2.下载安装 npm install pm2 -g  => pm2 --v ...

  8. 常用的UI控件

    关于本文:作为一名iOS软件工程师,熟练规范的使用常用的UI控件是必备的基础技能. 指示器(UIActivityIndicatorView)----转动的等待小菊花 提醒对话框(UIAlertView ...

  9. Pycharm设置默认HTML模板

    Pycharm设置默认HTML模板 Bootstrap导入链接 <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/ ...

  10. dir815_FW_102.bin路由器固件解压碰到的坑

    在跟随大神kczwa1进行路由器漏洞分析时,对dir815_FW_102.bin 固件文件用binwalk -e dir815_FW_102.bin命令进行解压时,在根目录squashfs-root下 ...