【c++】基础知识

ASCII码表

ASCII码表

c++map、unordered_map插入方法

  • map是底层是红黑树 故会自动排序 默认是升序 map支持[]运算符 set不行 因为set只是单个值 map是键值对
  • unordered_map 是无序的
  • set 底层也是红黑树 也是有序的
  • umap.insert(pair<string, string>(“天津”, “005”));
  • 例如:umap.insert(make_pair("香港","006"));
  • [重点!!!] 其实还有一种最简单的方法。 即umap["feng"] = "junshan"; map也是一样的;
  • unordered_map底层是一个散列表(哈希表),map底层是一个红黑树
  • c++ 中lower_bound(begin,end, val) 在指定范围内查找不小于目标值的第一个元素的值 并且返回指向该元素的指针,
  • upper_bound(begin,end,val) 在指定范围内寻找大于目标值的第一个元素的值 并且返回该指向元素的指针
  • 在这里插入图片描述

数据范围

  • unsigned int 0 ~ 232-1
  • byte -128 ~ 127
  • int -231 ~ 231-1 2147483647 大约是109
  • long -231 ~ 231-1
  • long long -263 ~ 263-1 大约是1018
  • unsigned long long 0 ~ 264-1

【关于计算中的强制类型转换 】:

int nums[i]
int sum = nums[a] + nums[b] + nums[c] + nums[d]
其中nums[a] 他们呢都是1e9  和会超出int 范围 
所有sum 要变成long long 
正确的转换方式应该是 
long long sum = (long long) nums[a] + nums[b] + nums[c] + nums[d]
不能是 : long long sum = (long long) (nums[a] + nums[b] + nums[c] + nums[d])
后面的括号不能加

寄存器变量

  • 由于受硬件寄存器长度的限制,所以寄存器变量只能是char、int或指针型。寄存器说明符只能用于说明函数中的变量和函数中的形参,因此不允许外部变量静态变量 说明为"register"。
  • 寄存器是与机器硬件密切相关的,不同类型的计算机,寄存器的数目是不一样的,通常为2到3个,对于在一个函数中说明的多于2到3个的寄存器变量,C编译程序会自动地将寄存器变量变为自动变量
  • 由于register变量使用的是硬件CPU中的寄存器,寄存器变量无地址,所以不能使用取地址运算符"&"求寄存器变量的地址
  • 当今的优化编译系统能够自动识别使用频繁的变量,从而自动地将这些变量放在寄存器中,而不需要程序设计者指定。因此在实际上用register声明变量是不必要的

新奇的语法

return string(n-1,'a') + 'b'
这是一种新发现的语法 string (n, 'a') n表示长度
string s s.push_back(‘d’); 竟然有这个方法 string 型数据有 push_back() 方法 内容是字符
sscanf(log.c_str(), "%d:%[^:]:%d", &idx, type, &timestamp 读取type是用的是正则表达式 表示当读取到 : 时结束

***STL总结

总结表

  • 只有有begin()和end()函数的容器才能够用如下for循环进行遍历, 例如队列和栈没有begin和end函数,不能用下面的语法

  • for (auto t : stl) {	
    	cout << t  << endl;
    }
    
  • 所有容器的大小都可以使用.size()函数, 平时写代码时都用size,不用考虑length。

  • string 有begin() and end() 函数

  • 队列queue 没有clear() 函数

  • vector对于二维数组

  • 声明: vector<vector> ans(n1, vector());

  • 插入的时候要先插入一个 数组 ans.push_back(vector ());

  • 再 ans.back().push_back(x);

对于set、multiset 容器

  • set是有序集合 而 multiset 是有序多重集合(即允许元素重复)
  1. 常用方法set < int > s
s.size()
s.empty()
s.clear()
s.begin()/s.end()
s.insert(x)
s.find(x) 如果找到 返回指向x的迭代器 如果找不到返回s.end()
s.lower_bound(x) 查找 <大于等于> x的元素中的最小的一个 并返回指向该元素的迭代器
s.upper_bound(x) 查找 大于 x的元素中最小的一个, 并返回指向该元素的迭代器
s.erase(it) / s.erase(x) 即可以根据 迭代器 和 值 进行删除
s.count(x)
  1. map容器
map<int, int> m;
map<string, int, greater<string> > ans; map降序排列
m.size()
m.empty()
m.clear()
m.begin()/m.end()
m.insert(make_pair(1,2))
m.erase(key) map删除可以直接用erase删除 键
m.find(x) 根据key值进行查找 如果找到返回指向该元素的迭代器 不存在就返回m.end()
!!!map最吸引人的地方是支持 []  m[key] = value 如果key不存在 那么会新建一个key

* stl 主要有 
  * vector 
  * queue  
  * stack  
  * deque  
  * priority_queue
* 其中 vector 和 deque 插入删除是用的push_back() pop_back()   其余的用的是push() pop() 
* 并且vector和deque 都有begin() 和end() stl都没有  map和set都有begin 和end 但是没有front 和back
* 都有clear()size() 方法  
* 只有vector 和 deque 有clear() 方法 

c++常用函数

unordered_map<int, int> map; 和map<int, int> map;
都支持[] 运算  例如map[0] = 1;  可以采取这种方式直接进行赋值

char* strlwr(char* s) 将s中的字母变成小写
char* strupr(char* s) 将s中的字母变成大写
char* strcpy(char* s1, char* s2) 将字符串s2拷贝到s1中
char* strncpy(char* s1, char* s2, int n) 最多拷贝n个字节
char* strcat(s1, s2) 字符串拼接
int strcmp(s1, s2) 字符串比较 返回 -1 0 1
int stricmp(s1, s2) 字符串比较 与大小写无关 
int strlen(const char *string) 注意是const  里面的字符串是不可变的
void * memcpy( void * s1, void * s2, int n) 将内存地址s2 处的n 字节内容拷贝到内存地址s1
cout << string(n, '1') << endl; // 连续输出n个字符1

ceil(5.2)  ->6向上取整
floor(5.2)  ->5向下取整
log(x)  求x的自然对数
log10(x) 求x的对数(10为底)

vecotr 中 insert() 函数
! 其中 push_back() 方法 和 emplace_back() 方法一样  甚至 emplace_back() 方法更优
iterator insert(pos,elem) 	在迭代器 pos 指定的位置之前插入一个新元素elem,并返回表示新插入元素位置的迭代器。
iterator insert(pos,n,elem) 	在迭代器 pos 指定的位置之前插入 n 个元素 elem,并返回表示第一个新插入元素位置的迭代器。
iterator insert(pos,first,last)  	在迭代器 pos 指定的位置之前,插入其他容器(不仅限于vector)中位于 [first,last) 区域的所有元素,并返回表示第一个新插入元素位置的迭代器。
iterator insert(pos,initlist) 	在迭代器 pos 指定的位置之前,插入初始化列表(用大括号{}括起来的多个元素,中间有逗号隔开)中所有的元素,并返回表示第一个新插入元素位置的迭代器。

string 方法中有一个find方法 用来寻找a是否为b的子字符串 
在作为判断条件时 必须让a.find(b) 与 string::npos 进行比较
string.find()在没找到的情况下会返回一个标志:string.npos。
int main() {
	string a = "anc";
	string c = "anc";
	string b = "ansffc";
	if (b.find(a) != string::npos) cout << "找到了" << endl; 
	else cout << "找不到" << endl;
	
	if (c.find(a) != string::npos)   // 找到了
		cout << "找到了" << endl;
}

在这里插入图片描述[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WYq0BjX4-1683388560739)(C:\Users\86176\AppData\Roaming\Typora\typora-user-images\image-20220807083418324.png)]在这里插入图片描述在这里插入图片描述

sort(subs.begin(), subs.end(), greater<string>{}); // 将字符串从大到小排序 降序排列
sort(ans.begin(), ans.end(), greater<int>{});  这个也是降序
sort(ans.begin(), ans.end(), less<int>{}); 这个是升序
memcpy(path, curpath, sizeof curpath); 将curpath中的值复制到path中
注意 用path = curpath 不行 这只是使得path指针指向curpath所指的数组 并没有改变path数组
string str = to_sting(123464);  // 将int型转换成 string
string 转换成int型 
string love = "77";
int a = atoi(love.c_str());  string-->int
cout << a << endl;
cout << typeid(a).name() << endl;    获取一个变量的类型

double b = atof(love.c_str());   string-->double
cout << b << endl;
cout << typeid(b).name() << endl;

float c = atof(love.c_str());   string-->float
cout << c << endl;
cout << typeid(c).n

ame() << endl;

vector数组初始化

在这里插入图片描述

scanf返回值

  1. 正整数,表示正确输入参数的个数。
    例如执行 scanf(“%d %d”, &a, &b);
    如果用户输入”3 4”,可以正确输入,返回2(正确输入了两个变量);
    如果用户输入”3,4”,可以正确输入a,无法输入b,返回1(正确输入了一个变量)。
  2. 表示用户的输入不匹配,无法正确输入任何值。如上例,用户如果输入”,3 4”,返回0。
  3. EOF,这是在 stdio.h 里面定义顺便说一下,printf 的常量(通常值为-1),表示输入流已经结束。在Windows 下,用户按下CTRL+Z(会看到一个^Z字符)再按下回车(可能需要重复2次),就表示输入结束;Linux/Unix下使用CTRL+D表示输入结束。
scanf("%d %*d %d",&a,&b);

当输入为:1 2 3时,把1赋予a,2被跳过,3赋予b。
scanf()函数成功读入会返回1, 读入失败是返回-1, 在有些题目中,并没有给出要读取的数据的个数,总之,没了就不读取了。
这是就可以用scanf()来操作
例如: if (scanf("%d") == -1) return false; 这就是如果没有输入就返回false

puts()

int puts(const char* str);
这是puts的定义
puts() 函数不能输出string 类型的数据  string a = "dsfjkl" puts(a) 这是不合法的
但是puts("dfasl") 这是合法的  还可以用这种方式来进行 puts(a.c_str());

关于a.c_str();
	const char* c;
	string s = "1234";
	c = s.c_str();
	cout << c << endl;
	s = "abcde";
	cout << c << endl;
其结果输出是 1234 
            abcde
 c_str() 相当于使c永远的指向了string s所代表的内存空间 当s内容发生变化时, 输出的c也会有相应的变化。

gets()函数 读取读取一行

  • attention
  • 对于gets()和getline()函数,如果在他们前面有读入了其他的数据,一定要用 getchar() 来把上一次的回车符读取
  • 否则后报错!!!!!!!!!!!!!!
	// get()函数从键盘读取字符函数,无线读取,不会判断上限,以回车结束读取,
	// 所以应该保证buffer的空间足够大 
	char c[15];
	gets(c);
	cout << c << endl;
	char *p;  // 这里不能是 char *p, 然后gets(p) 是错误的,因为p没有指向有效的内存 
	gets(p);
	cout << p << endl;

getline() 读取一行

  • getline()函数会读取一行文本(知道遇到换行符为止,并将读取的文本存在string变量中 ```c
string line;
getline(cin, line);

强制转换

void* 强制转换成别的 指针 
void* arg
(int*)arg  就强制转换成了了int型指针 如果在 *(int*)arg 就是取它的值

tuple<>

tuple<string, string, int> mytuple("feng", "junshan", 21);
cout << get<0>(mytuple) << endl;   // 得到第一个元素
cout << get<2>(mytuple) << endl;   // 得到第三个元素
cout << tuple_size<decltype(mytuple)>::value << endl;  // 获取tuple的大小
get<0>(mytuple) = "junshan";  // 修改对应位置的值
cout << get<0>(mytuple) << endl;  

map<string, int> 排序问题

class Solution {
public:
    vector<int> frequencySort(vector<int>& nums) {
        unordered_map<int, int> cnt;
        for (int num : nums) {
            cnt[num]++;
        }
        // 这里的a b 是nums中的  排序的依据是cnt[a] cnt[b]的关系
  		// 这是一种新方式
  		// 不不不 这种方式 也是类似于将map 中的数据传递到 nums中 同时用nums进行排序
        // 只不过这道题 元数据在nums中, 用map统计其各自 的出现顺序 
        // 然后再nums上 根据map中的second 进行排序
        sort(nums.begin(), nums.end(), [&](const int a, const int b) {
            if (cnt[a] != cnt[b]) {
                return cnt[a] < cnt[b];
            }
            return a > b;
        });
        return nums;
    }
};

map和set的排序功能

  • map和set 都是基于红黑树来实现的,具有自动排序功能
  • 而unordered_map和unordered_set是基于哈希表,不具有自动排序的功能,优点是数据的插入和查找的时间复杂度比较低,接近于常数,缺点是占用的内存比较大
map<int,string> mp;
mp[6] = "feng";
mp[2] = "jun";
mp[3] = "shan";

map<int,string>::iterator it = mp.begin(); // 迭代器语法
while (it != mp.end()) {
    cout << it->first << ' ' << it->second << endl;
    it++;  // 这里要手动自加
}
/*
	* 总结,map是具有排序功能的,是按照key值升序排列;
	* 而unordered_map 是没有排序功能,顾名思义
	*/
// 对于map的遍历方式一是使用auto for循环
// 二是使用迭代器 map<int,string>:: iterator it = map.begin()
unordered_map<int,string> ump;
ump[6] = "feng";
ump[2] = "jun";
ump[3] = "shan";
unordered_map<int,string>::iterator uit = ump.begin();
while (uit != ump.end()) {
    cout << uit->first << ' ' << uit->second << endl;
    uit++;
}

// 这是一个很好用的例子,set具有排序功能,这个例子是将set和vector进行组合 当我们进行排序的时候可以根据只进行排序
set<vector<int>> s;
s.insert({ 1,2,3 });
s.insert({ 1,1,3 });
s.insert({ 1,2,1 });

for (vector<int> v : s) {
    for (int i = 0; i < v.size(); i++) cout << v[i] << ' ';
    cout << endl;
}

1 1 3
1 2 1
1 2 3
    
// 每个vector的大小不必相同
1 1 3
1 2
1 2 3

在这里插入图片描述# 一个地址问题

#include <iostream>

using namespace std;

int main()
{
	for (int i = 0; i < 6; i++) {
		int copy = i;
		printf("%p\n", &copy);
	}
 }   
 运行结果:
000000000070fe18
000000000070fe18
000000000070fe18
000000000070fe18
000000000070fe18
000000000070fe18
 !!! attention 这里虽然每次都是copy 但是copy的地址并没有变  

重载运算符

// 重载运算符
bool cmp(pair<int, int> a, pair<int, int> b) {
	return a.second < b.second;
}
这里 > 是降序, < 是升序  不能有<=  >= 会报错

compare函数

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值