(C 허프만)바이너리 파일 작성 질문이요..

wkdquddn8824의 이미지

char 배열을 바이너리 파일로 저장하려고 합니다.
문제가 바이너리 파일이 원본 텍스트파일보다 작아야하는데 더 커서 문제입니다.

while(fgets(text,200,f1) != NULL){
------len = strlen(text);
------for(int z = 0; z < len; z++){
------------chk_ht_index = chk_HT(text[z]);
------------if(chk_ht_index != -1){
------------------//fwrite(HT[chk_ht_index].code,sizeof(HT[chk_ht_index].code),1,f2);//이녀석으로 하면 수십배 더 커집니다.
------------------fprintf(f2, "%s", HT[chk_ht_index].code);//이녀석으로 하면 4배정도 더 커집니다.
------------}
------}
------fprintf(f2,"\n");
}

File attachments: 
첨부파일 크기
Image icon 없음.png38.18 KB
twinwings의 이미지

제 기억에 허프만 코딩이 빈도수에 따라
가변길이 코딩하는 하는 것으로 아는데
허프만 코딩하려면 비트단위로 조작해야합니다.
코드 조각만 봐선 자세히 모르겠는데

10(binary)(2bit)
110(binary)(3bit)
110(binary)(3bit)

이렇게 세 개의 데이터를 저장하려면

10110110(binary)(8bit)

요렇게 직렬화 해줘야 합니다.

제 생각에는 단순히 (허프만)인코딩된 문자를

char 단위나 int 단위로 처리해서 그런가 아닌가 싶네요

10(binary)(2bit) -> 00000010(8bit)
110(binary)(3bit) -> 00000110(8bit)
110(binary)(3bit) -> 00000110(8bit)

000000100000011000000110(24bit)

아마 열어보면 이렇게 되어 있을 것 같네요.

hex editor 같은걸로 열어서 확인해보세요.

wkdquddn8824의 이미지

http://colorscripter.com/s/XanJ7zh
위 링크는 소스코드 입니다.

char배열안에 바이너리 값이 들어있습니다.
이 char배열을 바이너리로 어떻게 바꿔줄 수 있을까요..???

첨부파일을 보면 파일을 볼 수있습니다.

twinwings의 이미지

소스코드를 저에게 주지 마시고,

바이너리 파일을 hex editor로 먼저 열어보고 분석해보세요.

wkdquddn8824의 이미지

16진수 조회한 첨부파일 붙였습니다.
조회해 보니 바이너리로 읽히지 않고있습니다...
char배열을 그대로 넣은게 원인인거 같습니다..
혹시 어떻게 이진으로 넣는지 조언해 주시면 감사하겠습니다...

댓글 첨부 파일: 
첨부파일 크기
Image icon 없음.png68.52 KB
raymundo의 이미지

char 배열을 8바이트씩 끊어가면서 8비트 값을 만들어내면 되지 싶은데요.

char pack( const char * buf ) {
    char res = 0;
 
    for ( int i = 7; i >=0 ; i-- ) {
        res |= ( *buf - '0' ) < < i;
        buf++;
    }
 
    return res;  // 이걸 파일에 저장
}

<<를 썼더니 html 이스케이프되어버려서... 위에 < < 라고 띄어 쓴 건 붙여야 하고요.

그리고 문자열의 길이가 8의 배수가 아닌 경우가 더 많을 테니 앞에 길이를 따로 저장해두던가 해야 할 것 같네요.

좋은 하루 되세요!

wkdquddn8824의 이미지

파일에 쓰려고 하는데 어떻게 써야할까요.,../? 그냥 fwrite를 사용학 되면 이상한 값이 들어가네요..

raymundo의 이미지

어떻게 쓰셨는지 적어주셔야...

제가 테스트할 때는 fwrite로 문제 없었습니다.

ch = pack( buf );
fwrite( &ch, sizeof(ch), 1, fp );

좋은 하루 되세요!

wkdquddn8824의 이미지

http://colorscripter.com/s/4KY74Wb
위 소스코드를 보시면 사용한 함수에 주석을 달아 놨습니다.
적어주신 함수의 리턴값을 char로 하니 10000101의 경우 오버플로가 발생해 -124로 나와 int형으로 바꾸어 주었습니다.

우선 문제점중 하나는 리턴 값이 제대로 들어가지 않는다는 점입니다. 첨부된 사진파일을 보시면 10000101이 133이 아닌 132로 들어가고 1000001이 65가 아닌 64로 들어가 있는걸 보실 수 있으실겁니다.

또 바이너리 파일을 저장할때 저장된 바이너리를 보고 압축을 해제해야 해서 00001의 경우 1이 아닌 0이 4개 붙어있는 00001의 형태로 붙이고 싶은데 어떻게 해야 할 수 있을까요..? 구글링에 네이버 검색까지 모두 마쳤지만 도저히 해결법을 찾을 수 없어서 죄송하지만 이렇게 질문을 남깁니다..

댓글 첨부 파일: 
첨부파일 크기
Image icon 없음.png47.64 KB
raymundo의 이미지

일단 눈으로만 봐서는...

1.

pack 에서 루프를 한 바퀴 덜 돌기 때문에 마지막 자리가 반영이 안 되고 있습니다.
i > 0 이 아니라 i >= 0 이어야죠.

2.

애초에 제가 pack 함수를 예로 들면서 말을 꺼낸 건, 최종적으로 만들어진 전체 시퀀스 ('0'과 '1'로만 구성된 수백~수천 자리의 문자열)을 가지고 바이너리로 변환하시라고 제의한 거고,
지금 하신 것처럼 허프만 코드 트리의 각 노드에 대해 binary 필드를 만들어 거기에 저장하시는 건... 그다지 좋은 생각 같지가 않습니다.

예를 들어 'k'는 '1000000', 'x'는 '1000001' 이렇게 각각 7자리인데 이게 노드에는 8자리, 게다가 질문하신 분은 int 로 바꾸셨기 때문에 32자리로 저장되는데 이걸 어떻게 파일에 저장하시려고 하시는지... 지금 저 코드는 그냥 그 binary 필드의 값을 fwrite로 적고 있으니, 압축파일의 크기는 무조건 원본 길이의 4배가 되겠네요.

"kxx" 를 압축한다면
1. 일단 원래 소스 그대로 쓰면 압축 결과물이 문자열로 만들어지니 ( "100000010000011000001" 총 21자리 ) 이걸 굳이 고칠 것 없이 여기에 추가로
2. 이 문자열을 길이가 8의 배수가 되도록 뒤에 덧붙이고 ( "100000010000011000001000" 총 24자리 )
3. 이걸 8자리씩 끊어가며 pack에 넘기면 0b10000001, 0b00000110, 0b00001000 이렇게 char 값이 세 개 나오겠죠. 이걸 파일에 순서대로 적으면 3바이트네요.
이런 식으로 하면 어떻겠냐는 거였습니다. 대신 뒤의 세 자리 덧붙인 것을 압축 풀 때 다시 잘라내야 하니까 처음의 21자리라는 정보를 따로 기록해둬야겠고요.

3.

제가 돌려보려고 했더니 리눅스에서도 맥에서도 30RT! 까지 출력된 후 테이블이 안 나오고 세그먼트 폴트가 뜨던데, 어디 메모리 접근 잘못하고 있는 곳이 있지 않은가 확인해보시고 테스트용 원본 텍스트 파일도 올려주시면 좋겠네요. 제가 일일이 디버그하면서 볼 시간은 없어서...

좋은 하루 되세요!

wkdquddn8824의 이미지

우선 정말 감사드립니다...
단지 제 질문에서 화병이 나실것만 같아 너무 죄송합니다.. 두번째로 머리 싸매는 프로그램을 작성하고 있는 터라 아직 경험이 많지 않은점을 너그럽게 봐주시면 감사하겠습니다..

1. 숫자가 제대로 나오지 않았던 문제는 해결완료 되었습니다.... 알고보면 너무 간단한 문제인데 한 번 막히다 보니까 눈에 잘 안보이게 되어 너무 의지를 하게 되었습니다. 죄송하고 감사합니다.

제안해 주신 2번에 대해 질문이 있습니다.

텍스트 파일이 중복된 알파벳만 있지 않는 이상 최소한 7자리를 넘을것입니다. 현제 제 택스트 파일인

They scaled score is between 400 and 495.
Test taker who score around 400 typically have the following strengths.
They can infer the central idea, purpose, and basic context of short spoken exchanges
across a broad range of vocabulary, even when conversational responses are indirect or
not easy to predict.

만 하더라도 8자리를 넘어가는 알파벳 코드(?)가 있습니다. char은 -128 ~ 127까지가 범위인데 8자리를 넘어가게 되면 바로 오버플로우가 발생하여 제대로된 리턴값을 받지 못하는데 답변해주신 내용을 보면 8의 배수로 문자열을 만들어 8자리씩 끊어서 char를 리턴해 주는 pack함수에 넘기라고 하셨는데 8자리가 되면 10000001가 넘어가기만 하더라도 129로 오버플로우 발생으로 음수 값이 나오게 되는데 제대로 된 값을 얻을 수 있을까요?? 그리고 8의 배수가 되도록 문자열 뒤에 0을 덧붙이는데 덧붙이게 되서 나중에 해석할 때 다른 문자코드와 중복이 되어 잘못 해석 할 수도 있지 않을까요??

마지막으로 다시 코드를 올려드립니다.. 유닉스 서버에서 문제없이 돌아감을 확인했습니다. 실행시 매개변수로 txt파일, out_txt파일 압축해제_txt파일을 주어야 실행이 가능합니다.. 단지 out.txt파일이 불가능 할 뿐입니다..
텍스트 파일은 위 내용입니다. out파일은 이상한 특수문자 ( }▒▒C*z@)로 나와서 따로 올려 드리진 않겠습니다.
첨부된 사진파일은 실행 한 화면 입니다.
http://colorscripter.com/s/L7KCfbR
죄송하고 감사합니다.

댓글 첨부 파일: 
첨부파일 크기
Image icon 없음.png85.59 KB
raymundo의 이미지

화병이 날 상황이라면 신경 끊고 답글 달지 않을테니 너무 걱정하지 않으셔도 되고요 ^^;

계속 오버플로우 걱정을 하시는데... 지금 무엇을 했고 앞으로 무엇을 해야 하는지 혼동하시는 것 같습니다.

애초에 문제가 뭐였냐 하면,
허프만 코드를 써서 압축을 했더니 원본보다 더 커져버렸다! 였습니다.
그래서 다른 분 리플도 그렇고 직접 확인을 하셨다시피,
비트열을 바이너리 파일로 저장해야 할 것을 (01001101 - 8비트, 1바이트) 문자열로 텍스트 파일에 저장하고 ( "01001101" - 8바이트 ) 있기 때문에, 무조건 원본보다 커지고 있죠. (1자리 코드로 변환되는 경우 A => "0" 에 한해서 원본과 크기가 같을 것이고, 2자리 이상이면 무조건 커지니까)
그래서 원래 문자열로 저장되고 있는 것을, 비트열로 변환해야 하는 게 앞으로 해야 할 일인 거였죠.
(물론 애초에 문자열을 거치지 않고 비트열로 바로 구성하면 일이 줄어들 수도 있겠지만, 그러면 임의의 길이의 비트(어떤 문자는 1비트로 변환, 어떤 문자는 3비트로 변환...)를 계속 이어나가는 연산을 해야 하는데 제 생각에는 그게 더 까다로워보입니다)

그러니,
여기서 할 일은 "원본 텍스트를 변환하여 만들어진, '0'과 '1'로 조합된, 길이가 수 바이트일 수도 수십 바이트일 수도 수만 바이트일 수도 있는 **최종 결과물 문자열을 비트열로 변환**하는 것입니다.
따라서 원본의 각 문자들이 몇 자리 코드로 변환되느냐는 전혀 상관없는 얘기입니다.

예를 들어
매우 빈번하게 등장하는 A는 "0"으로 변환됨
매우 드물게 등장하는 Z는 "1101 0101 10" 이렇게 10자리로 변환됨

그러면 원본 문자열이 "AAZ"라면 변환한 문자열은 "0 0 1101 0101 10" 이죠. 12바이트. 이걸 파일로 저장하면 3바이트 원본이 12바이트 압축본이 되어서 크기가 네 배가 되어 버립니다.
이걸 12비트 001101010110 으로 만들어 저장하면 1.5바이트니까 크기가 절반이 되죠.

그런데 문제는 파일의 저장 단위는 비트가 아니라 바이트니까, 12비트만 저장할 방법이 없고 4비트를 더해서 16비트를 만들어야 하는 겁니다.

                  A A Z
문자열:           0 0 1101010110
4비트 패딩 추가:  0 0 1101010110 0000
첫 8바이트     :  0 0 110101
이걸 char로 압축:  00110101            - 파일에 저장
다음 8바이트   :            0110 0000
이걸 char로 압축:           01100000   - 파일에 저장

그러니 8바이트를 char로 압축하는 것은 개별 문자들의 허프만 코드가 몇 자리냐는 전혀 상관없는 얘깁니다. 아니 저 "001101010110"이 허프만 코딩을 해서 나왔건 고양이가 키보드를 가지고 놀다가 입력한 것이었건 상관없는 얘기인 거죠.
오버플로우 걱정을 하실 필요가 없습니다. 우리는 항상 한번에 8바이트씩만 읽을 것이고, 한 바이트마다 한 비트로 변환될 것이며, char 는 8비트를 담을 수 있으니까.
또한 제일 첫 비트가 1이라서 음수가 되는 것도 신경쓸 필요 없습니다. 우리는 산술 연산을 하려는 게 아니라 그저 비트열을 파일에 저장하는 게 목적이니까. 디버그 과정에서 음수로 출력되는 게 정 눈에 거슬리면 unsigned char 로 선언하고 printf 출력도 %d 대신에 %u로 하세요.

딱 하나 문제가 되는 것은 말씀하신 대로 8의 배수를 만들기 위해 덧붙이는 값입니다.
저걸 그대로 역순으로 변환해나가면
00110101 01100000 - 2바이트 바이트열
"00110101 01100000" - 16바이트(뒤에 널 캐릭터 붙는 건 무시하고) 문자열
"AAZAAAA" - 저 문자열을 가지고 허프만 코드를 써서 복원한 텍스트
이런 식으로 뒤에 덧붙인 게 엉뚱한 결과가 되겠죠.

이 문제의 해결 방법은
1) 압축파일을 저장할 때 제일 앞에는 변환 결과 문자열의 길이(이 경우 12)를 저장하고, 복원할 때도 그 값을 읽은 후 그 뒤에 있는 문자열에서 그 길이만큼만 남기고 뒤는 잘라냄
2) 아니면, 허프만 코드 테이블에 강제로 "1111111111111111" 이런 코드(길이는 다른 어느 문자의 코드보다도 긴)에 대응되는 엔트리를 하나 추가하고, 덧붙일 때 '1'로 덧붙이세요. 그럼 복원할 때 "AAZ"까지 복원한 상태에서 나머지 "1111"을 읽다보면 아직 트리의 단말 노드까지 도착하지 못하 상태에서 입력이 더 이상 없는 상태가 되겠죠. 이런 상태를 에러로 처리하지 말고 무시하게 하면 되겠네요. 근데 제 생각에는 이런 엔트리를 억지로 추가하는 것보다는 1)의 방법이 낫지 싶고요.
3) 아니면,... 여기 계신 고수님들이 더 좋은 방법을 이 아래 적어주실 거예요 :-)

코드 돌려보는 건 제가 시간 날 때 해보겠습니다.

---------------

살펴봤는데, 코드에 메모리 접근 관련한 버그가 있습니다.

예를 들어 원본 문자열이 "AABC" 였다면,

void mk() {//make the Huffman Tree
    int rt = HT_SIZE;      // HT_SIZE가 3이니 rt는 3부터 시작
 
    int size = ((HT_SIZE - 1) * 2);   // size = 4
    Tree node[size];    // node 테이블의 크기도 4
 
    if(node[rt].left == NULL && node[rt].right == NULL) {   // 이 시점에 rt = 3
       ...
        rt++;    // 이제 rt = 4
    }
    for(int i = 1; i < (size- HT_SIZE)+1  ; i++){    // i 는 1부터 1까지 한 번 반복
      ...
 
     // 현재 rt 가 4이니까
     // node 테이블의 크기가 4인데 node[4] 에 값을 써넣고 있습니다.
        node[rt].val = node[min[0].index].val + node[min[1].index].val;
        node[rt].left = &node[min[0].index];
        node[rt].right = &node[min[1].index];
    }
 
// 할당받은 node 테이블 범위 밖에다가 값을 썼기 때문에, node[4] 위치는 다른 변수 또는 함수호출 스택에서 사용되고 있을 수 있습니다.
// 그래서 제 컴퓨터에서 할 때는 그 다음 "make char code" 루프를 도는 시점에 값이 바뀌어버렸더군요.
	for(int g = 0; g < HT_SIZE; g++){// make char code
               ...
                // 원래는 node[4].dad_val 이 \0 이니까 여기까지 와서 끝나야 하는데
                // 값이 바뀌어 버리는 바람에 루프를 한 번 더 돌고
                // 그 다음 node[g].dad 에 엉뚱한 값이 들어있는 상태에서 *로 접근하다가 죽습니다.
		for(int index = 0; node[g].dad_val != '\0'; index++){
			code_tmp[ index] = node[g].dad_val;
			node[g] = *node[g].dad;
		}
	}

제 계산으로는 (이게 좀 자신이 없지만) size 값은 HT_SIZE + HT_SIZE - 1 ( = HT_SIZE * 2 - 1 )이어야 합니다. HT_SIZE 개의 원소를 토너먼트로 비교하면서 마지막 하나를 남기려면 HT_SIZE - 1 번 비교해야 하고, 비교할 때마다 매번 새로운 부모 노드가 생기니까. 그리고 그 아래 i 루프는 HT_SIZE - 2 번 반복해야 하니 i = 1 부터 i <= HT_SIZE - 2 아니면 i < size - HT_SIZE 정도로 쓰면 되겠네요.

좋은 하루 되세요!

익명 사용자의 이미지

댓글 감사합니다...
답글 달아주신 내용은 모두 이해를 하였습니다.. 하지만 제가 비트연산 자체를 해 본 적이 없어서 지금 인터넷을 찾아 보면서 하는데 역시 해 본적이 없어서 많은 어려움을 겪고 있습니다..
비트연산이라고 배울때는 <<, >>를 어떻게 쓰는지만 가르쳐 주고 잘 안쓰는 내용이니 비트연산은 넘어갔었습니다...
구글링해서 허프만 압축 코드를 찾아 봐도 무슨 소리인지 모르는 상황이니...
정말 죄송하지만 혹시 예제 같은곳을 볼 만한 곳을 알고 계시다면 가르쳐 주실 수 있으신가요..??? 인터넷 커뮤니티에 글을 올려 보고 찾아봐도 제가 원하는 답이 잘 안나옵니다...
염치를 불구하고 송구스럽지만 부탁드립니다....

wkdquddn8824의 이미지

..

raymundo의 이미지

글쎄요, 말씀하신 예제가 비트연산 예제인지 허프만 코딩 예제인지 모르겠는데, 비트연산 예제야 구글에 "비트 연산 예제"라고만 해도 숱하게 많고...

허프만 코딩 예제는 확실히 남이 짠 접근방법이 다르면 바로 적용하긴 어렵겠죠. 아래는 저도 그냥 방금 구글링해본 겁니다만.
http://bencrow.tistory.com/entry/%EC%95%95%EC%B6%95-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%86%8C%EC%8A%A4-%EB%B0%8F-%EC%A0%95%EB%A6%AC
http://www.programminglogic.com/implementing-huffman-coding-in-c/
https://www.daniweb.com/programming/software-development/code/216267/huffman-algorithm-implementation-in-c

솔직히 말씀드려서... 이진 트리를 만들고 변환 문자열을 만드는 과정이 훨씬 더 어렵지 싶은데 그 부분은 (앞서 언급한 루프 횟수 계산 오류 빼고는) 제대로 만드셨으면서 여기서 애를 먹으시는 게 잘 이해가 안 된달까요.

pack함수의 원리는 이런 겁니다.

만일 문자열이 "01101010" 이라면
 
첫번째 루프는 생략하고 두번째 루프( i가 6일 때 )에서
*buf 는 '1'
여기에 '0'을 빼면 '1' - '0' = 49 - 48 = 1
이걸 왼쪽으로 6비트 쉬프트하면 01000000
이걸 res 와 OR 연산하면
   00000000
OR 01000000
-----------
 = 01000000   (각 비트마다 비교해서 어느 한쪽이라도 1이면 결과도 1)
 
마찬가지로 세번째 루프에서
1을 왼쪽으로 5비트 쉬프트하면 00100000
이걸 res 와 OR 하면
   01000000
OR 00100000
-----------
 = 01100000
 
...
 
루프를 다 돌면 res 는
   01101010

아래는 임의의 길이의 문자열을 압축해서 바이너리로 저장하는 코드입니다. 최대한 직관적으로 만든건데(pack도 살짝 바꿨으나 원리는 똑같습니다) 참고가 되려나 모르겠네요.

#include <stdio.h>
#include <string.h>
 
 
unsigned char pack( char *str ) {
    unsigned char result = 0;
 
    for (int i = 7; i >= 0; i--) {
        if ( *str == '1' ) {
            result = result | ( 1 < < i );  // < < 는 붙여서
        }
        str++;
    }
 
    return result;
}
 
 
int main() {
    // 기록할 시퀀스
    char buf[40] = "010000010100001001000011010";  // 27자
 
    // 시퀀스의 원래 길이
    int str_len = strlen( buf );                        // 27
    // 8의 배수로 맞추기 위해서 몇을 더해야 하나?
    int padding_len = ( 8 - ( str_len % 8 ) ) % 8;      // 5
    // 필요한 만큼 '0'을 추가
    for (int i=0; i<padding_len; i++) {
        strcat(buf, "0");
    }
 
    // 파일에 기록
    FILE * fp = fopen("output.bin", "wb");
    char * buf_ptr = buf;   // 첫 글자를 가리키게 하고
    for (int i=0; i*8 < strlen(buf); i++) {
        // buf_ptr이 가리키는 곳부터 8바이트를 unsigned char 한 바이트로 압축
        unsigned char byte = pack( buf_ptr );
        // 파일에 기록
        fputc( byte, fp );
 
        // 그 뒤의 8바이트를 읽기 위해 이동
        buf_ptr += 8;
    }
    fclose(fp);
}

$ hexdump -C output.bin
00000000  41       42       43       40                                       |ABC@|
          01000001 01000010 01000011 01000000 (27+5 = 32비트)

좋은 하루 되세요!

wkdquddn8824의 이미지

도와주신 덕분에 방금 바이너리로 입출력, 그리고 바이너리 파일을 해독하여 원본파일과 똑같이 파일이 만들어 졌습니다. 파일크기는 3.32Kb - > 2.7Kb로 압축률이 크지는 않은거 같지만 완성했습니다!!!

이 감사함을 어떻게 전해드려야 할지 잘 모르겠습니다..
정말 진심으로 감사드립니다..
raymundo님이 안계셨더라면 아마 완성하지 못했을 과제입니다.
정말 감사드립니다.
기프티콘이라도 보내드리고 싶습니다..

raymundo의 이미지

축하드립니다 :-)

어려운 부분은 다 직접 해놓으신 상태였는데요 뭘.

압축률은... 원본에 들어있는 문자의 가짓수에 따라서 달라질 수 있을 것 같네요. 제가 테스트할 때는 13739바이트짜리 원본이 64314자리의 0/1 시퀀스가 되고 이걸 바이너리로 만드니까 4바이트(길이)+8040(패킹된 비트열) = 8044바이트짜리가 되어서 원본의 58% 정도로 줄었었거든요.

좋은 하루 되세요!

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.