태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

일반 C를 사용하여 Token을 하는 경우에는 그냥 strtok를 보통 사용하였습니다.

그러나 C++을 사용하게 될 때 구현하기 귀찮(?)아서 기존의 C 라이브러리 함수를 이용하게 되는데, 개인적으로

가장 자주 사용하는것이 strtok와 atoi입니다.

비주얼 스튜디오 2005 이후에서는 strtok를 이용하면 경고를 출력해줍니다.

이를 무시하고 코딩을 하는 경우가 많았는데........이를 무시하면 정말..무시무시한 디버깅의 세계로 빠져들 수 있으니 항상 조심하셔야합니다.


결론부터 말씀드리자면..strtok 함수는 비주얼 스튜디오 6.0 에서는 정상 작동하나, 그 이후 버전에서는

실행은 되지만 뒤에 쓰레기 값이 박히는 경우가 종종 발생합니다.

이를 대체하기 위해서 strtok_s를 이용하게 됩니다. 사용법은 아래 링크를 타고 가시면 됩니다.

출처 : http://harmonize84.tistory.com/112 

그런데 여기서 한가지 더 문제..strtok_s를 윈도우에서만 존재하는 함수라는 것입니다..

즉, 리눅스에서 같은 소스를 실행하면 에러가 난다는 것입니다.(물론 g++ 컴파일러 사용..)

그래서 다시 strtok로 변경하게 되면..쓰레기 값은 출력되지 않으나..자세히 보면 정상적인 출력이 아닌 경우가 발생합니다.

그래서 여기서 해결 방법은 strtok_r을 이용하는것입니다.

사용법은 man 페이지를 참고하세요 ~_~)~
예전에 map에서 key값이 아닌 value 값으로 정렬을 많이 했었는데, 항상 vector로 변환한 뒤에 sort 알고리즘을

사용했었습니다.

뭐, 이번에도 변함없이 map을 vector로 변한 한 뒤에 sort 알고리즘을 사용하여서 value로 정렬을 했습니다.

그런데..이게 무슨 일인가요..정렬알고리즘을 썼는데 정렬하지 않았을 때와 같은 내용이 파일에 써지는 것입니다!!

제 머리속이 살짝 복잡해서..이 당시에 생각했었던 알고리즘은 다음과 같습니다......멍청하게..ㅠ_ㅠ

1. map -> 변환 -> vector
2. vector - >sort
3. vector-> 변환 ->map (이게 무슨..개 풀 뜯어먹는 생각인지..)
4. 끝~

결과는 GG....이 걸로 30분을 고민했습니다.

"왜 안돼지..왜 안될까..왜 안될까.."

그러면서 1->2->3->4를 무한 반복해가면서 뭐가 잘못됐는지 계속 생각했습니다.

문득.....

1. map -> 변환 -> vector
2. vector - >sort
3. vector-> 변환 ->map (이게 무슨..개 풀 뜯어먹는 생각인지..)
제 스스로에게 : 지금 장난치냐?!?!?!?!?! 이게 왜 들어가..?!
4. 끝~

하...전 정말 바보인가 봅니다 ㅠ_ㅠ

vector<pair<int, string> > map_sort(map<string, int> &target)
{
    vector<pair<int, string> > vt;
    vector<pair<int, string> >::iterator it_vt;
    map<string, int>::iterator it_map;
    for(it_map  = target.begin(); it_map != target.end(); it_map++)
    {  
        vt.push_back(make_pair(it_map->second,it_map->first));
    }
    sort(vt.rbegin(),vt.rend());
    target.clear();
    /*
    for(it_vt = vt.begin(); it_vt < vt.end(); it_vt++)
    {
        cout<<it_vt->second<<"\t"<<it_vt->first<<endl;
        target[it_vt->second] = it_vt->first;
    }
    */
    return vt;    
}
저 빨간 부분이..바로..그....부분 입니다...하...눈물 나는군요 ㅠ_ㅠ

스팸을 분류하기 위한 여러가지 방법들이 존재하지만 그 중에서 다양한 방식으로 식이 변화되어서 쓰이고 있는

베이즈 이론이 가장 쉽고 간단하게 구현할 수 있지 않을까 생각을 해본다.

지금은 감정을 분류하기 위해서 이런 저런 방법들을 쓰고 있지만 베이지안 분류기를 사용해야 할 일이 있기 때문에 간단하게 몇 글자 적어보고자 한다.

먼저 베이즈 이론은 앞으로 일어날 일을 과거에 일어난 일을 기반으로 추정하는 것이다.

(베이즈 이론에 관한 내용은 여기저기 많으니 링크는 null....)

그리고 베이지안 분류기를 사용한 논문들의 실험을 보면 자질의 개수를 맞추는 경향이 많이 있다.

하지만 이는 베이즈 이론에서 과거에 일어날 확률에 대해서 전혀 가정을 하지 않는 꼴이 된다.

예를 들어 빨간공이 과거에 8개 나타났고 파란공이 과거에 2개 나타났다고 가정하자.

이때 빨간공일 확률을 계산 할 때는 0.8을 곱하게 되고 파란공이 나올 확률을 계산 할 때는 0.2를 곱하게 된다.

하지만 이것들을 강제적으로 빨간공을 5개로 맞추고 파란공을 5개로 맞췄다고 해보자.

이것이 과연 무슨의미가 있는 것일까....베이즈 이론은 "실제"로 일어난 일을 토대로 미래에 일어날 일을 예측 하는 것이 핵심이라고 필자는 그렇게 느끼고 있다.

그렇기 때문에 필자 역시 테스트를 해봤지만 빨간공, 파란공의 개수(feature의 개수)를 조절하지 않고서는 절대적으로 숫자가 많은 쪽에 속할 확률이 높아지게 된다.

최악의 경우에는 모두다 한쪽에 쏠리게 된다.(즉, 빨간공 재현율이 100%)

그러던 중에 여러가지 베이즈에 기반한 식들을 발견하게 되었다 그 중 대표적인 것이 Graham이다.

일단은 현재까지 이 식을 쓴 논문을 쉽게 찾을 수 없다.

이유가 뭘까 현재 곰곰히 생각중이다.

이 값을 간단하게 손으로 풀어본 결과 어느 정도 자질 개수에 영향을 받지않고 balance가 맞게 될 것 같다.

그래서 지금 이 식을 사용해 보려고 한다.

식에 대한 자세한 내용은 실험을 해본 뒤에 포스팅을 하도록 하겠다.

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#define MAX 25

typedef struct mine{
    int x;
    int y;
    int value;
    int temp;
}mine;

typedef struct me{
    int x;
    int y;
}me;

void print(mine L[])
{
    for(int i=0; i<MAX;i++)
    {
        if(i%5==0)
        {
            printf("\n");
            printf("(%d,%d)=%d\t",L[i].x,L[i].y,L[i].temp);
        }
        else
            printf("(%d,%d)=%d\t",L[i].x,L[i].y,L[i].temp);
    }
}

void clear()
{
    printf("\n\n\n\n\n\n\n\n\n\n");
}

main()
{
    int over =0;
    int map = 25;
    int num = 0;
    srand(time(NULL));
    mine L[MAX];
    me user;
    //맵의 x,y,value,temp를 초기화 한다.
    for(int i=0; i<MAX; i++)
    {
        L[i].value = 0;
        L[i].temp = 0;
        L[i].x = i/5;
        L[i].y = i%5;
    }
    //지뢰심기
    for(int k=0;k<5;k++)
    {
        num = rand() % 25;
        L[num].value=1;
    }
        
    print(L);
    //유저의 좌표 입력
    while(1)
    {
        printf("enter x,y :");
        scanf("%d",&user.x);
        scanf("%d",&user.y);
        //유저의 좌표와 지뢰의 비교
        for(int j=0;j<MAX;j++)
        {
            if(user.x==L[j].x && user.y==L[j].y)
            {
                //지뢰와 일치
                if(L[j].value == 1)
                {
                    printf("bomb!!\n");
                    over =1;
                    break;
                }
                //지뢰와 일치하지 않을때
                else
                {
                    //상단 모서리 일때
                    if(user.x==0)
                    {
                        if(user.y==0)
                        {
                            L[j].temp=L[j+1].value+L[j+5].value+L[j+6].value;
                        }
                        else if(user.y==4)
                        {
                            L[j].temp=L[j+5].value+L[j+4].value+L[j-1].value;
                        }
                        else
                            L[j].temp=L[j-1].value+L[j+1].value+L[j+4].value+L[j+5].value+L[j+6].value;
                        
                    }//하단 모서리 일때
                    else if(user.x==4)
                    {
                        if(user.y==0)
                        {
                            L[j].temp=L[j+1].value+L[j-5].value+L[j-4].value;
                        }
                        else if(user.y==4)
                        {
                            L[j].temp=L[j-5].value+L[j-6].value+L[j-1].value;
                        }
                        else
                            L[j].temp=L[j-1].value+L[j+1].value+L[j-4].value+L[j-5].value+L[j-6].value;
                        
                    }
                    //왼쪽 모서리 일때
                    else if(user.y==0)
                    {                    
                        L[j].temp=L[j+1].value+L[j-5].value+L[j-4].value+L[j+5].value+L[j+6].value;
                    }
                    //오른쪽 모서리 일때
                    else if(user.y==4)
                    {                    
                        L[j].temp=L[j-1].value+L[j-5].value+L[j-6].value+L[j+5].value+L[j+4].value;
                    }
                    //위의경우를 제외한 중심부분일때
                    else
                        L[j].temp=L[j+1].value+L[j-1].value+L[j+5].value+L[j-5].value+L[j+6].value+L[j-4].value+L[j+4].value+L[j-6].value;
                    print(L);
                }
            }
        }
        map=map-1;
        if(map==5){
            break;
        }
        if(over==1){
            break;
        }
    }
}

=========================================================================================
학부 2학년일 때 얘기군요..

그 전 제 블로그에 올려놓긴 했지만서도..일부러 부끄러워서 퍼오지 않았더랬죠 =_=;;

하지만 조금이라도 도움이 될까해서..올려봅니다.

C로만 작성한 지뢰찾기..보시면 아시겠지만 참 허접하네요 -_-;
namespace....

솔직히 전에 듣기로는 그냥 타자 여러번 치기 힘드니까 쓰는 것이라고 이해했습니다.

물론 맞는 말이기도 한 것 같습니다 =_-;

그런데 오늘 www.winapi.co.kr(나의 절대적인 레퍼런스)에서 심심해서 강의를 보는 도중 namespace

에 대해서 나와있었습니다.

"오..그렇구나..오? 오~ 오!!!! 대박인데!!!"

라고 생각을 하며 아래와 같은 소스를 실험해 봤습니다.

namespace me
{
    int a;
    int b;
    void print();
    class Test
    {
       
    };
}
void me::print()
{
    cout<<"!!"<<endl;
}

int main()
{
    me::a = 10;
    me::Test d;
    cout<<me::a<<endl;
    me::print();
    return 0;
}

결론은 다 됩니다..

구조체든..클래스든..뭐든지 간에 다 들어가서 박힐 수가 있습니다.

순간 번뜩!! 하면 뇌리를 스친 것이 있는데.....

그렇다면...클래스끼리 묶어두면 좋지 않을까? 하는 생각이 들었습니다.

함수끼리 묶어서 클래스 만들 듯이 클래스끼리 묶어서 namespace 안에 넣어두는..

그래서 선배님께 여쭤보았더니

"원래 이렇게 쓰잖아~"

두둥....역시 선배님은 모르는게 없습니다 =ㅅ=;;;

대학교 4학년에 이제야 깨우친..namespace.......

도대체 이런 것들은 누구에게 배워야 하는지..ㅠ_ㅠ

아무튼..오늘도 뇌에 나노미터의 줄을 하나 더 그었군요 =ㅅ-)v