c++ primer第三章复习

c++ primer第三章复习

3.1 命名空间的using 声明

1.使用命名空间用using

using这个不用说是使用namespace的


namespace testNamespace {
    class Test
    {

    };
}

using testNamespace::Test;

int main ()
{
    return 0;
}
2.头文件不要使用using

这个之前自己有一些错误,在头文件里使用了using 以后一定要注意!

3.别名声明

使用数组的一个例子,在这里做复习

一个简单的例子:

#include <cctype>
#include <iostream>
#include <string>
#include <vector>

class Test {
public:
    int a = 1;
};

using testStruct = Test;


int main ()
{
    testStruct* data = new Test();
    data->a = 1000;
    std::cout << data->a << std::endl;
    return 0;
}

书中最后一节的一个比较复杂第例子,我看到了一个demo 有了疑惑

using int_array = int[4];
typedef int int_array[4];

其实这是书中的一个等价声明,并没有别的意思。
已经用using了进行了别名声明,为什么又要使用typedef呢?

标准库类型 string

1. 初始化
string s1;
string s2(s1);
string s2 = s1;
string s2("aaa");
string s2 = "aaa";
string s4(n, 'c'); // 申请n个'c'字符串

等号赋值都会触发std::string的拷贝构造函数,第5条初始化的demo,再写一次强化记忆:

int main ()
{
    std::string s5(10, 'c');
    std::cout << s5 << std::endl;
    return 0;
}

输出的结果是 10个c

2. string对象上的操作

1.标准输入和输出

int main ()
{
    std::string s5(10, 'c');
    std::string s1;
    std::string s2;
    std::cin >> s5 >> s1 >> s2;
    std::cout << s1 << s2 << s5;
    return 0;
}
3.使用getline读取一整行

一次读一整行,直到末尾

int main ()
{
    std::string line;
    while (getline(std::cin, line)) {
        std::cout << line << std::endl;
    }

    return 0;
}

string的empty和size这个太简单了直接跳过

4.string::size_type

size函数返回的是一个string::size_type

auto len = line.size();

//推断类型
decltype(line.size()) len = line.size();
5.比较string对象

1.如果两个string对象的长度不同,而且较短的string对象的每个字符都和比较长的string对象对应位置上的字符相同,就说string 小于长的

    std::string line;
    line = "hello";
    std::string line2 = "hello2";
    std::cout << (line < line2) << std::endl;

结果是line2大

2.如果两个string对象在某些对应的位置上不一致,则string对象比较的结果其实是string对象中第一对相异字符比较的结果。

    line = "bb";
    std::string line2 = "az";
    std::cout << (line < line2) << std::endl;

输出了0 只会比较第一个不同字符的ascii码大小,结果是line大

6.std::string 相加

注意必须要触发std::string的运算符重载,字面值不能直接和对象相加,这其实是一个字符串拼接,太简单了就不做处理了。

7.处理std::string的字符

头文件

#include <cctype>

检查单个字符

isalnum 当字符是字母的时候是真的

#include <cctype>
#include <iostream>
int main ()
{
    std::cout << isalnum('9') << std::endl;
    return 0;
}

isalpha

当c是字母的时候为真

#include <cctype>
#include <iostream>
int main ()
{
    std::cout << isalpha('c') << std::endl;
    return 0;
}

iscntrl

当c是控制字符的时候为真

#include <cctype>
#include <iostream>
int main ()
{
    std::cout << iscntrl('\r') << std::endl;
    return 0;
}

isdigit
如果参数是数字(0-9),函数返回true

#include <cctype>
#include <iostream>
int main ()
{
    std::cout << isdigit('4') << std::endl;
    return 0;
}

等等

isgraph() 如果参数是除空格之外的打印字符,函数返回true

#include <cctype>
#include <iostream>
int main ()
{
    std::cout << isgraph('@') << std::endl;
    return 0;
}

islower() 如果参数是小写字母,函数返回true

#include <cctype>
#include <iostream>
int main ()
{
    std::cout << islower('a') << std::endl;
    return 0;
}

isprint() 如果参数是打印字符(包括空格),函数返回true

#include <cctype>
#include <iostream>
int main ()
{
    std::cout << islower('a') << std::endl;
    return 0;
}

ispunct() 如果参数是标点符号,函数返回true

#include <cctype>
#include <iostream>
int main ()
{
    std::cout << ispunct('.') << std::endl;
    return 0;
}

isspace() 如果参数是标准空白字符,如空格、换行符、水平或垂直制表符,函数返回true

#include <cctype>
#include <iostream>
int main ()
{
    std::cout << isspace('\n') << std::endl;
    return 0;
}

isupper() 如果参数是大写字母,函数返回true

#include <cctype>
#include <iostream>
int main ()
{
    std::cout << isupper('A') << std::endl;
    return 0;
}

isxdigit() 如果参数是十六进制数字,即0-9、a-f、A-F,函数返回true

#include <cctype>
#include <iostream>
int main ()
{
    std::cout << isxdigit('a') << std::endl;
    return 0;
}

tolower() 如果参数是大写字符,返回其小写,否则返回该参数

#include <cctype>
#include <iostream>
int main ()
{
    std::cout << tolower('A') << std::endl;
    return 0;
}

toupper() 如果参数是小写字符,返回其大写,否则返回该参数

8.范围for运算符

简单的demo

int main ()
{
    std::string data = "hduahduaishduias";

    for(auto c:data) {
        std::cout << c << std::endl;
    }
    return 0;
}

auto其实是char

标准库vector

其实这是一个c++的数组,相比于c的数组我认为是使用起来更加方便的,更加容易扩容,注意vector能容纳绝大多数对象作为他的元素,但是因为引用不是对象,所以不存在包含引用的vector

1 定义和初始化vector对象

vector v1 v1是一个空的vector,它的潜在元素类型是T
vector v2(v1) v2中包含v1的所有元素副本
vector v2 = v1 根v2(v1)一样
vector v3(n, val) v3中包含n个重复元素,每个都是val
std::vector v(5); 初始化5个T对象
std::vector v = {a, b, c, d}
std::vector v{a, b, c, d}

int main ()
{
    ;
    std::vector<int> v2{1, 2, 3, 4};

    std::cout << v[1] << std::endl;
    return 0;
}
2 其他vector操作

3.3.2 说的是添加元素就是说是动态扩容,所以在这里不说3.3.2 了,直接看3.3.3的其他操作

std::vector v

v.empty() 是否是空值
v.size() 是否是尺寸
v.push_back(t) 向v的尾端添加一个t的元素
v1 = v2 v2中的元素替换v1
v1 = {a,b,c}
v1 == v2
v1 != v2
> <= > >=

这个明显不全,但是先这样吧,毕竟第三章是不全的 还有data()等等api都没有说

注意不能使用下表来扩容std::vector

    std::vector<int> v2{1, 2, 3, 4};
    v2[5] = 5;
    std::cout << v2.size() << std::endl;

注意这么写是不会报错,但是是不对的,我们发现size没有变化,而且很容易出现core dump 或者内存溢出的问题所以说不要用下标

3. 迭代器

迭代器循环vector

    std::vector<int> v2{1, 2, 3, 4};
    std::vector<int>::iterator iteratorBegin = v2.begin();
    std::vector<int>::iterator iteratorEnd = v2.end();

    for(; iteratorBegin != iteratorEnd; iteratorBegin++) {
        std::cout << *iteratorBegin << std::endl;
    }
    return 0;

输出1 2 3 4 注意还有cbegin 和 cend,只读不能修改

    std::vector<int> v2{1, 2, 3, 4};
    std::vector<int>::const_iterator iteratorBegin = v2.cbegin();
    std::vector<int>::const_iterator iteratorEnd = v2.cend();

    for(; iteratorBegin != iteratorEnd; iteratorBegin++) {
        std::cout << *iteratorBegin << std::endl;
    }
    return 0;

cbegin 和 begin的区别是是否可以通过解引用改变他的值

4.迭代器运算符

关于迭代器的运算符:

主要是两个点 一个是迭代器之间相减的运算符,另一个是比较大小的运算符

1、相减
先看迭代器之间的相减,距离的类型是std::vector::difference_type,difference_type是有符号的可以正可以负,看一个例子:

    std::vector<int> v2{1, 2, 3, 4};
    std::vector<int>::iterator iteratorBegin = v2.begin();
    std::vector<int>::iterator iteratorDistance = v2.begin() + 3;
    std::vector<int>::difference_type distance = iteratorDistance - iteratorBegin;
    std::cout << distance << std::endl;

2、迭代器之间比大小,就是偏移量之间比大小

    std::vector<int> v2{1, 2, 3, 4};
    std::vector<int>::iterator iteratorBegin = v2.begin();
    std::vector<int>::iterator iteratorDistance = v2.begin() + 3;
    std::cout << (iteratorDistance > iteratorBegin) << std::endl;

数组

1.定义和初始化数组

初始化:

const unsigned sz = 3;
int ia1[sz] = {0, 1, 2}
int a2[] = {0, 1, 2}
string a3[3] = {"h1", "h2"}

注意char需要有一个单独的位置放空字符

const char a4[7] = "abcdef"

第7个字符是\0

数组不允许任何拷贝和赋值操作

数组也可以使用范围for语句

    char data[7] = "abcdef";
    for (char a: data) {
        std::cout << a << std::endl;
    }
    return 0;
2.指针和数组

指针和数组的关系非常紧密,使用数组的时候编译器一般会吧它转换成指针。

    int data[7] = {1, 2, 3, 4, 5, 6, 7};
    std::cout << data << std::endl;

输出 0x7ffdcbc546d0 ,说明了这个问题,编译器会把数组变为了指针

1.指针类似迭代器,除了进行加减运算,还有begin和end函数,用来获取数组的头部指针和尾部指针


    int data[7] = {1, 2, 3, 4, 5, 6, 7};
    int *beginPtr = std::begin(data);
    int *endPtr = std::end(data);
    for(; beginPtr != endPtr; beginPtr++) {
        std::cout << *beginPtr << std::endl;
    }
    return 0;

2.指针运算

必须是同一块指针,不同变量的指针进行比较,会变得毫无意义

int i = 0,sz = 42;
int *p = &i, *e = &sz;

3.c风格的字符

strlen 计算字符串的长度
strcmp 比较两个字符的长度
strcat(p1, p2) 将p2追加到p1后面
strcpy(p1, p2) 把p2 追加到p1 后面

4.使用数组初始化vector对象

    int int_arr[] = {1, 2, 3, 4, 5, 6};
    std::vector<int> arr(std::begin(int_arr), std::end(int_arr));
    std::vector<int>::const_iterator iteratorBegin = arr.cbegin();
    std::vector<int>::const_iterator iteratorEnd = arr.cend();

    for(; iteratorBegin != iteratorEnd; iteratorBegin++) {
        std::cout << *iteratorBegin << std::endl;
    }
    return 0;

输出了1、2、3、4、5、6
将数组内容全部复制初始化到了std::vector中

多维数组(矩阵)

1.初始化
int ia[3][4] = {
    {0, 1, 2, 3},
    {4, 5, 6, 7},
    {8, 9, 10, 11}
};

也可以直接平铺开

int ia2[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};

这种两种初始化都是一样的

显示的初始化每一行的第一个元素

int ia[3][4] = {{0}, {4}, {8}};

显示初始化的第一行元素

int a[3][4] = {0, 3, 6, 9};
2.多维数组的下标引用

比较简单不写了

3.for范围语句

多重for循环不写了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值