编程语言学习(随机数组,插入、冒泡、选择排序,Qt)

9 篇文章 0 订阅

1.C++

1.1 面向对象

①类

个人理解:类就是一种简单的数据结构,或者可以说就是像int、float等定义的数据类型。只不过类是我们自己定义的一种数据类型(里面可以包含成员变量,成员函数

②继承(is a

依据一个类来定义子类,重用代码,提高执行时间(class sub-class:base-class1,base-class2……)

③重载

同一作用域中,某个函数或运算符做多个定义,函数重载(参数个数、类型、顺序),运算符重载(关键字operater)

1.2 异常处理--详见代码(try中设置抛出throw,catch中捕获)

/*****
try的保护代码块有抛出throw,后面catch才能捕获
*****/
#include <iostream>
using namespace std;
double divide(double a, double b)
{
    if(b==0)
    {
        throw "zero exception";
    }
    return (a/b);
}
int main(int argc, char const *argv[])
{
    try{//放可能抛出异常的代码--保护代码
        cout<<divide(3,0)<<endl;//这里并不能直接抛出异常
    }
    catch(const char *msg)//需要用catch捕获异常---try的保护代码区若有多个异常,则需要多个catch捕获
    {
        cerr<<msg<<endl;
    }
    return 0;
}

1.3 内存

函数中声明的所有变量--栈内存

程序中未用到的内存,程序运行时动态分配--堆内存(new/delete)

double* pvalue  = NULL; // 初始化为 null 的指针
pvalue  = new double;   // 为变量请求内存

new--为变量请求内存,返回分配的空间的地址。(一般不知道变量需要多大内存时使用)

new与C语言中的malloc区别在于,new不仅分配内存,还创建对象。

1.4 随机数组

/*产生[left,right]区间的包含N个数的随机数组*/
int *randArray(int left, int right, int N)
{
	int *arr = new int[N];
	srand((unsigned)time(NULL));//产生随机数种子
	for (int i = 0; i<N; i++)
	{
		arr[i] = (left+rand()%(right-left));
	}
	return arr;
}

注意:①头文件需要include<ctime>   #include<cstdlib>。②这里new了一个内存空间,需要delete[]。

但仍然存在一个问题:返回后得到的数组长度是2,还没搞懂是为什么?

同时附上一个python语言实现的从start到end的随机数组(长度为proportion*10):

import os
import random

def rand_index_list(start=0,end=9,proportion=1):
    rand_index_list = []
    while len(rand_index_list)<proportion*10:   
        rand_index=random.randint(start,end)
        if rand_index not in rand_index_list:
            rand_index_list.append(rand_index)
    rand_index_list.sort()
    return rand_index_list

def rand_serial(path_fold=None):
    train_val_proportion = 0.8
    rand_train_val_index_list=rand_index_list(proportion=train_val_proportion)
    print("train_val_index:{}".format(rand_train_val_index_list))
    train_proportion = 0.6
    rand_train_index_list = [rand_train_val_index_list[x] for x in rand_index_list(start=0,end=train_proportion*10,proportion=train_proportion)]
    print("train_index:{}".format(rand_train_index_list))

if __name__ == "__main__":
    rand_serial()

1.5 插入排序

思想:从数组的第二个数(索引=1)开始,预先设定keyValue,分别与前面的数做对比,如果前面的数比keyValue小,则交换两者位置。因此,每轮排序后,keyValue前面都是排序好了的数组。

void insertSort(int *arr)
{
	cout<<endl;
	cout<<"before sort:"<<endl;
	for (int index = 0; index < arrayLength; index++)
	{
		cout<<arr[index]<<" ";
	}
	cout<<"\nsizeof(arr) = "<<sizeof(arr)<<endl;
	cout<<"the length of array is sizeof(arr)/sizeof(int) = "<<sizeof(arr)/sizeof(int)<<endl;
	for(int index = 1; index<arrayLength; index++)
	{
		int sortedIndex = index-1;
		int unsortedIndex = index;
		int keyValue = arr[index];
		while(keyValue >= arr[sortedIndex] && sortedIndex >= 0)
		{
			arr[unsortedIndex--] = arr[sortedIndex];
			arr[sortedIndex] = keyValue;
			sortedIndex--;
		}
	}
	cout<<"after sort:"<<endl;
	for (int index = 0; index < arrayLength; index++)
	{
		cout<<arr[index]<<" ";
	}
	cout<<endl;
}

其中arrayLength是4)中生成的数组长度。

1.6 冒泡排序

数组array[10]冒泡思想:

①第一轮:array[0]与array[1]对比交换,array[1]与array[2]对比交换……array[8]与array[9]对比交换,最终最大(或最小)的数被"冒泡"到最后一个位置;

②第二轮:array[0]与array[1]对比交换……array[7]与array[8]对比交换,因为array[9]在第①轮就已经被确定为最大(或最小)值;

……

/*思想:紧邻两个数进行对比交换,每一轮都会将最小的数交换到最后一个。
compareIndex<arrayLength-lunIndex表示每一轮"冒泡"完,就不用管后面"冒泡"好了的数*/
void bubleSort(int *arr)
{
    for (int lunIndex = 0; lunIndex<arrayLength; lunIndex++)
    {
        for (int compareIndex = 1; compareIndex<arrayLength-lunIndex; compareIndex++)
        {
            if(arr[compareIndex]>arr[compareIndex-1])
            {
                int temp = arr[compareIndex];
                arr[compareIndex]=arr[compareIndex-1];
                arr[compareIndex-1]=temp;
            }
        }
    }
}

1.7 选择排序

/*每一轮都选出其中最大值maxValue,分别与第1/2/3……交换位置*/
void selectSort(int *arr)
{
    for (int index = 0; index<arrLength-1; index++)
    {
        int maxValue=0;
        int maxValueIndex = 0;
        //find the max number
        for (int selectIndex = index+1; selectIndex<arrLength; selectIndex++)
        {
            if(arr[selectIndex]>=maxValue)
            {
                maxValue = arr[selectIndex];
                maxValueIndex = selectIndex;
            }
        }
        //exchange between maxValue with the value of index location
        int tempValue = arr[index];
        arr[index] = maxValue;
        arr[maxValueIndex] = tempValue;
    }
}

 

2.QT

2.1 配置

参考网址:https://blog.csdn.net/win_turn/article/details/50465127--亲测成功

为避免新旧版本兼容性,可查一下对应Qt是哪个版本的MinGW版本编译的,下载对应的安装包即可。

①MinGW安装:可下载压缩文件,解压后配好环境变量即可(path加入路径$mingw32\bin);

②Qt库安装:注意选择MinGW时,设置为$ming32的位置,提示“There is a problem with your MinGW installation:……”,则说明MinGW路径选择错误;

③QtCreater安装配置:(配置)工具->选项->Debuggers(Name自己定,Path设置为$mingw32\bin\gdb.exe)->编译器(手动设置Path为$mingw32\bin\g++.exe)->Qt Versions(选择qmake.exe)->构建套件Kit(编译器、调试器、Qt版本选择前几步设置好的Name)->新建项目(Qt Widgets Application,全部默认就行,左下角绿色三角形运行即可开始一个最简单的Qt开发界面)

2.2 对话框Dialog

①模式对话框(“主对话框”上生成一个“子对话框”,“主对话框”阻塞,必须关闭“子对话框”之后才能继续对“主对话框”进行操作。主要函数exec())

②非模式对话框(“主对话框”上生成一个“子对话框”,“主对话框”不会阻塞,可对“主/子对话框”同时操作。类似文字查找/替换功能。主要函数show())

③半模式对话框(“主对话框”上生成一个“子对话框”,“主对话框”阻塞。主要针对进度对话框,一定进度后仍需要交其具有信息交互能力。主要函数setModal(true),show())


3.c++基础知识

3.1 关键字explicit

参考:https://blog.csdn.net/qq_35524916/article/details/58178072

直观理解就是:防止隐式转换的。

使用情况:有时候我们需要防止隐式转换的发生,通过添加explicit实现,即需要显示调用函数

参考网站中的构造函数冒号(:)就是初始化,使用解释可以查看:https://www.cnblogs.com/qingyuanhu/p/4301691.html

 

3.2 关键字inline

参考:https://www.cnblogs.com/fnlingnzb-learner/p/6423917.html

解释:调用函数时,会重新开辟栈内存,使用inline的内联函数,相当于把函数中的代码复制到调用的位置。因此函数里面的内容需要简单,不包括循环结构for、 while、 switch等。

3.3 编程报错Core Dump (Segmentation fault) in C/C++

参考:https://www.geeksforgeeks.org/core-dump-segmentation-fault-c-cpp/

  • 修改只读内存
  • 访问已被释放的地址
  • 数组访问超出边界

3.OpenCV

3.1 获取图像像素值

图像读取imread函数执行之后,图像以Mat格式存储,获取图像某一像素值,有以下常用方式获取:

  • 最简单:image.at<uchar>(i, j)或image.at<vec3d>(i, j)读取(i,j)处的像素值;(但是terminal上看不见输出结果,因为uchar类型以ASCII码显示,会隐藏,需要强制转换为int类型,参考

 

3.2 sobel边缘检测算法

/****https://blog.csdn.net/u011486738/article/details/82256644
1.在C++中,内存分成5个区,他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。
2.栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清理的变量的存储区。里面的变量通常是局部变量、函数参数等。
3.堆,就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。
4.自由存储区,就是那些由malloc等分配的内存块,他和堆是十分相似的,不过它是用free来结束自己的生命的。
5.全局/静态存储区,全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量又分为初始化的和未初始化的,在C++里面没有这个区分了,他们共同占用同一块内存区。
6.常量存储区,这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改(当然,你要通过非正当手段也可以修改,而且方法很多)

不可return的变量:函数不能返回指向栈内存的指针或者引用
可return的变量:int类型,字符串常量(不能return字符串常量的引用),静态局部变量,堆内存中的局部变量(new出来的)
****/
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>

using namespace cv;
using namespace std;

bool changelabel=false; //用于协助查看图像像素值

vector<string> getFiles(string cate_dir)
{
	vector<string> files;//存放文件名
 
	DIR *dir;
	struct dirent *ptr;
	char base[1000];
 
	if ((dir=opendir(cate_dir.c_str())) == NULL)
        {
		perror("Open dir error...");
                exit(1);
        }
 
	while ((ptr=readdir(dir)) != NULL)
	{
		if(strcmp(ptr->d_name,".")==0 || strcmp(ptr->d_name,"..")==0)    ///current dir OR parrent dir
		        continue;
		else if(ptr->d_type == 8)    ///file
			//printf("d_name:%s/%s\n",basePath,ptr->d_name);
			files.push_back(ptr->d_name);
		else if(ptr->d_type == 10)    ///link file
			//printf("d_name:%s/%s\n",basePath,ptr->d_name);
			continue;
		else if(ptr->d_type == 4)    ///dir
		{
			files.push_back(ptr->d_name);
			/*
		        memset(base,'\0',sizeof(base));
		        strcpy(base,basePath);
		        strcat(base,"/");
		        strcat(base,ptr->d_nSame);
		        readFileList(base);
			*/
		}
	}
	closedir(dir);
 
	//排序,按从小到大排序
	sort(files.begin(), files.end());
	return files;
}
/*把超过1的像素全部置为1,防止卷积计算时超过uchar类型的范围,
这样计算sobel算子(x方向:[[-1,0,1],[-2,0,2],[-1,0,1]];y方向:[[-1,-2,-1],[0,0,0],[1,2,1]])的时候,
最大也就为4*/
static Mat set_1_fun(Mat matrix)
{
    /*不能直接修改传入函数的矩阵,否则会报错Segmentation fault (core dumped)必须通过新建一个临时矩阵,return
    */
    int m[3][3] = {{0,0,0},{0,0,0},{0,0,0}};
    static Mat temp_matrix=Mat(3,3,CV_8UC1,m);
    Mat matrix1 = matrix;
    uchar w=matrix1.cols;
    uchar h=matrix1.rows;
    for (int t_i=0;t_i<h;t_i++)
    {
         for (int t_j=0;t_j<w;t_j++)
         {
            uchar pixel_value = matrix1.ptr<uchar>(t_i)[t_j];
            if (pixel_value>1)
            {   
		//cout<<"pixel:"<<pixel_value<<endl;
 	        temp_matrix.ptr<uchar>(t_i)[t_j] = (uchar)1;
            }
         }
    }
    return temp_matrix;
}
/*这里用static是为了将局部变量放置到静态存储区,才能返回正常值*/
static Mat get_temp_matrix(Mat matrix,int h_j,int w_i)
{
    /*uchar 类型不能直接通过cout输出到terminal,ASCII码默认隐藏*/
    int m[3][3] = {{0,0,0},{0,0,0},{0,0,0}};
    static Mat temp_matrix=Mat(3,3,CV_8UC1,m);
    //cout<<matrix<<endl;
    temp_matrix.ptr<uchar>(0)[0] = matrix.ptr<uchar>(h_j)[w_i];
    temp_matrix.ptr<uchar>(0)[1] = matrix.ptr<uchar>(h_j)[w_i+1];
    temp_matrix.ptr<uchar>(0)[2] = matrix.ptr<uchar>(h_j)[w_i+2];
    temp_matrix.ptr<uchar>(1)[0] = matrix.ptr<uchar>(h_j+1)[w_i];
    temp_matrix.ptr<uchar>(1)[1] = matrix.ptr<uchar>(h_j+1)[w_i+1];
    temp_matrix.ptr<uchar>(1)[2] = matrix.ptr<uchar>(h_j+1)[w_i+2];
    temp_matrix.ptr<uchar>(2)[0] = matrix.ptr<uchar>(h_j+2)[w_i];
    temp_matrix.ptr<uchar>(2)[1] = matrix.ptr<uchar>(h_j+2)[w_i+1];
    temp_matrix.ptr<uchar>(2)[2] = matrix.ptr<uchar>(h_j+2)[w_i+2];
    //if((int)matrix.ptr<uchar>(h_j)[w_i]>0){
    //  cout<<"middle:\n"<<temp_matrix<<endl;
    //  cout<<(int)matrix.ptr<uchar>(h_j)[w_i]<<"\t"<<(int)matrix.ptr<uchar>(h_j)[w_i+1]<<"\t"<<(int)matrix.ptr<uchar>(h_j)[w_i+2]<<"\t"<<(int)matrix.ptr<uchar>(h_j+1)[w_i]<<"\t"<<(int)matrix.ptr<uchar>(h_j+1)[w_i+1]<<"\t"<<(int)matrix.ptr<uchar>(h_j+1)[w_i+2]<<"\t"<<(int)matrix.ptr<uchar>(h_j+2)[w_i]<<"\t"<<(int)matrix.ptr<uchar>(h_j+2)[w_i+1]<<"\t"<<(int)matrix.ptr<uchar>(h_j+2)[w_i+2]<<"\t"<<endl;
    //  changelabel = true;
    //}
    return temp_matrix;
}

int sobel_conv2d(Mat matrix1,Mat edge_opt)
{
    int gradient = abs(matrix1.ptr<uchar>(0)[0]*edge_opt.ptr<float>(0)[0]
                  +matrix1.ptr<uchar>(0)[1]*edge_opt.ptr<float>(0)[1]
                  +matrix1.ptr<uchar>(0)[2]*edge_opt.ptr<float>(0)[2]
                  +matrix1.ptr<uchar>(1)[0]*edge_opt.ptr<float>(1)[0]
                  +matrix1.ptr<uchar>(1)[1]*edge_opt.ptr<float>(1)[1] 
                  +matrix1.ptr<uchar>(1)[2]*edge_opt.ptr<float>(1)[2] 
                  +matrix1.ptr<uchar>(2)[0]*edge_opt.ptr<float>(2)[0]
                  +matrix1.ptr<uchar>(2)[1]*edge_opt.ptr<float>(2)[1]
                  +matrix1.ptr<uchar>(2)[2]*edge_opt.ptr<float>(2)[2]);
    //if(gradient>0)
    //{
    //    cout<<matrix1<<endl;
    //    cout<<edge_opt<<endl;
    //	  cout<<"in:"<<gradient<<endl;
    //    changelabel=true;
    //}
    return gradient;
}

static Mat edge_detect(Mat im, int sobel_thresh)
{
    /*开始犯了一个低级错误,edge_opt_Gx,edge_opt_Gy里面存在-1,-2,结果我还用的uchar,傻!!!*/
    Mat edge_opt_Gx=(Mat_<float>(3,3)<<-1,0,1,-2,0,2,-1,0,1);
    Mat edge_opt_Gy=(Mat_<float>(3,3)<<-1,-2,-1,0,0,0,1,2,1);
    Size image_size;
    image_size.width = im.cols;
    image_size.height = im.rows;
    static Mat edge_img=im.clone();
    im.copyTo(edge_img);
    int max_value=0;
    int min_value=0;

    for(int w_i = 0; w_i < image_size.width-2; w_i++)
    {
       for (int h_j = 0; h_j < image_size.height-2; h_j++)
       {
           //cout<<"im:"<<im.ptr<uchar>(h_j)[w_i]<<"\t";
           /*cv::Mat M(3, 3, CV_8U);--会报错Segmentation fault (core dumped)不明白为啥非得先用多维数组初始化矩阵,这种错误一般有3个原因:1--数组访问出界;2--访问到只读内存;3--访问到已释放的变量*/
           int m[3][3] = {{0,0,0},{0,0,0},{0,0,0}};
           Mat temp_matrix=Mat(3,3,CV_8UC1,m);
           //cout<<temp_matrix<<endl;
           //cout<<"im:"<<(int)im.at<uchar>(h_j,w_i)<<"\t"<<(int)im.ptr<uchar>(h_j+1)[w_i]<<"\t"<<(int)im.ptr<uchar>(h_j+2)[w_i]<<"\t"<<endl;
           temp_matrix = get_temp_matrix(im,h_j,w_i);
           //if((int)temp_matrix.ptr<uchar>(0)[0]>0)
           //if(changelabel==true)
           //{
           //	cout<<"before:\n"<<temp_matrix<<endl;
	   //}
           Mat temp1_matrix=Mat(3,3,CV_8UC1,m);
           temp1_matrix = set_1_fun(temp_matrix);
           //if((int)temp1_matrix.ptr<uchar>(0)[0]>0)
           if(changelabel==true)
	   //{
	   //     cout<<"after:\n"<<temp1_matrix<<endl;
	   //     //changelabel=false;
	   //}
           temp_matrix.release();
           int Gx = sobel_conv2d(temp1_matrix,edge_opt_Gx);
           //if(changelabel==true){
           //		cout<<"Gx:"<<Gx<<endl;
	   //     	changelabel=false;
	   //}
           int Gy = sobel_conv2d(temp1_matrix,edge_opt_Gy);
           //if(changelabel==true){
           //		cout<<"Gy:"<<Gy<<endl;
	   //     	changelabel=false;
	   //}
           temp1_matrix.release();
           if(Gx+Gy<sobel_thresh)
           {
              //cout<<"Gx+Gy:"<<Gx+Gy<<endl;
              edge_img.ptr<uchar>(h_j+1)[w_i+1]=0;
	   }
           //cout<<"dot result:"<<a<<endl;
       }
       //cout<<"total w:"<<image_size.width<<"\ttotal h:"<<image_size.height<<endl;
    }
    cout<<"max:"<<max_value<<"\tmin:"<<min_value<<endl;
    return edge_img;
}
int main(void)
{
    vector<string> files=getFiles("../chessboard/ori/");
    //批处理
    //for (int i=0; i<files.size(); i++)
    //{
    //    Mat imageInput = imread("../chessboard/ori/"+files[i]);
    //}   
    Mat imageInput = imread("../chessboard/ori/"+files[0]);
    Size image_size;
    image_size.width = imageInput.cols;
    image_size.height = imageInput.rows;
    Mat gray_img;
    cvtColor(imageInput, gray_img, CV_RGB2GRAY);
    imwrite("gray_img.jpg",gray_img);
    Mat binary_img;
    threshold(gray_img, binary_img, 50, 255, CV_THRESH_BINARY);
    
    Mat edge_im = binary_img.clone();
    edge_im = edge_detect(binary_img,1);
    imwrite("edge_img.jpg",edge_im);
    imwrite("binary_img.jpg",binary_img);
    cout<<"finish!"<<endl;
    return 0;
}

重点:

  • 对C++变量所处存储区的认识(局部变量存于栈区,static变量存于静态存储区,new分配的变量存于堆区,malloc分配的存于自由存储区,常量存于常量存储区)
  • 对于图像(Mat类型)的像素值访问(at方式,ptr指针方式,……)
待检测图像边缘检测结果

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值