初学者无痛C转C++

初学者无痛C转C++

文章目录

为什么要转C++

首先,对于C语言,它初见虽然简单,但是深入后确实非常的难并且不方便的。

例如C语言使用排序qsort必须要写排序函数,但是用C++的std::sort就很方便,而且对于一些常见的数据结构C++也有相对应的STL容器如:queue,stack,vector
最重要的还是C++在C++11之前和C语言相差不大,如果仅仅是打算法竞赛那么C++=C + STL,转起语言来几乎完全没有压力

C++语言基础

对于初学者而言,我们只需要记住如下代码

#include<bits/stdc++.h>usingnamespace std;intmain(void){return0;}

初看这个和C语言极为相似除了using namespace std;和#include <bits/stdc++.h>
对于using namespace std;我们只需要记住不需要了解,如果有人想了解的话可以去搜下C++的命名空间

然后对于#include <bits/stdc++.h>是C++的万能头(竞赛专用,你下的gcc里面是没有这个的,需要额外配置),后续内容中如果学习C++只为了打算法竞赛,那么后续所有头文件都不需要记忆

C++如何输入输出

#include<iostream>#include<string>usingnamespace std;intmain(void){int n; string s; cin >> n; cin >> s; cout << n <<"\n"<< s << endl;}

上述头文件的iostream就相当于C的stdio.h,而string是C++特有的字符串对象
其中C输入为scanf而且还需要记住类似于%d,%s之类的格式化符号,而C++之间cin就可以了,输出的话直接cout

C++string相关

对于C语言我们处理字符串很痛苦(虽然C++也很痛苦),但C++处理字符串却比C语言简单多了

以下列举一些本人常用的字符串处理方法

去除前导空格

#include<iostream>#include<string>usingnamespace std;intmain(void){ string s;while(getline(cin , s)){int pos = s.find_first_not_of(" "); s.erase(0, pos); std::cout << s <<"\n";} std::cout <<"hello , world";}

提示:C++的cin会自动去除掉前导空格
如果是去除前导0的话直接把" "换成"0"就可以了

提取和拼接子串

#include<iostream>#include<string>usingnamespace std;intmain(void){ string s ="hello , world";//从第0个位置开始截取长度为5的子串 string s1 = s.substr(0,5);//从第6个位置开始截取后面的所有字符 string s2 = s.substr(6);//将s1和s2拼接位一个字符串 string s3 = s1 + s2;//运行下二者输出的结果相同 cout << s1 << s2 <<"\n"; cout << s3;}

string截取子串的成员函数为substr相关解释已经在注释当中

一些常用的C++操作

C++sort(排序函数的用法)

#include<algorithm>#include<iostream>#include<string>usingnamespace std;boolcomp(int& a ,int& b){return a > b;}intmain(void){int a[1000]={0,1,1,4,5,1,4};//这个sort第一个参数是这是你要排序的起始位置,第二个参数是终止位置sort(a +1, a +1+6);for(int i =1; i <=6; i++) cout << a[i];//C++排序默认的升序 std::cout <<"\n";//如果我们要用降序的话可以添加第三个参数,也就是我们的自定义比较函数sort(a +1, a +1+6, comp);for(int i =1; i <=6; i++) cout << a[i];}

C++的sort排序的时间复杂度是O(nlogn)比大家常用的冒泡排序快速多了,所有如果要有排序的话推荐一直用这个,至于comp函数,我这里使用了&也就是引用,这样可以避免复制数值,但是大家在平时使用时不添加引用符也可以正常运行

数组去重

#include<algorithm>#include<iostream>#include<string>#include<vector>usingnamespace std;intmain(void){//使用原始数组的方法//数组去重需要我们先排序int a[1000]={0,1,1,4,5,1,4};sort(a +1, a +1+6);//这里去重int* pos =unique(a +1, a +1+6);//这里计算去重后的数组个数int new_count = pos -(a +1);for(int i =1; i <= new_count; i++) std::cout << a[i]<<" ";}//如果不打算了解C++进阶相关,这下面部分可以不看#include<algorithm>#include<iostream>#include<vector>intmain(void){//使用vector(动态数组的做法)  std::vector<int>arr ={0,1,1,4,5,1,4};//这里至于为什么使用arr.begin(),这里暂不讲解,在进阶部分再讲解 std::sort(arr.begin()+1, arr.begin()+1+6);//这里返回的是一个迭代器auto pos =unique(arr.begin()+1, arr.begin()+1+6); arr.erase(pos , arr.end());return0;}

unique函数返回的是检查范围的数据,如果有相同的则移到传入的末尾,之后直接计算剩余元素数量后使用去重过后的数组就行了,详细操作见上述代码

二分查找

在这里插入图片描述
#include<algorithm>#include<iostream>#include<vector>#include<stack>#include<queue>#include<map>#include<set>usingnamespace std;intmain(void){//这里为了演示,我这边就直接用有序数组了int a[105];for(int i =1; i <=100; i++) a[i]= i;//查找第一个小于等于25的元素int* lb1 = std::lower_bound(a +1, a +101,25);int index1 = lb1 - a;// 计算索引 std::cout <<"elem is"<<*(lb1)<<" index is"<< index1 << endl;//查找第一个大于25的元素int* lb2 = std::upper_bound(a +1, a +101,25);int index2 = lb2 - a;// 计算索引 std::cout <<"elem is"<<*(lb2)<<" index is"<< index2 << endl;int* result = std::lower_bound(a +1, a +101,101);//二分超出范围的话if(result == a +101){ std::cout <<"lower_bound(101) return a+101\n";// 因为数组中没有不小于101的元素}return0;}

STL容器相关

常见的STL容器使用

这部分设计数据结构,例如:栈,队列,红黑树,二叉搜索树

常见队列

#include<algorithm>#include<iostream>#include<queue>#include<vector>intmain(void){ std::queue<int>q;//这里模拟插入数据for(int i =0; i <10; i++) q.push(i);//一般我们是不知道队列里面的元素个数的,所以我们一般用while语句来处理//这里的empty返回的是一个bool变量,如果不了可以理解为true = 1(判断为真),false = 0(判断为假)while(!q.empty()){//队列可以查看队头和队尾的元素//其中队头的元素是第一个被插入的元素 std::cout << q.front()<<" "<< q.back()<<"\n";//这里默认弹出队头元素 q.pop();}//双端队列和普通队列的区别就是可以弹出和插入元素到队头和队尾的任意一部分 std::deque<int>qu;for(int i =0; i <10; i++){ qu.push_back(i);//qu.push_front(i);}while(!qu.empty()){ std::cout << qu.front()<<" "<< qu.back()<<"\n";//弹出队尾 qu.pop_back();//弹出队首 qu.pop_front();}}

C++的队列使用和声明极为简单,其中内部实现为一个数组,是根据先进先出(FIFO)思想设计的,所有上述操作时间复杂度都为O(1)
如果使用了using namespace std;,那么上述的的"std::"可以去掉

#include<algorithm>#include<iostream>#include<vector>#include<stack>#include<queue>usingnamespace std;intmain(void){ stack<int>s;for(int i =0; i <10; i++) s.push(i);while(!s.empty()){//默认弹出最后一个元素 std::cout << s.top()<<" "; s.pop();}}

栈和队列的使用方式差不多,最具有分辨力的区别是:栈是根据先进后出(FILO)的思想设计的

map(键值对)

键值对又称字典,是一个相互进行映射(一个键对应一个值)的STL容器,内部实现为红黑树或(二叉搜索树),其插入的时间复杂度为O(logn)是一个在算法竞赛中很实用的STL容器

#include<algorithm>#include<iostream>#include<vector>#include<stack>#include<queue>#include<map>usingnamespace std;intmain(void){ std::map<int,int>mp;int temp =114514;for(int i =0; i <10; i++){//插入数据(这两种方法都可以)if(i <4) mp[i]= temp *(10- i);else mp.insert({i , temp *(10- i)});}//遍历mapfor(auto&[key , value]: mp){//这里的key代表第一个也就是键,第二个代表值,这两个可以随意命名 std::cout <<"mp["<< key <<"] = "<< value <<"\n";//遍历是根据键的大小来输出的,也可以自定义排序(属于进阶内容,新手不必要掌握)}//查找操作,其中时间复杂度为O(logn)if(mp.find(2)!= mp.end()) std::cout <<"Yes";if(mp.find(10)== mp.end()) std::cout <<"No"; std::cout <<"\n";int idx =0;while(1){ mp.erase(idx); idx++;if(mp.empty()){ std::cout <<"已弹出所有元素";break;}}return0;}

我们这里只讲map的插入,删除和遍历以及查找这种基础内容

还有一种map是unordered_map,其结构和map很像,这里不再介绍。
unordered_map和map的区别是,map是红黑树,而它的实现为哈希表,查找,插入的速度为O(1),并且unordered_map是无序的

set(集合)

set和map极为相似,你可以把set理解为只有一个value的的map(一般map有键和值),其中时间复杂度和map基本一致,这里不再介绍

#include<algorithm>#include<iostream>#include<vector>#include<stack>#include<queue>#include<map>#include<set>usingnamespace std;intmain(void){ set<int>s;for(int i =0; i <100; i++) s.insert(0); s.insert(5); s.insert(3); s.insert(114514);//set里面是自动有序而且是会自动去重的for(auto i : s) cout << i <<" "; cout <<"\n";if(s.find(3)!= s.end()) cout <<"Yes"<<" ";if(s.find(6)== s.end()) cout <<"No"<<" "; cout <<"\n";//查看集合的大小 cout << s.size()<<"\n";for(auto i : s) s.erase(i); cout << s.size()<<"\n";return0;}

C++进阶相关

标准输入输出加快

 ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);

lambda表达式(无名函数)

 std::vector<int>arr ={1,1,4,5,1,4}; std::sort(arr.begin(), arr.end(),[](int& a ,int& b){return a > b;});

这里只不过是将函数换成了lambda表达式

优先对列自定义排序

structNode{int x , y;booloperator<(Node &a)const{return x < a.x;};};intmain(void){ std::priority_queue<Node>q;}

对于我们自定义的结构体它是无法直接比较大小的,那么直接使用operator进行重载,可以使它们在一个陌生的结构体有明确的大小顺序
由于作者赖的写了,这里简单的介绍下优先队列。优先队列就是我们所说的堆,其中内部是二叉搜索树,插入和弹出都是logn的复杂度,堆顶元素默认是最大(最小)元素

stringstream流

#include<vector>#include<string>#include<sstream>#include<iostream>usingnamespace std;intmain(void){//将字符类型转化为整数 std::string s ="1 2 3 4 5 6"; std::vector<int>arr; stringstream stream(s);int num;while(stream >> num){ arr.push_back(num);}for(auto i : arr) cout << i <<" "; cout <<"\n";//将数据为某个字符串分割 string data ="apple,banana,orange,grape"; stringstream ss(data); string fruit;while(getline(ss, fruit,',')) cout << fruit << endl;return0;}

结语

以上内容属于C++基础内容,如果以后有从事C++相关行业的话属于基础中的基础,相反则需要掌握一些C++基础内容,虽然文章中分为了基础和进阶,但即便是只打算打一些简单的算法比赛,以上编码技巧也只属于基础内容

Read more

pywebview:用Python+Web技术打造轻量级桌面应用!

pywebview:用Python+Web技术打造轻量级桌面应用!

✍️作者:唐叔在学习 💡专栏:唐叔学python ✨关键词:Python桌面开发、pywebview教程、WebView应用、前后端分离、JS与Python交互、桌面应用打包、Electron替代方案、Python GUI 大家好,我是唐叔。今天我们来聊聊一个非常轻量且强大的Python库——pywebview。如果你曾经为开发一个简单的桌面应用而纠结于Electron的笨重、PyQt的复杂,或是Tkinter的界面简陋,那pywebview或许正是你一直在找的解决方案。 文章目录 * 一、介绍 * 二、安装 * 安装全量版本 * 安装指定环境版本 * 三、使用入门 * 3.1 基本使用 * 3.2 应用程序架构 * 纯网络服务架构 * 无服务器架构 * 3.3 JS与Python交互 * 四、应用打包 * 五、常见使用场景 * 5.1 文件操作 * 文件下载

By Ne0inhk
⸢ 伍-Ⅱ⸥ ⤳ 默认安全治理实践:水平越权检测 & 前端安全防控

⸢ 伍-Ⅱ⸥ ⤳ 默认安全治理实践:水平越权检测 & 前端安全防控

👍点「赞」📌收「藏」👀关「注」💬评「论」         在金融科技深度融合的背景下,信息安全已从单纯的技术攻防扩展至架构、合规、流程与创新的系统工程。作为一名从业十多年的老兵,将系统阐述数字银行安全体系的建设路径与方法论,旨在提出一套可落地、系统化、前瞻性的新一代安全架构。 序号主题内容简述1安全架构概述全局安全架构设计,描述基础框架。👉2默认安全标准化安全策略,针对已知风险的标准化防控(如基线配置、补丁管理)。3可信纵深防御多层防御体系,应对未知威胁与高级攻击(如APT攻击、零日漏洞)。4威胁感知与响应 实时监测、分析威胁,快速处置安全事件,优化第二、三部分策略。 5实战检验通过红蓝对抗演练验证防御体系有效性,提升安全水位。6安全数智化运用数据化、自动化、智能化(如AI)提升安全运营(各部分)效率。 目录 5 默认安全治理应用实践 5.2 水平越权漏洞检测 1.水平越权检测的痛点

By Ne0inhk

Clawdbot Web Chat平台部署避坑指南:Qwen3:32B代理直连常见问题解析

Clawdbot Web Chat平台部署避坑指南:Qwen3:32B代理直连常见问题解析 1. 为什么需要这份避坑指南 你是不是也遇到过这样的情况:明明照着文档一步步操作,Clawdbot界面能打开,聊天框也能输入文字,可按下回车后——光标一直转圈,半天没反应,最后弹出“连接超时”或“API调用失败”?或者更糟,页面直接白屏、控制台报一堆502 Bad Gateway、ERR_CONNECTION_REFUSED? 这不是你的环境有问题,也不是Qwen3:32B模型本身不给力。真正卡住大多数人的,是Clawdbot与本地Ollama服务之间那层看似简单、实则脆弱的代理链路:从浏览器 → Clawdbot前端 → 内部反向代理(8080端口)→ Ollama网关(18789端口)→ Qwen3:32B模型。 这份指南不讲“如何安装Ollama”,也不重复官方启动命令。它只聚焦一件事:把你在真实部署中踩过的、查日志才定位到的、搜遍论坛都找不到答案的典型断点,一条条拎出来,配上可验证的检查项和一招见效的修复方法。全文基于实际生产环境反复验证,

By Ne0inhk
安利一款超实用的前端可视化打印设计器:Vue Print Designer

安利一款超实用的前端可视化打印设计器:Vue Print Designer

做前端开发的朋友应该都懂,业务开发中遇到打印需求真的头大 —— 手写分页逻辑繁琐、不同框架适配麻烦、票据 / 快递单这类定制化打印场景不好实现,找个趁手的打印插件更是难上加难。最近发现了一款开源的可视化打印设计器Vue Print Designer,完美解决了这些痛点,不管是快速开发还是企业级定制化需求都能满足,今天就跟大家详细聊聊这款工具。 一、Vue Print Designer 是什么? Vue Print Designer 是一款面向业务表单、标签、票据、快递单等打印场景的可视化设计器,核心主打模板化、变量化设计,还提供了静默打印、云打印能力,同时支持 PDF / 图片 / Blob 等多种导出方式,完全能覆盖日常开发中的各类打印需求。 它不是简单的打印插件,而是一套完整的打印解决方案,从可视化设计模板,到参数配置、多端打印,再到定制化扩展,一站式搞定,而且项目还在持续更新,最新版本已经支持英寸、厘米作为单位,对国际化和精细化设计更友好了。 项目地址:https://gitee.com/

By Ne0inhk