네트워크 프로그래밍

소켓이라는 것을 기반으로 프로그래밍을 하기 때문에 소켓 프로그래밍이라고도 함.

네트워크로 연결된 둘 이상의 컴퓨터 사이에서의 데이터 송수신 프로그램의 작성을 의미함.


소켓에 대한 간단한 이해

네트워크의 연결 도구

운영체제에 의해 제공이 되는 소프트웨어적인 장치


소켓의 비유와 분류

TCP 소켓은 전화기에 비유될 수 있음

소켓은 socket 함수의 호출을 통해서 생성됨

단 전화를 거는 용도의 소켓과 전화를 수신하는 용도의 소켓 생성 방법에는 차이가 있다.

1
2
3
4
#include<sys/socket.h>
 
int socket(int domain, int type, int protocol);
 
cs

소켓의 생성

=> 성공시 파일 디스크립터, 실패 시 -1 반환


소켓의 주소 할당 및 연결

전화기에 전화번호가 부여되듯이 소켓에도 주소정보가 할당

소켓의 주소정보는 IP와 PORT번호로 구성됨

1
2
3
#include<sys/socket.h>
int bind(int sockfd, struct sockaddr *myaddr, socklen_t addrlen);
 
cs

주소의 할당

=> 성공시 0, 실패 시 -1 반환


연결요청이 가능한 상태의 소켓

연결요청이 가능한 상태의 소켓은 걸려온느 전화를 받을 수 있는 상태에 비유할 수 있다.

전화를 거는 용도의 소켓은 연결요청이 가능한 상태의 소켓이 될 필요가 없다. 이는 걸려오는 전화를 받는 용도의 소켓에서 필요한 상태이다.

1
2
3
#include<sys/socket.h>
int listen(int sockfd, int backlog);
 
cs

연결요청 가능한 상태로 변경

=> 성공시 0, 실패시 -1 반환

소켓에 할당된 IP와 Port번호로 연결요청이 가능한 상태가 됨


연결요청의 수락

걸려오는 전화에 대해서 수락의 의미로 수화기를 드는 것에 비유 할수 있다.

연결요청이 수락되어야 데이터의 송수신이 가능

수락된 이후에 데이터 송수신이 양방향성으로 됨

1
2
3
#include<sys/socket.h>
int accept(int sockfd, int backlog);
 
cs


연결을 요청하는 소켓의 구현

리스닝 소켓과 달리 구현의 과정이 매우 간단

'소켓의 생성'과 연결의 요청'으로 구분


소켓을 사용하기 위한 연결

Server

Client

소켓 생성(socket)

IP/PORT (bind)

요청대기(listen)

수락(accept)

Read/Write

종료(close)

소켓 생성(Socket)

연결 요청(Connect)

Read/Write

종료(close)


소켓의 종류

 TCP

 UDP

동기식 연결 방식

데이터가 손실되지 않음

데이터가 순서대로 전달됨

비동기식 연결방식

데이터 손실 발생할 수 있음

속도가 빠름(상대적) 





간단한 예제 (C언어)

서버 : 포트를 열고 대기한 상태에서 클라이언트가 접속하면 Hello World를 전송

클라이언트 : 서버의 IP와 PORT번호를 입력하여 서버에 접근하자마자 Read하고 받은 데이터를 출력

서버와 클라이언트 프로젝트를 각각 만들어야함


프로젝트에 라이브러리 추가

프로젝트 오른쪽 클릭 -> 속성

링커 -> 입력으로 이동

추가 종속성 -> 편집 누르기


ws2_32.lib 를 적기


Hello_Client_win.c (클라이언트 소스)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
void ErrorHandling(char* message);
 
int main(int argc, char* argv[])
{
    WSADATA wsaData;
    SOCKET hSocket;
    SOCKADDR_IN servAddr;
 
    char message[30];
    int strLen;
 
    if(argc!=3)
    {
        printf("Usage : %s <IP> <port>\n", argv[0]);
        exit(1);
    }
 
    if(WSAStartup(MAKEWORD(22), &wsaData) != 0)
        ErrorHandling("WSAStartup() error!");  
    
    hSocket=socket(PF_INET, SOCK_STREAM, 0);
    if(hSocket==INVALID_SOCKET)
        ErrorHandling("hSocketet() error");
    
    memset(&servAddr, 0sizeof(servAddr));
    servAddr.sin_family=AF_INET;
    servAddr.sin_addr.s_addr=inet_addr(argv[1]);
    servAddr.sin_port=htons(atoi(argv[2]));
    
    if(connect(hSocket, (SOCKADDR*)&servAddr, sizeof(servAddr))==SOCKET_ERROR)
        ErrorHandling("connect() error!");
 
    strLen=recv(hSocket, message, sizeof(message)-10);
    if(strLen==-1)
        ErrorHandling("read() error!");
    printf("Message from server: %s \n", message);  
 
    closesocket(hSocket);
    WSACleanup();
    return 0;
}
 
void ErrorHandling(char* message)
{
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}
cs


Hello_server_win.c (서버 소스)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
void ErrorHandling(char* message);
 
int main(int argc, char* argv[])
{
    WSADATA    wsaData;
    SOCKET hServSock, hClntSock;        
    SOCKADDR_IN servAddr, clntAddr;        
 
    int szClntAddr;
    char message[]="Hello World!";
 
    if(argc!=2
    {
        printf("Usage : %s <port>\n", argv[0]);
        exit(1);
    }
  
    if(WSAStartup(MAKEWORD(22), &wsaData)!=0)
        ErrorHandling("WSAStartup() error!"); 
    
    hServSock=socket(PF_INET, SOCK_STREAM, 0);
    if(hServSock==INVALID_SOCKET)
        ErrorHandling("socket() error");
  
    memset(&servAddr, 0sizeof(servAddr));
    servAddr.sin_family=AF_INET;
    servAddr.sin_addr.s_addr=htonl(INADDR_ANY);
    servAddr.sin_port=htons(atoi(argv[1]));
    
    if(bind(hServSock, (SOCKADDR*) &servAddr, sizeof(servAddr))==SOCKET_ERROR)
        ErrorHandling("bind() error");  
    
    if(listen(hServSock, 5)==SOCKET_ERROR)
        ErrorHandling("listen() error");
 
    szClntAddr=sizeof(clntAddr);        
    hClntSock=accept(hServSock, (SOCKADDR*)&clntAddr,&szClntAddr);
    if(hClntSock==INVALID_SOCKET)
        ErrorHandling("accept() error");  
    
    send(hClntSock, message, sizeof(message), 0);
    closesocket(hClntSock);
    closesocket(hServSock);
    WSACleanup();
    return 0;
}
 
void ErrorHandling(char* message)
{
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}
 
cs



서버,클라이언트 둘다 실행시 main 에 매개변수를 줘야 실행이 됨


Cmd를 이용한 main문에 매개변수 전달 (프로젝트 빌드 후)

서버

실행 파일 + 포트번호 매개변수 입력


클라이언트 (출력결과)

IP번호 (현재는 같은 컴퓨터에서 실행해서 로컬호스트인 127.0.0.1 입력)와 서버에서 연 PORT번호 입력



스트림(stream) : 입력과 출력을 바이트(byte)들의 흐름으로 생각하는 것

스트림에는 기본적으로 버퍼가 포함되어 있다.

 이름

스트림

연결 장치

stdin

표준 입력 스트림

키보드

stdout

표준 출력 스트림

모니터의 화면

stderr

표준 오류 스트림

모니터의 화면

 


사용하는 스트림에 따른 분류

 

  • 표준 입출력 스트림을 사용하여 입출력을 하는 함수
  • 스트림을 구체적으로 명시해 주어야 하는 입출력 함수

데이터의 형식에 따른 분류

 

  • getchar()나 putchar()처럼 문자형태의 데이터를 받아들이는 입출력
  • printf()나 scanf()처럼 구체적인 형식을 지정할 수 있는 입출력

 

 

 스트림 형식

표준 스트림 

일반 스트림 

설명 

 형식이 없는 입출력(문자 형태)

 getchar()

 fgetc(FILE *f,...)

 문자 입력 함수

 putchar()

 fputc(FILE *f,...)

 문자 출력 함수

 gets()

 fgetcs(FILE *f,...)

 문자열 입력 함수

 puts()

 fputs(FILE *f,...)

 문자열 출력 함수

 형식이 있는 입출력(정수, 실수,..)

 printf()

 fprintf(FILE *f,...)

 형식화된 출력 함수

 scanf()

 fscanf(FILE *f,...)

 형식화된 입력 함수


스트림은 구체적으로 FILE 구조체를 통하여 구현

FILE은 stdio.h에 정의되어 있다.


파일의 개념


C에서의 파일은 일련의 연속된 바이트

모든 파일 데이터들은 결국은 바이트로 바뀌어서 파일에 저장


텍스트 파일 : 사람이 읽을 수 있는 텍스트가 들어 있는 파일

아스키 코드를 이용하여 저장, 연속적인 라인들로 구성


이진 파일 : 사람이 읽을 수는 없으나 컴퓨터는 읽을 수 있는 파일. 이진 데이터가 직접 저장되어 있는 파일. 

텍스트 파일과는 달리 라인들로 분리되지 않음. 모든 데이터들은 문자열로 변환되지 않고 입출력


파일 처리 순서

파일 열기 -> 파일 읽기 및 쓰기 -> 파일 닫기

디스크 파일은 FILE 구조체를 이용하여 접근

파일 포인터 : FILE 구조체를 가리키는 포인터


파일 열기

FILE *fopen(const char *name, const char *mode)

name : 파일의 이름(경로 포함) 

mode : 파일을 여는 모드 ("r" : 읽기, "w" : 쓰기, "a" : 이어 쓰기, 

         "b" : 이진 파일 모드로 열기 -> rb : 읽기 모드+이진, wb : 쓰기 모드 + 이진 파일 모드)


<!--[endif]-->

파일 닫기

int fclose(FILE *stream);

파일 지우기

int remove(const char *path);


파일 입출력 라이브러리 함수

 

종류

설명

입력 함수

출력 함수

문자 단위

문자 단위로 입출력

int fgetc(FILE *fp)

int fputc(int c, FILE *fp)

문자열 단위

문자열 단위로 입출력

char *fgets(FILE *fp)

int fputs(const char *s, FILE *fp)

서식화된 입출력

형식 지정 입출력

int fscanf(FILE *fp, ...)

int fprintf(FILE *fp,...)

이진 데이터

이진 데이터 입출력

fread()

fwrite()


버퍼링

fopen()을 사용하여 파일을 열면, 버퍼가 자동으로 만들어진다.

버퍼는 파일로부터 읽고 쓰는 데이터의 임시 저장 장소로 이용되는 메모리의 블록

디스크 드라이브는 블록 단위 장치이기 때문에 블록 단위로 입출력을 해야만 가장 효율적으로 동작

1024바이트의 블록이 일반적

파일과 연결된 버퍼는 파일과 물리적인 디스크 사이의 인터페이스로 사용


fflush(fp) : 버퍼의 내용이 디스크 파일에 써진다.

setbuf(fp,NULL) : 스트림의 버퍼를 직접 지정하는 함수로서 만약 버퍼자리에 NULL을 써주면 버퍼를 제거하겠다는 것을 의미


순차 접근 방법 : 데이터를 파일의 처음부터 순차적으로 읽거나 기록하는 방법

임의 접근 방법 : 파일의 어느 위치에서든지 읽기와 쓰기가 가능한 방법


임의 접근 파일의 원리

파일 위치 표시자 : 읽기와 쓰기 동작이 현재 어떤 위치에서 이루어지는 지를 나타낸다.

강제적으로 파일 위치 표시자를 이동시키면 임의 접근이 가능

int fseek(FILE *fp, long offset, int origin);

fp : 열린 파일을 저장한 변수

offset : 임의 접근할 곳 (단위 L 100L이면 100바이트 이동한다)

origin : SEEK_SET = 파일의 시작 SEEK_CUR = 현재 위치 SEEK_END = 파일의 끝


void rewind(FILE *fp) : 파일 위치 표시자를 0으로 초기화


long ftell(FILE*fp) : 파일 위치 표시자의 현재 위치를 반환


수식(A*B-C/D)에 대한 이진 트리를 연결 자료구조를 사용하여 표현하고 전위,중위, 후위 순회에 따른 경로를 출력한다.


 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <stdio.h>
#include<stdlib.h>
#include<memory.h>
 
typedef struct treeNode {
    char data;
    struct treeNode *left;
    struct treeNode *right;
} treeNode;
 
treeNode* makeRootNode(char data, treeNode* leftNode, treeNode* rightNode) {
    treeNode* root = (treeNode *)malloc(sizeof(treeNode));
    root->data = data;
    root->left = leftNode;
    root->right = rightNode;
    return root;
}
 
void preorder(treeNode* root) {
    if (root) {
        printf("%c", root->data);
        preorder(root->left);
        preorder(root->right);
    }
}
 
void inorder(treeNode* root) {
    if (root) {
        inorder(root->left);
        printf("%c", root->data);
        inorder(root->right);
    }
}
 
void postorder(treeNode* root) {
    if (root) {
        postorder(root->left);
        postorder(root->right);
        printf("%c", root->data);
    }
}
 
void main() {
    treeNode* n7 = makeRootNode('D'NULLNULL);
    treeNode* n6 = makeRootNode('C'NULLNULL);
    treeNode* n5 = makeRootNode('B'NULLNULL);
    treeNode* n4 = makeRootNode('A'NULLNULL);
    treeNode* n3 = makeRootNode('/', n6, n7);
    treeNode* n2 = makeRootNode('*', n4, n5);
    treeNode* n1 = makeRootNode('-', n2, n3);
 
    printf("\n preorder : ");
    preorder(n1);
 
    printf("\n inorder : ");
    inorder(n1);
 
    printf("\n postorder : ");
    postorder(n1);
 
    getchar();
}
cs


출력결과

 


(C언어) 순차 자료구조를 이용한 최대 히프 프로그램


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include <stdio.h>
#include <stdlib.h>
#define MAX_ELEMENT 100
typedef struct {    //히프에 대한 1차원 배열과 히프 원소의 갯수를 구조체로 묶어서 선언
    int heap[MAX_ELEMENT];
    int heap_size;
} heapType;
 
heapType* createHeap()        //공백 히프를 생성하는 연산
{
    heapType *= (heapType *)malloc(sizeof(heapType));
    h->heap_size = 0;
    return h;
}
 
void insertHeap(heapType *h, int item)    //히프에 item을 삽입하는 연산
{
    int i;
    h->heap_size = h->heap_size + 1;
    i = h->heap_size;
    while ((i != 1) && (item > h->heap[i / 2])) {
        h->heap[i] = h->heap[i / 2];
        i /= 2;
    }
    h->heap[i] = item;
}
 
int deleteHeap(heapType *h)        //히프의 루트를 삭제하여 반환하는 연산
{
    int parent, child;
    int item, temp;
    item = h->heap[1];
    temp = h->heap[h->heap_size];
    h->heap_size = h->heap_size - 1;
    parent = 1;
    child = 2;
    while (child <= h->heap_size) {
        if ((child <= h->heap_size) && (h->heap[child] < h->heap[child + 1]))
            child++;
        if (temp >= h->heap[child])    break;
        else {
            h->heap[parent] = h->heap[child];
            parent = child;
            child = child * 2;
        }
    }
    h->heap[parent] = temp;
    return item;
}
 
printHeap(heapType *h)    //1차원 배열 히프의 내용을 출력하는 연산
{
    int i;
    printf("Heap : ");
    for (i = 1; i <= h->heap_size; i++)
        printf("[%d]", h->heap[i]);
}
 
void main()
{
    int i, n, item;
    heapType *heap = createHeap();
    insertHeap(heap, 10);
    insertHeap(heap, 45);
    insertHeap(heap, 19);
    insertHeap(heap, 11);
    insertHeap(heap, 96);
 
    printHeap(heap);
 
    n = heap->heap_size;
    for (i = 1; i <= n; i++) {
        item = deleteHeap(heap);
        printf("\ndelete : [%d] ", item);
    }
 
    getchar();
}
 
 
cs




출력 결과


이진 탐색 트리를 연결 자료구조를 사용하여 표현하고 이진 탐색 트리에 대한 연산을 수행하는 프로그램


 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#include<stdio.h>
#include<stdlib.h>
 
typedef struct treeNode {
    char key;        //데이터 필드
    struct treeNode* left;    //왼쪽 서브 트리 링크 필드
    struct treeNode* right;    //왼쪽 서브 트리 링크 필드
} treeNode;
 
typedef char element; //char을 이진 탐색 트리 element의 자료형으로 정의
 
treeNode* insertNode(treeNode *p, char x)
{    //포인터 p가 가리키는 노드와 비교하여 노드 x를 삽입하는 연산
    treeNode *newNode;
    if (p == NULL){
        newNode = (treeNode*)malloc(sizeof(treeNode));
        newNode->key = x;
        newNode->left = NULL;
        newNode->right = NULL;
        return newNode;
    }
    else if (x < p->key) p->left = insertNode(p->left, x);
    else if (x > p->key) p->right = insertNode(p->right, x);
    else printf("\n 이미 같은키가 있습니다! \n");
 
    return p;
}
 
void deleteNode(treeNode *root, element key)
{    //root 노드부터 탐색하여 key 값과 같은 노드를 찾아 삭제하는 연산
    treeNode *parent, *p, *succ, *succ_parent;
    treeNode *child;
 
    parent = NULL;
    p = root;
    while ((p != NULL) && (p->key != key)){
        parent = p;
        if (key < p->key) p = p->left;
        else p = p->right;
    }
    if (p == NULL){
        printf("\n 찾는 키가 이진 트리에 없습니다!!");
        return;
    }
 
    //삭제할 노드가 단말 노드인 경우
    if ((p->left == NULL) && (p->right == NULL)){
        if (parent != NULL){
            if (parent->left == p) parent->left = NULL;
            else parent->right = NULL;
        }
        else root = NULL;
    }
 
    //삭제할 노드가 한 개의 자식 노드를 가진 경우
    else if ((p->left == NULL|| (p->right == NULL)){
        if (p->left != NULL) child = p->left;
        else child = p->right;
 
        if (parent != NULL){
            if (parent->left == p) parent->left = child;
            else parent->right = child;
        }
        else root = child;
    }
 
    //삭제할 노드가 두 개의 자식 노드를 가진 경우
    else{
        succ_parent = p;
        succ = p->left;
        while (succ->right != NULL){
            succ_parent = succ;
            succ = succ->right;
        }
        if (succ_parent->left == succ) succ_parent->left = succ->left;
        else succ_parent->right = succ->left;
        p->key = succ->key;
        p = succ;
    }
    free(p);
}
 
treeNode* searchBST(treeNode* root, char x)
{        //이진 탐색 트리에서 키값이 x인 노드의 위치를 탐색하는 연산
    treeNode* p;
    p = root;
    while(p != NULL){
        if (x < p->key)p = p->left;
        else if (x == p->key) return p;
        else p = p->right;
    }
    printf("\n 찾는 키가 없습니다!");
    return p;
}
 
void displayInorder(treeNode* root)
{    //이진 탐색 트리를 중위 순회하면서 출력하는 연산
    if (root){
        displayInorder(root->left);
        printf("%c_", root->key);
        displayInorder(root->right);
    }
}
 
void menu()
{
    printf("\n*---------------------------*");
    printf("\n\t1 : 트리 출력");
    printf("\n\t2 : 문자 삽입");
    printf("\n\t3 : 문자 삭제");
    printf("\n\t4 : 문자 검색");
    printf("\n\t5 : 종료");
    printf("\n*---------------------------*");
    printf("\napsbdlqfur >> ");
}
 
int main()
{
    treeNode* root = NULL;
    treeNode* foundedNode = NULL;
    char choice, key;
 
    root = insertNode(root, 'G'); //트리 만들기
    insertNode(root, 'I');
    insertNode(root, 'H');
    insertNode(root, 'D');
    insertNode(root, 'B');
    insertNode(root, 'M');
    insertNode(root, 'N');
    insertNode(root, 'A');
    insertNode(root, 'J');
    insertNode(root, 'E');
    insertNode(root, 'Q');
 
    while (1){
        menu();
        choice = getchar(); getchar();
 
        switch (choice){
        case '1'printf("\t[이진트리 출력] ");
            displayInorder(root); printf("\n");
            break;
 
        case '2'printf("삽입할 문자를 입력하세요 : ");
            key = getchar(); getchar();
            insertNode(root, key);
            break;
 
        case '3'printf("삭제할 문자를 입력하세요 : ");
            key = getchar(); getchar();
            deleteNode(root, key);
            break;
 
        case '4'printf("찾을 문자를 입력하세요 : ");
            key = getchar(); getchar();
            foundedNode = searchBST(root, key);
            if (foundedNode != NULL)
                printf("\n %c 를 찾았습니다! \n", foundedNode->key);
            else printf("\n 문자를 찾지 못했습니다. \n");
            break;
 
        case '5'return 0;
 
        defaultprintf("없는 메뉴입니다. 메뉴를 다시 선택하세요! \n");
            break;
        }
    }
}
cs

 


출력 결과

 


작성조건

1. 프로그램 메뉴 : 서비스 요청 등록(큐 삽입) / 대기번호 출력 / 서비스 처리(큐 삭제)

2. 서비스 요청 등록의 고객 입력 사항 : 이름, 전화번호, 서비스 요청 품목(냉장고, TV, 핸드폰)


소스코드

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include <stdio.h>
#include<stdlib.h>
#include <malloc.h>
#include<string.h>
#include <stdbool.h>
typedef char element;
typedef struct QNode {
    element name[10];
    element phonenumber[20];
    int service;
    struct QNode *rink;
} QNode;
 
typedef struct {
    QNode *front*rear;
} LQueueType;
 
LQueueType * createLinkedQueue()
{
    LQueueType *LQ;
    LQ = (LQueueType *)malloc(sizeof(LQueueType));
    LQ->front = NULL;
    LQ->rear = NULL;
    return LQ;
}
 
int isEmpty(LQueueType *LQ)
{
    if (LQ->front == NULL) {
        printf("\n Linked Queue is empty!\n");
        return 1;
    }
    else return 0;
}
 
void enQueue(LQueueType *LQ, QNode *item)
{
    if (LQ->front == NULL) {
        LQ->front = item;
        LQ->rear = item;
    }
    else {
        LQ->rear->rink = item;
        LQ->rear = item;
    }
}
 
void deQueue(LQueueType *LQ , QNode *obj)
{
    QNode *old = LQ->front;
 
    if (!isEmpty(LQ))
    {
        *obj = *old;
        LQ->front = LQ->front->rink;
        if (LQ->front == NULL)
            LQ->rear = NULL;
        free(old);
    }
}
 
void main(void)
{
    LQueueType *LQ1 = createLinkedQueue();
    QNode *newNode;
    int iCount = 0;
    int select = 0;
    bool flag = true;
    while (flag) {
        printf("항목을 선택해주세요. 1.서비스 요청 등록   2. 대기번호 출력   3. 서비스 처리   4. 종료\n");
        scanf("%d", &select);
        QNode old;
        switch (select)
        {
        case 1:
            newNode = (QNode *)malloc(sizeof(QNode));
            printf("이름 입력 : "); 
            char name[10];
            scanf("%s", name);
            strcpy(newNode->name, name);
            printf("전화번호 입력 : ");
            char num[20];
            scanf("%s", num);
            strcpy(newNode->phonenumber, num);
            printf("서비스 요청 품목(냉장고 : 1, TV : 2, 핸드폰 : 3 중 하나 입력) : ");
            scanf("%d", &newNode->service);
            enQueue(LQ1, newNode);
            printf("\n\n");
            iCount++;
            break;
        case 2:
            printf("대기번호 : %d\n", iCount);
            break;
        case 3:
            deQueue(LQ1, &old);
            switch (old.service)
            {
            case 1:
                printf("이름 : %s 전화번호 : %s 서비스 요청 품목 : 냉장고\n", old.name, old.phonenumber);
                break;
            case 2:
                printf("이름 : %s 전화번호 : %s 서비스 요청 품목 : TV\n", old.name, old.phonenumber);
                break;
            case 3:
                printf("이름 : %s 전화번호 : %s 서비스 요청 품목 : 핸드폰\n", old.name, old.phonenumber);
                break;
            }
            iCount--;
            break;
        default:
            flag = false;
            break;
        }
    }
}
cs

 


출력결과

 


(C언어) 후위표기 수식의 연산 프로그램


 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
typedef int element;    //int를 element로 변환
 
//원소를 저장할 스택노드 구조체 구현
typedef struct stackNode {
    element data;
    struct stackNode *link;
}stackNode;
 
//스택 최상단 변수 선언
stackNode* top;
 
 
void push(element item)        //연결 리스트 스택의 삽입 연산
{
    stackNode* temp = (stackNode *)malloc(sizeof(stackNode));
    temp->data = item;
    temp->link = top;
    top = temp;
}
 
element pop()        //연결 리스트 스택의 삭제 후 반환 연산
{
    element item;
    stackNode* temp = top;
 
    if (top == NULL) {
        printf("\n\n Stack empty!\n");
        return 0;
    }
    else {
        item = temp->data;
        top = temp->link;
        free(temp);
        return item;
    }
}
 
element peek()        //연결 리스트 스택의 top 원소 검색 연산
{
    element item;
    if (top == NULL) {
        printf("\n\n Stack is empty!\n");
        return 0;
    }
    else {
        item = top->data;
        return item;
    }
}
 
void del()        //연결 리스트 스택의 삭제 연산
{
    stackNode* temp;
    if (top == NULL) {
        printf("\n\n Stack is empty! \n");
    }
    else {
        temp = top;
        top = top->link;
        free(temp);
    }
}
 
void printStack()        //연결리스트 스택의 출력 연산
{
    stackNode* p = top;
    printf("\n STACK [ ");
    while (p) {
        printf("%d", p->data);
        p = p->link;
    }
    printf("] ");
}
 
element evalPostfix(char *exp)    //후위 표기법을 계산하는 연산
{
    int opr1, opr2, value, i = 0;
    int length = strlen(exp);
    char symbol;
    top = NULL;
 
    for (i = 0; i < length; i++) {
        symbol = exp[i];
        if (symbol != '+' && symbol != '-' && symbol != '*' && symbol != '/') {
            value = symbol - '0';
            push(value);
        }
        else {
            opr2 = pop();
            opr1 = pop();
            switch (symbol) {
            case '+': push(opr1 + opr2); break;
            case '-': push(opr1 - opr2); break;
            case '*': push(opr1 * opr2); break;
            case '/': push(opr1 / opr2); break;
            }
        }
    }
    return pop();
}
 
void main(void)
{
    int result;
    char* express = "35*62/-";
    printf("후위표기식 =>%s",express);
 
    result = evalPostfix(express);
    printf("\n\n연산결과 => %d", result);
 
    getchar();
}
cs

 


출력결과

 


(c언어) 이중 연결 리스트의 원소 삭제 알고리즘


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
 
//리스트 구조체 선언
struct Dnode {
    struct Dnode *llink;
    char data[5];
    struct Dnode *rlink;
};
struct DoubleList {
    struct Dnode *dNode;
};
 
struct DoubleList DL = { NULL };
 
void deleteNode(DoubleList DL, Dnode *old) 
{
    old->llink->rlink = old->rlink;
    old->rlink->llink = old->llink;
    free(old);
}
 
 
 
void main() {
    struct Dnode *dn, *dn1, *dn2;
    dn = (Dnode*)malloc(sizeof(Dnode));
    dn1 = (Dnode*)malloc(sizeof(Dnode));
    dn2 = (Dnode*)malloc(sizeof(Dnode));
    strcpy(dn->data, "apple");
    strcpy(dn1->data, "banana");
    strcpy(dn2->data, "orange");
 
    dn->llink = NULL;
    dn->rlink = dn1;
 
    dn1->llink = dn;
    dn1->rlink = dn2;
 
    dn2->llink = dn1;
    dn2->rlink = NULL;
    DL.dNode = dn;
 
    printf("------Before------\n");
    struct Dnode *Temp = DL.dNode;
    int cnt = 0;
    while (Temp != NULL)
    {
        printf("%d : %s\n", cnt++, Temp->data);
        Temp = Temp->rlink;
    }
 
 
    deleteNode(DL, dn1);
 
 
    printf("------after------\n");
    Temp = DL.dNode;
    cnt = 0;
    while (Temp != NULL)
    {
        printf("%d : %s\n", cnt++, Temp->data);
        Temp = Temp->rlink;
    }
 
    return;
}
 
 
cs

 


출력결과

 


(C언어) 원형 연결 리스트의 첫 번째 노드 삽입 알고리즘


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
 
struct List {
    char strData[11];
    struct List *nextList;
};
struct CircleList {
    struct List *List;
};
 
void insertFirstNode(struct CircleList *list, char *x);
 
void main() {
 
    struct CircleList CL = { NULL };
    
    insertFirstNode(&CL, "apple");
    insertFirstNode(&CL, "Banana");
    insertFirstNode(&CL, "Orange");
    struct List* temp = CL.List;
    do
    {
        printf("%s\t", temp->strData);
        temp = temp->nextList;
    } while (temp != CL.List);
    return;
}
 
void insertFirstNode(struct CircleList *list, char *x){
    struct List* newNode;
    newNode = (List*)malloc(sizeof(List));
    newNode->nextList = NULL;
    strcpy(newNode->strData, x);
 
    strcpy(newNode->strData, x);
    if (list->List == NULL) {
        list->List = newNode;
        newNode->nextList = newNode;
    }
    else {
        List *temp = list->List;
        while (temp->nextList != list->List)
        {
            temp = temp->nextList;
        }
        newNode->nextList = temp->nextList;
        temp->nextList = newNode;
        list->List = newNode;
    }
}
 
cs

출력화면


메인 문에서 연결형 리스트를 미리 생성해 놓고 검색하고자 하는 문자열을 입력받아 탐색알고리즘을 통해 탐색   결과를 출력 하는 프로그램




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include<stdio.h>
#include<string.h>
 
//리스트 구조체 선언
struct List {
    char strData[11];
    struct List *nextList;
};
 
//탐색 알고리즘 함수 선언
struct List* searchNode(struct List *list, char *x);
 
void main() {
    //연결형 리스트 생성
    struct List appleList = { "apple",NULL };
    struct List BananaList = { "Banana", &appleList };
    struct List melonList = { "Melon", &BananaList };
    struct List piList = { "Rassbary", &melonList };
    struct List nameList = { "신홍기", &piList };
    struct List *search;
 
    //검색할 이름을 저장할 변수 선언과 값 받기
    char strTemp[11];
    
    printf_s("검색할 것을 입력하세요 : ");
    scanf("%s", strTemp);
    //search에 searchNode함수를 실행한 결과를 저장
    search = searchNode(&nameList, strTemp);
 
    //탐색알고리즘을 통해 찾은경우와 못찾은 경우를 출력
    if (search != NULL)
    {
        printf_s("%s를 리스트에서 찾았습니다.\n", strTemp);
    }
    else {
        printf_s("%s를 리스트에서 찾지 못했습니다.\n", strTemp);
    }
    return;
}
 
//리스트 L에서 x 노드 탐색 알고리즘
struct List* searchNode(struct List *list, char *x) {
    //시작주소를 temp에 저장;
    struct List *temp = list;
    //마지막 노드일 때 까지 반복문 돌리는 것
    while (temp != NULL)
    {
        //temp의 현재 노드에 저장된 strData와 검색하려는 x노드가 같은지 비교
        if (!strcmp(temp->strData, x)) {
            //맞을경우 temp반환
            return temp;
        }
        //다음 노드로 이동
        temp = temp -> nextList;
    }
    //찾지 못하여 NULL값 반환
    return temp;
}
 
cs


+ Recent posts