跳转至

基础知识

运算符优先级

优先级值越大,表示优先级越高。

优先级 分类 运算符 结合性
1 逗号运算符 , 从左到右
2 赋值运算符 =、+=、-=、*=、/=、 %=、 >=、 <<=、&=、^=、 =
3 逻辑或
4 逻辑与 && 从左到右
5 按位或
6 按位异或 ^ 从左到右
7 按位与 & 从左到右
8 相等/不等 ==、!= 从左到右
9 关系运算符 <、<=、>、>= 从左到右
10 位移运算符 <<、>> 从左到右
11 加法/减法 +、- 从左到右
12 乘法/除法/取余 *(乘号)、/、% 从左到右
13 单目运算符 !、*(指针)、& 、++、–、+(正号)、-(负号) 从右到左
14 后缀运算符 ( )、[ ]、-> 从左到右

类的概念及简单应用

定义类

类使用关键字 class 或者 struct 定义,下文以 class 举例。

class myclass{
  public:

}a;

// 等效于

struct mystruct{

}a;

与使用 struct 大同小异。该例定义了一个名为 Object 的类。该类拥有两个成员元素,分别为 weight,value;并在 } 后使用该类型定义了一个数组 e

定义类的指针形同 [struct](https://oi-wiki.org/lang/struct/)

访问说明符

不同于 [struct](https://oi-wiki.org/lang/struct/) 中的举例,本例中出现了 public,这属于访问说明符。

  • public:该访问说明符之后的各个成员都可以被公开访问,简单来说就是无论 类内 还是 类外 都可以访问。

  • protected:该访问说明符之后的各个成员可以被 类内、派生类或者友元的成员访问,但类外 不能访问

  • private:该访问说明符之后的各个成员 只能类内 成员或者友元的成员访问,不能 被从类外或者派生类中访问。

对于 struct,它的所有成员都是默认 public。对于 class,它的所有成员都是默认 private

成员函数和运算符重载

int operator*(const node& other)const{
    return x * other.x + y * other.y; 
}//对乘法进行重载运算符
bool operator <(const node& b)const{
    return x>b.x;
}//对小于号进行重载运算符,默认的sort和优先队列之类的结构都是使用<进行比较的

下面是一个两数取min的代码

#include<bits/stdc++.h>
using namespace std;

struct node{
    int x;
    bool operator <(const node& b)const{
        return x>b.x;
    }
}a,b;

int main(){
    cin>>a.x>>b.x;
    cout<<max(a,b).x;
    return 0;
} 

我们在使用map构造以结构体为下标的映射时,必须要求我们有对结构体<比较的函数定义。此时我们就需要重载运算符。注意!如果结构体为struct{int a,b,c},那么应该如此重载

bool operator <(const Node x)const{
    if(a!=x.a)return a<x.a;
    if(b!=x.b)return b<x.b;
    return c<x.c;
}

如果仅仅比较部分项目,那么会有意想不到的效果(如标记了{3,4,1},实际上把{3,,}都标记上了)。当然这有妙用。

字符串与数字转换

printf 的规定符

  • %d 十进制有符号整数

  • %u 十进制无符号整数

  • %f 浮点数

  • %s 字符串

  • %c 单个字符

  • %p 指针的值

  • %e 指数形式的浮点数

  • %x, %X 无符号以十六进制表示的整数

  • %o 无符号以八进制表示的整数

  • %g 把输出的值按照 %e 或者 %f 类型中输出长度较小的方式输出

  • %p 输出地址符

  • %lu 32位无符号整数

  • %llu 64位无符号整数

  • %% 输出百分号字符本身。

除了格式化说明符之外,printf() 函数还支持一些标志和选项,用于控制输出的精度、宽度、填充字符和对齐方式等。例如:

  • %-10s:左对齐并占用宽度为 10 的字符串;

  • %5.2f:右对齐并占用宽度为 5,保留两位小数的浮点数;

  • %#x:输出带有 0x 前缀的十六进制数。

define 用法

最基本的字符替换功能这里就不再介绍了。

//第一种写法,建议用于写函数,必须写成函数类型
#define add(x,y) (x+y)
#define rp(1,a,b) for(int i=1;i<=(a),i+=(b))
//第2种写法,"#n"可以将n转换为字符串嵌入
#define PXN(n) printf(" x"#n" \n")
//第3,##n可以将n与前面的部分联合起来
#define PXN(n) printf("%d\n",b##n)

注意,以下写法不可取

#define PXN(n) printf("##n\n",b2)//期望PXN(abc)>>输出字符串abc
#define PXN(n) printf("%d \n",b"#n")//期望PXN(2)>>输出b2的值

  • #n可以将n转换为字符串嵌入

  • ##n可以将n与前面的部分联合起来

通过了解define的基本用法,我们可以很简单的写出升级版的cerr

#define dbg(x) cerr<<#x<<" : "<<x<<endl;

memset 函数

memset函数是基于字节来清空的。

  • char是一种字符类型,用来表示单个字符。每个字符占用一个字节的内存空间。

  • int是一种整数类型,用来表示整数。每个整数占用四个字节的内存空间。

因此我们再使用memset批量赋值char[]时是不会有任何问题的

但是以为我们的int是4个字节,于是赋值就会出现问题

例如:对于int型数组a,我们尝试使用memset将数组中的元素都赋值为100,即:

memset(a,100,sizeof a);

输出结果为1684300900,这与我们希望得到的结果截然不同。接下来我们将分析该结果产生的原因:

100表示:内存中每个字节都赋予ASCII码为100的字符。我们将十进制数100转化为十六进制,得到0x64(0x为十六进制前缀)。则 memset(a,100,sizeof a) 表示:将目标内存中的每个字节都赋为0x64。

image.png

如上图所示,由于a为int型数组,每个元素占四个字节的内存空间。由于每个字节都被赋值为0x64,因此每个int型元素的值都为0x64646464。将其转化为十进制,得到输出结果1684300900。

但是以为0,-1所有码位都一样,所以我们可以正确赋值。

这样可以解释为什么写0x3f3f和0x3f是一样的了。因为实际上只能够存下0x3f。

但是注意,在对double[]进行赋值时,规则不一样!0x3f非常小。建议赋值时输出看看。