C++小知识点总结

C++小知识点总结

   C++的知识点有很多,但此处只总结我在工程实践中常用到的一些知识点。

一 将程序运行结果输出到txt文本文件中

//头文件
#include<fstream>
//函数体:
char* fname = "F:/1.txt";/////此处为程序运行结果存入路径。
ofstream fout(fname,ios::app);//ios::app 用来追加文件 不会覆盖原有数据
fout << << endl;
fout.close();

//如果想将TXT文本中的内容在屏幕中显示,需要再加下面语句
ifstream fin(fname);
char ch;
while (fin.get(ch))
{
cout <<ch;
}
fin.close();
//如果对于输入到文件中的数据有精度要求,该如何操作? 
//代码如下:
char *fname = "D:/DataForEllipseDetection/检测误差精度.txt";
ofstream fout(fname, ios::app);
fout.setf(ios::fixed, ios::floatfield);//设置保留小数点后5位小数
fout.precision(5);
fout << ……<<endl;
fout.close();
ifstream fin(fname);
char ch;
while (fin.get(ch))
{
cout << ch;
}
fin.close();

二 排序

vector<TagPoint2f>  tagPnts
// 对标记好的点,按照标记点进行排序
for(unsigned int i=0;i<tagPnts.size()-1;i++)
{
      for(unsigned int j = i+1; j<tagPnts.size(); j++)
       {
           if(tagPnts[i][0] > tagPnts[j][0])
             {
             swap(tagPnts[i],tagPnts[j]);
             }
       }
}

三 生成随机数

//头文件
#include"stdafx.h"
//封装好的函数
double Rand(double dMin, double dMax)
{
double dVal=(double)rand()/RAND_Max;
return dMin+dVal*(dMax-dMin);
}

四 异常处理

//示例代码:
#include "iostream"
using namespace std;
int abc(int a, int b, int c);
int main()
{
          try{ cout << abc(2, 0, 4) << endl; }
      catch (char* e)
      {
        cout << "The parameters to abc were 2,0,and 4"<<endl;
        cout << "An exception has been thrown" << endl;
        cout << e << endl;
        return 1;
       }
           return 0;
}
//抛出一个类型为char* 的异常
int abc(int a, int b, int c)
{
    if (a <= 0 || b <= 0 || c <= 0)
        throw "All parameters should be >0";
    return a + b*c;
}

 4.1 关于异常处理的简单理论

  程序可能抛出的异常有很多类型,例如0除数、非法参数值、非法输入值、数组下标越界等。如果对每一种类型的异常都定义一个异常类,那么异常处理就有了更多的灵活性。例如,C++具有一个异常类的层次结构,类exception是根。标准C++函数通过抛出一种异常来表明异常的出现,而这种异常是从基类exception派生的类型。例如,C++的动态内存分配操作符new,在得不到内存空间分配时,就抛出类型为bad_alloc的异常,而bad_alloc是一种从基类exception派生的类型。类似的,确定一个对象类型的C++函数typeid,在遇到NULL对象时,就会抛出类型为bad_typeid的异常,而bad_typeid也是从基类exception派生的。

  4..1.1 处理异常

  一段代码抛出的异常由包含这段代码的try快来处理。紧跟在try块之后的是catch块。每一个catch块都有一个参数,参数的类型决定了这个catch块要捕捉的异常的类型。例如,块

catch( char * e) {}

  捕捉的异常类型是bad_alloc。块

catch(exception& e){}

  捕捉的异常类型是基类型exception以及所有从exception派生的类型(例如bad_alloc和bad_typeid)。块

catch(…){}

  捕捉所有异常,不管是什么类型。

 4.2 动态存储空间分配的异常处理

  执行语句

float *x=new float[n];

  可能出现这样的情况,对n个浮点数,计算机没有足够的内存可以分配。在这样的情况下,操作符new也不会分配内存,而是抛出一个类型为bad_alloc的异常。利用try-catch结构,我们可以捕获这个因new操作失败而引发的异常:

float *x;
try{x=new float[n];}
catch(bad_alloc e)
{
//仅当new失败时才会进入
cerr<<"Out of
Memory"<<endl;
exit(1);
}

五 关于 #if…#else

#if 0
A
#else
B
#endif

关于这段代码的理解:

   #if 0 之后的A永远不会执行,肯定会执行B,直到endif.

但如果把述代码改为:

#if 1
A
#else
B
#endif

  就可以让系统只编译A部分代码而不编译B部分代码,这样改起来会很方便。如果发行代码和调试代码是不同的,这是一个很常见的做法。

六 关于GitHub上zip与tar.gz的区别

  从VTK官网下载源码包,本文下载的是VTK-7.0.0.zip.
这里写图片描述
  两个压缩文件内容应该是一样的,只不过zip是全平台通用(windows也能解压),tar.gz是linux下通用的压缩文件格式。

七 容器中查找最大值所在的位置

  参考博文:http://blog.csdn.net/woddle/article/details/27543281
  vector dv;
  假设dv的数值已经赋值好了。
  最大值所在的位置是:
   pos(int)(max_element(dv.begin(),dv.end())-dv.begin());

  说明:
   max_element(dv.begin(),dv.end()) 返回的是:vector::iterator,相当于指针的位置,减去初始指针的位置,就得到我们需要的。

  以后如果要用最大值即可使用dv[pos].

  示例如下:

#include<iostream>
#include<vector>
#include<opencv.hpp>

using namespace std;

/////冒泡法排序,从小到大排序
void reArrange(vector<int>  &Num)
{
    for (unsigned int i = 0; i < Num.size() - 1; i++)
    {
        for (unsigned int j = i + 1; j<Num.size(); j++)
        {
            if (Num[i] > Num[j])
            {
                swap(Num[i], Num[j]);
            }
        }
    }
}

void main()
{
    vector<int> Num(3,9);////定义一个容器中含有3个数,并且都为9;
    Num.push_back(10);
    Num.push_back(5);
    reArrange(Num);////进行排序
    cout << "排好序之后的数" << endl;
    for (size_t i = 0; i < Num.size(); i++)
    {
        cout << Num[i]<<"  ";
    }
    int MaxValue = (int)(max_element(Num.begin(), Num.end()) - Num.begin());
    cout <<"最大值为:"<< Num[MaxValue] << "   "<<"最大值所在的位置为:"<<MaxValue<<endl;

}

八 C++中关联容器的使用

  关联容器的使用案例如下代码(同时需要关注包括switch语句调用以及opencv中add()函数的一个用法):

///////STEP-1:计算椭圆中心之间的距离并除以主椭圆长轴半径,将其存储在矩阵中
    for (int i = 0; i < pntsSize; i++)
    {
        for (int j = i + 1; j < pntsSize; j++)
        {
            distanceMatrix1.at<double>(i, j) = CoreAlgorithm::distancePoints(centerPnt[i], centerPnt[j]) / (longaxisRadius[i] * gamma);
        }
    }
    add(distanceMatrix1, distanceMatrix1.t(), distanceMatrix);
    ////////分析数据矩阵,得出每个点临近点的序号和个数
    /////////关联容器  关联容器   关联容器    关联容器(里面的数据类型可以
    根据自己的需要再修改)
   //////此处pair<int, vector<int>>可以看成是一个结构体,
     通过first和second来调用里面的数据。
    for (int i = 0; i< distanceMatrix.rows; i++)
    {
        pair<int, vector<int>>  tempData;
        tempData.first = i;
        for (int j = 0; j < distanceMatrix.cols; j++)
        {
            if (distanceMatrix.at<double>(i, j)>0.8&&distanceMatrix.at<double>(i, j)<1)
                tempData.second.push_back(j);
        }
        switch (tempData.second.size())
        {
        case 3:
            threeVec.push_back(tempData);
            continue;
        case 4:
            fourVec.push_back(tempData);
            continue;
        case 5:
            fiveVec.push_back(tempData);
            continue;
        default:
            continue;
        }
    }

九 C++标准模板库

 STL:标准模板库 STL:Standard Template Lib

 9.1 vector 向量

 本质:对数组的封装。
 特点:读取能在常数时间完成。

  • 初始化vector对象的方式

    这里写图片描述

  • 遍历vector中的数据的常用方法
     第一种方法:

forint k=0;k<vec.size();K++)
{
  cout<<vec[k]<<endl;
}

   第二种方法:
    迭代器:iterator

  int main(void)
  {
   vector vec;
   vec.push_back("hello");
   vector<string>::iterator citer=vec.begin();
   for(;citer!=vec.end();citer++)
   {
    cout<<*citer<endl;
   }
   return 0;
  }  

 9.2 list:链表

这里写图片描述
 特点:数据插入速度快。

 9.3 map:映射

这里写图片描述

map<int,string> m;
pair<int,string> p1(10,"shanghai");
pair<int,string> p2(20,"beijing");
m.insert(p1);
m.insert(p2);
cout<<m[10]<<endl;
cout<<m[20]<<endl;
map<string,string> m;
pair<string,string> p1("S","shanghai");
pair<string,string> p2("B","beijing");
m.insert(p1);
m.insert(p2);
cout<<m["S"]<<endl;
cout<<m["B"]<<endl;

 9.4 标准模板库的编码实现

 由于vector使用方法已经掌握差不多,此处只想着重强调两个函数:front()以及 back()这两个函数,表示vector中的首和尾。接下来,重点学习一下 list以及map的使用方法。
关于list用法示例代码:

//关于list的使用方法
void main()
{
    list<int> list1;
    list1.push_back(4);
    list1.push_back(7);
    list1.push_back(10);
    //以下方法不可行
    //for (int i = 0; list1.size(); i++)
    //{
    //  cout << list1[i] << endl;
    //}


    //使用迭代器遍历可行
    list<int>::iterator itor = list1.begin();
    for (; itor != list1.end(); itor++)
    {
        cout << *itor << endl;
    }

}
关于map示例代码:
  void main()
{
    map<int, string> m;
    pair<int, string> p1(3, "hello");
    pair<int, string> p2(6, "world");

    //m.push_back(p1);//map中没有push_back
    m.insert(p1);
    m.insert(p2);

    cout << m[3] << endl;
    cout << m[6] << endl;

    map<int, string>::iterator itor = m.begin();

    /*for (; itor != m.end(); itor++)
    {
        std::cout<<*itor << endl;//这种方法不可行
    }*/

    for (; itor != m.end(); itor++)
    {
    std::cout<<itor->first << endl;
    cout << itor->second << endl;
    cout << endl;
    }
}

  注意到:对于map里的数据,是根据first的大小自动进行排序,而与insert调用顺序无关。同样,对于map<string,string> 也取决于第一个string的大小顺序。

综合示例如下:

#include <iostream>
#include <string>
#include <stdlib.h>
#include<list>
#include<vector>
#include<map>
using namespace std;


///////关于list的使用方法

int main()
{
    // 使用vector存储数字:3、4、8、4
    vector<int> vec;
    vec.push_back(3);
    vec.push_back(4);
    vec.push_back(8);
    vec.push_back(4);
    //循环打印数字
    vector<int>::iterator itor = vec.begin();
    for (; itor != vec.end(); itor++)
    {
        cout << *itor << endl;
    }

    // 使用map来存储字符串键值对
    map<int, string> m;
    pair<int, string> p1(5, "Shang Hai");
    pair<int, string> p2(10, "Bei Jing");
    pair<int, string> p3(7, "Guang Zhou");
    m.insert(p1);
    m.insert(p2);
    m.insert(p3);
    // 打印map中数据
    map<int, string>::iterator it = m.begin();
    for (; it!=m.end(); it++)
    {
        cout << it->first << endl;
        cout << it->second << endl;
        cout << endl;
    }

    return 0;
}

十 sprintf()函数用法小结

   此处需要将图片按如下方式存放到本地。
这里写图片描述

   其中用到sprintf()函数用法如下:

    char imgName[50];
    string  nameTemL= "D:/DataFiles/triger/L/image";
    for(size_t i=1;i<300;i++)
    {
     sprintf(imgName, "%s%d%s", nameTemL.data(), i, ".bmp");
     ……
    }

  如若按如下方式保存图片:
这里写图片描述

 for (size_t i = 0; i < PointVec.size(); i++)
    {
        ...
        sprintf(imageName, "./image/%d.bmp", i);
        ...
        cv::namedWindow("result", 1);
        cv::imshow("result", image);
        cv::imwrite(imageName,image);
    }

  个人公众号:

这里写图片描述

3D视觉工坊 CSDN认证博客专家 算法 3D视觉
个人公众号:3D视觉工坊。公众号特邀嘉宾及合伙人,先后就职于国内知名研究机构、自动驾驶公司、海康研究院,主要研究方向为深度学习、目标检测、语义分割、图像处理、自动驾驶感知算法等,CSDN博客专家。博主先后任职于国内知名研究院、知名大厂,致力于3D视觉算法、VLAM算法开发,涉及相机标定、手眼标定、结构光、点云后处理、三维重建等相关领域的研究,同时也是CSDN博客专家。3D视觉工坊坚持原创,近一年来输出了非常多的高质量文章,获得了粉丝的一致好评,我们将始终坚持走原创路线,打造一个铁杆粉丝的聚集区。
©️2020 CSDN 皮肤主题: 书香水墨 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值