레이블이 c인 게시물을 표시합니다. 모든 게시물 표시
레이블이 c인 게시물을 표시합니다. 모든 게시물 표시

2017년 5월 28일 일요일

load & load file with header in C ( C언어에서 헤더있는 file 저장과 읽기 )

load & load file with header in C ( C언어에서 헤더있는 file 저장과 읽기 )

헤더를 가지는 file의 save, load 입니다.

저장시 : header + 실제 데이터
로딩시 : header + 실제 데이터

typedef struct {
 char header_str[4];
 long int real_size;
}data_header;
헤더는 data_header 구조체로 만들어서 data의 앞쪽에 먼저 저장해서, 로딩시에는 처음 로딩이 됩니다.

long int load_file_with_header(char *filename, char *buf, long int buf_size, char *header, long int header_size)
filename : 읽고자 하는 파일이름
buf : 읽어서 저장되는 data buf 
buf_size : data buf 에 얼마나 읽어야 하는지에 대한 정보, 읽는양
header : header구조체의 pointer
header_size : 헤더의 크기

long int save_file_with_header(char *filename, char *buf, long int buf_size, char *header, long int header_size)
filename : 저장하고자 하는 파일이름
buf : 저장하고자 하는 data buf 
buf_size : data buf_size 크기정보
header : header구조체의 pointer
header_size : 헤더의 크기


헤더를 가지는 file의 save, load 예제
#include <stdio.h>
#include <stdlib.h>

typedef struct {
 char header_str[4];
 long int real_size;
}data_header;

long int load_file_with_header(char *filename, char *buf, long int buf_size, char *header, long int header_size)
{
 FILE *fp;
 long int rwsize1 = 0;
 long int rwsize2 = 0;
 fp = fopen(filename,"rb");
 if(fp==NULL) return -1;
 
 rwsize1 = fread(header,1,header_size,fp);
 if(rwsize1<=0){
  fclose(fp);
  return -1;
 }
 
 rwsize2 = fread(buf,1,buf_size,fp);
 if(rwsize2<=0){
  fclose(fp);
  return -1;
 }
 fclose(fp);
 return rwsize1+rwsize2;
}

long int save_file_with_header(char *filename, char *buf, long int buf_size, char *header, long int header_size)
{
 FILE *fp;
 long int rwsize1 = 0;
 long int rwsize2 = 0;
 fp = fopen(filename,"wb");
 if(fp==NULL) return -1;
 
 rwsize1 = fwrite(header,1,header_size,fp);
 if(rwsize1<=0){
  fclose(fp);
  return -1;
 }

 rwsize2 = fwrite(buf,1,buf_size,fp);
 if(rwsize2<=0){
  fclose(fp);
  return -1;
 }
 fclose(fp);
 return rwsize1+rwsize2;
}

// it returns sizes of file.
// if have an error, it will return the value minus.
long int get_file_length(char *filename)
{
 long int length = 0;
 FILE *fp;
 fp = fopen(filename,"rb");
 if( fp == NULL ) return -1;
 fseek(fp,0,2);
 length = ftell(fp);
 fclose(fp);
 return length;
}

int main()
{
 char data[]={'D','a','t','a','\n'};
 char *loaddata;
 long int size;
 data_header header_load;
 data_header header_save;
 
 header_save.header_str[0]='H';
 header_save.header_str[1]='E';
 header_save.header_str[2]='A';
 header_save.header_str[3]='D';
 header_save.real_size = sizeof(data);
 
 printf("saved size : %ld\n",save_file_with_header("sample.dat",data,sizeof(data),(char *)&header_save,sizeof(header_save)));
 
 size = get_file_length("sample.dat");
 loaddata = malloc(size+1-sizeof(header_save)); 
 printf("load size : %ld\n",load_file_with_header("sample.dat",loaddata,size-sizeof(header_save),(char *)&header_load,sizeof(header_load)));
 loaddata[size] = 0;
 
 printf("header:%c%c%c%c %ld\n",header_load.header_str[0],header_load.header_str[1],header_load.header_str[2],header_load.header_str[3],
  header_load.real_size);
 printf("data:%s\n",loaddata);
 free(loaddata);
 return 1;
}


실행 결과
E:\blogdata>gcc save_load_file_with_header.c

E:\blogdata>a
saved size : 13
load size : 13
header:HEAD 5
data:Data


E:\blogdata>dir sample.dat
 E:\blogdata 디렉터리

2017-05-28  오후 09:01                13 sample.dat
               1개 파일                  13 바이트



save & load file example in C ( c 언어 file 저장 읽기 예제 )

C 언어 file 저장 읽기 예제 입니다.


save_file 에서는 fwrite 함수를 이용합니다. 전체적으로 write되는 양은 rwsize = fwrite(buf,1,datasize,fp); 이런 함수에서 1*datasize 가 됩니다. rwsize = fread(buf,1,fsize,fp); 읽을때도 1*fsize만큼 읽습니다.
읽을때는 배열의 크기를 미리 할당해서 해당 크기만큼 읽도록 합니다.
저장시에는 저장된 배열과 크기를 함께 넘기도록 합니다.

long int load_file(char *filename, char *buf, long int fsize)
filename : 읽어오는 파일의 이름입니다.
buf : 읽어오는 데이터를 저장하는 buffer입니다. 미리 메모리 할당이 되어있어야 합니다.
fsize : 읽어올때의 양을 설정합니다. byte 단위

long int save_file(char *filename, char *buf, long int datasize)
filename : 저장할때 파일의 이름입니다.
buf : 저장하고자 하는 데이터가 저장된 buffer입니다.
datasize : buf의 크기를 나타냅니다. byte 단위

long int get_file_length(char *filename)
아래 함수에 대한 설명이 있습니다.
http://swlock.blogspot.com/2017/05/get-filesize-function-in-c-file-in-c.html

load_file, save_file 예제
#include <stdio.h>
#include <stdlib.h>

// load filedata in buf.
// You should set a filesize in advance.
long int load_file(char *filename, char *buf, long int fsize)
{
 FILE *fp;
 long int rwsize = 0;
 fp = fopen(filename,"rb");
 if(fp==NULL) return -1;
 
 rwsize = fread(buf,1,fsize,fp);
 
 if(rwsize<=0){
  fclose(fp);
  return -1;
 }
 fclose(fp);
 return rwsize;
}

// save file.
long int save_file(char *filename, char *buf, long int datasize)
{
 FILE *fp;
 long int rwsize = 0;
 fp = fopen(filename,"wb");
 if(fp==NULL) return -1;
 
 rwsize = fwrite(buf,1,datasize,fp);
 
 if(rwsize<=0){
  fclose(fp);
  return -1;
 }
 fclose(fp);
 return rwsize;
}

// it returns sizes of file.
// if have an error, it will return the value minus.
long int get_file_length(char *filename)
{
 long int length = 0;
 FILE *fp;
 fp = fopen(filename,"rb");
 if( fp == NULL ) return -1;
 fseek(fp,0,2);
 length = ftell(fp);
 fclose(fp);
 return length;
}

int main()
{
 char data[]={'D','a','t','a','\n'};
 char *loaddata;
 long int size;
 printf("saved size : %ld\n",save_file("sample.dat",data,sizeof(data)));
 size = get_file_length("sample.dat");
 loaddata = malloc(size+1);
 printf("load size : %ld\n",load_file("sample.dat",loaddata,sizeof(data)));
 loaddata[size] = 0;
 printf("data:%s\n",loaddata);
 free(loaddata);
 return 1;
}

실행 예제
E:\blogdata>gcc load_save_file.c

E:\blogdata>a
saved size : 5
load size : 5
data:Data


E:\blogdata>dir *.dat

2017-05-28  오후 08:01                 5 sample.dat
               1개 파일                   5 바이트

E:\blogdata>type sample.dat
Data



( get filesize function in C ) file의 크기 구하기 in C

C 언어 file의 크기 구하기


파일의 크기는 ftell과 fseek라는 함수를 이용해서 구할 수 있습니다.
ftell은 파일에서 읽는 위치를 나타내는 함수인데, fseek가 파일의 위치를 이동할 수 있습니다.
fseek(fp,0,2); 라고 호출하면 2:제일 마지막에서 0:첫번째 위치가 되어서 마지막 위치로 이동하게 됩니다.
아래는 구현한 함수 입니다.

get file length
#include <stdio.h>

// it returns sizes of file.
// if have an error, it will return the value minus.
long int get_file_length(char *filename)
{
 long int length = 0;
 FILE *fp;
 fp = fopen(filename,"rb");
 if( fp == NULL ) return -1;
 fseek(fp,0,2);
 length = ftell(fp);
 fclose(fp);
 return length;
}

int main(int argc, char *argv[])
{
 long int size;
 size = get_file_length(argv[1]);
 printf("file size:%ld\n",size);
 return 0;
}

get_file_size.c 파일의 크기가 452 byte 일때

실행화면
E:\download\data>gcc get_file_size.c

E:\download\data>a get_file_size.c
file size:452






2016년 11월 13일 일요일

중복 순열 (Permutation) 조합(combination)알고리즘 생성 방법 algorithm (full search 부터 이해)

중복 순열 (Permutation) 조합(combination)알고리즘 생성 방법 algorithm (full search 부터 이해)


앞에서 아래와 같이 정리했었습니다.

N=3 {1,2,3} 존재시 R=2
순열은 N개의 항목에서 R개를 선택할때 순서를 가지면서 나열하는 방법입니다.
{1,2},{1,3},{2,1},{2,3},{3,1},{3,2}

중복 순열은 R개 선택시 중복이 가능하다는 의미입니다.
{1,1},{1,2},{1,3},{2,1},{2,2},{2,3},{3,1},{3,2},{3,3}

조합은 N개의 항목에서 R개를 선택할때 순서를 갖지지 않은면서 나열하는 방법입니다.
{1,2},{1,3},{2,3}

중복 조합은 R개 선택시 중복이 가능하다는 의미입니다.
{1,1},{1,2},{1,3},{2,2},{2,3},{3,3}


일단 전체 탐색을 하는 내용을 그림으로 정리해 보겠습니다.


그림이 커져서 오른쪽 절반 정도는 그림을 생략하였습니다.
이 그림의 의미는 4개의 data가 주어질때 3개를 선택하는 방법에 대한 내용입니다. 순열로 할지 조합을 할지 중복이 되게 할지는 아직 고민하지 않고 그린 그림입니다.
선택을 할때마다 depth가 증가하게 됩니다. R이 depth가 되면 선택된 항목을 출력하면 될겁니다.
아래는 2->3->1 3개를 선택하는 순서를 나타냅니다.



각각 선택해서 출력하는 알고리즘 입니다. 즉 처음에는 1-1-1, 그리고 1-1-2, 1-1-3, 1-1-3, 1-1-4, 1-2-1 ... 이런식으로 출력이되어야 합니다.
이걸 코드로 구현해 보도록 하겠습니다.

그래서 첫번째 depth 0 에서는 1, 2, 3, 4 른 순차적으로 선택한 후 다음 depth로 넘기는 과정이 필요합니다.
코드를 대충 만들어 보면 아래와 같습니다.
full()
{
  int i;
  for(i=1;i<=N;i++){
    selected[]=i;
    full(depth+1);
  }
}
그다음 고민해볼것은 선택되는것을 어디엔가 저장해야할텐데요 그걸 selected 배열에 넣었습니다. 순차적으로 뒤에 추가해주면 됩니다.
그림에서 잘보면 depth가 증가될때마다 하나씩 선택되고 있기 때문에 선택되는 갯수는 depth의 수와 일치합니다.
따라서 선택 하는 코드는 selected[]=i; => selected[depth]=i; 로 해주면 됩니다.
그리고 전체적으로 얼마나 depth가 진행되고 있는지 depth를 인자로 넘겨받아야 할 겁니다.
지금까지 코드를 만들어 보면 아래와 같습니다.
full(int depth)
{
  int i;
  for(i=1;i<=N;i++){
    selected[depth]=i;
    full(depth+1);
  }
}

full(depth+1); 함수 호출 후 복귀했을때 다른 값을 선택해야 합니다. 즉 이 의미는 아래와 같이 복귀하게되면 더이상 이전에 선택했던것을 취소해야한다는 의미입니다.
아래과 같이 구현해야합니다.
    selected[depth]=i;
    full(depth+1);
    selected[depth]=-1;
하지만 아래 그림을 보면 다시 해당 depth로 돌아왔을때 새로 선택하는 index가 depth에 의해 결정되므로 이전 선택했던 depth를 취소할 필요는 없습니다. 즉  selected[depth]=-1; 이건 다음번 loop를 진행할때 selected[depth]=i; 이 코드에 의해서 필요없는 코드라는 의미입니다.

마지막으로 종료하는 코드를 넣어야 합니다.
재귀 종료 조건은 여기에서는 3개 선택될때까지, R=3 즉 R==depth 가 되면 모두 선택하고나서 다시 재귀를 들어왔다는 의미입니다. depth 가 0일때 하나를 선택하게되고 R=depth-1 일때 모두 선택이 되고 다음번 depth가 되는 재귀함수를 들어올때 모두 선택이 완료되게 됩니다.

void full(int depth)
{
  int i;
  if( R==depth){
    // 모두 선택 되었음 출력하기
    for(i=0;i<N;i++){
      printf("%d ",selected[i]);
    }
    printf("\n");
    return;
  }
  for(i=1;i<=N;i++){
    selected[depth]=i;
    full(depth+1);
  }
}

아래는 완성된 코드입니다.

Cpasted 1 second ago: 
#include <stdio.h>

#define N 4
#define R 3

int selected[R];

void full(int depth)
{
  int i;
  if( R==depth){
    // 모두 선택 되었음 출력하기
    for(i=0;i<R;i++){
      printf("%d ",selected[i]);
    }
    printf("\n");
    return;
  }
  for(i=1;i<=N;i++){
    selected[depth]=i;
    full(depth+1);
  }
}

int main()
{
  full(0);
  return 0;
}


Output:
1 1 1 
1 1 2 
1 1 3 
1 1 4 
1 2 1 
1 2 2 
1 2 3 
1 2 4 
1 3 1 
1 3 2 
1 3 3 
1 3 4 
1 4 1 
1 4 2 
1 4 3 
1 4 4 
2 1 1 
2 1 2 
2 1 3 
2 1 4 
2 2 1 
2 2 2 
2 2 3 
2 2 4 
2 3 1 
2 3 2 
2 3 3 
2 3 4 
2 4 1 
2 4 2 
2 4 3 
2 4 4 
3 1 1 
3 1 2 
3 1 3 
3 1 4 
3 2 1 
3 2 2 
3 2 3 
3 2 4 
3 3 1 
3 3 2 
3 3 3 
3 3 4 
3 4 1 
3 4 2 
3 4 3 
3 4 4 
4 1 1 
4 1 2 
4 1 3 
4 1 4 
4 2 1 
4 2 2 
4 2 3 
4 2 4 
4 3 1 
4 3 2 
4 3 3 
4 3 4 
4 4 1 
4 4 2 
4 4 3 
4 4 4 



순열 만들기
http://swlock.blogspot.com/2016/11/permutation-combination-algorithm_13.html
조합 만들기
http://swlock.blogspot.com/2016/11/permutation-combination-algorithm_45.html

중복 순열 (Permutation) 조합(combination)알고리즘 생성 방법 algorithm (combination 구현)

중복 순열 (Permutation) 조합(combination)알고리즘 생성 방법 algorithm (combination 구현)

이전글
http://swlock.blogspot.com/2016/11/permutation-combination-algorithm-full.html

계속해서 조합에 대해 알아보겠습니다.
출발은 full search에서부터 출발합니다.

여기에서 조합할때 선태되는 부분에 원을 그려보도록 하겠습니다.

중복이 안되어야하고 순서도 관계없으니 {1,2,3} {1,2,4} {1,3,4} {2,3,4} 더는 없는것 같습니다.
그림을 봐서는 어떤 규칙성을 찾기가 어려워 보입니다.



루프를 돌기 위한을 시작점의 숫자에서, 부모 depth 와 자식 depth와의 관계에서 보면 자식은 부모 +1 만큼 더해주는 위치에서 시작합니다.  왜냐하면 순열과 다르게 조합은 부모보다 같거나 작은 index의 경우 이미 검토가 끝났기 때문입니다. 이것을 코드로 구현해보면 다음과 같습니다.

void full(int depth,int index)
{
  int i;
  if( R==depth){
    // 모두 선택 되었음 출력하기
    return;
  }
  for(i=index;i<=N;i++){
    selected[depth]=i;
    full(depth+1,i+1);
  }
}
주의할점은 재귀 호출시 여기 예제에서는 1부터 나오기 때문에 시작지점을 1로 호출했습니다. 아래 완성된 코드를 보면 됩니다.


Cpasted just now: 
#include <stdio.h>

#define N 4
#define R 3

int selected[R];

void full(int depth,int index)
{
  int i;
  if( R==depth){
    // 모두 선택 되었음 출력하기
    for(i=0;i<R;i++){
      printf("%d ",selected[i]);
    }
    printf("\n");
    return;
  }
  for(i=index;i<=N;i++){
    selected[depth]=i;
    full(depth+1,i+1);
  }
}

int main()
{
  full(0,1);
  return 0;
}


Output:
1
2
3
4
1 2 3 
1 2 4 
1 3 4 
2 3 4 

그리고 좀 더 성능을 높이기 위해서는 여기에서는 2,3,4 까지 진입하게되는데 4는 진입할 필요가 없으므로 i<=N 조건을 추가로 변경이 가능하리라 봅니다.

이번에는 중복이 가능한 조합을 살펴보겠습니다.
중복 가능한 조합의 경우 그림에 표시를 해봤습니다. 빨간색


자식과 부모의 관계를 파란색으로 표시해봤습니다.
자식의 loop와 부모 loop의 index가 동일하게 하면 될것 같습니다.
소스에서 i+1 => i 로 변경하면 됩니다.
void full(int depth,int index)
{
  int i;
  if( R==depth){
    // 모두 선택 되었음 출력하기
    return;
  }
  for(i=index;i<=N;i++){
    selected[depth]=i;
    full(depth+1,i);
  }
}


Cpasted 1 second ago: 
#include <stdio.h>

#define N 4
#define R 3

int selected[R];

void full(int depth,int index)
{
  int i;
  if( R==depth){
    // 모두 선택 되었음 출력하기
    for(i=0;i<R;i++){
      printf("%d ",selected[i]);
    }
    printf("\n");
    return;
  }
  for(i=index;i<=N;i++){
    selected[depth]=i;
    full(depth+1,i);
  }
}

int main()
{
  full(0,1);
  return 0;
}


Output:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
1 1 1 
1 1 2 
1 1 3 
1 1 4 
1 2 2 
1 2 3 
1 2 4 
1 3 3 
1 3 4 
1 4 4 
2 2 2 
2 2 3 
2 2 4 
2 3 3 
2 3 4 
2 4 4 
3 3 3 
3 3 4 
3 4 4 
4 4 4 



중복 순열 (Permutation) 조합(combination)알고리즘 생성 방법 algorithm (Permutation 구현)

중복 순열 (Permutation) 조합(combination)알고리즘 생성 방법 algorithm (Permutation 구현)


이전글
http://swlock.blogspot.com/2016/11/permutation-combination-algorithm-full.html

계속해서 순열에 대해서 알아보겠습니다.
앞에서 full search에대해서 아래 그림을 그렸습니다.




위 그림중에 순열이 가능한 부분을 표시해 보자면 아래와 같습니다. 아래는 첫번째로 선택이  되는 항목입니다. 순열이란 주어진 data={1,2,3,4} 에서 원소를 뽑아서 나열하는데 중복이 안되도록 하나씩 뽑는겁니다. 물론 순서가 있고요.. R=3일때 3개를 뽑아보자면 {1,2,3} 이 될겁니다. {1,1,1},{1,1,2}.. 이런건 중복되기 때문에 뽑을수가 없습니다.

그럼 이전 소스를 다시가져와서 고민해 보도록 하겠습니다.
void full(int depth)
{
  int i;
  if( R==depth){
    // 모두 선택 되었음 출력하기
    return;
  }
  for(i=1;i<=N;i++){
    selected[depth]=i;
    full(depth+1);
  }
}
위 그림을 자세히 살펴보면 앞에서 이미 선택한 부분에 대해서는 선택을 안하도록 하면 됩니다. 그렇게 하기위해서는 선택했는지 flag가 필요하고 flag를 보고 선택을 하면 될겁니다.
void full(int depth)
{
  int i;
  if( R==depth){
    // 모두 선택 되었음 출력하기
    return;
  }
  for(i=1;i<=N;i++){
    if(flag[i]==1)continue;
    flag[i]=1;
    selected[depth]=i;
    full(depth+1);
  }
}
아주 훌륭합니다.
이렇게하면 결과가 아라와 같이 나옵니다.
1
2
1 2 3 
1 2 4 

왜냐하면 한번 선택된 flag를 제거해주는 곳이 없습니다.
그래서 selected 변수에서도 언급했지만 선택하고나서 다음 재귀를 호출한뒤 복귀시에는 flag를 꺼줘야합니다.
void full(int depth)
{
  int i;
  if( R==depth){
    // 모두 선택 되었음 출력하기
    return;
  }
  for(i=1;i<=N;i++){
    if(flag[i]==1)continue;
    flag[i]=1;
    selected[depth]=i;
    full(depth+1);
    flag[i]=0;
  }
}

아래는 전체 코드 입니다.
순열 중복 없음
Cpasted 1 second ago: 
#include <stdio.h>

#define N 4
#define R 3

int selected[R];
int flag[N+1];

void full(int depth)
{
  int i;
  if( R==depth){
    // 모두 선택 되었음 출력하기
    for(i=0;i<R;i++){
      printf("%d ",selected[i]);
    }
    printf("\n");
    return;
  }
  for(i=1;i<=N;i++){
    if(flag[i]==1)continue;
    flag[i]=1;
    selected[depth]=i;
    full(depth+1);
    flag[i]=0;
  }
}

int main()
{
  full(0);
  return 0;
}


Output:
1 2 3 
1 2 4 
1 3 2 
1 3 4 
1 4 2 
1 4 3 
2 1 3 
2 1 4 
2 3 1 
2 3 4 
2 4 1 
2 4 3 
3 1 2 
3 1 4 
3 2 1 
3 2 4 
3 4 1 
3 4 2 
4 1 2 
4 1 3 
4 2 1 
4 2 3 
4 3 1 
4 3 2 



여기에서 중복에 대한 고민을 한번 더 해보면 좋겠습니다.
1,1,1 도 되고 1,1,2 도되고 2,1,1,도 될테고 음 이렇게 해보면 중복 순열은 결국 아래 그림이 됩니다.
지금까지 모든 node를 탐색했던 full search가 됩니다.
코드는 이미 만들어 뒀던 내용입니다.



중복을 허용하는 순열 소스

Cpasted just now: 
#include <stdio.h>

#define N 4
#define R 3

int selected[R];

void full(int depth)
{
  int i;
  if( R==depth){
    // 모두 선택 되었음 출력하기
    for(i=0;i<R;i++){
      printf("%d ",selected[i]);
    }
    printf("\n");
    return;
  }
  for(i=1;i<=N;i++){
    selected[depth]=i;
    full(depth+1);
  }
}

int main()
{
  full(0);
  return 0;
}


Output:
1 1 1 
1 1 2 
1 1 3 
1 1 4 
1 2 1 
1 2 2 
1 2 3 
1 2 4 
1 3 1 
1 3 2 
1 3 3 
1 3 4 
1 4 1 
1 4 2 
1 4 3 
1 4 4 
2 1 1 
2 1 2 
2 1 3 
2 1 4 
2 2 1 
2 2 2 
2 2 3 
2 2 4 
2 3 1 
2 3 2 
2 3 3 
2 3 4 
2 4 1 
2 4 2 
2 4 3 
2 4 4 
3 1 1 
3 1 2 
3 1 3 
3 1 4 
3 2 1 
3 2 2 
3 2 3 
3 2 4 
3 3 1 
3 3 2 
3 3 3 
3 3 4 
3 4 1 
3 4 2 
3 4 3 
3 4 4 
4 1 1 
4 1 2 
4 1 3 
4 1 4 
4 2 1 
4 2 2 
4 2 3 
4 2 4 
4 3 1 
4 3 2 
4 3 3 
4 3 4 
4 4 1 
4 4 2 
4 4 3 
4 4 4 







2016년 11월 12일 토요일

중복 순열 (Permutation) 조합(combination)알고리즘 생성 방법 algorithm


앞에서 순열과 조합에 대해서 정리해보았습니다.

아래 코드는 중복을 허용할때와 하지않을때 코드를 모두 정리하였습니다.

N=3 {1,2,3} 존재시 R=2
순열은 N개의 항목에서 R개를 선택할때 순서를 가지면서 나열하는 방법입니다.
{1,2},{1,3},{2,1},{2,3},{3,1},{3,2}
중복 순열은 R개 선택시 중복이 가능하다는 의미입니다.
{1,1},{1,2},{1,3},{2,1},{2,2},{2,3},{3,1},{3,2},{3,3}

조합은 N개의 항목에서 R개를 선택할때 순서를 갖지지 않은면서 나열하는 방법입니다.
{1,2},{1,3},{2,3}
중복 조합은 R개 선택시 중복이 가능하다는 의미입니다.
{1,1},{1,2},{1,3},{2,2},{2,3},{3,3}

하지만 아래 코드가 일반적으로 책에서 많이 나오는 방식입니다. 따라서 자세한 하지 않겠습니다.

다음에는 아래 코드 보다 이해하기 쉬운 코드를 만들어서 공유하도록 하겠습니다.

Cpasted just now: 

#include <stdio.h>

#define NN 5

int array[] = {0, 1, 2, 3, 4};
int r = 3; //추출할 개수   
int N = NN;
int out[NN];
int count = 0;

void swap(int i, int start) {
 int temp = out[i];
 out[i] = out[start];
 out[start] = temp;
}

void permutation(int start, int end) {
 int i;
 if(start == end) {
  for(i = 0; i < end; i++) {
   printf("%d ",out[i]);
  }
  printf("\n");
  count++;
  return;
 }
  
 for(i = start; i < N; i++) {
  swap(i, start);
  permutation(start+1, end);
  swap(i, start);
 }
  
}

void dpermutation(int start, int end) {
 int i;
 if(start == end) {
  for(i = 0; i < end; i++) {
   printf("%d ",out[i]);
  }
  printf("\n");
  count++;
  return;
 }
  
 for(i = 0; i < N; i++) {
  out[start] = array[i];
  dpermutation(start+1, end);
 }
}
 
 
void combination(int start, int end, int index) {
 int i;
 if(end==0) {
  for(i = 0; i < start; i++) {
   printf("%d ",out[i]);
  }
  printf("\n");
  count++;
 }else if (index == N) {
  return;
 } else {
  out[start] = array[index];
  combination(start+1, end-1, index+1); // 여기 다름
  combination(start, end, index+1);
 }
  
}
  
void dcombination(int start, int end, int index) {
 int i;
 if (end == 0) {
  for(i = 0; i < start; i++) { 
   printf("%d ",out[i]);
  }
  printf("\n");
  count++;
 } else if (index == N) {
  return;
 } else {
  out[start] = array[index];
  dcombination(start+1, end-1, index); // 여기 다름
  dcombination(start, end, index+1);
 }  
}
  
  
void main() 
{
 int i;
 //중복 조합
 count = 0;
 dcombination(0, r, 0);
 printf("1:%d\n\n",count);

 //조합
 count = 0;
 combination(0, r, 0);
 printf("2:%d\n\n",count);

 //중복 순열
 count = 0;
 dpermutation(0, r);
 printf("3:%d\n\n",count);

 //순열
 //순열시 출력에 초기값 필요함
 for(i = 0; i < N; i++) {
  out[i] = array[i];
 }
 count = 0;
 permutation(0, r);
 printf("4:%d\n\n",count);

}


Output:
0 0 0 
0 0 1 
0 0 2 
0 0 3 
0 0 4 
0 1 1 
0 1 2 
0 1 3 
0 1 4 
0 2 2 
0 2 3 
0 2 4 
0 3 3 
0 3 4 
0 4 4 
1 1 1 
1 1 2 
1 1 3 
1 1 4 
1 2 2 
1 2 3 
1 2 4 
1 3 3 
1 3 4 
1 4 4 
2 2 2 
2 2 3 
2 2 4 
2 3 3 
2 3 4 
2 4 4 
3 3 3 
3 3 4 
3 4 4 
4 4 4 
1:35

0 1 2 
0 1 3 
0 1 4 
0 2 3 
0 2 4 
0 3 4 
1 2 3 
1 2 4 
1 3 4 
2 3 4 
2:10

0 0 0 
0 0 1 
0 0 2 
0 0 3 
0 0 4 
0 1 0 
0 1 1 
0 1 2 
0 1 3 
0 1 4 
0 2 0 
0 2 1 
0 2 2 
0 2 3 
0 2 4 
0 3 0 
0 3 1 
0 3 2 
0 3 3 
0 3 4 
0 4 0 
0 4 1 
0 4 2 
0 4 3 
0 4 4 
1 0 0 
1 0 1 
1 0 2 
1 0 3 
1 0 4 
1 1 0 
1 1 1 
1 1 2 
1 1 3 
1 1 4 
1 2 0 
1 2 1 
1 2 2 
1 2 3 
1 2 4 
1 3 0 
1 3 1 
1 3 2 
1 3 3 
1 3 4 
1 4 0 
1 4 1 
1 4 2 
1 4 3 
1 4 4 
2 0 0 
2 0 1 
2 0 2 
2 0 3 
2 0 4 
2 1 0 
2 1 1 
2 1 2 
2 1 3 
2 1 4 
2 2 0 
2 2 1 
2 2 2 
2 2 3 
2 2 4 
2 3 0 
2 3 1 
2 3 2 
2 3 3 
2 3 4 
2 4 0 
2 4 1 
2 4 2 
2 4 3 
2 4 4 
3 0 0 
3 0 1 
3 0 2 
3 0 3 
3 0 4 
3 1 0 
3 1 1 
3 1 2 
3 1 3 
3 1 4 
3 2 0 
3 2 1 
3 2 2 
3 2 3 
3 2 4 
3 3 0 
3 3 1 
3 3 2 
3 3 3 
3 3 4 
3 4 0 
3 4 1 
3 4 2 
3 4 3 
3 4 4 
4 0 0 
4 0 1 
4 0 2 
4 0 3 
4 0 4 
4 1 0 
4 1 1 
4 1 2 
4 1 3 
4 1 4 
4 2 0 
4 2 1 
4 2 2 
4 2 3 
4 2 4 
4 3 0 
4 3 1 
4 3 2 
4 3 3 
4 3 4 
4 4 0 
4 4 1 
4 4 2 
4 4 3 
4 4 4 
3:125

0 1 2 
0 1 3 
0 1 4 
0 2 1 
0 2 3 
0 2 4 
0 3 2 
0 3 1 
0 3 4 
0 4 2 
0 4 3 
0 4 1 
1 0 2 
1 0 3 
1 0 4 
1 2 0 
1 2 3 
1 2 4 
1 3 2 
1 3 0 
1 3 4 
1 4 2 
1 4 3 
1 4 0 
2 1 0 
2 1 3 
2 1 4 
2 0 1 
2 0 3 
2 0 4 
2 3 0 
2 3 1 
2 3 4 
2 4 0 
2 4 3 
2 4 1 
3 1 2 
3 1 0 
3 1 4 
3 2 1 
3 2 0 
3 2 4 
3 0 2 
3 0 1 
3 0 4 
3 4 2 
3 4 0 
3 4 1 
4 1 2 
4 1 3 
4 1 0 
4 2 1 
4 2 3 
4 2 0 
4 3 2 
4 3 1 
4 3 0 
4 0 2 
4 0 3 
4 0 1 
4:60