※요약

당연한 얘기겠지만 비트 연산자는 비트를 연산하기 위한 연산자입니다.

비트란( bit )란 기억 장치의 최소 단위로써 1이나 0을 저장하며 8개가 모여 1Byte를 이룹니다.

비트 연산은 정수나 정수로 변환 가능한 타입만 가능하며, 실수나 포인터 등은 비트 연산을 할 수 없습니다.


아래는 8bit( 1Byte )공간에 10진수로는 89, 16진수로는 0x59가 저장되어 있는 모양입니다.

128

64

32

16

8

4

2

1

0

1

0

1

1

0

0

1

64 + 16 + 8 + 1 = 89 입니다.



※비트 연산자 표

연산자

피연산자 개수

설명

~ (NOT)

1개, 단항

비트를 반전 시킨다.

& (AND)

2개, 이항

두 개의 비트가 모두 1일 때 1

| (OR)

2개, 이항

두 개의 비트 중 1개만 1이어도 1

^ (XOR)

2개, 이항

두 개의 비트가 같으면 0, 다르면 1

<<

2개, 이항

지정한 수만큼 왼쪽으로 비트들을 이동

>>

2개, 이항

지정한 수만큼 오른쪽으로 비트들을 이동

마스크 오프 : 특정 비트를 강제로 0으로 만드는 연산을 mask off라고 하며 &연산자가 쓰인다.

마스크 온 : 특정 비트를 강제로 1로 만드는 연산을 mask on이라고 하며 |연산자가 쓰인다.

마스크 반전 : 반전시키고자 하는 부분만 반전 시키는 연산을 마스크 반전이라 하며 ^연산자가 쓰인다.



※비트 연산자 진리표

b1

b2

b1 & b2

b1 | b2

b1 ^ b2

~b1

0

0

0

0

0

1

0

1

0

1

1

1

1

0

0

1

1

0

1

1

1

1

0

0



※쉬프트 연산자 <<, >>

0

1

0

1

1

0

0

1

상기의 0101 1001을 a라고 하고 쉬프트 연산을 통해 좌측으로 2칸 옮겨 보겠습니다.


a << 2

0

1

0

1

1

0

0

1

<<2

0

1

1

0

0

1

0

0

보시다시피 좌측으로 2칸 이동하였습니다.

이 때 좌측 두 칸은 버리고, 오른쪽 두 칸은 0으로 채웁니다.



※예제

#include <stdio.h>

int main( )
{
	int nNum1 = 3;
	int nNum2 = 5;
	int nResult = 0;

	nResult = nNum1 & nNum2;
	printf( "%d & %d 연산 : %d\n", nNum1, nNum2, nResult );

	nResult = nNum1 | nNum2;
	printf( "%d | %d 연산 : %d\n", nNum1, nNum2, nResult );

	nResult = nNum1 ^ nNum2;
	printf( "%d ^ %d 연산 : %d\n", nNum1, nNum2, nResult );

	nResult = ~nNum1;
	printf( "%d ~ %d 연산 : %d\n", nNum1, nNum2, nResult );

	nResult = nNum1 << 2;
	printf( "%d << %d 연산 : %d\n", nNum1, 2, nResult );

	nResult = nNum1 >> 2;
	printf( "%d >> %d 연산 : %d\n", nNum1, 2, nResult );

	return 0;
}




※요약

rand : 예측할 수 없는 하나의 난수를 생성한다.

난수의 범위는 0~RAND_MAX 까지이며 RAND_MAX는 0x7fff이므로 , 결국 난수의 범위는 0~32767 이다.

srand : rand 함수만으로 생성되는 난수는 일정한데 

srand를 이용, 시간 값을 매개로 초기화하면 일정하지 않고 불규칙적인 난수가 생성된다.



※함수 원형 및 설명

int rand( void );

void srand( unsigned int seed );



※사용법 ( 사용법 부분은 "C언어를 배우자" 카페의 라이터님의 게시물을 허락 후 옮겼습니다. )

1. 기본 사용법

i = rand()%n

이것은 0 ~ n-1 범위의 난수를 i에 대입합니다.

예를 들어 n=6 이라 하면 0, 1, 2, 3, 4, 5, 중 하나가 i에 대입되는 셈이지요.

 


2. 기본 응용

i = rand()%n + m

이것은 1번을 응용한 것으로, 0+m ~ n-1+m 범위의 난수를 i에 대입합니다.

예를 들어 n=6, m=4 라 하면 4, 5, 6, 7, 8, 9, 중 하나가 i에 대입되는 셈이지요.

다른 예로 n=5, m= -2 라 하면 -2, -1, 0, 1, 2 중 하나가 i에 대입되는 것이죠.

 

 

i = rand()%n * m

이것은 0 ~ n-1 으로 나올 수 있는 수에 m을 곱한 수를 i에 대입하는 식입니다.

예를 들어 n=4, m=2 이라 하면, 0, 2, 4, 6 중 하나가 i에 대입되는 것이죠.

m의 값을 2로 주면 2의 배수, 3을 주면 3의 배수가 나오는군요.

 

이제 두개를 섞어서,


i = (rand()%n + m) * o

이것은 0+m ~ n+m-1 으로 나올 수 있는 난수에 o을 곱한 수를 i에 대입하는 식입니다.

n = 3, m = 2, o = 4 라 하면, 8, 12, 16 중 하나가 i에 대입되는 것이죠.

이것도 어떤 수의 배수를 사용할 때 용이하겠습니다.


i = rand()%n * m + o

이건 0 ~ n-1 으로 나올 수 있는 수에 m을 곱하고, o를 더한 수를 i에 대입하는 식입니다.

n = 3, m = 2, o = 5 라 하면, 5, 7, 9 중 하나가 i에 대입되는 것이죠. 




3. 기본 심화 응용

i = rand()%n * m + o

이 식을 다시 한번 봅시다.

n의 값이야 0 이상으로 주고, m = 2, o = 0 으로 주면, 짝수가 생성됩니다.

m = 2, o = 1 으로 주면, 홀수가 생성되는것을 볼 수 있습니다.



4. 배열을 이용한 응용 - 1 기본 기법

배열을 이용한 응용이라...  rand() 의 마법을 보실 수 있겠군요.

int ar[MAX] = {원하는 원소 MAX개}; 라는 배열이 있다고 생각하고...


i = ar[rand()%MAX]

이 식은 상당히 유용합니다. 예를 들어보는게 제일 빠르겠지요.

MAX = 4로 잡고, ar 배열의 원소를 { 2, 5, 9, 3214324 } 이라 합시다.

저 4개의 숫자는 규칙성도 뭣도 없어서 위에서 본 응용법으로는 뽑아 낼 수가 없지요.

하지만 배열과 4번의 식을 이용한다면?


rand()%MAX 는 0 ~ MAX-1 범위의 수를 뽑아낼 것입니다.

MAX 가 4니까 0, 1, 2, 3, 이 나오겠지요? 그런 다음에 ar[rand()%MAX] 으로 ar배열 속에 있는 원소에 접근하는데...

rand()%MAX 가

0 이면 2

1 이면 5

2 이면 9

3 이면 3214324

를 i 에 대입할 수 있는거죠.

 

이렇게 배열을 이용하면 rand() 함수 한번의 호출로 불규칙한 수를 난수로 뽑아내 쓸 수 있는거죠.

응용법은... 아래쪽에 있습니다.



5. 배열을 이용한 응용 - 2 자세한 응용

이번엔 다른 배열 응용법을 알아봅시다.


복권을 만들었는데, 1/10 의 확률로 1등, 3/10의 확률로 2등, 6/10의 확률로 3등이라고 하고,

rand() 를 이용해 랜덤하게 추첨을 하려고 하는데..


" 3가지 경우가 있으니 rand()%3 해서 0 이면 1등, 1이면 2등... "

이런 생각은 떙 !!!!

0, 1, 2, 가 나올 확률은 같습니다!!!


" 그럼 rand()%10 해서 0 은 1등, 1~3 은 2등, 4~9 는 3등으로... 이런 복잡한 걸"

정답인데, 이러면 조건문이 들어가야 하는 복잡함이!!!!


배열 하나면 됩니다.

int ar[10] = { 1, 2, 2, 2, 3, 3, 3, 3, 3, 3 }

이런 배열 하나 준비 하시고!!!!


i = ar[rand()%10]

아하하하하하, 이러면 끝 !! i에는 추첨된 등수가 들어가게 됩니다.

설명해 드리죠.


rand()%10 으로 나올 수 있는 수는

0, 1, 2, 3, 4, 5, 6, 7, 8, 9 이고, 이 10가지 수가 나올 수 있는 수학적 확률은 같습니다.


그러나, 0이 나올 확률은 1/10,

1, 2, 3 이 나올 학률은 3/10,

4, 5, 6, 7, 8, 9 가 나올 확률은 6/10  !!!


배열 원소를 보면, ar[0] 은 1이고

ar[1] ~ ar[3]은 2,   ar[4] ~ ar[9]는 3!!!!


배열로는 이런일이 가능합니다 !!!




※예제

아래는 중복 없는 난수 생성 예제입니다. 

로또 번호 생성 예제이며, 제가 배포하는 로또 프로그램에서 일부 가져와 군더더기를 제거하고  예제에 맞게 수정했습니다.

중복을 방지하기 위해 생성 여부에 대한 일종의 인덱스를 둬서 따로 검사하지 않아도 중복을 방지할 수 있게 했습니다.

흔히 사용하는 배열 요소를 처음부터 끝까지 조사 방식은 배열 개수에 따라 속도가 엄청 느려지므로 추천하지 않습니다.

이렇게 인덱스를 두는 방법은 에라토스테네스의 체를 구할 때도 이용되고 

데이터를 캐싱할 때 이미 불러들인 데이터인지 판별할 때도 사용됩니다.

#include <stdio.h>
#include <stdlib.h>       //srand
#include <time.h>     //time
 
//#define _MAX 6
const int nMAX = 6;
 
void BubbleSort( int *nArr, int nArrSize );
 
int main( )
{
    //변수 생성 및 초기화 부분
    srand( (unsigned)time(NULL) );              //srand로 초기화
 
    int nLottoNum[nMAX] = { 0, };               //생성된 로또 번호를 저장할 변수
    bool bCheckExistOfNum[45] = { false, };     //생성된 번호가 중복인지 체크할 변수(인덱스)
 
    //번호 생성 부분
    for( int i=0 ; i<nMAX ; )                    //번호가 6개 생성될 때까지 돈다.
    {
        int nTemp = rand()%45;                  //0~44 범위의 번호를 생성한다.
 
        if( bCheckExistOfNum[nTemp] == false )  //중복 여부 판단
        {
            bCheckExistOfNum[nTemp] = true;     //번호가 중복 생성되지 않게 존재 여부를 true로 한다.
            nLottoNum[i] = nTemp+1;             //+1을 안해주면 범위가 0~44이다.
            ++i;                                //증감 연산을 for문에서 하지 않고 여기서 한다.
        }
    }
 
    //버블 정렬
    BubbleSort( nLottoNum, sizeof(nLottoNum)/sizeof(int) );
 
    //출력 부분
    for( int i=0 ; i<nMAX ; ++i )
    {
        printf( "%2d ", nLottoNum[i] );
    }
 
    return 0;
}
 
void BubbleSort( int *nArr, int nArrSize )
{
    for( int i=0 ; i<nArrSize-1 ; i++ )
    {
        for( int j=0 ; j<nArrSize-(i+1) ; j++ )
        {
            if( nArr[j] > nArr[j+1] )    //꺽쇠 방향으로 오름 차순, 내름 차순 결정
            {//값 교환 부분
                int temp = nArr[j];
                nArr[j] = nArr[j+1];
                nArr[j+1] = temp;
            }
        }
    }
}




아래는 MFC 프로젝트에 디버깅을 위한 콘솔 창을 띄운 모습입니다. (아래 프로그램은 로또 프로그램)



사실 MFC의 경우는 아래 캡쳐와 같이 TRACE 매크로를 통해 로그(디버깅 메시지)를 확인할 수 있지만

Win32 API의 경우는 TRACE 매크로가 없으며, 있어도 TRACE보다는 printf로 출력하는 게 더 편할 때도 있어서 

가끔 콘솔창을 이용합니다.



TRACE보다 printf로 출력하면 더 편한 몇 가지 이유로는

 - printf의 경우 서식문자를 쓸수 있다.  ex) printf( "에러 번호 : %d, 에러 내용 : %s", nErrorNum, GetLastError() );

 - TRACE의 경우 출력 창에 내용이 표시되는데, TRACE 내용 말고도 잡다한 내용이 많다.

 - 콘솔 창의 경우는 내가 남긴 로그만 볼 수 있어서 깔끔하다.




제가 아는 콘솔창 띄우는 방법은 2가지가 있습니다. ( 그 외 AllocConsole 등도 있음 )

아래와 같이 프로젝트 속성에서 창을 띄우는 방법이 있고



아래의 소스를 추가하는 방법이 있습니다.

아래 소스는 아시다시피 디버깅 모드일 때만 콘솔창이 뜨도록 한 겁니다.

#ifdef _DEBUG #pragma comment(linker, "/entry:WinMainCRTStartup /subsystem:console") #endif


 

 

cmd 창 색상 변경 방법입니다.

먼저 cmd(커맨드) 창을 띄웁니다.


캡션바를 마우스 우클릭하면 팝업 메뉴가 뜨는데, 속성을 클릭합니다.


배경색과 폰트 색을 취향에 맞게 설정하면 됩니다.



※ 요약

OpenGL 처음 배울 당시인 2011년도 쯤에 공부할겸 만든 프로그램이다.

프로그램 창이 투명하기 때문에 뒤에 있는 그림이나 사진의 각도를 간단하게 측정할 수 있다.

사용법은 마우스 좌, 우 클릭과 "i"키가 전부다.


※ 개발 환경

Windows 7 x64

Visual Studio 2010 SP1


C++


Win32 API

OpenGL


※ 다운로드

각도기.zip



※ 사용 방법

아래는 프로그램을 실행한 화면이다. 위에서도 말했지만 창이 투명하기 때문에 각도를 측정할 때 편하다.


마우스 좌클릭과 우클릭으로 각도를 측정할 수 있다. 또 i키를 누르면 화면에 표시되는 정보를 On/Off 할 수 있다.




※ 버전

-


 

 

1. 각 디스크의 주 파티션 0 

2. 디스크 0의 확장 파티션 

3. 디스크 n의 확장 파티션 

4. 각 디스크의 파티션 n



콘솔창은 형형색색으로 꾸며도 정말 촌스럽네요.




※소스 코드

#include <windows.h>
#include <stdio.h>

#define RED         (FOREGROUND_RED | FOREGROUND_INTENSITY)
#define BLUE        (FOREGROUND_BLUE | FOREGROUND_INTENSITY)
#define PINK        (RED | BLUE)
#define WHITE       (RED | GREEN | BLUE)
#define GREEN       (FOREGROUND_GREEN | FOREGROUND_INTENSITY)
#define YELLOW      (RED | GREEN)
#define SKYBLUE     (GREEN | BLUE)

#define RED_BG      (BACKGROUND_RED | BACKGROUND_INTENSITY)
#define BLUE_BG     (BACKGROUND_BLUE | BACKGROUND_INTENSITY)
#define PINK_BG     (RED_BG | BLUE_BG)
#define WHITE_BG    (RED_BG | GREEN_BG | BLUE_BG)
#define GREEN_BG    (BACKGROUND_GREEN | BACKGROUND_INTENSITY)
#define YELLOW_BG   (RED_BG | GREEN_BG)
#define SKYBLUE_BG  (GREEN_BG | BLUE_BG)

void PrintString( HANDLE hStdOut, WORD Attribute, LPCSTR str )
{
    SetConsoleTextAttribute( hStdOut, Attribute );
    puts(str);
}

int main( )
{
    HANDLE hStdOut = GetStdHandle( STD_OUTPUT_HANDLE );

    PrintString(hStdOut, RED, "빨간색");
    PrintString(hStdOut, BLUE, "파란색");
    PrintString(hStdOut, PINK, "분홍색");
    PrintString(hStdOut, WHITE, "하얀색");
    PrintString(hStdOut, GREEN, "초록색");
    PrintString(hStdOut, YELLOW, "노란색");
    PrintString(hStdOut, SKYBLUE, "하늘색\n");

    PrintString(hStdOut, RED_BG, "빨간배경");
    PrintString(hStdOut, BLUE_BG, "파란배경");
    PrintString(hStdOut, PINK_BG, "분홍배경");
    PrintString(hStdOut, WHITE_BG, "하얀배경");
    PrintString(hStdOut, GREEN_BG, "초록배경");
    PrintString(hStdOut, YELLOW_BG, "노란배경");
    PrintString(hStdOut, SKYBLUE_BG, "하늘배경\n");

    PrintString(hStdOut, YELLOW_BG | PINK, "노란배경 빨간글씨");
	PrintString(hStdOut, WHITE_BG | GREEN, "하얀배경 빨간글씨");
	PrintString(hStdOut, GREEN_BG | WHITE, "초록배경 빨간글씨");
	PrintString(hStdOut, BLUE_BG | RED, "파랑배경 빨간글씨");

    CloseHandle(hStdOut);

    return 0;
}


'C > 기타' 카테고리의 다른 글

[C언어] 플랫폼 독립적 COLORREF <-> RGB 서로 변환  (0) 2014.03.12



무설치 프로그램으로 공인 ip 확인하기


사이트에서 공인ip 확인하기


자신의 공인ip를 확인하고 싶으면 상기의 링크로 가면 됩니다.

그럼 아래와 같이 자신의 공인ip주소가 나옵니다.(모자이크 부분)

또한 다른 사람의 ip주소를 넣으면 해당 ip의 국가나 접속 위치를 대략적으로 알 수 있습니다.



사설ip 알아내는 방법은 cmd창에 "ipconfig"라고 치면 됩니다.

"ipconfig -all"이라고 치면 좀 더 상세한 정보가 나옵니다.

저의 사설ip는 아래와 같이 192.168.128.20 입니다.





※요약

SELECT문으로 검색된 데이터를 오름차순(ASC)이나 내림차순(DESC)으로 정렬 시킬 때 사용한다.

Default값은 Ascending(오름차순)으로써 ASC는 생략해도 되며, 문자는 알파벳 순서로 출력된다.

ORDER BY절에 선택된 컬럼이 여러 개일 경우 앞(왼쪽)에 정의된 컬럼을 기준으로 먼저 분류한 후,

이후에 나열된 순서대로 분류한다.



※용어 설명

오름차순 : 작은 값부터 큰 값 쪽으로의 순서 ex)1, 2, 3, 4, n, n+1...

내림차순 : 큰 값부터 작은 값 쪽으로의 순서 ex)5, 4, 3, 2, 1



※예제에 쓰일 emp 테이블



※예제

1. SELECT empno FROM emp ORDER BY empno DESC

2-1. SELECT empno FROM emp ORDER BY empno ASC

2-2. SELECT empno FROM emp ORDER BY empno   <- ASC는 Default 값이라 생략해도 됨. 2번과 동일

3. SELECT job FROM emp ORDER BY empno  <- ORDER BY절에 지정된 컬럼이 SELECT절에 지정 안되도 됨



※결과

1. SELECT empno FROM emp ORDER BY empno DESC



2-1. SELECT empno FROM emp ORDER BY empno ASC

2-2. SELECT empno FROM emp ORDER BY empno

2-1, 2-2는 결과가 같다.



3. SELECT job FROM emp ORDER BY empno



'DB 및 SQL > SELECT문' 카테고리의 다른 글

[Oracle SQL] Alias - 컬럼에 별칭 붙이기  (2) 2013.11.30
[Oracle SQL] DISTINCT 키워드  (0) 2013.11.27
[Oracle SQL] SELECT문  (0) 2013.11.27



printf 끝에 붙어 있는 f는 Formatting의 약자로써, 서식화된 출력을 한다는 뜻입니다.

printf함수는 %로 시작하는 서식과 인수(변수)를 대응시켜 조립(Formatting)하는 과정을 거친 뒤 문자열로 출력합니다.


아래는 서식 표 입니다.

출처 책 : 혼자 연구하는 C/C++( page 86 )에 제가 조금 덧붙였습니다.

서식

의미

출력 타입

설명 

%hd

short integer

unsigned short 

 부호없는 10진 정수 출력

%d 또는 %i

Decimal, Integer

int 

10진 정수 출력

%ld


long

10진 정수 출력

%lld


long long

10진 정수 출력

%lu


unsigned long

부호없는 10진 정수 출력

%I64d


__int64

10진 정수 출력 

%I64u


unsigned __int64

부호없는 10진 정수 출력 

%o

Octal

unsigned int

8진 정수 출력

%x 또는 %X

heXadecimal

unsigned int

16진 정수로 출력.

대문자 X 쓰면 A~F도

대문자 출력

%u

Unsigned

unsigned int

부호없는 10진 정수 출력

%c

Character

char, unsigned char

1개의 문자 출력

%s

String

char*, string, CString

문자열 출력

%f

Float

float

고정 소수점 형식의 실수 출력

%lf


double

고정 소수점 형식의 실수 출력

%e 또는 %E


float, double

부동 소수점 형식의 실수 출력

%g 또는 %G


float, double

%e, %f 중 

더 짧은 형식으로 출력

%p

Pointer

void *

포인터의 번지값 출력

%n



출력된 문자 개수를

포인터에 대입

%%



%문자 자체를 출력


혹시 틀린 부분이 있거나 빠진게 있을 경우, 알려주시면 감사하겠습니다.

+ Recent posts