2012. 11. 30. 10:48

SafeInt

http://vsts2010.net/530


C++ AMP

http://vsts2010.net/591


류광의 C++0x 이야기

http://occamsrazr.net/tt/tag/C++0x


최흥배의 C++11 슬라이드

http://www.slideshare.net/OnGameServer/boost-c11


김학규의 Elements of Modern C++ style

http://www.lameproof.com/844613


C++ rvalue 레퍼런스

http://itguru.tistory.com/189



multiplatform network programming : asio

multiplatform gpgpu programming : amp


Posted by Нуеоп

보통 < operator를 이용한다. x라는 데이터가 set에 있는지 없는지 검사를 다음과 같이 한다.

!(x<y) && !(y<x)


그런데 x가 edge를 나타내는 등, 구조체인 경우, less operator를 지정할 수 있다.


typedef struct Edge

{

int v1, v2, w;

bool operator <(const Edge &rhs) const{

bool b = (v1 < rhs.v1 || v2 < rhs.v2);

return (b);

}

} edge;


이렇게 하면 (3, 7) 과 (7, 3)을 비교하는 과정에서 문제가 생긴다.


http://stackoverflow.com/questions/13548472/using-stdset-find-with-struct-data


typedef struct Edge

{

int v1, v2, w;

bool operator <(const Edge &rhs) const{

bool b = v1 < rhs.v1 || (v1 == rhs.v1 && v2 < rhs.v2);

return (b);

}

} edge;


위와 같이 검사해야 제대로 작동한다.


추가로 less와 greater는 다음과 같이 직접 구현할 수 있다. visual studio 2012부터는 less만 기본으로 제공하고 greater등은 제공하지 않는것 같다.


template <class T>

struct _less

{

bool operator()(const T& _Left, const T& _Right) const

{

return (_Left < _Right);

}

};


template <class T>

struct _greater

{

bool operator()(const T& _Left, const T& _Right) const

{

return (_Left > _Right);

}

};



각 컨테이너에서 다음과 같이 선언하여, comparator를 지정할 수 있다.


priority_queue<edge, vector<edge>, _greater<edge> > pq;

set<edge, _less<edge> > s;



별도로 comparator를 지정하지 않으면, less가 default로 지정된다.


priority_queue<edge, vector<edge> > pq;

set<edge > s;






Posted by Нуеоп
2012. 10. 4. 15:50
Posted by Нуеоп

기본적으로 Visual studio 2010을 기준으로 설명하되, 소스코드는 gcc에서도 문제없이 작동한다.


SSE2를 사용하기 위해서는 [Project properties]에서 C/C++의 Code Generation 부분에서 

Enable Enhanced Instruction Set을 /SSE2로 세팅한다. 


그리고 다음 헤더 파일을 추가한다.

#include <xmmintrin.h>



행렬의 구조체는

typedef struct _Matrix

{

int row, col;

float **matrix;

} Matrix;

와 같이 만든다. row와 col은 각각 행과 열의 크기(길이)를 뜻한다.


SSE2를 사용할 때는 기본적으로 float 4개를 한번에 연산하는 것을 목표로 한다.

(double같은경우 2개를 한번에 연산)





행렬의 실제 값이 들어갈 2차원 배열은, malloc()가 아닌 _aligned_malloc()를 이용해야 한다.

2차원 배열을 동적으로 만들때, 열 배열을 가리킬 행 배열은 malloc()로 할당해도 상관없지만,

열 배열은 반드시 _aligned_malloc()로 할당해야 하는데, 이유는 최소한 4개의 float공간이 

물리적으로 연속적으로 할당받음이 보장되어야 하기 때문이다.


malloc()로 연속적으로 할당해도, 가상메모리상에서만 연속일뿐, 실제로는 연속적이지 않다.

_aligned_malloc()에서 첫번째 인자는, malloc()에서의 첫번째 인자와 같은 의미로 사용하면 된다.

할당받을 배열의 길이를 첫번째 인자로 넣어준다.

그리고 _aligned_malloc()의 두번째 인자는, aligned되어야 할 크기를 넣어줘야 한다.

즉, 반드시 연속적으로 할당해야할 크기를 말한다.

float 4개를 연속해서 받아야 하기 때문에, sizeof(float) * 4를 두번째 인자로 넣어준다. (즉, 16)


float **make2dArray(int rows, int cols)

{

float **x = NULL;

int height = cols, width = rows;

x = (float **)malloc(height*sizeof(float*));

for(int i=0; i<height; i++){

x[i] = (float *)_aligned_malloc(((width*sizeof(float)+15)>>4)<<4, 16);

}


return x;

}



해제 역시 _aligned_free()로 해제한다.


void delete2dArray(float **arr, int rows, int cols)

{

if( arr != NULL ){

for(int i=0; i<cols; i++){

_aligned_free(arr[i]);

}

free(arr);

}

arr = NULL;

}




다음과 같은 함수가 있으면 테스트하기 편하다.


void initRandom(Matrix& m)

{

for(int i=0; i<m.col; i++){

for(int j=0; j<m.row; j++){

m.matrix[i][j] = (float)(rand()%4);

}

}

}

void initZero(Matrix& m)

{

for(int i=0; i<m.col; i++){

for(int j=0; j<m.row; j++){

m.matrix[i][j] = (float)(0.0f);

}

}

}

bool makeMatrix(Matrix& m, int col, int row)

{

m.matrix = make2dArray(row, col);

m.col = col;

m.row = row;

return true;

}

bool deleteMatrix(Matrix& m)

{

delete2dArray(m.matrix, m.row, m.col);

m.col = 0;

m.row = 0;

return true;

}



SSE2를 사용하지 않고, 두 행렬 m1, m2를 곱하려면 다음과 같이 구현하면 된다.


bool Multiply(Matrix& m1, Matrix& m2, Matrix& res)

{

bool bRet = false;

do

{

if( m1.row != m2.col ) break;

if( m1.col != res.col ) break;

if( m2.row != res.row ) break;


for(int i=0; i<m1.col; i++){

for(int j=0; j<m2.row; j++){

float e = 0.0f;

for(int k=0; k<m1.row; k++){

e += m1.matrix[i][k] * m2.matrix[k][j];

}

res.matrix[i][j] = e;

}

}


bRet = true;

} while(0);


return bRet;

}




SSE2를 이용한 행렬 곱 함수이다.


bool MultiplySSE(Matrix& m1, Matrix& m2, Matrix& res)

{

if( m1.row != m2.col ) break;

if( m1.col != res.col ) break;

if( m2.row != res.row ) break;


initZero(res);


for(int i=0; i<m1.col; i++) {

for(int j=0; j<m1.row; j++) {

int k = 0;

int n = (m2.row - (m2.row % 4))/4;

__m128 sse_m1 = _mm_set1_ps(m1.matrix[i][j]);

while( n --> 0 ){

__m128 *sse_mR = (__m128 *)(res.matrix[i]+k);

__m128 *sse_m2 = (__m128 *)(m2.matrix[j]+k);

*sse_mR = _mm_add_ps(*sse_mR, _mm_mul_ps(sse_m1, *sse_m2));

k += 4;

}

switch( m2.row - k ) {

case 3: res.matrix[i][k] += m1.matrix[i][j] * m2.matrix[j][k]; k++;

case 2: res.matrix[i][k] += m1.matrix[i][j] * m2.matrix[j][k]; k++;

case 1: res.matrix[i][k] += m1.matrix[i][j] * m2.matrix[j][k]; k++;

}

}

}

}


4의 배수만큼은 sse로 계산하고, 나머지 부분은 그냥 평범하게 계산하였다.

여기서 순서가 중요하다.

열의 크기가 23인 행렬을 계산할 경우, 4개의 float를 한번에 5번 sse로 계산한뒤, 나머지 3개를 계산하면 문제없다. 하지만, 먼저 3개를 계산하고나서, 5번의 sse연산을 할 경우 문제가 된다.

이유는 열 벡터를 0번째부터 aligned되게 할당하였기 때문이다.

즉, _aligned_malloc( 23, 4*sizeof(float) )으로 할당한 경우, 메모리는

[3][4][4][4][4][4] 가 아니라

[4][4][4][4][4][3] 처럼 배치된다.

따라서 remain 3은 맨 마지막에 고려해야 한다.



main()에서는 다음과 같이 테스트하였다.


int main(int argc, char *argv[]){

,,, 생략 ,,,


makeMatrix(m1, i, j);

makeMatrix(m2, j, k);

makeMatrix(res1, m1.col, m2.row);

makeMatrix(res2, m1.col, m2.row);


initRandom(m1);

initRandom(m2);


Multiply(m1, m2, res1);

MultiplySSE(m1, m2, res2);


,,, 생략 ,,,

}





Posted by Нуеоп

bool Multiply2(Matrix& m1, Matrix& m2, Matrix& res)

{

bool bRet = false;

do

{

if( m1.row != m2.col ) break;

if( m1.col != res.col ) break;

if( m2.row != res.row ) break;


initZero(res);


for(int i=0; i<m1.col; i++){

for(int j=0; j<m1.row; j++){

for(int k=0; k<m2.row;){

int n = m2.row - k;

switch( n % 4 ) {

case 0: res.matrix[i][k] += m1.matrix[i][j] * m2.matrix[j][k]; k++;

case 3: res.matrix[i][k] += m1.matrix[i][j] * m2.matrix[j][k]; k++;

case 2: res.matrix[i][k] += m1.matrix[i][j] * m2.matrix[j][k]; k++;

case 1: res.matrix[i][k] += m1.matrix[i][j] * m2.matrix[j][k]; k++;

}

}

}

}


bRet = true;

} while(0);


return bRet;

}













#include <stdio.h>

#include <stdlib.h>


typedef struct _Matrix

{

int row, col;

float **matrix;

} Matrix;


typedef struct _Point

{

int x, y;

} Point;


typedef struct _Rect

{

Point st, ed;

} Rect;


bool mult(Matrix& m1, Rect& r1, Matrix& m2, Rect& r2, Matrix& res, Rect& r3)

{

bool bRet = false;

do

{

int col1 = r1.ed.y - r1.st.y;

int row1 = r1.ed.x - r1.st.x;

int col2 = r2.ed.y - r2.st.y;

int row2 = r2.ed.x - r2.st.x;

int col3 = r3.ed.y - r3.st.y;

int row3 = r3.ed.x - r3.st.x;

if( row1 != col2 ) break;

if( col1 != col3 ) break;

if( row2 != row3 ) break;

if( col1 < 0 || row1 < 0 || col2 < 0 || row2 < 0 ) break;

if( col1 != col3 || row2 != row3 ) break;


for(int i=0; i<col1; i++){

for(int j=0; j<row2; j++){

float e = 0.0f;

for(int k=0; k<row1; k++){

e += m1.matrix[r1.st.y+i][r1.st.x+k] * m2.matrix[r2.st.y+k][r2.st.x+j];

}

res.matrix[r3.st.y+i][r3.st.x+j];

}

}


bRet = true;

} while(0);


return bRet;

}


bool add(Matrix& m1, Rect& r1, Matrix& m2, Rect& r2, Matrix& res, Rect& r3)

{

bool bRet = false;

do

{

int col1 = r1.ed.y - r1.st.y;

int row1 = r1.ed.x - r1.st.x;

int col2 = r2.ed.y - r2.st.y;

int row2 = r2.ed.x - r2.st.x;

int col3 = r3.ed.y - r3.st.y;

int row3 = r3.ed.x - r3.st.x;

if( row1 != row2 || row1 != row3 ) break;

if( col1 != col2 || col1 != col3 ) break;

if( col1 < 0 || row1 < 0 || col2 < 0 || row2 < 0 ) break;

if( col1 != col3 || row2 != row3 ) break;


for(int i=0; i<col1; i++){

for(int j=0; j<row1; j++){

res.matrix[r3.st.y+i][r3.st.x+j] = m1.matrix[r1.st.y+i][r1.st.x+j] + m2.matrix[r2.st.y+i][r2.st.x+j];

}

}


bRet = true;

} while(0);


return bRet;

}


bool sub(Matrix& m1, Rect& r1, Matrix& m2, Rect& r2, Matrix& res, Rect& r3)

{

bool bRet = false;

do

{

int col1 = r1.ed.y - r1.st.y;

int row1 = r1.ed.x - r1.st.x;

int col2 = r2.ed.y - r2.st.y;

int row2 = r2.ed.x - r2.st.x;

int col3 = r3.ed.y - r3.st.y;

int row3 = r3.ed.x - r3.st.x;

if( row1 != row2 || row1 != row3 ) break;

if( col1 != col2 || col1 != col3 ) break;

if( col1 < 0 || row1 < 0 || col2 < 0 || row2 < 0 ) break;

if( col1 != col3 || row2 != row3 ) break;


for(int i=0; i<col1; i++){

for(int j=0; j<row1; j++){

res.matrix[r3.st.y+i][r3.st.x+j] = m1.matrix[r1.st.y+i][r1.st.x+j] - m2.matrix[r2.st.y+i][r2.st.x+j];

}

}


bRet = true;

} while(0);


return bRet;

}


float **make2dArray(int rows, int cols)

{

float **x = NULL;

int height = cols, width = rows;

x = (float **)calloc(height, sizeof(float*));

x[0] = (float *)calloc(width*height, sizeof(float));

for(int i=1; i<height; i++)

x[i] = x[i-1]+width;

return x;

}


void delete2dArray(float **arr)

{

if( arr != NULL ){

if( arr[0] != NULL )

free(arr[0]);

free(arr);

}

arr = NULL;

}


void initRandom(Matrix& m)

{

for(int i=0; i<m.col; i++){

for(int j=0; j<m.row; j++){

m.matrix[i][j] = (float)(rand()%4);

}

}

}


void initZero(Matrix& m)

{

for(int i=0; i<m.col; i++){

for(int j=0; j<m.row; j++){

m.matrix[i][j] = (float)(0.0f);

}

}

}


bool Multiply(Matrix& m1, Matrix& m2, Matrix& res)

{

bool bRet = false;

do

{

if( m1.row != m2.col ) break;

if( m1.col != res.col ) break;

if( m2.row != res.row ) break;


for(int i=0; i<m1.col; i++){

for(int j=0; j<m2.row; j++){

float e = 0.0f;

for(int k=0; k<m1.row; k++){

e += m1.matrix[i][k] * m2.matrix[k][j];

}

res.matrix[i][j] = e;

}

}


bRet = true;

} while(0);


return bRet;

}


bool Multiply2(Matrix& m1, Matrix& m2, Matrix& res)

{

bool bRet = false;

do

{

if( m1.row != m2.col ) break;

if( m1.col != res.col ) break;

if( m2.row != res.row ) break;


initZero(res);


for(int i=0; i<m1.col; i++)

{

for(int j=0; j<m1.row; j++)

{

int k = 0;

int n = (m2.row-1)/4; 

switch( m2.row % 4 ) {

case 0: do{ res.matrix[i][k] += m1.matrix[i][j] * m2.matrix[j][k]; k++;

case 3: res.matrix[i][k] += m1.matrix[i][j] * m2.matrix[j][k]; k++;

case 2: res.matrix[i][k] += m1.matrix[i][j] * m2.matrix[j][k]; k++;

case 1: res.matrix[i][k] += m1.matrix[i][j] * m2.matrix[j][k]; k++;

}while( n-- > 0);

}

}


//for(int j=0; j<m1.row; j++)

//{

// int k = 0;

// switch( m2.row % 4 ) {

// case 0: res.matrix[i][k] += m1.matrix[i][j] * m2.matrix[j][k]; k++;

// case 3: res.matrix[i][k] += m1.matrix[i][j] * m2.matrix[j][k]; k++;

// case 2: res.matrix[i][k] += m1.matrix[i][j] * m2.matrix[j][k]; k++;

// case 1: res.matrix[i][k] += m1.matrix[i][j] * m2.matrix[j][k]; k++;

// }

// int n = (m2.row - k)/4;

// while( n --> 0 )

// {

// res.matrix[i][k] += m1.matrix[i][j] * m2.matrix[j][k];

// res.matrix[i][k+1] += m1.matrix[i][j] * m2.matrix[j][k+1];

// res.matrix[i][k+2] += m1.matrix[i][j] * m2.matrix[j][k+2];

// res.matrix[i][k+3] += m1.matrix[i][j] * m2.matrix[j][k+3];

// k += 4;

// }

//}

}


bRet = true;

} while(0);


return bRet;

}


bool printMatrix(Matrix& m)

{

bool bRet = false;

do

{

for(int i=0; i<m.col; i++){

for(int j=0; j<m.row; j++){

printf("%7.1f ",m.matrix[i][j]);

}printf("\n");

}printf("\n");


bRet = true;

} while(0);


return bRet;

}


bool makeMatrix(Matrix& m, int col, int row)

{

m.matrix = make2dArray(row, col);

m.col = col;

m.row = row;

return true;

}

bool deleteMatrix(Matrix& m)

{

delete2dArray(m.matrix);

m.col = 0;

m.row = 0;

return true;

}


bool compareMatrix(Matrix& m1, Matrix& m2)

{

bool bRet = false;

do

{

if( m1.row != m2.row ) break;

if( m1.col != m2.col ) break;


for(int i=0; i<m1.col; i++){

for(int j=0; j<m1.row; j++){

if( m1.matrix[i][j] != m2.matrix[i][j] )

return false;

}

}


bRet = true;

} while(0);


return bRet;

}


int main(int argc, char *argv[])

{

Matrix m1, m2, res1, res2;




for(int x=0; x<10; x++)

for(int i=4; i<10; i++)

for(int j=3; j<10; j++)

for(int k=5; k<10; k++){

bool bRet = false;

do

{

makeMatrix(m1, i, j);

makeMatrix(m2, j, k);

makeMatrix(res1, m1.col, m2.row);

makeMatrix(res2, m1.col, m2.row);


initRandom(m1);

initRandom(m2);


Multiply(m1, m2, res1);

Multiply2(m1, m2, res2);

//printMatrix(res1);

//printMatrix(res2);

if( compareMatrix(res1, res2) ){

printf("result = true\n");

}

else{

printf("result = false\n");

break; 

}

deleteMatrix(m1);

deleteMatrix(m2);

bRet = true;

} while(0);

if( bRet == false ){ printf("assert!!\n"); system("pause"); return 0; }

}

system("pause");

return 0;

}

Posted by Нуеоп

vector<int> vec;


1.

&vec[0]


2.

&*vec.begin()



Posted by Нуеоп
Posted by Нуеоп

http://kukuta.tistory.com/81




for( map<string,vector<int> >::iterator iter = MyMap.begin(); iter != MyMap.end(); ) {

if( iter->second.size() < 1 ) {

MyMap.erase(iter++);

}

else{

iter++;

}

}


위처럼 erase(iter++);하지 않으면, iter을 미리 다른곳에 보관한다음, 삭제후 복원해야 한다.




혹은

for( map<string,vector<int> >::iterator iter = MyMap.begin(); iter != MyMap.end(); ) {

if( iter->second.size() < 1 ) {

iter = MyMap.erase(iter);

}

else{

iter++;

}

}


Posted by Нуеоп

http://kukuta.tistory.com/81




Posted by Нуеоп

http://www.winapi.co.kr/clec/cpp3/30-2-5.png



'c/c++' 카테고리의 다른 글

STL iterator로 erase()사용시 주의해야할 점  (0) 2012.08.27
C++ STL 에서 iterator사용시 주의점  (0) 2012.08.20
c/c++ 연산자 우선순위표  (0) 2012.07.13
(void) param  (0) 2012.07.12
c++ string 에서 c의 char 배열로 변환  (0) 2012.07.05
Posted by Нуеоп

http://ko.wikipedia.org/wiki/C%EC%99%80_C%2B%2B%EC%97%90%EC%84%9C%EC%9D%98_%EC%97%B0%EC%82%B0%EC%9E%90


우선순위연산자설명결합법칙
1::범위 확인 (C++만)왼쪽에서 오른쪽
2++접미사 증가
--접미사 감소
()함수 호출
[]배열 첨자
.참조에 의한 요소 선택
->포인터를 통해 요소 선택
typeid()런타임 형식 정보 (C++만) (typeid 참조)
const_cast자료형 캐스트 (C++만) (const cast 참조)
dynamic_cast자료형 캐스트 (C++만) (dynamic_cast 참조)
reinterpret_cast자료형 캐스트 (C++만) (reinterpret cast 참조)
static_cast자료형 캐스트 (C++만) (static cast 참고)
3++접두사 증가오른쪽에서 왼쪽
--접두사 감소
+단항 덧셈
-단항 뺄셈
!논리적 NOT
~논리적 비트 NOT
(자료형)자료형 캐스트
*우회 (역참조)
&의-주소
sizeof의-크기
newnew[]동적 메모리 할당 (C++만)
deletedelete[]동적 메모리 할당취소 (C++만)
4.*멤버로의 포인터 (C++만)왼쪽에서 오른쪽
->*멤버로의 포인터 (C++만)
5*곱셈
/나눗셈
%계수 (나머지)
6+덧셈
-뺄셈
7<<비트 왼쪽 쉬프트
>>비트 오른쪽 쉬프트
8<관계적 연산자들에 대해 < 각각의
<=관계적 연산자들에 대해 ≤ 각각의
>관계적 연산자들에 대해 > 각각의
>=관계적 연산자들에 대해 ≥ 각각의
9==관계적 = 각각의
!=관계적 ≠ 각각의
10&비트 AND
11^비트 XOR (배타적 or)
12|비트 OR (포함적 or)
13&&논리 AND
14||논리 OR
15?:삼중 조건부 (?: 참조)오른쪽에서 왼쪽
16=직접 할당 (C++ 클래스를 위해 기본적으로 제공됨)
+=덧셈에 의한 할당
-=뺄셈에 의한 할당
*=곱셈에 의한 할당
/=나눗셈에 의한 할당
%=나머지에 의한 할당
<<=비트 왼쪽 쉬프트에 의한 할당
>>=비트 오른쪽 쉬프트에 의한 할당
&=비트 AND에 의한 할당
^=비트 XOR에 의한 할당
|=비트 OR에 의한 할당
17throw던지기 연산자 (던지기 예외, C++만)
18,쉼표왼쪽에서 오른쪽

'c/c++' 카테고리의 다른 글

C++ STL 에서 iterator사용시 주의점  (0) 2012.08.20
가상함수 virtual은 어떤 경우에 써야 할까 ?  (0) 2012.07.18
(void) param  (0) 2012.07.12
c++ string 에서 c의 char 배열로 변환  (0) 2012.07.05
fflush  (0) 2012.05.31
Posted by Нуеоп
2012. 7. 12. 16:14

void foo( int param1, int param2 ){

(void)param1;

(void)param2;


return;

}


사용하지 않는 파라미터 param1, param2 경고를 제거하기 위해 (void)param1, (void)param2 을 사용한다.

'c/c++' 카테고리의 다른 글

가상함수 virtual은 어떤 경우에 써야 할까 ?  (0) 2012.07.18
c/c++ 연산자 우선순위표  (0) 2012.07.13
c++ string 에서 c의 char 배열로 변환  (0) 2012.07.05
fflush  (0) 2012.05.31
STL - vector  (0) 2012.05.31
Posted by Нуеоп

string str = "hello world";

const char * cstr = str.c_str();




'c/c++' 카테고리의 다른 글

c/c++ 연산자 우선순위표  (0) 2012.07.13
(void) param  (0) 2012.07.12
fflush  (0) 2012.05.31
STL - vector  (0) 2012.05.31
[c언어] 이차원 배열 사용 함수  (0) 2012.04.21
Posted by Нуеоп
2012. 5. 31. 13:12

while( getchar() != '\n' ) ;

'c/c++' 카테고리의 다른 글

(void) param  (0) 2012.07.12
c++ string 에서 c의 char 배열로 변환  (0) 2012.07.05
STL - vector  (0) 2012.05.31
[c언어] 이차원 배열 사용 함수  (0) 2012.04.21
[c언어] sin그래프 그리기  (0) 2011.11.09
Posted by Нуеоп
2012. 5. 31. 00:18

vector<Edge> graph;


graph.push_back( Edge() );

graph.push_back( Edge() );

graph.push_back( Edge() );



vector<Edge>::Iterator iter;


for( iter = graph.begin(); iter != graph.end(); ++iter )

    cout<< iter->key << endl;


sort(graph.begin(), graph.end(), less<Edge>());

Posted by Нуеоп

int **make2dArray(int width, int height) {

  int **arr;

  int i;


  arr = (int **) malloc(sizeof(int *) * height);

  for (i = 0; i < height; i++) {

    arr[i] = (int *) malloc(sizeof(int) * width);

  }

  return arr;

}



void free2dArray(int **arr, int height) {

  int i;

  for (i = 0; i < height; i++) {

    free(arr[i]);

  }

  free(arr);

}


void print2dArray(int **arr, int w, int h) {

  int x, y;

  for (y = 0; y < h; y++) {

    for (x = 0; x < w; x++) {

      printf("%3d", arr[y][x]);

    }

    printf("\n");

  }

  printf("\n\n");

}


void init2dArray(int **arr, int w, int h, int a) {

  int x, y;

  for (y = 0; y < h; y++) {

    for (x = 0; x < w; x++) {

      arr[y][x] = a;

    }

  }

}

'c/c++' 카테고리의 다른 글

fflush  (0) 2012.05.31
STL - vector  (0) 2012.05.31
[c언어] sin그래프 그리기  (0) 2011.11.09
[c언어] strtok 사용법 및 쓰레드에서 사용시 유의사항  (0) 2011.11.02
[c언어] 변수 초기화  (0) 2011.11.02
Posted by Нуеоп

sin 그래프 그리기



#include<stdio.h>
#include<math.h>

#define WIDTH 19
#define HEIGHT 100
#define PI (3.141592)


int isEqual(double d1, double d2, double e);

int main(int argc, char *argv[])
{
    double x=0.0;
    double y=0.0;
    int col=0,row=0;
    printf("%-*d%1d%*d\n",WIDTH,-1,0,WIDTH,1);
    for(row=0;row<WIDTH*2+1;row++) printf("-");
    printf("\n");
    for(col=0;col<HEIGHT;col++)
    {
        y=sin(2*PI*x);
        for(row=0;row<WIDTH*2+1;row++)
        {
            if(isEqual((double)row,(y+1.0)*(double)WIDTH,0.5))
                printf("*");
            else if(row == WIDTH)
                printf("|");
            else
                printf(" ");
        }
        x += 0.05;
        printf("\n");
    }
}

int isEqual(double d1, double d2, double e)
{
    if( (d1-d2>0.0?d1-d2:d2-d1)<e )
        return 1;
    return 0;
}
결과



-1                 0                  1
---------------------------------------
                   *                   
                   |     *             
                   |          *        
                   |              *    
                   |                 * 
                   |                  *
                   |                 * 
                   |              *    
                   |          *        
                   |     *             
                   *                   
             *     |                   
        *          |                   
    *              |                   
 *                 |                   
*                  |                   
 *                 |                   
    *              |                   
        *          |                   
             *     |                   
                   *                   
                   |     *             
                   |          *        
                   |              *    
                   |                 * 
                   |                  *
                   |                 * 
                   |              *    
                   |          *        
                   |     *             
                   *                   
             *     |                   
        *          |                   
    *              |                   
 *                 |                   
*                  |                   
 *                 |                   
    *              |                   
        *          |                   
             *     |                   
                   *                   
                   |     *             
                   |          *        
                   |              *    
                   |                 * 
                   |                  *
                   |                 * 
                   |              *    
                   |          *        
                   |     *             
                   *                   
             *     |                   
        *          |                   
    *              |                   
 *                 |                   
*                  |                   
 *                 |                   
    *              |                   
        *          |                   
             *     |                   
                   *                   
                   |     *             
                   |          *        
                   |              *    
                   |                 * 
                   |                  *
                   |                 * 
                   |              *    
                   |          *        
                   |     *             
                   *                   
             *     |                   
        *          |                   
    *              |                   
 *                 |                   
*                  |                   
 *                 |                   
    *              |                   
        *          |                   
             *     |                   
                   *                   
                   |     *             
                   |          *        
                   |              *    
                   |                 * 
                   |                  *
                   |                 * 
                   |              *    
                   |          *        
                   |     *             
                   *                   
             *     |                   
        *          |                   
    *              |                   
 *                 |                   
*                  |                   
 *                 |                   
    *              |                   
        *          |                   
             *     |                   
 

Posted by Нуеоп
문자열을 특정 기준으로 분리하는 함수이다.
가령
char text[] = "The quick brown fox jumps over the lazy dog."; 라는 문자열을 단어로 분리하고 싶은 경우,
' ' 공백 문자를 기준으로 토큰 분리하면 된다.
"The", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog."

char text[] = "The quick brown fox jumps over the lazy dog."; char seps[] = " "; // 이곳에 분리의 기준이 되는 문자를 나열하면 된다. char *p; if( (p = strtok( text, seps )) != NULL ){ printf("%s\n", p); while( (p = strtok( NULL, seps) != NULL){ printf("%s\n", p); } }

여기서 처음 strtok()를 사용할때, 첫번째 인자로, 분리의 대상이 되는 문자열을 파라미터로 넘겼다.
하지만, 이후 strtok()에서는, NULL을 넘기면서, 분리의 대상이 되는 문자열을 넘기지 않았다.
strtok() 함수 내부에서, 처음 넘긴 문자열을 가리키는 포인터를 보관하고 있다는 뜻이다.
따라서, strtok()로 모두 분리가 완료 되기 전에, 다른 문자열을 분리할 수 없다.

쓰레드를 이용해서 동시에 작업하는 경우, 이 내부 변수가 문제가 될 수 있다. 각 쓰레드별로 이런 내부변수를 개별적으로 가지고 있어야 할것이다. 윈도우 환경에서, CreateThread()로 쓰레드를 생성할 경우, 이런 내부 변수를 두고 사용하는 함수에서 문제가 된다. _beginthreadex()로 쓰레드를 생성해야 하는 이유중 하나다.

_beginthreadex()는 내부적으로 CreateThread()를 호출하여 쓰레드를 생성한다. 하지만, 그전에 struct _tiddata 구조체를 통해, 이런 내부 변수를 저장하는 별도의 공간을 마련한 후 쓰레드를 생성한다.

쓰레드가 종료되면, _tiddata 구조체 블록을 해제해야 한다. CreateThread()로 쓰레드 생성한 경우, 대부분 _tiddata 블록이 잘 관리가 되지만, 비정상적인 쓰레드 종료시 _tiddata 블록이 해제 되지 않으면, 메모리 누수가 된다. 


Posted by Нуеоп
2011. 11. 2. 12:47
기본적으로 변수의 종류에는 static 과 auto 가 있다.
static라고 명시 하지 않으면, 모든 지역변수는 auto 이다.
auto는 변수가 선언됨과 동시에 자동으로 할당되고, 해당 지역이 끝나면 자동으로 해제된다.
static는 한번 할당되면, 해당 프로그램이 종료되기 전까지 해제되지 않고 스택영역에 남는다.

auto 변수는 자동으로 초기화 되지 않는다. 따라서 초기화 하지 않고 사용할 경우, auto 변수에는 의도하지 않는 의미 없는 값이 들어있다. 쓰레기 값이라고도 부른다. 디버깅 환경에서는 초기화 하지 않는 변수에 특별한 값으로 초기화 하기도 한다. 이 값을 보고, 어떤 변수가 어디에 할당되었는지 알수 있다. 이런 특별한 경우를 제외하면, 쓰레기 값이 들어있기 때문에(이전 메모리에 있던 값) 초기화 하지 않은 변수를 사용할땐 조심해야 한다.

static 로 선언된 변수와, 전역변수는 명시적으로 초기화 하지 않아도 자동으로 초기화 된다.
우선 정수는 0, 실수는 0.0 이 기본 초기화 값이다.
문자열은 '\0', 포인터는 NULL으로 초기화 된다.
구조체의 경우, 구조체 멤버가 각각 위의 기본 초기화 값으로 초기화된다.
배열의 경우, 일부분만 초기화 되면, 초기화 하지 않은 나머지 부분이 모두 기본 초기화 값으로 초기화 된다.

int num;             // num이 전역변수인 경우 0으로 자동으로 초기화 된다.
double real;         // real이 전역변수인 경우 0.0으로 자동으로 초기화 된다.
char *ptr            // ptr역시 NULL로 자동으로 초기화 된다.
struct {
    int a;
    double b;
    char *c;
} A;                 // A.a는 0, A.b는 0.0, A.c는 NULL로 초기화 된다.




int arr[10] = { 7, 8 };
int arr2[10] = { [3] = 7, [4] = 8 };


이경우 arr이 전역배열이나 static형 배열이 아니어도, 나머지 arr[2] ~ arr[9]는 int의 기본 초기화 변수인 0으로 초기화 된다. arr2의 경우 arr2[3], arr2[4]는 각각 7,8로 초기화 되고, 나머지 arr2[0]~arr2[2], arr2[5]~arr2[9]는 0으로 초기화 된다.


int arr[10] = {0};
int arr[10] = {0,};

간혹 int arr[10]을 0으로 초기화 하기 위해, int arr[10] = {0,}; 라고 0뒤에 , 콤마를 써주는 경우를 자주 볼수 있는데, 반드시 필요한 것은 아니다. 위의 두가지 배열은 정확히 똑같다.

 
Posted by Нуеоп
sizeof

sizeof 연산자는 피연산자를 저장하는데 필요한 메모리 바이트수를 리턴한다.
return과 마찬가지로 함수가 아니고 연산자이므로, 괄호가 필요하진 않다. 

int age = 16;
printf("%u\n", sizeof(age) );
printf("%u\n", sizeof age );



결과는 모두 같다. 하지만 sizeof의 피연산자로 타입이 오는 경우, 괄호는 꼭 써줘야 한다.

printf("%u\n", sizeof(int) );
printf("%u\n", sizeof int ); // 에러!!



sizeof 연산이후 나오는 결과값은 unsigned int형이다.

char x;
printf("%u\n", sizeof( sizeof x ));    // unsigned int의 크기인 4가 출력됨




literal constant

5, 7 등의 정수는 기본적으로 signed int 형으로 취급한다.
3.4, 5.0, 9. 등은 기본적으로 double 형으로 취급한다.
1.2f, 20f 등 f를 명시한 상수는 float 형으로 취급한다.
'a', 'b' 등은 기본적으로 signed int 형으로 취급한다.
char 형도 수식에선 각각을 int 형으로 취급하여 계산한다.
float 형과 double형이 섞인 수식은 double 형으로 취급한다.
float 형 끼리의 수식은 double 형으로 취급하는 시스템도 있다.
최근 표준에선, double로 취급하지 않고 float로 계산한다.

char c = 'a';
printf("%u\n", sizeof(c));    // c는 char형이므로 1이 출력된다.
printf("%u\n", sizeof('a'));  // 하지만 'a'는 int형으로 취급하여 4가 출력된다.
printf("%u\n", sizeof(c+c));  // char형끼리의 연산은 int형으로 취급하여 계산한다.
                              // 따라서 4가 출력된다.




 
Posted by Нуеоп

<math.h>의 sqrt()함수를 이용하지 않고, 간단하게 for문 몇번 돌리는 것으로 제곱근을 구할 수 있다.
뉴튼-랩슨법을 이용해서 빠르게 제곱근을 계산할 수 있다.



double mysqrt(unsigned int number)
{
    unsigned int NUM_REPEAT = 16;
    unsigned int k;
    double res;
    double tmp = (double)number;
    for(k=0,res=tmp;k<NUM_REPEAT;k++)
    {
        if(res<1.0)
            break;
        res = (res*res+tmp)/(2.0*res);
    }
    return res;
}


여기서 NUM_REPEAT는 for문의 반복 횟수를 의미하는데, 크면 클 수록 정확한 값을 구한다. 16~20정도면 상당히 정확한 값을 구할 수 있다. 10진법 소수점 단위로 비교하면서 구하는것보단 훨씬 빠르게 구하지만, <math.h>의 sqrt()함수보다 빠르진 않다.

뉴튼-랩슨법의 자세한 원리는 인터넷에서 찾아보면 된다. 원리만 알면 매우 쉽다.
Posted by Нуеоп

c언어에서 2차원배열을 만드는 방법은 다음과 같다.

int arr[6][8];
그러면 가로 8, 세로 6의 2차원 배열이 생성된다. 하지만 가로의 크기와 세로의 크기를 컴파일 이전 시간에 미리 정해줘야 한다. 사용자로부터 입력받은 가로와 세로의 크기로, 혹은 실행시간 도중에 정한 크기로 2차원 배열을 만들기 위해선 다른 방법을 사용해야한다.

int height = 6, width = 8;
int arr[ height ][ width ];    // 이런식으로 배열을 만들수 없다.
malloc()로 동적으로 할당 받아야 한다.
1차원 배열을 동적으로 할당 받는 방법은 다음과 같다.

int width = 8;
int *arr;
arr = (int *) malloc ( sizeof(int) * width );
동적으로 할당받은 메모리도, 배열처럼 접근이 가능하다.
arr[0], arr[1], ... arr[7]

2차원 배열을 할당받는 방법은, malloc()를 여러번 호출하는 것이다.

int height = 6, width = 8;
int **arr;
arr = (int**) malloc ( sizeof(int*) * height );
for(int i=0; i<height; i++){
    arr[i] = (int*) malloc ( sizeof(int) * width );
}




할당받은 2차원배열을 다 사용하고 나서, 해제해줘야 한다.
for문을 이용해서 여러번 malloc()로 메모리 공간을 할당 받았기 때문에, 해제할때도, for을 이용해서 여러번 해제해야 한다.
위 그림에서 세로의 크기만큼 malloc()를 호출하고, 또 그전에 한번 malloc()를 호출했다. 따라서, (height + 1)번 해제해야 한다.

for(int i=0; i<height; i++){
    free(arr[i]);
}
free(arr);

2차원 배열 할당과 해제가 번거롭다. 조금 방법을 달리 하면, 한번에 해제할 수 있는 구조로 2차원 배열을 만들 수 있다.


int height=8,width=6;
int **arr;
arr = (int **) malloc ( sizeof(int *) * height);
arr[0] = (int *) malloc ( sizeof(int) * width*height );
for( int i=1; i<height; i++){
    arr[i] = arr[ i-1 ] + width;
}
malloc()를 딱 두번만 사용했다. 두번째 malloc()에서, 배열의 크기를 width*height 로 한번에 크게 할당받았다.
그리고 이후에 for문을 통해 연결만 해주었다.

해제하는 방법도 간단하다.

free(arr[0]);
free(arr);


Posted by Нуеоп

퀵정렬, 퀵소트, Quick sort 를 구현해보았다.

실행화면




소스코드

#include<stdio.h>
#include<stdlib.h>

void shuffle(int *arr);
void swap(int *a, int *b);
void print(int * arr, int st, int ed);
void quick(int *arr);
void partition(int *arr,int _st, int _ed);

int main(int argc, char *argv[])
{
    int arr[16];
    for(int r=0; r<50; r++){
        for(int i=0; i<16; i++){
            arr[i] = i;
        }
     srand(r);
     shuffle(arr);
     printf("%10s : ","shuffle");
     print(arr,0,15);

     quick(arr);
     printf("%10s : ","quick");
     print(arr,0,15);

     printf("=============================================================\n");
     //break;
    }
    system("pause > nul");
    return 0;
}

void quick(int *arr){
    partition(arr,0,15);
}
void partition(int *arr,int _st, int _ed){
    int p = _ed;
    int buf_p = arr[p];
    int st=_st,ed=_ed-1;
    while(st<ed){
        //if(st<p){
        if( arr[st]<arr[p]){
            st++;
            continue;
        }
        if( arr[ed]>arr[p]){
            ed--;
            continue;
        }
        if( arr[st] > arr[ed]){
            swap(arr+st, arr+ed);
        }
    }
    //printf("st=%d,ed=%d,p=%d\n",st,ed,p);
    if( st < p ){
        if( arr[st]>arr[p]){
            swap(arr+st, arr+p);
            int t = p;
            p = st;
            st = t;
        }
    }

    st = _st;
    ed = _ed;
    printf("(%2d)%6s : ",buf_p,"quick");
    print(arr,st,ed);
    if (st < p) 
        partition(arr, st, p-1); 
          if (ed > p) 
              partition(arr, p+1, ed); 
}

void shuffle(int *arr){
    int n = 100;
    int a,b;
    while(n--){
        a = rand()%16;
        b = rand()%16;
        swap(arr+a,arr+b);
    }
}

void swap(int *a, int *b){
    int t = *a;
    *a = *b;
    *b = t;
}

void print(int * arr, int st, int ed){
    for(int i=0; i<16; i++){
        if( st<=i && i<=ed){
            printf("%3d",arr[i]);
        }
        else{
            printf("   ");
        }
    }printf("\n");
}

 
참고자료
http://ko.wikipedia.org/wiki/%ED%80%B5_%EC%A0%95%EB%A0%AC#.EC.95.8C.EA.B3.A0.EB.A6.AC.EC.A6.98
Posted by Нуеоп







무료로 다운 받아 사용할수 있는 IDE들이다.
몇몇 제품은 기능의 제약이 있는데, 사용하는데 별 무리는 없다.





1. microsoft visual c++ express

visual c++ 2005 express
http://www.microsoft.com/korea/msdn/vstudio/express/visualc/download/
visual c++ 2008 express
http://www.microsoft.com/express/Downloads/#2008-Visual-CPP
visual c++ 2010 express
http://www.microsoft.com/express/Downloads/#2010-Visual-CPP




설치후 30일 이내에 간단한 등록만 하면 기간 제한 없이 무료로 사용할 수 있다.
등록 절차 http://www.microsoft.com/express/support/regins/

대학생이라면, 대학교 e-mail계정을 통해 Dreamspark로 최신 visual studio를 받을 수 있다.
https://www.dreamspark.com/default.aspx



2. code::blocks
http://www.codeblocks.org/downloads





3. dev-cpp
http://www.bloodshed.net/dev/devcpp.html
http://sourceforge.net/projects/dev-cpp/





4. sharp develop
http://www.icsharpcode.net/OpenSource/SD/Download/





5. 기타

이클립스
http://www.eclipse.org/downloads/

넷빈
http://netbeans.org/downloads/index.html


 

Posted by Нуеоп
이전버튼 1 이전버튼