프로그래밍을 하다 보면 파일 또는 폴더의 path 를 자주 다루게 됩니다.

 

아래 포스팅에서는 Autohotkey 에서 SplitPath 함수를 사용해서 file path 를 구분하는 방법에 대해 소개한 적이 있는데~

  

2013/11/14 - [programming language/Autohotkey] - Autohotkey SplitPath 를 이용하여 폴더, 파일명, 확장자, 드라이브 구분하기

 

오늘은 C++ 를 사용한 file path 구분 방법에 대해 소개하려 합니다.

 

코드는 굉장히 간단한데요~

 

위 코드와 같이 stringstream 과 getline 함수를 사용하고~

 

C:/Windows/System32/vbscript.dll 라는 path 를 '/' 에 따라 나눠보면~

 

다음과 같은 결과가 나옵니다. 다음 그림에서 보는 바와 같이 C:, Windows, System32, vbscript.dll 로 구분되는 것을 확인 할 수 있습니다.



이전 포스팅들에서도 소개한 Cartesian Product 를 C++ 를 사용하여 구성하는 방법에 대해 소개해 드리려 합니다.

  

2013/08/18 - [programming language/MATLAB] - MATLAB 모든 경우의 수 뽑기 Cartesian Product


2013/08/18 - [programming language/powershell] - Powershell 경우의 수 조합 다 구하기(Cartesian Product)

 

아래 주소를 보니 Cartesian Product 와 관련하여 좋은 예제들이 많이 있더군요.

 

http://stackoverflow.com/questions/5279051/how-can-i-create-cartesian-product-of-vector-of-vectors

 

그 중에서 저는 가장 간단해 보이는 anumi 라는 분의 코드를 가져다 사용했습니다.

 

물론 template 형태로 약간 수정만 했습니다.

 

코드를 보다 보니 vector 의 swap 함수를 사용했더군요. Swap 함수는 말 그대로 벡터간에 값을 교환하는 겁니다.

 

Vector 의 Swap 에 대한 설명은 아래 주소 참조바랍니다.

 

http://www.cplusplus.com/reference/vector/vector/swap/

 

요즘 C++ STL 은 정말 좋은 것 같습니다.

 

결과적으로 작성된 cartesian.h 파일은 아래와 같습니다. 

  

cartesian.h


#include <vector>

 

using namespace std;

 

template<typename T>

vector<vector<T>> cart_product (const vector<vector<T>>& v) {

vector<vector<T>> s = {{}};

for (auto& u : v) {

vector<vector<T>> r;

for (auto& x : s) {

for (auto y : u) {

r.push_back(x);

r.back().push_back(y);

}

}

s.swap(r);

}

return s;

}

 

테스트를 위한 main.cpp 파일은 아래와 같이 작성했습니다.

 

#include <iostream>

#include "cartesian.h"

 

using namespace std;

 

int main()

{

    vector<vector<int>> test{{1,2, 56 ,3}, {4,5,6}, {12,32,56}};

    vector<vector<int>> cartprodResult; // result

 

    cartprodResult=cart_product(test); // Cartesian Product

 

    int cnt=0;

 

    for (auto& x : cartprodResult)

    {

        ++cnt;

        cout << cnt << ": \t";

 

        for (auto y : x)

        {

            cout << y << "\t";

        }

        cout << endl;

    }

 

    return 0;

}

 

Cartesian product 를 수행해보면 아래와 같이 결과가 나오는 것을 확인 할 수 있습니다. 간단하죠~ 현재 컴파일러는 gcc (tdm64-2) 4.8.1 이고~ C++11 Compiler Flag를 On 했습니다.



C 코딩 시 동적 배열은 malloc() 또는 calloc() 함수를 주로 사용한다.

 

보통 malloc() 함수는 다음과 같이 사용한다.

 





Int * Arr; // 배열에 대한 포인터 선언

 

Arr=(int *)malloc(X * sizeof(int)); // malloc() 함수 이용 동적 배열 선언, X 는 배열의 크기 , Arr[0], Arr[1]… 등으로 각 인자의 값에 접근

 

free(Arr); // 동적 배열 free


 

 

calloc() 함수는 다음과 같이 사용한다.

 

Int * Arr; // 배열에 대한 포인터 선언

 

Arr=(int *)calloc(X , sizeof(int)); // calloc() 함수 이용 동적 배열 선언, X 는 배열의 크기 , Arr[0], Arr[1]… 등으로 각 인자의 값에 접근

 

free(Arr); // 동적 배열 free 

 

malloc(), calloc() 함수의 차이는 calloc() 함수의 경우 초기값을 0으로 셋팅 한다는 거다.

 

두 함수는 stdlib.h 안에 포함되어 있으므로 두 함수를 이용할 때는 파일의 윗줄에 #include <stdlib.h> 를 해 줘야 한다.

 

동적 배열을 이용한 이차원 배열은 다음과 같다.

 

int i, m, n ; // m 행 n 열 배열을 잡기 위한 변수

double** matrix; // double 형 2차원 동적 배열을 잡기 위한 포인터

matrix=( double **)calloc(m, sizeof(double *)); // m 행을 동적 배열로 잡음

 

for (i=0;i<m; i++) // m 행만큼 루프를 돌면서 각 행 마다 n 열씩 동적 배열을 잡음

{

       matrix[i]=( double *)calloc(n,sizeof(double));

}


 

matrix[0] [0], matrix[0] [1] … 과 같이 2차원 배열의 각 인자에 접근

 

 

동적 배열을 해제 할 때는 다음과 같이 한다.

 

for (i=0;i<m;i++)

{

    free(matrix [i]);

}

free(matrix);


 

이상이 C 코딩 시의 2차원 동적 배열 설정 및 해제 방법 이다.

 



그런데 저런 2차원 배열을 여러 개 쓸 때는 매번 저렇게 설정하는 게 짜증 날 것이다.

 

따라서 동적 배열의 설정 및 해제를 함수로 만들어서 사용한다.

 

다음은 Numerical Recipe in C 라는 책에 소개된 동적 메모리 할당 및 해제 하는 함수들이다.

 

double * get_dvector_space(int m) // 1차원 double 형 동적 메모리 할당 , m 행

{

    double* cm;

    cm=(double *)calloc(m,sizeof(double));

    return cm;

}

 

void free_dvector(double* cm) // 1차원 double 형 동적 메모리 해제

{

    free(cm);

}

 

double** get_dmatrix_space(int m,int n) // 2차원 double 형 동적 메모리 할당 , m 행 n 열

{

    int i;

    double** cm;

    cm=(double **)calloc(m,sizeof(double *));

    

    for (i=0;i<m;i++)

    {

        cm[i]=(double *)calloc(n,sizeof(double));

    }

    return cm;

}

 

void free_dmatrix(double** cm, int m) // 2차원 double 형 동적 메모리 해제

{

    int i;

    

    for (i=0;i<m;i++)

    {

        free(cm[i]);

    }

    

    free(cm);

 



Int 형 동적 메모리 할당 및 해제 함수는 저 위의 함수에서 double 만 int 로 바꾸고 함수이름도 dvector 부분을 ivector 등으로 적절히 바꿔서 만들어 주면 될 것이다.


다른 형으로 바꿀 때도 마찬가지다.

 
위 함수를 이용하는 방법은 다음과 같다.

 

double * arr;

arr = get_dvector_space(10); // 1차원 배열 선언

free_dvector(arr); // 해제

  

double ** matrix;

matrix = get_dmatrix_space (10,10); // 2차원 배열 선언

free_dmatrix (matrix, 10); // 해제


 

근데 C 언어에서는 각 변수 타입 마다 저 위와 같은 함수들을 다 만들어줘야 한다. Double 일 때 함수 int일 때 함수 float 일 때 함수 …등... 다 만들어 줘야 한다. ㅡㅡ;

 



이렇게 만들기도 참 귀찮은 일이다.

 

따라서 C++ 로 갈아타서 template 을 사용하자.

 

다음과 같이 template 함수로 선언 할 수 있다.

 

// template_buffer.h 파일

 

#include <stdlib.h>

 

template<typename T>

 

T* get_vector_space(int m)

{

    T* cm;

    cm=(T *)calloc(m,sizeof(T));

    return cm;

}

 

 

template<typename T>

void free_vector(T* cm)

{

    free(cm);

}

 

template<typename T>

T** get_matrix_space(int m,int n)

{

    int i;

    T** cm;

    cm=(T **)calloc(m,sizeof(T *));

    

    for (i=0;i<m;i++)

    {

        cm[i]=(T *)calloc(n,sizeof(T));

    }

    return cm;

}

 

template<typename T>

void free_matrix(T** cm, int m)

{

    int i;

    

    for (i=0;i<m;i++)

    {

        free(cm[i]);

    }

    

    free(cm);

}

 




Template 함수에 대한 내용은 이전 포스팅을 참조하자.

2011/03/06 - [컴퓨터일반] - [C++] template
 



위 함수들을 이용한 간단한 예제 코드는 다음과 같다.

 

// Vector_test.cpp

 

 

#include <stdio.h>

#include "template_buffer.h"

 

 

int main(int argc, char **argv)

{    

    int n, i;

      

    

    double *double_vector, **double_matrix;

    int * int_vector, **int_matrix;    

    

    double_vector = get_vector_space<double>(2);     // double 형 1차원 배열

    int_vector = get_vector_space<int>(2); // int 형 1차원 배열

    

    double_matrix = get_matrix_space<double>(2, 3);     // double 형 다차원 배열, 2 x 3

    int_matrix = get_matrix_space<int>(2, 3);          // int 형 다차원 배열, 2 x 3

        

    for (n=0;n<2;n++)

    {

        double_vector[n]=n*3.1;  // 걍 곱하기

        int_vector[n]=n*3;          // 걍 곱하기

        

        

        for (i=0;i<3;i++)

        {

            double_matrix[n][i]=n*i*3.1;   // 걍 곱하기

            int_matrix[n][i]=n*i*3;             // 걍 곱하기

     }

    }    

                

        

    // Buffer 입력된 값 확인

    

    for (n=0;n<2;n++)

    {

        printf("vector %g    %d\n",double_vector[n],int_vector[n]);

        

        for (i=0;i<3;i++)

        {            

            printf("Matrix %g    %d\n",double_matrix[n][i],int_matrix[n][i]);                    

     }

    }        

                

    free_vector(double_vector); // double vector 해제

    free_vector(int_vector); // int vector 해제

      

    

    free_matrix(double_matrix,2); // double matrix 해제

    free_matrix(int_matrix,2); // int matrix 해제

            

    return 0;

}

 




위 코드를 Geany 에서 컴파일 및 실행 하면 다음과 같은 결과가 나온다

 

 

 

C 동적 메모리 할당부터 쭉 어케 저케 오다 보니 위와 같은 C++ template까지 설명을 했다.

 



 

참고로 … C++ 에서 동적 배열 생성시에는 malloc(), calloc() 보다는 new 라는 키워드를 이용한다.

 

또한 벡터를 저렇게 template 을 만들면서 까지 쓸 필요가 없다.

C++ STL (Standard Template Library) 에 <
vector > 라는 헤더 파일이 있으니 참조하기 바란다.


cumsum() 함수를 이용하면 vector 또는 matrix 에 대한 누적 합을 아주 쉽게 구할 수가 있다.

 

사용법은 다음과 같으며, 행 또는 열 별로 이전 값과 누적이 되는 것을 확인 할 수 있다.

 




 

cumprod() 함수는 누적 곱을 할 때 이용한다.

 

 

cumtrapz() 함수는 누적 사다리꼴 수치 적분을 할 때 이용한다.

 

 

위 결과에서 trapz() 함수를 이용한 것과 cumtrapz() 함수의 마지막 값이 같음을 알 수 있다.


+ Recent posts