1. 程式人生 > 其它 >C/C++將切片資料列表轉換為二維陣列形式

C/C++將切片資料列表轉換為二維陣列形式

Slice2Matrix

本文件將以切片資料為例介紹讀入文字格式資料,並將一維屬性值寫為二維陣列的過程。

實際工區中的切片常常是不規則的,因此在將其轉換為二維陣列的過程中,需將切片填充為一個規則的矩形。

需要用到的檔案:

1-4 SliceData IO.md中建立的標頭檔案SliceDataIO.h與C++檔案SliceDataIO.cpp

新建標頭檔案SliceDataIO.h與C++檔案SliceDataIO.cpp,以及主函式main.cpp

1 編寫標頭檔案SliceDataMatrix.h

1.1 程式描述、呼叫、宣告、定義

/**********************************************************************

 * Copyright(C) 2018,Company All Rights Reserved   
   *
 * @file    : SliceDataMatrix.cpp                      
   *
 * @brief   :  實現切片資料向二維陣列的轉換                 
   *
 * @version : 1.0                                 
   *
 * @author  : Fan XinRan                           
   *
 * @date    : 2022/2/8 星期二                       
   *
 * Others  :                                      
   **********************************************************************/

#pragma once
#include"SliceDataIO.h"  //SliceDataIO.h中包含了需要的標準庫,全域性常量等

1.2 宣告最大、最小值結構體

此結構體用於存放最大/最小 Line/CDP的值及索引。

typedef struct MaxminResultInt{		
	int value;
	int index;
} MaxminResultInt;

1.3 宣告SliceDataMatrix類

class SliceDataMatrix{

public:
	SliceDataMatrix();		//建構函式
	~SliceDataMatrix();		//解構函式

	bool setData(SliceDataIO *datainput,int incLine,int incCDP);	// set()方法
	bool writeData(float **dataouput,const char *filenameOutput);	// 寫入方法
	float **getTimeMatrix();		//在實際應用時,通常需要的是Time和Value這兩個屬性
	float **getValueMatrix();
private:

	int _nline;				// 宣告:匯流排數
	int _ncdp;				//     總道數
	int _IncLine;			//     線取樣間隔
	int _IncCDP;			//     道取樣間隔

	int _maxLineIndex;		// 宣告: 最大線號
	int _minLineIndex;		// 		最小線號
	int _maxCDPIndex;		// 		最大道號
	int _minCDPIndex;		// 		最小道號

	int **_sliceIndexdataMatrix;	// 宣告: 1 切片號二維陣列
	int **_lineIndexMatrix;			// 		2 線號...
	int **_cdpIndexMatrix;			// 		3 道號...
	float **_Xmatrix;				// 		4 X座標...
	float **_Ymatrix;				// 		5 Y座標...
	float **_TimeMatrix;			// 		6 時間...
	float **_ValueMatrix;			// 		7 屬性值...

	bool **_flagMatrix;				// 		標識矩陣,用於標記該點是否有值

	MaxminResultInt _maxminInt(int *dataInput, int n, bool flag);	// 新建一個存放最大最小值的結構體物件

};

完整程式碼

/**********************************************************************

 * Copyright(C) 2018,Company All Rights Reserved   
   *
 * @file    : SliceDataMatrix.cpp                      
   *
 * @brief   :  實現切片資料向二維陣列的轉換                 
   *
 * @version : 1.0                                 
   *
 * @author  : Fan XinRan                           
   *
 * @date    : 2022/2/8 星期二                       
   *
 * Others  :                                      
   **********************************************************************/

#pragma once
#include"SliceDataIO.h"  //SliceDataIO.h中包含了需要的標準庫,全域性常量等

typedef struct MaxminResultInt{
	int value;
	int index;
} MaxminResultInt;


class SliceDataMatrix{

public:
	SliceDataMatrix();
	~SliceDataMatrix();

	bool setData(SliceDataIO *datainput,int incLine,int incCDP);
	bool writeData(float **dataouput,const char *filenameOutput);
	float **getTimeMatrix();
	float **getValueMatrix();
private:

	int _nline;
	int _ncdp;
	int _IncLine;
	int _IncCDP;

	int _maxLineIndex;
	int _minLineIndex;
	int _maxCDPIndex;
	int _minCDPIndex;

	int **_sliceIndexdataMatrix;
	int **_lineIndexMatrix;
	int **_cdpIndexMatrix;
	float **_Xmatrix;
	float **_Ymatrix;
	float **_TimeMatrix;
	float **_ValueMatrix;

	bool **_flagMatrix;

	MaxminResultInt _maxminInt(int *dataInput, int n, bool flag);

};

2 編寫C++檔案SliceDataMatrix.cpp

2.1 定義建構函式與解構函式

SliceDataMatrix::SliceDataMatrix(){
    
	this->_IncCDP = 0;			// 定義取樣間隔和匯流排、道數
	this->_IncLine = 0;	
	this->_ncdp = 0;	
	this->_nline = 0;	

	this->_minCDPIndex = 0;		// 定義最大||最小 線號||道號
	this->_maxCDPIndex = 0;
	this->_minLineIndex = 0;
	this->_maxLineIndex = 0;

	this->_sliceIndexdataMatrix = NULL;		// 定義slice相關的Matrix
	this->_cdpIndexMatrix = NULL;
	this->_lineIndexMatrix = NULL;
	this->_TimeMatrix = NULL;
	this->_ValueMatrix = NULL;
	this->_Xmatrix = NULL;
	this->_Ymatrix = NULL;

	this->_flagMatrix = NULL;	//   定義標識矩陣
}
// 解構函式
SliceDataMatrix::~SliceDataMatrix(){

	if(this->_sliceIndexdataMatrix!=NULL){
		free2int(_sliceIndexdataMatrix);
		this->_sliceIndexdataMatrix = NULL;
	}

	if(this->_cdpIndexMatrix!=NULL){
		free2int(_cdpIndexMatrix);
		this->_cdpIndexMatrix = NULL;
	}

	if (this->_lineIndexMatrix != NULL) {
		free2int(_lineIndexMatrix);
		this->_lineIndexMatrix = NULL;
	}

	if (this->_Xmatrix != NULL) {
		free2float(_Xmatrix);
		this->_Xmatrix = NULL;
	}

	if (this->_Ymatrix != NULL) {
		free2float(_Ymatrix);
		this->_Ymatrix = NULL;
	}

	if (this->_TimeMatrix != NULL) {
		free2float(_TimeMatrix);
		this->_TimeMatrix = NULL;
	}

	if (this->_ValueMatrix != NULL) {
		free2float(_ValueMatrix);
		this->_ValueMatrix = NULL;
	}

	if (this->_flagMatrix != NULL) {		
		free2bool(_flagMatrix);				
		this->_flagMatrix = NULL;
	}
}

2.2 定義方法函式

(1) set()方法

bool SliceDataMatrix::setData(SliceDataIO *datainput, int incLine, int incCDP){

    // 此時輸入為SliceDataIO類物件
    
	if(datainput==NULL){			// 判空
		return false;
	}

	if((incLine<0)||(incCDP<0)){	// 判定傳入的取樣間隔是否合法
		return false;
	}
												// 通過SliceDataIO類中的get()方法獲取基礎資料...
	int *slice = datainput->getSliceIndex();	// 切片號
	int *lineIndex = datainput->getLineIndex();	// 線號
	int *cdpIndex = datainput->getCDPIndex();	// 道號
	float *X = datainput->getX();				// X座標
	float *Y = datainput->getY();				// Y座標
	float *time = datainput->getTime();			// time值
	float *value = datainput->getValue();		// value值

	int nsample = datainput->getSampleNum();	// nsample取樣點

	int index_Xtemp = 0;						// 線、道號在陣列中的重新定位
	int index_Ytemp = 0;

	MaxminResultInt maxline;					// 針對切片4個角點,新建四個結構體
	MaxminResultInt maxcdp;
	MaxminResultInt minline;
	MaxminResultInt mincdp;


	maxline = this->_maxminInt(lineIndex, nsample, true);		// 計算出最大/最小的值、索引
	maxcdp = this->_maxminInt(cdpIndex, nsample, true);
	minline= this->_maxminInt(lineIndex, nsample, false);
	mincdp= this->_maxminInt(cdpIndex, nsample, false);

	this->_maxCDPIndex = maxcdp.value;		// 存為當前類物件的屬性
	this->_minCDPIndex = mincdp.value;
	this->_maxLineIndex = maxline.index;
	this->_minLineIndex = minline.index;


	this->_IncCDP = incCDP;					// 賦值
	this->_IncLine = incLine;

	this->_ncdp = (this->_maxCDPIndex - this->_minCDPIndex) / (this->_IncCDP) + 1;  // 計算線數、道數
	this->_nline = (this->_maxLineIndex-this->_minLineIndex)/ (this->_IncLine) + 1;

	// alloc2為各變數分配二維陣列
    // alloc2int、alloc2float與alloc2bool相似,均由alloc2衍生,而alloc2()返回一個void **ptr
    this->_sliceIndexdataMatrix = alloc2int(this->_ncdp,this->_nline);		
	this->_cdpIndexMatrix = alloc2int(this->_ncdp, this->_nline);
	this->_lineIndexMatrix= alloc2int(this->_ncdp, this->_nline);
	this->_Xmatrix= alloc2float(this->_ncdp, this->_nline);
	this->_Ymatrix = alloc2float(this->_ncdp, this->_nline);
	this->_TimeMatrix= alloc2float(this->_ncdp, this->_nline);
	this->_ValueMatrix= alloc2float(this->_ncdp, this->_nline);
	this->_flagMatrix = alloc2bool(this->_ncdp, this->_nline);		// flagMatrix為bool型
    

	// 初始化
	memset(this->_sliceIndexdataMatrix[0],0,(_ncdp)*(_nline)*sizeof(int));
	memset(this->_cdpIndexMatrix[0], 0, (_ncdp)*(_nline) * sizeof(int));
	memset(this->_lineIndexMatrix[0], 0, (_ncdp)*(_nline) * sizeof(int));
	memset(this->_Xmatrix[0], 0, (_ncdp)*(_nline) * sizeof(float));
	memset(this->_Ymatrix[0],0, (_ncdp)*(_nline) * sizeof(float));
	memset(this->_TimeMatrix[0], 0, (_ncdp)*(_nline) * sizeof(float));
	memset(this->_ValueMatrix[0],0, (_ncdp)*(_nline) * sizeof(float));
	memset(this->_flagMatrix[0],0, (_ncdp)*(_nline) * sizeof(bool));
	
    // 遍歷取樣點
	for(int isample = 0; isample < nsample;isample++){

        // 以左上角(cdp[0],line[0])為起點(0,0)換算相對索引
		index_Xtemp = (cdpIndex[isample]-_minCDPIndex)/ _IncCDP;	
		index_Ytemp= (lineIndex[isample] - _minLineIndex) / _IncLine;

		// 如果這個點落在劃定的矩形陣列內
        if((index_Xtemp>=0)&&(index_Xtemp<_ncdp)&&(index_Ytemp>=0)&&(index_Ytemp<_nline)){
			
            // 在相應的Matrix上填入該點資料
			this->_sliceIndexdataMatrix[index_Ytemp][index_Xtemp] = slice[isample];
			this->_cdpIndexMatrix[index_Ytemp][index_Xtemp] = cdpIndex[isample];
			this->_lineIndexMatrix[index_Ytemp][index_Xtemp] = lineIndex[isample];
			this->_Xmatrix[index_Ytemp][index_Xtemp] = X[isample];
			this->_Ymatrix[index_Ytemp][index_Xtemp] = Y[isample];
			this->_TimeMatrix[index_Ytemp][index_Xtemp] = time[isample];
			this->_ValueMatrix[index_Ytemp][index_Xtemp] = value[isample];

			this->_flagMatrix[index_Ytemp][index_Xtemp] = true;	// true--->data exist

		}//end if((index_Xtemp>=0)&&(index_Xtemp<_ncdp)&&(index_Ytemp>=0)&&(index_Ytemp<_nline))

	}//end for(int isample = 0; isample < nsample;isample++)

	return true;
}

(2) 求最大、最小座標

MaxminResultInt SliceDataMatrix::_maxminInt(int *dataInput, int n, bool flag){
    
    // 輸入為一個

	int value=dataInput[0];	
	int index=0;

	MaxminResultInt maxmin;
	
	if(flag==true){

		for(int i= 0; i<n; i++){
			if(dataInput[i] >value){
				value = dataInput[i];
				index = i;
			}//end if(dataInput[i] >= value)
		}//end for(int i= 0; i<n; i++)

    }else{

		for (int i = 0; i < n; i++) {
			if (dataInput[i] < value) {
				value = dataInput[i];
				index = i;
			}//end if(dataInput[i] >= value)
		}//end for(int i= 0; i<n; i++)

	}//end if(flag==true)

	maxmin.value = value;
	maxmin.index = index;

	return  maxmin;

}

(3) get()方法

float** SliceDataMatrix::getTimeMatrix(){
	return this->_TimeMatrix;
}

float** SliceDataMatrix::getValueMatrix(){
	return this->_ValueMatrix;
}

2.3 定義寫入函式

在這個複製切片的任務中,並未用到寫入函式,此步驟可忽略

bool SliceDataMatrix::writeData(float **dataouput, const char *filenameOutput){
	
	int nx = 0;
	int ny = 0;

	return true;
}

完整程式碼

#include "SliceDataMatrix.h"

SliceDataMatrix::SliceDataMatrix(){		// 建構函式

	this->_IncCDP = 0;		// 取樣間隔
	this->_IncLine = 0;
	this->_ncdp = 0;		// 匯流排、道數
	this->_nline = 0;

	this->_minCDPIndex = 0;		
	this->_maxCDPIndex = 0;
	this->_minLineIndex = 0;
	this->_maxLineIndex = 0;

	this->_sliceIndexdataMatrix = NULL;	// 切片屬性的二維陣列
	this->_cdpIndexMatrix = NULL;
	this->_lineIndexMatrix = NULL;
	this->_TimeMatrix = NULL;
	this->_ValueMatrix = NULL;
	this->_Xmatrix = NULL;
	this->_Ymatrix = NULL;

	this->_flagMatrix = NULL;		// 標識矩陣

}

SliceDataMatrix::~SliceDataMatrix(){		// 解構函式

	if(this->_sliceIndexdataMatrix!=NULL){
		free2int(_sliceIndexdataMatrix);
		this->_sliceIndexdataMatrix = NULL;
	}

	if(this->_cdpIndexMatrix!=NULL){
		free2int(_cdpIndexMatrix);
		this->_cdpIndexMatrix = NULL;
	}

	if (this->_lineIndexMatrix != NULL) {
		free2int(_lineIndexMatrix);
		this->_lineIndexMatrix = NULL;
	}

	if (this->_Xmatrix != NULL) {
		free2float(_Xmatrix);
		this->_Xmatrix = NULL;
	}

	if (this->_Ymatrix != NULL) {
		free2float(_Ymatrix);
		this->_Ymatrix = NULL;
	}

	if (this->_TimeMatrix != NULL) {
		free2float(_TimeMatrix);
		this->_TimeMatrix = NULL;
	}

	if (this->_ValueMatrix != NULL) {
		free2float(_ValueMatrix);
		this->_ValueMatrix = NULL;
	}

	if (this->_flagMatrix != NULL) {
		free2bool(_flagMatrix);
		this->_flagMatrix = NULL;
	}
}

// set method
bool SliceDataMatrix::setData(SliceDataIO *datainput, int incLine, int incCDP){


	if(datainput==NULL){		// 判空
		return false;
	}

	if((incLine<0)||(incCDP<0)){		// 判定輸入的取樣間隔是否合法
		return false;
	}

	int *slice = datainput->getSliceIndex();		// 通過SliceDataIO類中的get()方法獲取各類屬性值
	int *lineIndex = datainput->getLineIndex();
	int *cdpIndex = datainput->getCDPIndex();
	float *X = datainput->getX();
	float *Y = datainput->getY();
	float *time = datainput->getTime();
	float *value = datainput->getValue();

	int nsample = datainput->getSampleNum();

	int index_Xtemp = 0;				// 線、道號在陣列中的重新定位
	int index_Ytemp = 0;

	MaxminResultInt maxline;			// 針對切片的4個角點,新建四個結構體變數
	MaxminResultInt maxcdp;
	MaxminResultInt minline;
	MaxminResultInt mincdp;


	maxline = this->_maxminInt(lineIndex, nsample, true);	// 計算出最大/最小的值、索引
	maxcdp = this->_maxminInt(cdpIndex, nsample, true);
	minline= this->_maxminInt(lineIndex, nsample, false);
	mincdp= this->_maxminInt(cdpIndex, nsample, false);

	this->_maxCDPIndex = maxcdp.value;		//存到當前類物件
	this->_minCDPIndex = mincdp.value;
	this->_maxLineIndex = maxline.value;
	this->_minLineIndex = minline.value;


	this->_IncCDP = incCDP;
	this->_IncLine = incLine;

	this->_ncdp = (this->_maxCDPIndex - this->_minCDPIndex) / (this->_IncCDP) + 1;		// 計算匯流排、道數
	this->_nline = (this->_maxLineIndex-this->_minLineIndex)/ (this->_IncLine) + 1;

	// alloc2為各屬性分配二維空間
	this->_sliceIndexdataMatrix = alloc2int(this->_ncdp,this->_nline);
	this->_cdpIndexMatrix = alloc2int(this->_ncdp, this->_nline);
	this->_lineIndexMatrix= alloc2int(this->_ncdp, this->_nline);
	this->_Xmatrix= alloc2float(this->_ncdp, this->_nline);
	this->_Ymatrix = alloc2float(this->_ncdp, this->_nline);
	this->_TimeMatrix= alloc2float(this->_ncdp, this->_nline);
	this->_ValueMatrix= alloc2float(this->_ncdp, this->_nline);
	this->_flagMatrix = alloc2bool(this->_ncdp, this->_nline);

	// 初始化
	memset(this->_sliceIndexdataMatrix[0],0,(_ncdp)*(_nline)*sizeof(int));
	memset(this->_cdpIndexMatrix[0], 0, (_ncdp)*(_nline) * sizeof(int));
	memset(this->_lineIndexMatrix[0], 0, (_ncdp)*(_nline) * sizeof(int));
	memset(this->_Xmatrix[0], 0, (_ncdp)*(_nline) * sizeof(float));
	memset(this->_Ymatrix[0],0, (_ncdp)*(_nline) * sizeof(float));
	memset(this->_TimeMatrix[0], 0, (_ncdp)*(_nline) * sizeof(float));
	memset(this->_ValueMatrix[0],0, (_ncdp)*(_nline) * sizeof(float));
	memset(this->_flagMatrix[0],0, (_ncdp)*(_nline) * sizeof(bool));

	for(int isample = 0; isample < nsample;isample++){

		index_Xtemp = (cdpIndex[isample]-_minCDPIndex)/ _IncCDP;		// 以左上角為(0,0)轉換後的索引
		index_Ytemp= (lineIndex[isample] - _minLineIndex) / _IncLine;

		if((index_Xtemp>=0)&&(index_Xtemp<_ncdp)&&(index_Ytemp>=0)&&(index_Ytemp<_nline)){		// 如果該點落在矩形陣列範圍內

			this->_sliceIndexdataMatrix[index_Ytemp][index_Xtemp] = slice[isample];		// 相應的Matrix中填入該點資料
			this->_cdpIndexMatrix[index_Ytemp][index_Xtemp] = cdpIndex[isample];
			this->_lineIndexMatrix[index_Ytemp][index_Xtemp] = lineIndex[isample];
			this->_Xmatrix[index_Ytemp][index_Xtemp] = X[isample];
			this->_Ymatrix[index_Ytemp][index_Xtemp] = Y[isample];
			this->_TimeMatrix[index_Ytemp][index_Xtemp] = time[isample];
			this->_ValueMatrix[index_Ytemp][index_Xtemp] = value[isample];

			this->_flagMatrix[index_Ytemp][index_Xtemp] = true;		// true--->data exist

		}//end if((index_Xtemp>=0)&&(index_Xtemp<_ncdp)&&(index_Ytemp>=0)&&(index_Ytemp<_nline))


	}//end for(int isample = 0; isample < nsample;isample++)


	return true;
}
// 計算切片角點的最大、最小  Line/CDP
MaxminResultInt SliceDataMatrix::_maxminInt(int *dataInput, int n, bool flag){

	int value=dataInput[0];
	int index=0;

	MaxminResultInt maxmin;
	

	if(flag==true){						// flag=true---> max value/index

		for(int i= 0; i<n; i++){
			if(dataInput[i] >value){
				value = dataInput[i];
				index = i;
			}//end if(dataInput[i] >= value)
		}//end for(int i= 0; i<n; i++)

    }else{								// else---> min value/index

		for (int i = 0; i < n; i++) {
			if (dataInput[i] < value) {
				value = dataInput[i];
				index = i;
			}//end if(dataInput[i] >= value)
		}//end for(int i= 0; i<n; i++)

	}//end if(flag==true)

	maxmin.value = value;
	maxmin.index = index;

	return  maxmin;

}

// -------------------get()方法------------------
float** SliceDataMatrix::getTimeMatrix(){
	return this->_TimeMatrix;
}

float** SliceDataMatrix::getValueMatrix(){
	return this->_ValueMatrix;
}

bool** SliceDataMatrix::getFlagMatrix(){
	return this->_flagMatrix;
}

int SliceDataMatrix::getNumLine(){
	return this->_nline;
}

int SliceDataMatrix::getNumCdp(){
	return this->_ncdp;
}

// write data to outputfile
bool SliceDataMatrix::writeData(float **dataouput, const char *filenameOutput){
	
	int nx = 0;
	int ny = 0;

	return true;
}

3 編寫主函式main.cpp

#include"SliceDataIO.h"

int main(int argc, char *agrv) {
	
	SliceDataIO *slice = readSliceData("W11.slice");	// 讀入切片資料
	
	writeSliceData("W11copy.slice", slice);		// 寫入切片資料

	delete slice;								// 釋放分配給類物件slice的動態記憶體空間
	
	return 1;

}

執行主函式之後,程式將讀入W11.slice,並將切片資料寫至W11copy.slice中。

delete:用以釋放動態分配的記憶體空間,要求被釋放的指標必須是指向動態分配的記憶體空間。

附錄

void*

void被翻譯為“無型別”,相應的void*為“無型別指標”。

  • 當函式不需要返回值時,必須使用void限定,如:void func(int a,char *b)
  • 當函式不允許接受引數時,同樣必須使用void加以限定,如:int func(void)

void指標的使用規則:

1.void指標可以指向任意型別的資料,即可以用任意型別的指標對void指標賦值。如:

int *a;
void *p;
p = a;		// int * 型的a可以直接賦值給void * 型的p

2.如果要將void指標p賦值給其他型別的指標,則需要強制型別轉換,如:a = (int *)p

在上文中提及的alloc2()函式,其定義為:

void **alloc2(size_t n1, size_t n2, size_t size)
{
	size_t i2;
	void **p;

    ...
        
	return p;		// p是一個void ** 型的指標變數
}

alloc2int()函式的定義為:

int **alloc2int(size_t n1, size_t n2)
{
	return (int**)alloc2(n1, n2, sizeof(int));		// 使用(int **)強制型別轉換
}

同理,可以依據此規則寫出alloc2bool()

bool **alloc2bool(size_t n1, size_t n2)
{
	return (bool**)alloc2(n1, n2, sizeof(bool));	// 使用(bool **)強制型別轉換
}