首先声明一下,由于水平有限,所以这里的代码没有加入错误处理程序,为version1;

第一步:明确wav格式:

一、综述
    WAVE文件作为多媒体中使用的声波文件格式之一,它是以RIFF格式为标准的。
RIFF是英文Resource Interchange File Format的缩写,每个WAVE文件的头四个
字节便是“RIFF”。
    WAVE文件是由若干个Chunk组成的。按照在文件中的出现位置包括:RIFF WAVE
Chunk, Format Chunk, Fact Chunk(可选), Data Chunk。具体见下图:

------------------------------------------------
|             RIFF WAVE Chunk                  |
|             ID  = 'RIFF'                     |
|             RiffType = 'WAVE'                |
------------------------------------------------
|             Format Chunk                     |
|             ID = 'fmt '                      |
------------------------------------------------
|             Fact Chunk(optional)             |
|             ID = 'fact'                      |
------------------------------------------------
|             Data Chunk                       |
|             ID = 'data'                      |
------------------------------------------------
            图1   Wav格式包含Chunk示例

其中除了Fact Chunk外,其他三个Chunk是必须的。每个Chunk有各自的ID,位
于Chunk最开始位置,作为标示,而且均为4个字节。并且紧跟在ID后面的是Chunk大
小(去除ID和Size所占的字节数后剩下的其他字节数目),4个字节表示,低字节
表示数值低位,高字节表示数值高位。下面具体介绍各个Chunk内容。
PS:
    所有数值表示均为低字节表示低位,高字节表示高位。

二、具体介绍
RIFF WAVE Chunk
    ==================================
    |       |所占字节数|  具体内容   |
    ==================================
    | ID    |  4 Bytes |   'RIFF'    |
    ----------------------------------
    | Size  |  4 Bytes |             |
    ----------------------------------
    | Type  |  4 Bytes |   'WAVE'    |
    ----------------------------------
            图2  RIFF WAVE Chunk

以'FIFF'作为标示,然后紧跟着为size字段,该size是整个wav文件大小减去ID
和Size所占用的字节数,即FileLen - 8 = Size。然后是Type字段,为'WAVE',表
示是wav文件。
    结构定义如下:
 struct RIFF_HEADER
 {
  char szRiffID[4];  // 'R','I','F','F'
  DWORD dwRiffSize;
  char szRiffFormat[4]; // 'W','A','V','E'
 };

Format Chunk
    ====================================================================
    |               |   字节数  |              具体内容                |
    ====================================================================
    | ID            |  4 Bytes  |   'fmt '                             |
    --------------------------------------------------------------------
    | Size          |  4 Bytes  | 数值为16或18,18则最后又附加信息     |
    --------------------------------------------------------------------  ----
    | FormatTag     |  2 Bytes  | 编码方式,一般为0x0001               |     |
    --------------------------------------------------------------------     |
    | Channels      |  2 Bytes  | 声道数目,1--单声道;2--双声道       |     |
    --------------------------------------------------------------------     |
    | SamplesPerSec |  4 Bytes  | 采样频率                             |     |
    --------------------------------------------------------------------     |
    | AvgBytesPerSec|  4 Bytes  | 每秒所需字节数                       |     |===> WAVE_FORMAT
    --------------------------------------------------------------------     |
    | BlockAlign    |  2 Bytes  | 数据块对齐单位(每个采样需要的字节数) |     |
    --------------------------------------------------------------------     |
    | BitsPerSample |  2 Bytes  | 每个采样需要的bit数                  |     |
    --------------------------------------------------------------------     |
    |               |  2 Bytes  | 附加信息(可选,通过Size来判断有无) |     |
    --------------------------------------------------------------------  ----
                            图3  Format Chunk

以'fmt '作为标示。一般情况下Size为16,此时最后附加信息没有;如果为18
则最后多了2个字节的附加信息。主要由一些软件制成的wav格式中含有该2个字节的
附加信息。
    结构定义如下:
 struct WAVE_FORMAT
 {
  WORD wFormatTag;
  WORD wChannels;
  DWORD dwSamplesPerSec;
  DWORD dwAvgBytesPerSec;
  WORD wBlockAlign;
  WORD wBitsPerSample;
 };
 struct FMT_BLOCK
 {
  char  szFmtID[4]; // 'f','m','t',' '
  DWORD  dwFmtSize;
  WAVE_FORMAT wavFormat;
 };

Fact Chunk
    ==================================
    |       |所占字节数|  具体内容   |
    ==================================
    | ID    |  4 Bytes |   'fact'    |
    ----------------------------------
    | Size  |  4 Bytes |   数值为4   |
    ----------------------------------
    | data  |  4 Bytes |             |
    ----------------------------------
            图4  Fact Chunk

Fact Chunk是可选字段,一般当wav文件由某些软件转化而成,则包含该Chunk。
    结构定义如下:
 struct FACT_BLOCK
 {
  char  szFactID[4]; // 'f','a','c','t'
  DWORD  dwFactSize;
 };

Data Chunk
    ==================================
    |       |所占字节数|  具体内容   |
    ==================================
    | ID    |  4 Bytes |   'data'    |
    ----------------------------------
    | Size  |  4 Bytes |             |
    ----------------------------------
    | data  |          |             |
    ----------------------------------
             图5 Data Chunk

Data Chunk是真正保存wav数据的地方,以'data'作为该Chunk的标示。然后是
数据的大小。紧接着就是wav数据。根据Format Chunk中的声道数以及采样bit数,
wav数据的bit位置可以分成以下几种形式:
    ---------------------------------------------------------------------
    |   单声道  |    取样1    |    取样2    |    取样3    |    取样4    |
    |           |--------------------------------------------------------
    |  8bit量化 |    声道0    |    声道0    |    声道0    |    声道0    |
    ---------------------------------------------------------------------
    |   双声道  |          取样1            |           取样2           |
    |           |--------------------------------------------------------
    |  8bit量化 |  声道0(左)  |  声道1(右)  |  声道0(左)  |  声道1(右)  |
    ---------------------------------------------------------------------
    |           |          取样1            |           取样2           |
    |   单声道  |--------------------------------------------------------
    | 16bit量化 |    声道0    |  声道0      |    声道0    |  声道0      |
    |           | (低位字节)  | (高位字节)  | (低位字节)  | (高位字节)  |
    ---------------------------------------------------------------------
    |           |                         取样1                         |
    |   双声道  |--------------------------------------------------------
    | 16bit量化 |  声道0(左)  |  声道0(左)  |  声道1(右)  |  声道1(右)  |
    |           | (低位字节)  | (高位字节)  | (低位字节)  | (高位字节)  |
    ---------------------------------------------------------------------
                         图6 wav数据bit位置安排方式

Data Chunk头结构定义如下:
    struct DATA_BLOCK
 {
  char szDataID[4]; // 'd','a','t','a'
  DWORD dwDataSize;
 };

以上是wav格式的完整解释,我们最常用的是16字节单声道音频即:

前44个字节为头信息,我们可以直接使用;

另一个需要注意的是,wav文件以二进制打开,二进制的编码方式为补码;

一,首先定义上述的几个类,我们操纵文件时,直接操纵缓冲区;

#include<fstream>
#include<string>
#include<sstream>//几种wav文件中会遇到的数据类型
typedef unsigned long DWORD;//4个字节
typedef unsigned short WORD;//2个字节
//-----------------------------------------------------------------------------------------------------------
//用于打开一个输入文件
inline std::ifstream& gl_open_file(std::ifstream& in, const std::string& filename,std::ios::openmode mode=std::ios::in)
{in.close();in.clear();in.open(filename.c_str(),mode);return in;
}
//用于打开一个输出文件
inline std::ofstream& gl_open_file(std::ofstream& out, const std::string& filename,std::ios::openmode mode=std::ios::out|std::ios::app)
{out.close();out.clear();out.open(filename.c_str(),mode);return out;
}
//-------------------------------------------------------------------------------------------------------------
//将两个字节的补码转化为一个带正负号的整数
inline int bytes_complement(unsigned char lowbyte,unsigned char highbyte)
{WORD num=((highbyte<<8)+lowbyte);return num&0x8000 ? (-((~num+1)&0x7fff)) : num;
}
//--------------------------------------------------------------------------------------------------------------
//wave数据格式的头信息:
/* 一个wav数据由RIFF WAVE Chunk, Format Chunk ,Fact Chunk, Data Chunk组成*/
struct Riff_Header{public:char riff_id[5];  // 'R','I','F','F'DWORD riff_size;char riff_format[5]; // 'W','A','V','E'size_t  object_size;//本对象中数据所需要的字节数//以c字符串为参数,构造riff——header对象Riff_Header(char* buf);//以文件流为参数直接构造对象Riff_Header(std::ifstream& in);Riff_Header(){}//默认构造函数};struct Format_Chunk{ char format_id[5];DWORD format_size;WORD format_tag;//编码方式WORD channels;//通道数DWORD samplesPerSec;//采样频率DWORD avgBytesPerSec;//每秒需要字节数 Byte率WORD blockAlign;//每个采样需要的字节数   WORD bitsPerSample;// 每个采样需要的bit数  size_t object_size;//本对象中数据所需要的字节数//以c字符串为参数,构造Wave_format对象Format_Chunk(char* buf);//以文件流为参数构造对象Format_Chunk(std::ifstream& in);Format_Chunk(){}};struct Data_Block
{char data_id[5];// 'd','a','t','a'DWORD data_size;size_t object_size;Data_Block(char* buf);Data_Block(std::ifstream& in);Data_Block(){}};
//wav 文件中除数据之外的包含文件信息的头数据
class Wave_Header
{
public:Riff_Header riff;Format_Chunk   fmt;Data_Block data;size_t   object_size;
public:Wave_Header(char* buf);Wave_Header(std::ifstream& in);Wave_Header(){}
};
//------------------------------------------------基本头信息类完成----------------------------------------//

上述的类每个都有一个以char指针为参数的构造函数,这里我没有定义,因为一这里没有使用这一版本构造函数;二它的实现非常简单但是很繁琐;所以就没有实现;

二,重载输入输出操作符:

/*************下为各个结构的重载的输入输出操作符**************************************/
//-------------------------------------------------------------------------------------
//面向wav文件的输入,这里定义更加普遍的模板函数,非格式化输入
template<typename charT,typename traits>
std::basic_istream<charT,traits>& operator>>(std::basic_istream<charT,traits>&  strm,Riff_Header& rf)
{std::streambuf* strm_buffer=strm.rdbuf();//rdbuf()返回缓冲区的指针strm_buffer->sgetn(rf.riff_id,4);strm_buffer->sgetn(rf.riff_format,4);//riff_format此处为缓冲区,用于读取riff_size的信息memcpy(&rf.riff_size,rf.riff_format,4);strm_buffer->sgetn(rf.riff_format,4);//后面的完善工作:ID,format变为c字符串,以便与输出操作rf.riff_id[4]='\0';rf.riff_format[4]='\0';rf.object_size=12;return strm;
}
//格式化输出
template<typename charT,typename traits>
std::basic_ostream<charT,traits>& operator<<(std::basic_ostream<charT,traits>&  strm,Riff_Header& rf)
{std::basic_ostringstream<charT,traits> s;s.copyfmt(strm);s.width(0);s<<" RIFF WAVE Chunk :"<<'\n'<<"ID:"<<rf.riff_id<<'\n'<<"TYPE:"<<rf.riff_format<<'\n';strm<<s.str();return strm;
}//------------------------------------------------------------------------------------------------------------
template<typename charT,typename traits>
std::basic_istream<charT,traits>& operator>>(std::basic_istream<charT,traits>&  strm,Format_Chunk& fc)
{std::streambuf* strm_buffer=strm.rdbuf();char tmp_buf[4];//小小缓冲区strm_buffer->sgetn(fc.format_id,4);fc.format_id[4]='\0';strm_buffer->sgetn(tmp_buf,4);memcpy(&fc.format_size,tmp_buf,4);strm_buffer->sgetn(tmp_buf,4);memcpy(&fc.format_tag,tmp_buf,2);memcpy(&fc.channels,tmp_buf+2,2);strm_buffer->sgetn(tmp_buf,4);memcpy(&fc.samplesPerSec,tmp_buf,4);strm_buffer->sgetn(tmp_buf,4);memcpy(&fc.avgBytesPerSec,tmp_buf,4);strm_buffer->sgetn(tmp_buf,4);memcpy(&fc.blockAlign,tmp_buf,2);memcpy(&fc.bitsPerSample,tmp_buf+2,2);if(fc.format_size==16){//无附加信息fc.object_size=24;}else{strm_buffer->sgetn(tmp_buf,2);//耗用两个字节fc.object_size=26;}return strm;
}
//格式化输出
template<typename charT,typename traits>
std::basic_ostream<charT,traits>& operator<<(std::basic_ostream<charT,traits>&  strm,Format_Chunk& fc)
{std::basic_ostringstream<charT,traits> s;s.copyfmt(strm);s.width(0);s<<"FORMAT CHUNK:"<<'\n'<<"FORMAT ID:"<<fc.format_id<<'\n'<<"FormatTag: "<<fc.format_tag<<'\n'<<"Channels: "<<fc.channels<<'\n'<<"SamplesPerSec:"<<fc.samplesPerSec<<'\n'<<"AvgBytesPerSec: "<<fc.avgBytesPerSec<<'\n'<<"BlockAlign: "<<fc.blockAlign<<'\n'<<"BitsPerSample(每个采样需要的bit数 ):"<<fc.bitsPerSample<<'\n';strm<<s.str();return strm;
}//-----------------------------------------------------------------------------------------------------------
template<typename charT,typename traits>
std::basic_istream<charT,traits>& operator>>(std::basic_istream<charT,traits>&  strm,Data_Block& db)
{std::streambuf* strm_buffer=strm.rdbuf();char tmp_buf[4];//小小缓冲区strm_buffer->sgetn(db.data_id,4);db.data_id[4]='\0';strm_buffer->sgetn(tmp_buf,4);memcpy(&db.data_size,tmp_buf,4);db.object_size=8;return strm;
}
//格式化输出
template<typename charT,typename traits>
std::basic_ostream<charT,traits>& operator<<(std::basic_ostream<charT,traits>&  strm,Data_Block& db)
{std::basic_ostringstream<charT,traits> s;s.copyfmt(strm);s.width(0);s<<"DATA BLOCK:"<<'\n'<<"DATA ID:"<<db.data_id<<'\n'<<"DATA SIZE:"<<db.data_size<<'\n';strm<<s.str();return strm;
}
//--------------------------------------------------------------------------------------------------------------
template<typename charT,typename traits>
std::basic_istream<charT,traits>& operator>>(std::basic_istream<charT,traits>&  strm,Wave_Header& wh)
{strm>>wh.riff>>wh.fmt>>wh.data;wh.object_size=wh.riff.object_size+wh.fmt.object_size+wh.data.object_size;return strm;
}template<typename charT,typename traits>
std::basic_ostream<charT,traits>& operator<<(std::basic_ostream<charT,traits>&  strm,Wave_Header& wh)
{std::basic_ostringstream<charT,traits> s;s.copyfmt(strm);s.width(0);s<<wh.riff<<wh.fmt<<wh.data;strm<<s.str();return strm;
}
//----------------------------------------------------------------------------------------------------------

其中的输出操作符的实现参考的是:《C++标准程序库》

三:

struct Out_Place
{std::string place_id;//"vector","file","array"....virtual void put(int elem){};virtual ~Out_Place(){}
};  //一个wav文件的完整对象,一个对象关联就是wav文件
class Wave_Total
{
public:Wave_Header* header;//数据头信息Out_Place* out_place;//out_place 是转化后内容的输出处:可能是数组,文件,和各种容器Wave_Total(){}//以wav文件名为参数,构造本文件的对象。当第二个参数是true时,我们构造头信息,否则直接读取数据Wave_Total(std::string& filename,Out_Place* op,bool need_header=true);Wave_Total(char* buf);//每个对象关联的是一个数组buf
};

这里需要说明的是,我写到这儿时候,想到并不一定是将转化后的信息输出到文件,可以输出到内存中使用,也可以输出到GUI中直接作出波形图,或者函数中直接处理(例如FFT),所以就有一个Out_Place类,代表了输出对象,其中id标示输出地,put定义输出方式;

四,构造函数:

inline Riff_Header::Riff_Header(std::ifstream& in)
{in>>*this;
}
inline Format_Chunk::Format_Chunk(std::ifstream& in)
{in>>*this;
}
inline Data_Block::Data_Block(std::ifstream& in)
{in>>*this;
}
inline Wave_Header::Wave_Header(std::ifstream& in)
{in>>*this;
}

五,由于我的任务是输出到文件中,所以我需要一个Out_place与文件关联:

Wave_Total::Wave_Total(std::string& filename,Out_Place* op,bool need_head)
{out_place=op;std::ifstream in;gl_open_file(in,filename,std::ios::binary|std::ios::in);if(need_head){//此时需要头信息header=new Wave_Header;in>>*header;}else{//此时按照一般的wav文件格式跳过头信息,一般为44个字节in.seekg(44,std::ios::beg);}//下为主要读取程序:std::streambuf* in_buffer=in.rdbuf();char tmp_buf[2];//小小缓冲区while(in_buffer->sgetn(tmp_buf,2))out_place->put(bytes_complement(tmp_buf[0],tmp_buf[1]));in.close();
}
//此类用于表示输出到文件,其中文件名作为信息存储在此对象中
struct out_to_file:public Out_Place
{std::ofstream strm;std::string outfilename;out_to_file(std::string& filename);out_to_file();void put(int elem);~out_to_file(){strm.close();}
};
out_to_file::out_to_file(std::string& filename)
{place_id="file";outfilename=filename;gl_open_file(strm,filename);
}
//此处的put控制输出操作,输出格式,输出信息
void out_to_file::put(int elem)
{strm.precision(4);strm.setf(std::ios::fixed,std::ios::floatfield);float tmp;if(elem<0){tmp=(float)elem/32768;}else{tmp=(float)elem/32767;}strm<<tmp<<'\n';
}

六:主体部分已经完成了,但是我们需要批量操作,下面定义批量操作:

#include<io.h>
//以文件名为参数的函数指针
typedef void(*PFN)(std::string& filename);
//遍历同一文件夹下的所有文件,以pfn处理每个文件
bool transfer(std::string& filename, std::string& postfix , PFN pfn );
//遍历一个文件夹下所有文件(包括被嵌套的文件),以pfn处理
void dfsFolder(std::string& folderpath,std::string& postfix,PFN pfn);
/*
struct _finddata_t
{unsigned attrib;     //文件属性time_t time_create;  //文件创建时间time_t time_access;  //文件上一次访问时间time_t time_write;   //文件上一次修改时间_fsize_t size;  //文件字节数wchar_t  name[_MAX_FNAME]; //文件名
};
*/#include"read.h"
#include<iostream>
//遍历同一文件夹下的所有文件
bool transfer(std::string& directoryname ,std::string& postfix ,PFN pfn)
{_finddata_t fileInfo;//搜索与指定的文件名称匹配的第一个实例,若成功则返回第一个实例的句柄,否则返回-1Llong handle = _findfirst(directoryname.c_str(), &fileInfo);std::string pathname=directoryname.substr(0,directoryname.size()-postfix.size()-1);if (handle == -1L){std::cerr << "failed to transfer files" << std::endl;return false;}do {pfn(pathname+std::string(fileInfo.name));} while (_findnext(handle, &fileInfo) == 0);//_findnext搜索与_findfirst函数提供的文件名称匹配的下一个实例,若成功则返回0,否则返回-1return true;
}
//某一目录下包括多个文件夹
void dfsFolder(std::string& folderPath,std::string& postfix,PFN pfn)
{_finddata_t FileInfo;std::string strfind = folderPath + "\\*";long Handle = _findfirst(strfind.c_str(), &FileInfo);if (Handle == -1L){std::cerr << "can not match the folder path" << std::endl;exit(-1);}do{//判断是否有子目录if (FileInfo.attrib & _A_SUBDIR)    {//这个语句很重要if( (strcmp(FileInfo.name,".") != 0 ) &&(strcmp(FileInfo.name,"..") != 0))   {std::string newPath = folderPath + "\\" + FileInfo.name;dfsFolder(newPath,postfix,pfn);}}else  {pfn(folderPath+"//"+std::string(FileInfo.name));}}while (_findnext(Handle, &FileInfo) == 0);_findclose(Handle);}

最后,我们定义一个函数指针,对于每一个文件都调用它,这里我们需要的函数指针的功能是:将wav转化为txt并储存;

//传入文件名,转换为同名txt文件
void wav_to_txt(std::string& filename)
{//假设wav转化后的txt文件都存储在E:\\wavtotxt目录下std::string outfilename=filename.substr(0,filename.size()-3);//去除wavoutfilename=outfilename+"txt";out_to_file out(outfilename);Wave_Total wt(filename,&out);
}

使用函数:

//简单版
int main()
{dfsFolder(string("E:\\wav2"),string(".wav"),wav_to_txt);
}
 //复杂版
int main(){cout<<"如果想转化一个文件,请输入f,如果想转化一个目录,请输入d:"<<endl;char c;cin>>c;switch(c){case 'd':{cout<<"Please enter your directory:  ";string directoryname;cin>>directoryname;dfsFolder(directoryname,string(".wav"),wav_to_txt);break;}case 'f':{cout<<"Please enter your directory:  ";string filename;cin>>filename;wav_to_txt(filename);break;}default:cout<<"invalid input!"<<endl;break;}cout<<"success!";char c2=getchar();}

ok,任务完成。

对于不明白补码的同学,这里二进制原码反码补码有百度文库的参考

(-):wav文件转化为txt文件相关推荐

  1. 如何用python修改pdf内容_如何利用python将pdf文件转化为txt文件?

    https://www.wukong.com/answer/6579491774144708872/?iid=15906422033&app=news_article&share_an ...

  2. java scel_使用java将搜狗词库.scel文件转化为.txt文件

    需求:批量将.scel文件转化为可视的txt文件(支持1对1,多对1,多对多),并从中提取中文词(去重),支持追加内容. 成果: 使用: package com.hxl.files; import j ...

  3. python快速将excel文件转化为txt文件

    在进行数据预处理的时候,我们可能习惯于将用于存储数据的其他格式的文件转换为.txt文件,因为这类文件读取.写入和处理起来都比较高效.这篇博客主要介绍一种快速地将excel文件转化为.txt文件的方法, ...

  4. python 将html文件转化为txt文件

    python 将html文件转化为txt文件 ①需求:一千多篇乌云知识库的文章,收集下来后是html文件,需要将它们都转化为txt文件.由于本人又菜又懒,找了很久代码想要ctrl+c和ctrl+v大佬 ...

  5. 将npz文件转化为txt文件中出现错误(ValueError: Expected 1D or 2D array, got 3D array instead)的解决办法

    seq.npz直接使用Notepad++打开发生错误,试着使用python去读这个文件包. import numpy as np# %% seq_data = np.load('seq.npz') p ...

  6. 如何将nc文件转化为txt格式

    如何将nc文件转化为txt格式 该类型文件全成为netCDF文件格式 需要使用netCDF软件体系 目前CSDN和百度出的结果均使用的是该软件下面的支持保 但是流传的版本过低,许多新的nc文件打不开 ...

  7. python 把txt文件转化为pcd文件并用open3D可视化

    python 把txt文件转化为pcd文件并用open3D进行可视化 最近在弄3D点云的一些东西,遇到一个问题:很多数据集给的点云数据都是txt格式的,但是在模型上用到的数据集基本是pcd格式!找了很 ...

  8. xps数据怎么导出为txt_WFP: 读取XPS文件或将word、txt文件转化为XPS文件

    读取XPS格式文件或将doc,txt文件转化为XPS文件,效果图如下: 1.XAML页面代码: xmlns="http://schemas.microsoft.com/winfx/2006/ ...

  9. 使用pcl将bin文件转化为pcd文件

    使用pcl将bin文件转化为pcd文件 环境搭载:ubuntu16.04 之后正式操作具体如下: 在home下,新建文件夹PointCloud(我建在这里,大家随意),在PointCloud文件里继续 ...

最新文章

  1. 【UI设计培训】字体设计-偏旁部首变形
  2. python增删改查人名管理_python3字典列表的增删改查(名片管理系统函数版)
  3. 怎样将Excel中的数据导入到SQL Server 2000数据库中
  4. 不想用宝塔面板建站,如何手动搭建LAMP环境安装wordpress
  5. codewars033: Duplicate Encoder 重复编码器
  6. MATLAB均值滤波
  7. 一个黑客都要学习什么语言呢?
  8. AsyncTask下载图片
  9. TextView列表页面跳转的简洁写法.
  10. word表格分开快捷键_Word用鼠标和快捷键拆分单元格与合并单元格
  11. 多元统计分析笔记二——多元分布
  12. 06 Errors For Go1.13
  13. SYN攻击原理以及防范技术
  14. Oauth2.0搭建开放平台接口
  15. 免费PPT模板网站,模板精品好用,直接下载
  16. c++数独游戏3.0
  17. set_xscale 表示x轴缩放比例,一张图明明白白
  18. Su+ELK实现网络监测(1)——Suricata安装与配置
  19. 打破空间探索边界:曲速引擎或将实现超光速
  20. 矩阵的基本运算(相乘、相加、求逆、转置)

热门文章

  1. 分析与设计建模——类图
  2. 【编程题练习】牛客-阿里:二叉树(卡特兰数)
  3. 智能催收取代人工催收只是噱头吗?
  4. 嵌入式学习笔记——使用寄存器编程操作GPIO
  5. 魅族系统更新flyme 8.0.0.0A后,卡到爆的进来!
  6. 不做raid 两块硬盘 不做raid 不做raid 装系统
  7. python批量下载上交所上市公司报告
  8. 手机端无法识别Chrome谷歌浏览器了?
  9. i18n实现SpringBoot后端多语言化(前后端分离)
  10. 【Gin-v1.9.0源码阅读】version.go