C++
文章平均质量分 63
师范大学生
登峰造极境
展开
-
c++函数返回字符串指针
在以上代码中,在函数中创建一个字符数组,直接将字符数组的名称作为char类型的指针作为返回值向外传递。这种做法是错误的,编译器会弹出警告:Address of stack memory associated with local variable 'chp' returned。意思是将在栈上的局部变量返回了,这在c++中是不推荐的。问题的原因在于,testfunc1中的字符数组chp属于局部变量,位于内存的栈区,因此指针*p指向的是栈里的局部变量。原创 2022-09-22 16:54:39 · 2402 阅读 · 1 评论 -
c++ strcpy相关坑点
strcpy的作用是将一个字符串的内容复制到另外一个字符串中,覆盖原有的内容。常见的例程有:将字符数组里的内容复制到字符数组里。将字符串常量里的内容复制到字符数组里。需要注意的是,在c++中char *p这样的变量是存放在常量区。原创 2022-09-22 15:31:24 · 1071 阅读 · 0 评论 -
Linux 文件/目录访问(opendir/closedir/readdir)
在Linux系统中我们需要在一个特定目录下对该目录下所有的文件以及目录(文件夹)进行便利访问。Linux获取目录文件的流程如下:1.打开指定目录,使用opendir得到目录句柄。2.while循环中使用readdir获取目录的内容,并存储到struct dirent 结构体变量中。3.dirent结构体变量存储了文件/文件夹的一些属性,可以通过这些属性进行一些差异化操作。4.最后关闭目录句柄closedir。原创 2022-09-21 16:23:02 · 2023 阅读 · 0 评论 -
c++ void*讲解
在指针操作中void* 是常用的一种指针,也被称为无类型指针,该指针可以认为是指针类型的一种抽象。原创 2022-09-16 11:00:11 · 603 阅读 · 0 评论 -
JNI学习5.jstring的处理
代码中GetStringUTFChars能够得到一个修改后的utf8类型的字符串,将该字符串赋值给需要返回的字符串即可。此外需要ReleaseStringUTFChars对临时创建的char指针进行内存释放。原创 2022-09-02 15:01:02 · 2367 阅读 · 0 评论 -
c++ RTTI
RTTI的意思是运行时类型识别,之所以存在这个功能,是因为c++通过父类指针实现多态,父类指针可以指向自己所有的派生类对象,指的多了就会出现问题,程序到某一时刻,父类指针究竟指向哪种派生类对象呢?假设有个父类是Human,子类是Men(毕竟男人属于人类的一种)。通过以上语句,令Human类型的指针指向一个Men对象,Human类中存在虚函数,因此构成了一种多态。但是时间久了,隔了好多行代码,Human这个父类又有一堆子类,因此很容易在某个时间节点搞不清楚当前的*phuman指向的到底是哪种类型,因此需原创 2022-06-20 11:27:09 · 483 阅读 · 0 评论 -
c++读取配置文件
在实际开发中,程序读取配置文件以加载数据非常常见,如何安全高效地读取文件比较重要。本文代码来自于《c++新经典》。 假设有一个txt格式的文件,里面记录了花里胡哨的内容,需要把这些内容一字不差地读取到程序中,应该如何用c++实现?书中的代码如下:结果如下图所示,已经完整地将配置文件的内容打印出来了。 代码使用一个字符数组记录每行内容,为防止读取失败,代码中通过第一位清零并查询的方式检查:如果不需要代码非常严谨,可以将以上的内容从代码中删除。读取一行文本的核心实现是以下代码:fgets函数读原创 2022-06-18 21:19:48 · 3139 阅读 · 0 评论 -
ffmpeg+SDL2实现音频播放
本文记录使用ffmpeg+SDL2进行视频文件内的音频播放,注意是播放视频文件内的音频,不是播放音频文件。本文使用的ffmpeg版本为5.0.1,SDL的版本为2.022。c++环境为vs2017。和之前的播放视频或音频明显的区别是,播放视频文件内的音频需要进行重采样操作,代码中会引入重采样结构体SwrContext。重采样结构体能够改变原先音频的采样率、声道数等参数,令各种音频能够按照我们设定的参数进行输出。这样做的原因是不同视频文件内的音频参数通常区别较大,如果分别处理工作量太大,不如将其统一成相同的格原创 2022-06-17 10:14:43 · 993 阅读 · 0 评论 -
SDL2播放pcm音频
作为播放器,只会播放视频还是不行的,因此需要研究一下SDL如何播放音频。SDL播放音频的过程相对于播放视频更为简单,主要流程如下:初始化工作:1.初始化SDL2.根据设定参数打开音频设备循环播放:1.播放音频数据2.延时等待播放完成#include <stdio.h>#include <tchar.h>#include <iostream>extern "C"{#include "SDL.h"};using namespac原创 2022-05-21 09:58:12 · 745 阅读 · 1 评论 -
ffmpeg+SDL2实现播放器(三)
前面的文章中实现一个固定帧率的视频播放器,但是光有播放功能似乎没有那个味道。因此本次增加了暂停/继续功能,按键关闭播放器功能,以及帧率改变功能。PS:实现帧率改变的初衷是改变播放视频的速度,但是总感觉这样的实现方式并不好,因为当你加速播放的时候,一秒内极有可能处理相当多的视频帧,会对播放设备产生明显影响,因此暂时认为对视频的加减速播放应该有更优的方案。整体代码如下:#include<iostream>#include<string.h>#include<SDL原创 2022-05-20 10:08:57 · 372 阅读 · 0 评论 -
ffmpeg+SDL2实现播放器(二)
在上一篇文章中,代码的画面刷新不是定期实现的,这就导致视频的播放速度与实际不符,因此我们需要对其进行修改,使用多线程实现画面刷新的控制。该工程使用的ffmpeg版本为5.01,SDL版本为2.0.22。#include<iostream>#include<string.h>#include<SDL.h>extern "C"{#include "libavformat/avformat.h" //头文件不仅要在项目中鼠标点击配置,在代码中也要引入#in原创 2022-05-13 16:06:10 · 787 阅读 · 0 评论 -
ffmpeg + SDL2 实现播放器(一)
使用的ffmpeg版本为5.0.1,SDL的版本为2.022。c++环境为vs2017。先上最简易的整体代码,初步实现了SDL和ffmpeg的结合。#include<iostream>#include<string.h>#include<SDL.h>extern "C"{#include "libavformat/avformat.h" //头文件不仅要在项目中鼠标点击配置,在代码中也要引入#include "include/libavformat/原创 2022-05-12 15:46:20 · 2630 阅读 · 1 评论 -
SDL2画面刷新
学会SDL的事件与渲染机制之后,增加画面刷新机制就可以成为一个播放器了。在上一篇文章中讲过,似乎循环执行SDL_RenderPresent(renderer)就可以令视频逐帧播放了,为什么还要引入刷新机制呢?这是因为在一个循环中,重复执行一个函数的效果通常不是周期性的,因为每次加载和处理的数据所消耗的时间是不固定的,因此单纯地在一个循环中使用SDL_RenderPresent(renderer)会令视频播放产生帧率跳动的情况。因此需要引入一个定期刷新机制,令视频的播放有一个固定的帧率。通常使用多原创 2022-05-11 14:34:11 · 1317 阅读 · 0 评论 -
SDL2的渲染
使用SDL2播放视频时需要通过渲染操作令视频的每一帧在窗口的显示。SDL播放视频的流程如下图所示:初始化组件:SDL_Init(); //初始化SDLSDL_CreateWindow(); //创建播放器的窗口SDL_CreateRenderer(); //创建基于窗口的渲染器SDL_CreateTexture(); //创建基于渲染器与视频格式的纹理循环渲染:SDL_UpdateTexture(); //设置纹理的数据SDL_Rende原创 2022-05-10 19:14:16 · 781 阅读 · 0 评论 -
SDL2播放yuv视频文件与事件(event)
1.整体代码先上代码:#include <stdio.h>#include <string.h>#include <SDL.h>//自定义消息类型#define REFRESH_EVENT (SDL_USEREVENT + 1) // 请求画面刷新事件#define QUIT_EVENT (SDL_USEREVENT + 2) // 退出事件//定义分辨率// YUV像素分辨率#define YUV_WIDTH原创 2022-05-10 15:57:13 · 550 阅读 · 0 评论 -
使用ffmpeg指令转换出yuv视频文件
播放器播放的都是经过解码后的视频,也就是yuv格式的视频文件,因此在学习的过程中需要准备一下yuv格式的视频做实验素材,这里演示如何在电脑中使用ffmpeg指令将一个视频文件转换为.yuv格式。1.打开视频文件路径下的shell视频文件一般存放在电脑中任何位置里,因此需要将shell定位到该路径下才能使用命令行。在视频所在的文件夹里按住shift键右键单击空白处,选择“在此处打开powershell窗口”,这样shell就定位到当前位置了。2.使用ffmpeg指令以该文件下的ds原创 2022-05-02 21:10:56 · 5752 阅读 · 0 评论 -
vs配置SDL2.0
这里记录下在vs2017配置SDL2.0。1.下载源文件下载地址如下图所示,注意需要下载visual c++对应的版本。2.解压将文件夹存放在一个不包含中文路径的地方,解压,注意文件夹中只有include文件夹和lib文件夹是我们需要的。3.新建一个vc++项目注意我们使用的版本是x64的,因此在配置过程中所看到的一切“x86”的东西都要改成“x64”。4.右键单击左侧管理器的项目名称(“SDL2Test”),选择属性,进行配置。平台的类型要改成x64..原创 2022-05-02 20:10:45 · 1410 阅读 · 1 评论 -
ffmpeg读取packet数据
在ffmpeg中,使用AVPacket结构体表示视频文件中的压缩数据,也就是还未进行解压缩的原始视频帧与音频帧。整体代码如下:#include<iostream>#define __STDC_CONSTANT_MACROSextern "C"{#include "libavcodec/avcodec.h"#include "include/libavformat/avformat.h"#include "include/libswscale/swscale.h"#incl原创 2022-05-02 16:23:07 · 1801 阅读 · 0 评论 -
ffmpeg视音频解码器启动
其实ffmpeg音视频的解码器调用流程在上一篇文章中已经讲述完成了,本文主要是将已有的程序进行了一定的封装处理,令其更符合工程规范。先上代码:#include<iostream>extern "C"{#include "libavcodec/avcodec.h"#include "include/libavformat/avformat.h"#include "include/libswscale/swscale.h"#include "include/libavdevi原创 2022-04-29 21:23:26 · 1643 阅读 · 0 评论 -
ffmpeg音视频解码器
在获取到视频文件的视频流与音频流之后,需要进行解码操作以还原其原本格式进行播放。先上代码:#include<iostream>extern "C"{#include "libavcodec/avcodec.h"#include "include/libavformat/avformat.h"#include "include/libswscale/swscale.h"#include "include/libavdevice/avdevice.h"}using nam原创 2022-04-28 21:54:13 · 1420 阅读 · 0 评论 -
ffmpeg对视频流、音频流的抽象
从前面的文章中我们实现了对一个视频文件的拆封装,拆出来的结果通常是视频流与音频流,一般一个视频会有一个视频流与一个音频流(视具体情况而定)。随后我们实现了两种流的信息查询,了解了视频文件的各个流的参数类型查看。现在,我们需要以流为单位进行处理,但在这之前我们需要理解在ffmpeg中视频流与音频流是如何进行抽象和管理的。先上全部代码:#include<iostream>extern "C"{#include "libavformat/avformat.h" //头文件不仅要在项目原创 2022-04-28 15:51:08 · 600 阅读 · 0 评论 -
ffmpeg获取视频流信息
在视频文件中,被压缩的视频和音频会被封装为一个文件,因此在解封装之后,我们还需要对视频流与音频流进行拆分,之后实现不同方式的处理。本程序实例用于获取具体视频文件的视频流与音频流的信息。#include<iostream>extern "C"{#include "libavformat/avformat.h" //头文件不仅要在项目中鼠标点击配置,在代码中也要引入}using namespace std;int main(int argc, char *argv[]){原创 2022-04-28 09:33:49 · 4904 阅读 · 0 评论 -
ffmpeg打开视频文件
本文ffmpeg的版本为当前最新的5.01版本,与网络上常见的2,3版本在函数和变量的使用上有较大差异。首先往工程目录里放进去一个视频文件,这样方便在代码中进行路径书写(偷懒)。当然代码中的注释也会提示如何直接完整书写视频的路径。#include<iostream>extern "C"{#include "libavformat/avformat.h" //头文件不仅要在项目中鼠标点击配置,在代码中也要引入}using namespace std;int main.原创 2022-04-27 22:14:22 · 1821 阅读 · 1 评论 -
vs配置ffmpeg
继前文windows安装ffmpeg之后,我们不仅要考虑怎么在电脑上使用命令来操作ffmpeg,还需要考虑如何在程序编写中使用ffmpeg中的功能。1.先把需要的头文件、链接库等下载了这里需要注意,我们这次下载的版本是带有shared的那一项,这个版本不仅包含了能允许pc操作ffmpeg的文件,还包含了供程序使用的各种文件。从上图中可见,bin,include,lib是我们需要的文件夹。2.新建c++工程不多说,先新建一个全新的c++工程,这里用的开发工具是vs2017...原创 2022-04-25 22:08:33 · 3752 阅读 · 2 评论 -
windows安装ffmpeg
ffmpeg非常强大,本文记录于2022.4.25,ffmpeg的发行版本为5.0.1。下载的链接为Download FFmpeg在上面的网页中选择Download,选择Windows builds from gyan.dev在左侧的release builds里面选择当前最新的发行版本,即ffmpeg-release-full.7z,通过浏览器下载。下载完毕之后进行解压,可以看到在bin文件夹下面有三个.exe文件。需要在环境变量中将该bin文件进行注...原创 2022-04-25 20:13:54 · 3795 阅读 · 1 评论 -
剑指数组c++
1. 两数之和给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回答案。 经典的哈希表问题。我们用哈希表记录每个值的下标,当合适的数值出现时我们就能直接获得该数值的下标。class Solution {public: vector<int> twoSum(vector<原创 2021-09-04 23:15:33 · 346 阅读 · 0 评论 -
剑指中的字符串
剑指 Offer 05. 替换空格 极致的快乐,可以用新建一个字符串的方式实现。class Solution {public: string replaceSpace(string s){ if(s.size()==0){ return s; } string ans; for(int i=0;i<s.size();i++){ if(s[i] == ' '){原创 2021-09-02 23:07:43 · 159 阅读 · 0 评论 -
在二叉树中寻找快乐c++
经典二叉树问题,快乐是要保证的。二叉树的最大深度 典中典之二叉树最大深度,非常经典的深度搜索和递归。 对左右子树深度搜索,如果碰到空节点就返回,每次返回计数都+1,最后在左子树和右子树中取最大值。class Solution {public: int maxDepth(TreeNode* root) { if(root==nullptr) return 0; return max(maxDepth(root->left),maxDepth(ro原创 2021-08-31 23:08:41 · 171 阅读 · 0 评论 -
剑指中的链表总结c++
剑指链表总结。剑指 Offer 06. 从尾到头打印链表 可以用朴素的数组记录,最后倒序一下就好了。class Solution {public: vector<int> reversePrint(ListNode* head) { vector<int> ans; if(head == nullptr){ return ans; } while(head!=nullptr)原创 2021-08-31 19:31:51 · 135 阅读 · 0 评论 -
lc743 网络延迟时间学习
弗洛伊德算法: 弗洛伊德算法能记录出图中任何一点到其他任何一点的最短距离。class Solution {public: int networkDelayTime(vector<vector<int>>& times, int n, int k) {//k是起点 //定义图 vector<vector<long long>> graph(n+1,vector<long long>(n+1,原创 2021-08-25 16:10:53 · 241 阅读 · 0 评论 -
手写string类
自己撸一个常见的string类。#include <iostream>#include <string>using namespace std;class mystring{public: mystring(const char *str = nullptr);//构造函数 mystring(const mystring &other);//拷贝构造函数 ~mystring();//析构函数 mystring& operator = (con原创 2021-08-13 10:33:02 · 220 阅读 · 0 评论 -
指针通过函数指向新内存的方法
前言 最近在攻读《深入理解C指针》,做一下笔记。问题 我们都知道,在C语言里动态分配内存并不难:int* p = (int*)malloc(sizeof(int)); 如果我们希望通过一个函数,令一个指针指向一块新分配的内存,并在函数中完成赋值呢? 根据函数设计的本质来区分,有两个方案。方案一:返回指针 这个是最好想的方案了。首先,让一个指针指向一块新分配的内存,并在内存中依次赋值(可以将内存理解为一个数组),这种事,不需要封装在函数里也OK的吧。既然你非得把它放到函数里,那我就原创 2021-07-31 22:03:29 · 619 阅读 · 0 评论 -
C++工厂模式笔记
简单工厂模式 简单工厂模式由三个部分组成: 1.工厂类:用于创建指定的实例对象。 2.抽象产品类:所有产品类的父类。 3.具体产品类:使用工厂类创建的实例对象所属的类别。 简单工厂模式的核心思路是使用工厂类来统一各种产品的实例对象的生成(通过输入不同的参数)。 比如说有一台机器,我按下“生产巧克力”的按钮,它就生产巧克力;我按下“生产羽绒服”的按钮,它就生产羽绒服。这样我无需关心巧克力和羽绒服到底是怎么回事,只需要学会操作这台机器就可以了。 上代码。 首先去定义抽象产品原创 2021-07-28 16:50:35 · 342 阅读 · 2 评论 -
对类Nginx服务器框架运行流程的理解(三)
前言 前面的两篇文章已经记录了服务器收到完整的数据包之前的所有流程,这篇将记录收发数据包、线程池的使用以及多线程技术。 实际上,数据包的定义和多线程的实现都是可以长篇大论的内容,但是目前我们只去梳理一下服务器框架的核心流程,所以暂时不会详细去讲。研究的出发点 上一篇已经把网络通信的架构实现了,那么接下来研究的问题就是,收到客户端数据之后我们服务器该干什么。 回忆一下上篇的内容,我们的客户端socket连接到服务器,即完成三次握手之后,其对应的epoll类型事件会被我们取出来。我们暂时取出来原创 2021-07-08 22:50:10 · 116 阅读 · 1 评论 -
对类Nginx服务器框架运行流程的理解(二)
前言 虽然服务器架构使用了多种技术,但实际上,只有在收到完整数据后,线程池和多线程技术才参与到服务器架构的工作中来,因此我们可以将工作流程按照事件的发生时刻进行分割,进一步剖析各个技术在服务器架构程序中的实现方式。 本篇详细记录socket与epoll技术(含连接池)在收到一个完整的数据包之前的工作分析。epoll对象的节点 epoll对象的节点是如何加入到红黑树,如何从红黑树中删除;如何加入到双向链表,如何从双向链表中删除的? 我们知道,在网络通信中,操作系统帮助我们完成了一些工作,这样原创 2021-07-08 11:18:18 · 119 阅读 · 0 评论 -
Linux守护进程的创建方式
前言 守护进程可以运行在后台,不受某个特定终端的限制,安全稳定地持续运行,一般会作为程序中的“监管进程存在”。 守护进程有以下特点: 1.不属于任何终端的会话分组,自己拥有会话分组。 2.没有显示终端,一般不与用户交互。 3.一般持续运行在后台。源代码//描述:守护进程初始化//执行失败:返回-1, 子进程:返回0,父进程:返回1int ngx_daemon(){ //(1)创建守护进程的第一步,fork()一个子进程出来 switch (fork())原创 2021-06-22 10:58:34 · 259 阅读 · 0 评论 -
C/C++ typedef用法总结
前言 今天学习遇到了一些关于typedef的问题,火速学习并记录。别名替换 typedef和宏定义#define一样,都可以对已有内容进行替换。 但是#define仅仅是做了字符串的替换,等于是生搬硬套换一下,在复杂表达式中没有小括号的辅助很容易翻车。 而typedef则是为一种类型起了个别名,使用起来比#define安全一些。 此外typedef还能提供一种“同时声明”的功能,对简化编程很有帮助:int *a,b;//一个是指针,一个是普通变量int *a,*b;//两个都是指针原创 2021-06-13 11:17:43 · 260 阅读 · 0 评论 -
c++ 多线程 生产者与消费者模型
前言 在多线程中,生产者与消费者模型是一个非常经典的问题。 假设有一个厨师做馒头,另外一个顾客吃厨师做的馒头,这样生产者(厨师)和消费者(顾客)两个元素就到位了。一般来讲,厨师做馒头的速度和顾客吃馒头的速度应该是不一样的,如果厨师做馒头的速度比顾客吃馒头的速度快,那么一定时间后一定是馒头堆积如山顾客永远也吃不完;如果厨师做馒头的速度比顾客吃馒头的速度慢,那么一定时间后一定是餐桌空空厨师永远不能停下工作。 显然这个结果一般是人们不愿意看到的,于是我们希望有一种机制,能够对厨师和顾客的行为进行一定的原创 2021-06-12 17:24:03 · 2293 阅读 · 1 评论 -
基于QT的翻金币小游戏项目总结记录(五)
前言 最近为了学习C++和qt5,跟着教程写了一个翻金币的小游戏,源码和资源文件的链接在这里:翻金币小游戏源码和资源文件的下载链接。里面有自己写的超多代码注释,只要2个C币,去秒。 第四章我们分析了这个小游戏的游戏机制,现在我们开始想办法去实现他们。初始界面的数据结构 第一关的初始界面如上图所示。 经过上一章的分析,我们认为应该用二维数组保存初始游戏阵列。另外,每一关都对应一个特定的二维数组,这个“一一对应”的关系应当如何实现呢?我们可以立刻想到哈希表,也就是依靠键值对的映射原创 2021-06-03 20:10:32 · 1136 阅读 · 6 评论 -
c++ 单例模式与多线程
单例模式 单例模式的概念比较简单,即某一类只能创建一个对象,这样设计类的方式就是单例模式。 在直接看代码之前,可以稍微思考一下这个单例模式大概会是个什么情况。 在C++中,调用一次构造函数就会创建一个对象,这个机制是货真价实的,因此也可以推测出,单例模式某种程度上实现了构造函数的“隐藏”。 构造函数怎么藏这个具体想不到,不过大致能想出来一个点,应该将构造函数放在private区域内,令其属于类的私有成员,这样在对象中(类的区域之外)就不能直接调用构造函数了。如果不这样做,构造函数天天露在外面原创 2021-05-31 20:31:30 · 2352 阅读 · 11 评论