加载中...

C++ 基础语法

C++ 基础语法

基本输入输出

#include<iostream>

using namespace std;

int main()
{
    cout<<"xt love ac"<<endl;
    return 0;
}

头文件

#include <cstdio> 包含 printf (输出), scanf (输入)

#include <iostream> 包含 cin (读入), cout (输出)

using namespace std 使用 std 命名空间

万能头文件 #include <bits/stdc++.h>

//关闭同步流
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);

变量类型

布尔型 bool , 字符型 char

整型 int , 浮点型 float , 双精度浮点型 double

char 类型和整型做运算, 会转化为整型. 若想输出 char 类型, 需要强制类型转换

char c = 'A' , cout << (char)(c+32) << endl




循环语句

打印菱形 : 输入一个奇数 n , 输出一个由 * 构成的n阶实心菱形

曼哈顿距离

(x1,y1) 与点 (x2,y2) 之间的曼哈顿距离

c = |x1 - x2| + |y1 - y2|

//打印n阶实心菱形

cin>>n;
int cx=n/2,cy=n/2;
for(int i=0;i<n;i++)
{
    for(int j=0;j<n;j++)
        if(abs(i-cx)+abs(j-cy)<=n/2)cout<<'*';
		else cout<<' ';
    cout<<'\n';
}



数组

数组操作常用函数:

翻转数组函数 reverse(a,a+n) , 第一个参数表示翻转的数组的起始位置, 第二个参数表示翻转的数组的末位置的下一个位置

初始化数组函数 memset(a,0,sizeof a) , 第一个参数表示初始化起点, 第二个参数表示初始化数组(只有0和-1是原值), 第三个参数表示初始化长度

复制数组函数 memcpy(b,a,sizeof a) , 第一个参数表示目标数组, 第二个参数表示待复制数组, 第三个参数表示复制长度


打印蛇形矩阵

偏移量技巧

dx[4] = {0,1,0,-1} , dy[4] = {1,0,-1,0}

//打印蛇形矩阵

int res[100][100];
int main()
{
    int n,m;
    cin>>n>>m;
    
    int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
    
    for(int x=0,y=0,d=0,k=1;k<=n*m;k++)
    {
        res[x][y]=k;
        int a=x+dx[d],b=y+dy[d];
        if(a<0||a>=n||b<0||b>=m||res[a][b])
        {
            d=(d+1)%4;
            a=x+dx[d],b=y+dy[d];
        }
        x=a,y=b;
    }
    
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
            cout<<res[i][j]<<' ';
        cout<<'\n';
    }
    
    return 0;
}



字符串

字符串的输入输出:

cin 读取到 空格 , 回车 即停止读入

读入带 空格 的字符串:

fgets(a,100,stdin)

getline(cin,a)

printf 输出字符串:

printf("%s",a.c_str)


string 初始化:

string s1 , 默认初始化, s1 是一个空字符串

string s2 = s1 , s2s1 的副本, 注意 s2 只是与 s1 的值相同, 并不指向同一地址

string s3 = "xietong" , s3 是该字符串字面量的副本

string s4 = (10,'c') , s4 的内容是 cccccccccc


字符串常用操作:

求字符串长度 strlen(str) (不含空字符)

比较两个字符串的大小 strcmp(a,b) (a<b 返回 -1 , a==b 返回 0 , a>b 返回 1 )

将字符串 b 复制给从 a 开始的字符串 strcpy(a,b)

下标遍历字符串 for(int i = 0, len = strlen(str); i < len ; i++ )

范围遍历字符串(不能改变字符串内容) for(char c : s)

范围遍历并改变字符串中的内容 for(char &c : s)




类、结构体、指针和引用

类:\(\quad\) 关键字 class

类里面有两个关键字 privatepublic

private 后面的内容是私有成员变量, 在类的外部不能访问

public 后面的内容是公有成员变量, 在类的外部可以访问

结构体: \(\quad\) 关键字 struct

区别: 对于没有声明 private / public 的成员变量

class 默认为 private , 结构体 struct 默认为 public


定义指针:

int a = 10

int *p = &a , pint 类型变量的指针, 定义 pa 的地址

int * 看作一个类型——指针

改变地址内变量的值: *p = 12

数组名是一种特殊的指针, 指针可以做运算

int a[5] = {1,2,3,4,5} , cout << a << endl

输出的是 数组a 的地址, 也是 a[0] 的地址


引用: int &p = a

定义 pa 相同地址, pa 共用相同的地址和值


调用成员变量:

调用的变量是一个变量:

Node a = Node(1)

a.next , a.val

调用的变量是一个指针:

Node *p = new Node(1)

p->next = p , p->val


链表

struct Node
{
    int val;
    Node* next;
};

Node *p = new Node(1) 返回值是地址

Node p = Node(1) 返回值是值

struct Node
{
    int val;
    Node* next;
    Node(int_val):val(_val),next(NULL){}
}

int main()
{
    auto p = new Node(1);
    auto q = new Node(2);
    auto o = new Node(3);
    
    p->next = q;
    q->next = o;
    
    return 0;
}
//通常将头节点的地址存储到head变量中
Node* head = p;
//遍历链表
for(Node* i=head;i;i=i->next)
{
    cout << i->val << endl;
}
//创建新节点
Node* u = new Node(4);
u->next = head;
head = u;
//删除节点
head->next = head->next->next;



STL容器

vector , #include <vector>

vector 是一个变长数组

int main()
{
    vector<int> a;	//相当于一个长度动态变化的int数组
    vector<int> b[233];		//相当于第一维长233,第二维长度动态变化的int数组
    
    a.size();		//返回元素个数
    a.empty();		//若a为空返回true,否则返回false
    a.clear();		//清空数组a
    
    struct ret{...};
    vector<ret> c;		//结构体类型也可以保存在vector中
}

迭代器, 类似于指针

定义迭代器 vector<int>::iterator it =a.begin(), 定义 a 的迭代器

取值: *it , 取地址: it

a.begin() 返回 a 的第一个元素的地址

a.end() 返回 a 的最后一个元素的下一个位置的地址

//遍历vector
vector<int> a ({1,2,3});
for(int i=0;i<a.size();i++)cout<<a[i]<<' ';
for(auto it=a.begin();it!=a.end();it++)
    cout<<*it<<' ';
a.front()		//返回a的第一个元素
a.back()		//返回a的最后一个元素
a.push_back(x)		//把元素x插入到a的尾部
a.pop_back()		//删除a的最后一个元素

queue , #include <queue>

priority_queue , #include <queue>

queue 循环队列: 优先弹出先进入的元素(先进先出)

priority_queue 优先队列: 大根堆优先弹出最大的元素, 小根堆优先弹出最小的元素

queue<int> a;		//循环队列
struct rec{...};priority_queue<rec>a;	//结构体中必须定义小于号
priority_queue<int> a;		//大根堆
priority_queue<int,vector<int>,greater<int>>a;		//小根堆
//在结构体rec中定义小于号
struct rec
{
    int a,b;
    bool operator<(const rec &t)const
    {
        return a<t,a;
    }
};
//大根堆要重载小于号,小根堆要重载大于号
//循环队列 queue
queue<int> q;
q.push(x)		//在队尾插入元素x
q.pop()			//弹出队头元素
q.front()		//返回队头元素
q.back()		//返回队尾元素
//优先队列 priority_queue
priority_queue<int> q;	//大根堆
q.push(x)		//插入元素x
q.top()			//返回最大值
q.pop()			//删除最大值

队列、优先队列、栈没有 clear 函数


stack , #include <stack>

栈: 后进先出

stack<int> q;
q.push(x)		//插入一个元素x
q.top()			//返回栈顶元素(输入的最后一个元素)
q.pop()			//弹出栈顶元素

双端队列 deque , #include <deque>

deque<int> a;
a.begin(),a.end()		//返回队头/队尾的迭代器
a.front(),a.back()		//返回队头/队尾元素
a.push_back(x)		//从队尾入队
a.push_front(x)		//从队头入队
a.pop_back()		//删除队尾元素
a.pop_front()		//删除队头元素
a.clear()		//清空队列
a[0]			//双端队列支持随机访址

set , #include <set>

multiset , #include <set>

set<int> s 元素不能重复, 会自动删掉重复元素

multiset<int> s 元素可以重复

结构体定义为set , 要重载小于号

itset 的一个迭代器, set<int>::iterator it

it++ 会指向 it 下一个元素, it-- 会指向 it 上一个元素(元素从小到大排序)

a.begin(),a.end()		//返回队头/队尾的迭代器
a.insert(x)			//插入一个元素x
a.find(x)			//若查找到元素x,返回x的迭代器,否则返回a.end()
if(a.find(x)==a.end())		//判断x在a中是否存在
a.lower_bound(x)		//返回大于等于x的最小元素的迭代器
a.upper_bound(x)		//返回大于x的最小元素的迭代器
a.erase(x)			//删掉x的所有迭代器
a.erase(it)			//删掉迭代器it
a.count(x)			//返回a中x的个数

map , #include <map>

map 是映射, 存储数对(有序,按第一个参数从小到大排序)

map<int,int> a;
a[1]=2;
a[7]=96;
cout<<a[1]<<endl;	//输出2

a.insert({,})		//插入
a.find(第一个参数)		//返回第二个参数的迭代器
a[第一个参数]			//返回第二个参数的值
//可通过"a[]= "来修改第二个参数的值

unordered_set , #include <unordered_set>

无序的 set , 元素不能重复

除不含 lower_boundupper_bound 外, 其余函数同 set

unordered_multiset , #include <unordered_set>

无序的 multiset , 元素可以重复

除不含 lower_boundupper_bound 外, 其余函数同 multiset

unordered_map , #include <unordered_map>

无序的 map


bitset , #include <bitset> , 01串

bitset<1000>a;		//定义长度为1000的01串
a[0]=1;			//没有定义的默认为0
a.count()		//返回a中1的个数
a.set(i)		//把第i位设为1
a.reset(i)		//把第i位设为0

pair , #include <utility>

pair<int,int> a,b;
a = make_pair(,)	//赋值
cout << a.first << ' ' << a.second << endl;		//输出

pair 可比较, if(a==b) / if(a>b) / if(a<b)

先比较 first 参数, 后比较 second 参数




位运算

位运算
与 & 0 & 0 = 0 0 & 1 = 0 1 & 0 = 0 1 & 1 = 1
或 | 0 | 0 = 0 0 | 1 = 1 1 | 0 = 1 1 | 1 = 1
取反 ~ ~ 0 = 1 ~ 1 = 0
异或 ^ 0 ^ 0 = 0 0 ^ 1 = 1 1 ^ 0 = 1 1 ^ 1 = 0
右移 >> a = 11011 a>>1 = 1101 a右移k次, a>>k 等价于 \(\dfrac{a}{2^k}\)
左移 << a = 110 a<<1 = 1100 a左移k次, a<<k 等价于 \(a\cdot2^k\)

x 的第 k 位数字: x>>k&1

返回 x 的最后一位 1 : x&-x




常用库函数

reverse 翻转

vector<int> a({1,2,3,4,5});
reverse(a.begin(),a.end());

int a[]={1,2,3,4,5};
reverse(a,a+5);

//reverse第一个参数为起始指针,第二个参数为末位下一位指针

unique 去重

//unique返回值为新数组的end()

//求不同元素的个数
int m=unique(a.begin(),a.end())-a.begin();
int m=unique(a,a+n)-a;

//排序并删除多余元素
a.erase(unique(a.begin(),a.end()),a.end());
//a.erase(l,r)    删除[l,r)内元素

random_shuffle 随机打乱

random_shuffle(a.begin(),a.end());
#include<ctime>
srand(time(0));	//返回到1970年1月1日的秒数
//生成随机种子

sort 排序

sort(a.begin(),a.end());	//按从小到大排序
sort(a.begin(),a.end(),greater<int>());		//按从大到小排序

bool cmp (int a,int b)	//a是否应该排在b前面
{
    return a>b;
}
sort(a.begin(),a.end(),cmp);

//结构体排序:
//1.传入第三个参数(定义比较方案的函数)
//2.在结构体内重载比较方法
struct Rec
{
    int x,y;
}a[5];
sort(a,a+5,cmp);

struct Rec
{
    int x,y;
    bool operator<(const Rec &t)const
    {
        return x<t.x;
    }
}a[5];
sort(a,a+5);

lower_bound / upper_bound 二分

lower_bound 返回大于等于 x 的第一个元素的迭代器

upper_bound 返回大于 x 的第一个元素的迭代器

前提: 区间内有序(从小到大排序)

int a[]={1,2,4,5,6};
int *p=lower_bound(a,a+5,4);
cout<<*p<<endl;

int t=lower_bound(a,a+5,4)-a;
cout<<a[t]<<endl;

vector<int> a({1,2,4,5,6});
int t=lower_bound(a.begin(),a.end(),4)-a.begin();
cout<<a[t]<<endl;


posted @ 2023-04-30 14:41  邪童  阅读(71)  评论(0编辑  收藏  举报