当前位置: 首页 > biancheng >正文

这些c++的基础知识,你都知道吗

1. 清空数组:


memset(a, n, m): 包含在<cstring>头文件
将数组a第n个字节到第m个字节清空。
sizeof a   可以算出每个数组占用的字节数量

2.复制数组


memcpy(b, a, m): 包含在<cstring>头文件
将数组a复制给b数组,m表示复制多长
sizeof a 可以算出每个数组占用的字节数量

3.内置最大最小值:


INT_MAX和INT_MIN, 包含在头文件<limits.h>中

4.倒置函数:


reverse,头文件是algorithm需要填入首尾地址进行倒置数组或字符串
reverse(&a[0], &a[n])

5.字符数组要比字符长度多一,因为要存一个 \0 表示结束

6.读入一行字符:


fgets(s, n, stdin)  存入字符数组s(char[]),读n个,从stdin文件读入,系统的一个变量
getline(cin, s)  存入字符串s(string),读取一行
cin.getline(s, 100)  存入字符数组s(char[]), 读100个

7.字符数组函数


 cstring头文件中
strlen(s) //返回字符数组s的长度,不包含回车
strcmp(a, b) // 按照字典序比较,大于 1  ;等于  0; 小于  -1;
strcpy(a, b)  //将字符数组b复制给字符数组a

8.自己实现求长度函数:


int len = 0;
for (int i = 0; s[i]; i ++) len ++ ;

9.字符串 string  s


用printf输出string字符串:printf("%s\n", s.c_str());
用s.empty()判断字符串是否为空
用s.size()返回字符串的长度
用s.substr(n, m)返回从n开始长度为m的字符,返回子字符串,只填写一位数字n,就默认返回[n,s.size())
用s.back()可以返回字符串最后一个字符
用s.pop_back()可以去掉字符串最后一个字符
可以用 运算符号直接进行运算(只能用+)和比较

10.c++特有的遍历string字符串方式:


for (char c : s) cout << c << endl;
char 表示字符串s中每一个元素的数据类型,c单独表示字符串s中的一个元素,s表示需要遍历的字符串,
如果需要改变s里的值则在c前面加一个取地址符号&即可

11将字符串变成字符串流,即将字符串以空格分开:


#include <sstream>
.stringstream ssin(s);  //将字符串s变成字符串流
string str;
ssin >> str; //将字符串流读入

13.swap函数:


交换两个变量, 头文件为<algorithm>

14.静态变量只执行一次 :

大致上等价于开了一个只能在函数内调用的全局变量
static  int n = 0;

15.c++引用:&


函数传参的时候,加上引用,可以改变外部传入函数的参数的实际值
数组传递默认为引用传递

16.inline

可以加在函数定义前,表示将该函数内的代码直接替换到主函数中

17.类和结构体:

唯一区别,struct中默认为共有变量,类中默认为私有变量
class Person
{
    private://后面的东西是私有的,只能在该类中调用

    public: //后面的东西是公共,外部可以调用
};  //一定要加上分号
同一个类中可以出现多个private和public,他们后面的变量和函数统一称为成员变量

18.类和结构体的构造函数:


struct Person
{
    int age, height;
    double money;

    Person() {}  //第一种构造函数类型 空

    Person(int _age, int _height, double _money)  //第二种构造函数
    {
        age = _age;
        height = _height;
        money = _money;
    }
    Person(int _age, int _height, double _money) : age(_age), height(_height), money(_money) {}第二种构造函数的快捷写法
};

int main()
{
    Person p1;  //调用第一种,没给初始值,调用默认构造函数
    Person p2(18, 180, 100);  //调用第二种构造函数 进行赋值
    Person p3 = {18, 180, 100);  //根据定义顺序进行赋值, 在没有对应构造函数时,会报错

    return 0;
}

19.变量用 . 访问, 指针用 -> 访问

20.将字符串转换为整数:


stoi函数 stoi("123"),直接将字符串123变成数字123 ,参数是string类型
atoi函数 ,参数是char类型

20.容器

vector:变长原理是每次不够用就将数组扩大到自身的两倍【倍增】
头文件:<vector>
是一个变长数组,支持随机访问,不支持任意位置O(1)插入
vector<type> a;    type可以是各种基本类型以及结构体
a.size()    得知长度 时间复杂度为O1
a.empty()    得知是否为空 时间复杂度为O1
以上两个函数基本上所有容器都有
a.clear()    清空所有元素 时间复杂度为O1
迭代器:相当于地址
vector<int>::iterator it; 可以把vector的迭代器与一个整数相加减,与指针的移动类似, 可以用*it取得迭代器的值
每一个vector都会有两个特殊的迭代器:[begin,end)左闭右开
a.begin()    a的第一个元素的地址
a.end()    a的最后一个元素的位置的下一个位置的地址
遍历方式:
vector<int> a({1, 2, 3});
一、数组遍历的方式
for (int i = 0; i < a.size(); i ++ ) cout << a[i] << ' ';
二、迭代器遍历
for (auto i = a.begin(); i != a.end(); i ++) cout << *i << ' ';
三、范围遍历
for (int x : a) cout << x << ' ';
a.front()    返回第一个元素,等价于a[0]和*a.begin();
a.back()    返回最后一个元素,等价于a[a.size() - 1]

a.push_back(x)    在最后一个元素之后加一个元素x,时间复杂度为O1
a.pop_back()    删除最后一个元素,时间复杂度为O1

很重要的一个数据结构
队列:queue 以下三个容器没有clear()函数,其他都有, 若需要清空一个队列,则进行重新初始化即可:q = queue<int>();
头文件:queue, 包含了队列queue和优先队列priority_queue两个容器(默认是大根堆)

队列先进先出,相当于一个管道左进右出
queue<int> q;
普通队列都是循环队列: queue
q.push(1)    队头插入一个元素
q.pop()    队尾弹出元素
q.front()    返回队头元素
q.back()    返回队尾元素

优先队列:每次弹出所有数的最大值,默认是大根堆
priority_queue<int> a;
a.push(1)        插入一个元素,插入的位置不确定
a.top()        取出最大值
a.pop()        删除最大值
若是自己定义结构体类型的优先队列,需要重载小于号
struct Rec
{
    int a, b;
    bool operator< (const Rec& t) const
    {
        return a < t.a;
    }
};

priority_queue<Rec> d;
d.push({1, 2});


优先队列:小根堆,每次弹出所有数的最小值
priority_queue<int, vector<int>, greater<int>> b;
若是自己定义结构体类型的优先队列,需要重载大于号
struct Rec
{
    int a, b;
    bool operator > (const Rec& t) const
    {
        return a > t.a;
    }
};

priority_queue<Rec, vector<Rec>, greater<Rec>> d;
d.push({1, 2});

栈:
用法和队列类似,不过是先进后出,队尾插入队尾弹出,一端
头文件<stack>
定义:stack<int> stk;
stk.push(1)    向栈顶插入一个元素
stk.pop()        弹出栈顶元素
stk.top()

双端队列:随机存储,相当于扩展版的vector(队尾插入O1),队头队尾插入都是O1
头文件<deque>
定义:duque<int> a;
a.begin(), a.end()
a.front(), a.back();

a.push_back(1), a.push_front(2);
a[0];随机访问一个元素
a.pop_back(), a.pop_front()

a.clear();


set:
动态维护一个有序的集合
头文件:<set>
有两种容器:
set <int> a;    元素不能重复,插入重复的元素会被忽略
multiset<int> b;    元素可以重复
内部实现和函数基本相同,也可以定义结构体类型的set,但需要重载小于号
size/empty/clear,迭代器与vector类似

a.insert(x)        插入一个元素
a.find(x)        查找一个元素,会返回x的迭代器
if (a.find(x) == a.end()) //判断x在a中是否存在

a.lower_bound(x)    找到大于等于x的最小的元素的迭代器
a.upper_bound(x)    找到大于x的最小的元素的迭代器

a.erase(it)        删除it的迭代器
a.count(x)        返回x的个数,没有就会返回0

迭代器可以理解成指针

map:    【特别有用】              pair类似【自己认为】
头文件:<map>,原理与set一样,但用法神奇
定义:
map<type1, type2> a;
可以看成数组,相当于type1是下标,type2是数组下标对应的值
size/empty/clear/begin/end/insert/earse/find 的用法与set类似
a.insert({type1, type2});


unordered_set:做不了二分,目前一些比赛不支持该容器
无序的集合,与set相对,用法与set完全一致,除了没有a.upper_bound(x)a.lower_bound(x)两个函数
unordered_set<int> a;
unordered_multiset<int> b;


21.位运算: 


与 & and
或 | or
非 ~ not
异或 ^ xor
对于一个整型进行位运算,计算机是将该数转换为二进制数,一位对一位得出结果,输出该二进制数的十进制数

将整数转换为二进制进行移动,再转换为十进制数输出
左移 << ,在最后一位后补0 等价于* pow(2,k)
右移 >>将最后一位移出去,即抹去,右移等价于 / pow(2,k)

常用操作:
(1)求x的第k位数字: x >> k & 1
(2)lowbit(x) = x & (~x + 1), 返回x的最后一位1以及后面的数字


22.常用库函数:都在algorithm库中,算法库


(1)reverse 翻转 On
翻转一个vector:
reverse(a.begin(), a.end());
翻转一个数组:
reverse(a, a + size)传入首地址和尾地址后一个地址

(2)unique 去重,删去重复元素,需要保证相同元素挨在一起,原理是将去重后的数据放在前面,其他放在后面
会返回去重后的末尾元素的下一个地址

int a[] = {1, 1, 2, 2, 3, 4, 5};
    int m = unique(a, a + 7) - a;  //去重的同时,返回尾地址元素的下一个地址,减去首地址元素,等于之间的数据量
    cout << m << endl;

如果是vector可以这样:
vector<int> a({1, 1, 2, 2, 3, 4, 5});
a.erase(unique(a.begin(), a.end()), a.end());  
这句话完成了两个操作,一是去重,二是通过返回的新的地址,将新地址到末尾的元素全部删掉
for (auto x : a) cout << x << ' ';

(3)random_shuffle 打乱顺序

random_shuffle(a.begin(), a.end());      但每次打乱的顺序都一样
想要达到不一样的效果:
先在头文件加上<ctime>加上时间
然后加上随机种子 srand(time(0));  //这个时间函数返回1970年到当前的时间秒数

(4)sort函数      【【【【超级重要】】】
sort(a.begin(), a.end());                  从小到大排
sort(a.begin(), a.end(), greater<int>());    从大到小排
若想要按照自己想的方式排序,可以自己定义一个cmp函数,然后
bool cmp (int a, int b)    //这里可以理解为 a 是否应该排在 b的前面
{
    return a < b;
}

sort(a.begin(), a.end(), cmp);      即可

也可以排结构体:
bool cmp (Rec a, Rec b)
{
    return a.x < b.x
}或者在结构体的定义中重载小于号

(5)lower_bound/upper_bound 二分
传入的参数需要已经排好序了
lower_bound(a, a + size, x) 在a中查找x,返回第一个大于等于x的元素的迭代器, 传入首地址,尾地址后一位
upper_bound(a, a + size, x) 在a中查找x,返回第一个大于x的元素的迭代器


(6)next_permuatatin(a.begin(), a.end()), 
从小到大,进行返回下一次全排列
若后面不能排序了,就会返回false,反之返回1

相关文章:

  • 牛客练习赛#84 F 莫比乌斯反演+杜教筛+技巧+斐波那契数列和gcd的结论+矩阵快速幂
  • ZZNUOJ_用C语言编写程序实现1342:支配值数目(附完整源码)
  • java毕业设计后勤管理系统餐饮评价监督系统(附源码、数据库)
  • 前端基础学习笔记
  • 【TS】联合类型--类型断言--类型推断
  • 谈笑风声的秘密
  • QT影城网上售票系统
  • NetCDF数据在ArcMap中的使用
  • 打怪升级(考验思路)
  • 持续精进,改变自己