经典数据结构沉思录(二):数组和链表

记录关于C/C++的自学路线 文章目录一、前言二、C/C++语言学习1.C/C++语言三、编程四大件1.数据结构与算法2.计算机网络3.操作系统4.设计模式与SQL数据库编程四、总结 一、前言 博主,一名小硕,记录下从化学到机械到计算机的踩坑记录。这篇博文目的其一是为了记录下自己的学习经历,其二是为了与大家分享和交流心得。以下就分享下个人的部分学习过程。 二、C/C++语言学习 1.C/C++语言 C语言的学习,应该学习如下内容:编译四步骤(预处理、编译、汇编、链接)、变量、条件循环、结构体、字符串、函数、指针和内存管理等。其中最. 阅读详情

经典数据结构沉思录(二):数组和链表

 

特别声明:此系列博文代码编译环境需为DEV-C++、G++或VS等支持C++99标准的,VC6.0不支持。

经典数据结构涵盖了多种抽象数据类型(ADT),其中包括栈、队列、有序列表、排序表、哈希表及分散表、树、优先队列、集合和图等。对于每种情况,都可以选用数组或某一种链表数据结构来实现其抽象数据类型(ADT)。由于数组和链表几乎是建立所有ADT的基础,所以称数组与链表为基本数据结构。

一、数组

也许聚集数据最常用的方法是利用数组,虽然C++提供了对数组的内嵌式支持,但是这种支持并非没有缺点。在C++中,数组并不是一级数据类型,也没有有关数组求值的表达式。结果,既不能把数组用途一个函数的实际值参数,也不能从一个函数返回一个数组值;还不能把一个数组赋给另一个数组(当然,利用指向数组的指针可以做到)。另外,数组下标是从0~N-1的范围(N为数组元素个数),对数组下标表达式也不提供越界检查。最后,在编译期间一个数组的规模大小是静态和固定的,除非程序员显式使用动态内存分配。

数组这些特性有一部分源于这样一个事实,在C++中,就指向某一T类型的指针T *ptr而言,仅仅从指针本身来说,也不可能说清它是指向一个T类型变量的单一实例还是指向一个T类型的数组。而且,即使知道指针指向一个数组,也无法确定该数组中元素的实际数目。

我们将用面向对象的设计模式来思考数据结构及相关和算法,在本系列后续的博文中也将基于面向对象来设计和实现。统一的设计思路将使得后续博文中出现的程序能够建立于前面博文的程序之上。

我们第一个基本的数组结构Array的设计包含了两个域:data、和length,其中data是一个指向数组数据的指针,length表示数组长度。考虑到Array存储的数据类型的不确定性,我们借助于C++的泛型特性进行设计,则Array的类定义如下:

template <class T>
class Array
{
    protected:
        /*指向的数据*/ 
        T* data;
        /*数组长度*/
        unsigned int length;
    
    public:
        /*构造函数及析构函数*/
        Array();
        Array(unsigned int);
        ~Array();
    
        /*拷贝构造函数、等号操作符、下标操作符*/
        Array(Array const&);
        Array& operator = (Array const&);
        T const& operator [] (unsigned int) const;
        T& operator [] (unsigned int);
    
        /*Get方法*/
        T const* Data() const;
        unsigned int Length() const;
    
        /*Set方法*/
        void SetLength(unsigned int);
    };

有了最基本的Array之后,我们就需要对其API函数进行逐个实现,并进行测试。在实际的编码过程中,我们设置了一个全局的.H文件Global.h用于定义一些公共的变量,随着编码工作的进行,我们将不断地更新和扩充Global.h文件。目前Global.h的定义如下,它对于我们本节的数据结构讲解已经够用了。

//Global.h
#ifndef GLOBAL_H_
#define GLOBAL_H_

#include <iostream>
#include <stdexcept>

#define DEFAULT_ARRAY_SIZE 10
#define EXIT_INFO "Press Any Key To Continue!"

using namespace std;

namespace OP
{
    template <class T>
    void swap(T& x, T& y)
    {
        T tmp;
        
        tmp = x;
        x = y;
        y = tmp;
    }
}

#endif

一份完整的Array类C++代码清单如下所示,为了避免与其他命名空间函数或变量重名,而造成不可用的情况,我们自定义了命名空间OP,当然你可以换成其他名字,之所以用OP是因为我比较喜欢看《海贼王》。代码比较清晰,只给出了简单的注释,并没有过多解释,大家都看的懂的~

//Array.h
#ifndef ARRAY_H_
#define ARRAY_H_

#include "Global.h"

namespace OP
{
    /*数组对象*/
    template <class T>
    class Array
    {
    protected:
        /*指向的数据*/ 
        T* data;
        /*数组长度*/
        unsigned int length;
    
    public:
        /*构造函数及析构函数*/
        Array();
        Array(unsigned int);
        ~Array();
    
        /*拷贝构造函数、等号操作符、下标操作符*/
        Array(Array const&);
        Array& operator = (Array const&);
        T const& operator [] (unsigned int) const;
        T& operator [] (unsigned int);
    
        /*Get方法*/
        T const* Data() const;
        unsigned int Length() const;
    
        /*Set方法*/
        void SetLength(unsigned int);
    };
    
    /*默认构造函数*/
    template <class T>
    Array<T>::Array() : 
        data(new T[DEFAULT_ARRAY_SIZE]), 
        length(0)
        {}
   
    /*带参数的构造函数*/
    template <class T>
    Array<T>::Array(unsigned int n) : 
        data(new T[n]), 
        length(n)
        {}
           
    
    /*析构函数*/
    template <class T>
    Array<T>::~Array()
    {
        delete [] data;
    }
    
    /*拷贝构造函数*/
    template <class T>
    Array<T>::Array(Array<T> const& array) : 
        data(new T[array.length]), 
        length(array.length)
        {
            for (unsigned int i = 0; i < length; ++i)
            {
                data[i] = array.data[i];
            }
        }
    
    /*重载=操作符*/
    template <class T>
    Array<T>& Array<T>::operator = (Array const& array)
    {
        if (this != &array)
        {
            delete [] data;
            length = array.length;
            data = new T[length];
            for (unsigned int i = 0; i < length; ++i)
            {
                data[i] = array.data[i];
            }
        }
        
        return *this;
    }
    
    /*重载[]下标操作符,默认为只读类型,数据不可修改*/
    template <class T>
    T const& Array<T>::operator [] (unsigned int position) const
    {      
        if (position >= length)
        {
            throw out_of_range("Invalid Position!");
        }
        return data[position];
    }
    
    /*重载[]下标操作符,数据可修改*/
    template <class T>
    T& Array<T>::operator [] (unsigned int position)
    {
        if (position >= length)
        {
            throw out_of_range("Invalid Position!");
        }
        return data[position];
    }
    
    /*Get方法*/
    template <class T>
    T const* Array<T>::Data() const
    {
        return data;
    }

    template <class T>
    unsigned int Array<T>::Length() const
    {
        return length;
    }
    
    /*当length<newLength时,[length,newLength)区间的元素赋初值为0*/    
    template <class T>
    void Array<T>::SetLength(unsigned int newLength)
    {
        T* const newData = new T[newLength];
        unsigned int const min = length < newLength ? length : newLength;
        for (unsigned int i = 0; i < min; ++i)
        {
            newData[i] = data[i];
        }
        
        /*[length,newLength)区间赋初值*/ 
        for (unsigned int i = min; i < newLength; ++i)
        {
            newData[i] = 0;
        }
        
        delete [] data;
        data = newData;
        length = newLength;
    }
}

#endif

完成了Array的类之后,我们对所有函数进行测试,以保证其能够正常工作。我们实现了一个Test的类,代码清单如下。

//ArrayTest.cpp
#include "Array.h"
#include "string"

using namespace OP;

/*遍历数组*/ 
void traverse(const Array<int>& array);

int main()
{
    /*构造函数测试*/ 
    Array<int> array1(10);
    Array<int> array2;
    
    /*下标操作符测试*/
    for (unsigned int i = 0; i < 10; ++i)
    {
        array1[i] = i*i;
    }
    traverse(array1);
    
    /*=操作符测试*/
    array2 = array1;
    traverse(array2);
    
    /*拷贝构造函数测试*/
    Array<int> array3(array1);
    traverse(array3);
    
    /*设置数组长度测试*/
    array1.SetLength(20);
    traverse(array1);
    array1.SetLength(5);
    traverse(array1);
    
    getchar();
    return 0;
}

/*遍历数组*/
void traverse(const Array<int>& array)
{
    for (unsigned int i = 0; i < array.Length(); ++i)
    {
        cout << array[i] << "  ";
    }
    cout << endl;
}

二、单链表

单链表在所有的基于指针的数据结构中是最基本的,它由一系列动态分配的存储元素组成,且每个元素都含有一个指向后继元素的指针。虽然单链表的表达简洁明晰,但实现形式却可以是多种多样的:循环链表、头节点为空、头节点不为空等;链表插入的方式也可以不同:前插或后插。

我们的LinkedList设计中包含了两个重要的指针:head和tail,分别指向头节点和尾结点,其中头节点不为空,插入方式提供前插和后插两种。LinkedList的设计依赖于链表节点的数据结构ListElement。LinkedList的代码清单如下:

//LinkedList.h
#ifndef LINKEDLIST_H_
#define LINKEDLIST_H_

#include "Global.h"

namespace OP
{
    template <class T>
    class LinkedList;
    
    /*链表节点*/
    template <class T>
    class ListElement
    {
    private:
        /*链表节点数据元素*/
        T datum;
        /*链表节点next指针*/
        ListElement* next;
        /*链表构造函数*/
        ListElement(T const&, ListElement*);
        
    public:
        /*Get方法*/
        T const& Datum() const;
        ListElement const* Next() const;
        
        /*链表对象为友元*/
        friend class LinkedList<T>;
    };
    
    /*链表对象*/
    template <class T>
    class LinkedList
    {
    private:
        /*头节点*/
        ListElement<T>* head;
        /*尾节点*/
        ListElement<T>* tail;
        
    public:
        /*构造函数和析构函数*/
        LinkedList();
        ~LinkedList();
        
        /*拷贝构造函数和赋值函数*/
        LinkedList(LinkedList const&);
        LinkedList& operator=(LinkedList const&);
        
        /*Get方法*/
        ListElement<T> const* Head() const;
        ListElement<T> const* Tail() const;
        
        /*链表是否为空*/
        bool IsEmpty() const;
        /*链表首元素*/
        T const& First() const;
        /*链表尾元素*/
        T const& Last() const;
        
        /*链表首前插一个元素*/
        void Prepend(T const&);
        /*链表尾插入一个元素*/ 
        void Append(T const&);
        /*删除链表中指定元素节点*/ 
        void Extract(T const&);
        /*清空链表*/ 
        void Purge();
        /*后插*/
        void InsertAfter(ListElement<T> const*, T const&);
        /*前插*/
        void InsertBefore(ListElement<T> const*, T const&);
    };
    
    /*构造函数*/
    /*构造函数*/
    template <class T>
    LinkedList<T>::LinkedList() : 
        head(0), 
        tail(0)
        {}
    
    template <class T>
    ListElement<T>::ListElement(T const& _datum, ListElement<T>* _next) : 
        datum(_datum),
        next(_next)
        {}
        
    /*Get方法*/
    template <class T>
    T const& ListElement<T>::Datum() const
    {
        return datum;
    }
    
    template <class T>
    ListElement<T> const* ListElement<T>::Next() const
    {
        return next;
    }
    
    /*销毁链表*/
    template <class T>
    void LinkedList<T>::Purge()
    {
        while (head != 0)
        {
            ListElement<T>* const tmp = head;
            head = head->next;
            delete tmp;
        }
        tail = 0;
    }
    
    /*析构函数*/
    template <class T>
    LinkedList<T>::~LinkedList()
    {
        Purge();
    }
    
    /*Get方法*/
    template <class T>
    ListElement<T> const* LinkedList<T>::Head() const
    {
        return head;
    }
    
    template <class T>
    ListElement<T> const* LinkedList<T>::Tail() const
    {
        return tail;
    }
    
    /*是否为空*/
    template <class T>
    bool LinkedList<T>::IsEmpty() const
    {
        return head == 0;
    }
    
    /*链表首元素*/
    template <class T>
    T const& LinkedList<T>::First() const
    {
        if (head == 0)
        {
            throw domain_error("List Is Empty!");
        }
        return head->datum;
    }
    
    /*链表尾元素*/
    template <class T>
    T const& LinkedList<T>::Last() const
    {
        if (tail == 0)
        {
            throw domain_error("List Is Empty!");
        }
        return tail->datum;
    }
    
    /*前插*/
    template <class T>
    void LinkedList<T>::Prepend(T const& item)
    {
        ListElement<T>* const tmp = new ListElement<T>(item, head);
        if (head == 0)
        {
            tail = tmp;
        }
        head = tmp;
    }
    
    /*后插*/
    template <class T>
    void LinkedList<T>::Append(T const& item)
    {
        ListElement<T>* const tmp = new ListElement<T>(item, 0);
        if (head == 0)
        {
            head = tmp;
        }
        else
        {
            tail->next = tmp;
        }
        tail = tmp;
    }
    
    /*拷贝构造函数*/
    template <class T>
    LinkedList<T>::LinkedList(LinkedList<T> const& linkedList) : 
        head(0), 
        tail(0)
    {
        ListElement<T> const* ptr;
        for (ptr = linkedList.head; ptr != 0; ptr = ptr->next)
        {
            Append(ptr->datum);
        }
    }
    
    /*赋值构造函数*/
    template <class T>
    LinkedList<T>& LinkedList<T>::operator = (LinkedList<T> const& linkedList)
    {
        if (&linkedList != this)
        {
            Purge();
            ListElement<T> const* ptr;
            for (ptr = linkedList.head; ptr != 0; ptr = ptr->next)
            {
                Append(ptr->datum);
            }
        }
        return *this;
    }
    
    /*删除该元素节点*/
    template <class T>
    void LinkedList<T>::Extract(T const& item)
    {
        ListElement<T>* ptr = head;
        ListElement<T>* prevPtr = 0;
        while (ptr != 0 && ptr->datum != item)
        {
            prevPtr = ptr;
            ptr = ptr->next;
        }
        if (ptr == 0)
        {
            cout << "Item not Found!" << endl;
            return;
        }
        if (ptr == head)
        {
            head = ptr->next;
        }
        else
        {
            prevPtr->next = ptr->next;
        }
        if (ptr == tail)
        {
            tail = prevPtr;
        }
        delete ptr;
    }
    
    /*在节点arg处前插入一个节点*/
    template <class T>
    void LinkedList<T>::InsertAfter(ListElement<T> const* arg, T const& item)
    {
        ListElement<T>* ptr = const_cast<ListElement<T>*>(arg);
        if (ptr == 0)
        {
            throw invalid_argument("Invalid Position!");
        }
        ListElement<T>* const tmp = new ListElement<T>(item, ptr->next);
        ptr->next = tmp;
        if (tail == ptr)
        {
            tail = tmp;
        }
    }
    
    /*在节点arg处后插入一个节点,这里使用了一个技巧,先实现前插,后将节点数据进行交换*/
    template <class T>
    void LinkedList<T>::InsertBefore(ListElement<T> const* arg, T const& item)
    {
        /*先实现前插,后将节点数据进行交换*/
        ListElement<T>* ptr = const_cast<ListElement<T>*>(arg);
        if (ptr == 0)
        {
            throw invalid_argument("Invalid Position!");
        }
        ListElement<T>* const tmp = new ListElement<T>(item, ptr->next);
        ptr->next = tmp;
        if (tail == ptr)
        {
            tail = tmp;
        }
        
        /*交换数据实现前插*/
        swap(tmp->datum, ptr->datum);
    }
}

#endif

完成了LinkedList的类之后,我们对所有函数进行测试,以保证其能够正常工作。我们实现了一个Test的类,代码清单如下。

//LinkedListTest.cpp
#include "Global.h"
#include "LinkedList.h"

using namespace OP;

void traverse(LinkedList<int>& linkedList);

int main()
{
    /*构造函数测试*/
    LinkedList<int> l1;
    
    /*后插函数测试*/ 
    for (int i = 0; i < 10; ++i)
    {
        l1.Append(i + 1);
    }
    traverse(l1);
    
    /*拷贝构造函数测试*/
    LinkedList<int> l2(l1);
    traverse(l2);
    
    /*前插函数测试*/
    LinkedList<int> l3;
    for (int i = 0; i < 10; ++i)
    {
        l3.Prepend(i + 1);
    }
    traverse(l3);
    
    /*后插函数测试*/
    l1.InsertAfter(l1.Head()->Next(), -1);
    traverse(l1);
    
    /*前插函数测试*/
    l1.InsertBefore(l1.Head()->Next()->Next(), -2);
    traverse(l1);
    
    /*删除节点函数测试*/
    l1.Extract(1);
    traverse(l1);
    l1.Extract(10);
    traverse(l1);
    l1.Extract(5);
    traverse(l1);
    l1.Extract(1);
    traverse(l1);
    
    getchar();
    return 0;
}

/*遍历链表*/
void traverse(LinkedList<int>& linkedList)
{
    ListElement<int> const* ptr;
    for (ptr = linkedList.Head(); ptr != 0; ptr = ptr->Next())
    {
        cout << ptr->Datum() << "  ";
    }
    cout << endl;
}

博文的撰写参考了《数据结构与算法-面向对象的C++设计模式》一书,再此向该书作者表示致敬!本系列博文将继续基于面向对象对经典的数据结构进行设计和封装,并用C++实现,请持续关注本博客~

Unity中实现HLS视频加密与流式播放的完整方案 本文详细介绍了在Unity中实现HLS视频加密与流式播放的完整方案。针对Unity原生VideoPlayer无法直接支持实时解密的问题,提出了基于HLS协议与AES-128加密的成熟解决方案,并重点阐述了如何利用AVPro Video插件进行集成。文章涵盖了从密钥生成、使用FFmpeg进行视频加密切片,到在Unity中动态加载密钥并播放加密流的全流程,为保护付费课程、独家动画等视频内容提供了安全且高效的实践路径。 阅读详情

相关推荐

遥感图像融合实战:5分钟搞懂全色与多光谱图像如何提升分辨率(附Python代码)

本文通过实战案例,详细解析了如何利用全色锐化技术融合全色与多光谱遥感图像,以提升图像分辨率。文章深入浅出地介绍了核心概念、环境配置、经典GS融合算法的Python代码实现,并对比了不同算法的优劣,最后提供了效果评估方法与实战陷阱分析,帮助读者快速掌握遥感图像融合的关键技术。

weixin_29041195的博客 394

C++之string类型详解

目录 1.声明一个C++字符串 2.字符串操作函数 2.1 C++字符串和C字符串的转换 2.2 大小和容量函数 2.3元素存取 2.4比较函数 2.5 更改内容 2.6提取子串和字符串连接 2.7输入输出操作 2.8搜索与查找 之所以抛弃char*的字符串而选用C++标准程序库中的string类,是因为他和前者比较起来,不必担心内存是否足够、字符串长度等等,而且作为一个泛型类出现,他集成的操作函数足以完成我们大多数情况下(甚至是100%)的需要。我们可以用 = 进行赋值操作,== 进

weixin_36670529的博客 4487

编译opencv4.2时出现undefined reference to `jpeg_default_qtables‘错误的解决方案

操作系统:kylinV10 opencv版本:4.2.0 在编译opencv4.2.0的版本时,出现undefined reference to `jpeg_default_qtables’的错误提示,导致openc编译中断,不能继续编译,所以这个错误必须解决。 解决方案 查看错误的名字,根据名字分析,很有可能是当前系统中没有安装jpeg第三方库,到 http://www.ijg.org/上下载最新的源码包 jpegsrc.v9e.tar.gz,按如下顺序开始编译安装: tar -xzvf jpegsr.

jndingxin的专栏 5105

out_of_range 标准异常

#include #include using namespace std; class 学生 { public: 学生(int 年龄) { if(年龄 150) throw out_of_range("年龄不能小于0或大于150"); this->年龄 = 年龄; } private: int 年龄; }; int main() { try { 学生 小

qq_31248551的博客 3049

【学习笔记】一文搞懂IEPE传感器

本文介绍了IEPE(集成电路压电式)传感器的工作原理及其在振动监测中的应用。通过压电效应原理,IEPE传感器将机械振动转换为电信号,内置电荷放大器将高阻抗电荷信号转换为低阻抗电压信号输出。还介绍了传感器的三轴测量结构、4mA恒流源供电机制以及灵敏度与量程的关系,并通过风扇实验演示了故障诊断过程。实验使用USB-3123采集卡和SRD-1104信号调理器,展示了正常与异常状态下的振动数据差异,验证了IEPE传感器在设备状态监测中的有效性。

m0_62969865的博客 2813

Autodesk全家桶怎么选?AutoCAD、Revit、Fusion 360等7款软件超全对比指南

本文深入对比了Autodesk旗下七款核心软件(AutoCAD、Revit、Inventor、Fusion 360、Maya、3ds Max、Forge)的核心定位与适用场景。针对建筑、制造、创意设计等不同专业需求,提供精准的选型指南,帮助用户根据自身工作流(如二维绘图、BIM协同、产品开发、影视动画)选择最匹配的工具,避免资源浪费并提升效率。

stone的博客 434

高频知识——C++进阶知识(高级教程)

参考链接:https://www.runoob.com/cplusplus/cpp-interfaces.html 之前分别介绍了C++的基本语法,面向对象的设计方法,下面介绍一下C++的一些高级教程,也是面试的高频问题。 1 文件和流 iostream标准库,它提供了cin和cout方法分别用于从标准输入读取流和向标准输出写入流。 从文件读取流和向文件写入流。需要用到 C++ ...

wulitaotao96的博客 1万+

一文解释电路中常用电子元器件应用和选型01

电容和二极管是电路中最常用的两个电子元器件,种类和系列众多,这里简单总结一下应用场景和选型方式 电容(Capacitor) 电容的种类(20种以上)和应用非常广泛,但是我经常遇到的无非就是下面这几种: 应用 1.隔直流。 2.旁路(去耦) 3.耦合 4.滤波 5.温度补偿 6.计时 7.调谐 8.整流 9.储能 种类 1. 陶瓷电容 2. 云母电容 3. 铝电解电容 4. 钽

weixin_43904073的博客 2236

C++异常处理

C++异常处理 异常,让一个函数可以在发现自己无法处理的错误时抛出一个异常,希望它的调用者可以直接或者间接处理这个问题。但传统错误的处理技术,检查到一个错误,返回退出码或者终止程序等等。此时我们只知道程序有错误,但不能更加清楚知道是很忙错误,所以使用异常,就是把错误和处理分开,由库函数抛出异常,由调用者捕获这个异常,调用者可以知道程序函数库调用出现了错误,并根据错误去处理,而是否终止程序就由调用...

King逍灬遥 783

【加密社】私钥碰撞器,秒杀市面上的碰撞器

基于上述的逻辑和代码,开发了ETH挖掘器(图1.1)这里有个亮点是:1.很多开发者在判断地址是否有效的环节上,用的是查询余额,其实这是不对的,查询余额你可能只能查询对应代币的余额,例如usdt,eth等但是如果用查询交易次数就不一样了,你只要是交易过,我就认为是有效钱包,这样的速度比查询余额要快,也要更准确。2.rpc节点可配置。

加密社的博客 1576

光斑定位 - MATLAB实现

光斑定位是一种常见的图像处理任务,它涉及到在图像中准确定位光斑或亮点的位置。在本篇文章中,我们将使用MATLAB来实现光斑定位的算法,并提供相应的源代码。希望本文提供的MATLAB代码和步骤能够帮助您实现光斑定位任务。通过这些代码,您可以在MATLAB环境中轻松地定位光斑,并在图像上进行可视化展示。这样,我们就完成了光斑定位算法的MATLAB实现。通过以上步骤,我们可以得到一个在光斑位置上标记的图像,从而实现了光斑的准确定位。光斑定位 - MATLAB实现。

qq_39605374的博客 764

我在代码随想录|写代码总结篇| 数组 |链表|哈希表|字符串|双指针法|栈与队列|二叉树|回溯算法|贪心算法|动态规划|单调栈

因为想要成为代码大神所以开始了我代码随想录的刷题过程。

2303_79299383的博客 866

OpenClaw第2章:快速安装

本章将手把手教你安装 OpenClaw。

Maynor的博客 3233

如何提升C++水平?

你希望系统地提升自己的 C++ 编程水平,并想知道有哪些适合的书籍可以作为学习参考。提升 C++ 水平是一个循序渐进的过程,需要结合理论学习、大量实践和代码阅读,我会按学习阶段给你梳理清晰的路径和对应的书籍推荐。

人邮异步社区 2608

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

新手集合--嵌入式linux学习路线--三大阶段

微信公众号:二进制人生 专注于嵌入式linux开发。 本文持续更新,第一版先面世,转发请保留出处:二进制人生。这个学习路线是遵照大多数人的认知规律来的, 第一阶段 1.1 C语言入门 入门选一本简单的、薄一点、不要出错的书就可以了,例如谭浩强老爷子的书,选太厚的容易打击你的信心和学习兴趣,谭老爷子的书虽然被很多人喷,但对于初学者来说还是比较合适的。在入门之后才建议去看C语言的经典教程: 《C Primer Plus》 这本书比较厚,知识点比较全,可以用于查漏补缺。 《C程序设计语言》(Th.

二进制君 2万+

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

std::out_of_range异常的解决方案

std::out_of_range 是 C++ 标准库中的一个异常类,它表示尝试访问的容器元素索引超出了容器的有效范围。这个异常通常与 STL(Standard Template Library)容器,如 std::vector、std::string、std::array 等一起使用,当尝试通过 at() 成员函数访问一个不存在的元素时,就会抛出此异常。

2301_79779756的博客 3325

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

C++ 异常处理总结

一、 参考文献: 【1】C++异常处理:https://www.runoob.com/cplusplus/cpp-exceptions-handling.html

灰太狼的小秘密 3700

对std::out_of_range抛出异常进行处理

对std::out_of_range抛出异常进行处理 #include    #include    #include    using namespace std;   int main() {       vector int> a;       a.push_back(1);       try {           a.at(1);  

wxqian25的专栏 2万+

vs2017c语言未声明标识符,错误:在vscode上使用未声明的标识符'out_of_range'

错误消息Vector.cpp:9:49: error: expected ';' after expressionif (i < 0 || size() <= i) throw out_of_range{"Vector::operator[]"};^;Vector.cpp:9:37: error: use of undeclared identifier 'out_of_range'i...

weixin_42533910的博客 1223

对‘std::__throw_out_of_range_fmt(car const*, ...)@GLIBCXX_3.4.20’未定义的引用

cmake编译报错: libgflags.so:对‘std::__throw_out_of_range_fmt(char const*, ...)@GLIBCXX_3.4.20’未定义的引用 先将g++版本修改,然后 在CMakeLists.txt添加编译选项 set(CMAKE_CXX_COMPILER g++) ...

宁静致远的博客 6256

C++异常

C++异常1 异常的基本概念2 比较C语言中处理异常的方法3 异常的语法3.1 异常的基本语法3.2 异常严格类型匹配3.3 栈解旋(unwinding)3.4 异常的接口声明3.5 异常变量的生命周期3.6 异常的多态使用 1 异常的基本概念 Bjarne Stroustrup说:提供异常的基本目的就是为了处理上面的问题。基本思想是:让一个函数在发现了自己无法处理的错误时抛出(throw)一个异常,然后它的(直接或者间接)调用者能够处理这个问题。也就是《C++ primer》中说的:将问题检测和问题处理相

linuxcpp_的博客 579

std::out_of_range 抛出抛出异常

[code=cpp] // out_of_range example #include // std::cerr #include // std::out_of_range #include // std::vector  int main (void) { std::vectorint> myvector(

xiyangyanging2的博客 4824

关于部分编译器out_of_range报错的解决

今天在使用CodeBlocks编译器时,对于下面的代码public: SmallInt(int i=0):val(i){ if(i<0||i>255) throw out_of_range("error"); } 编译器报错: error: 'out_of_range' w...

weixin_34080903的博客 1729

数据结构与算法系列之一:八大排序之归并排序

转载请注明作者和出处:http://blog.youkuaiyun.com/u011475210 个人博客:https://wordzzzz.github.io/ && https://wordzzzz.gitee.io/ 代码地址:https://github.com/WordZzzz/Note/tree/master/DS-A 博客作者:WordZzzz,一只热爱技术的文艺青年 归并排序 前

WordZzzz 1927
上一篇: 我们为什么会对富二代有偏见?
下一篇: 树形结构的数据库表Schema设计
MONKEY_D_MENG
博客等级 码龄17年 705粉丝 97原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值