1. 배열 재배열 예제 - 마지막 요소로 덮어쓰는 방식(O(1))

더보기
#include <stdio.h>
#include <stdlib.h>

#define MAX_SOCK 10  // [1] 최대 소켓 수 (클라이언트 수 제한)

// [2] 소켓 번호 배열과 현재 접속자 수 변수
int clnt_socks[MAX_SOCK];
int num_user = 0;

// [3] 클라이언트 소켓 번호 추가 함수
void AddClient(int sock) {
    if (num_user >= MAX_SOCK) {
        printf("[오류] 최대 인원 초과! 추가 불가\n");
        return;
    }
    clnt_socks[num_user++] = sock;
    printf("[추가] 소켓 %d 추가됨. 현재 인원: %d명\n", sock, num_user);
}

// [4] 특정 인덱스의 소켓을 제거하는 함수
// 마지막 요소와 교체하여 빠르게 삭제
void RemoveClient(int index) {
    if (index < 0 || index >= num_user) {
        printf("[오류] 잘못된 인덱스입니다.\n");
        return;
    }

    int removed = clnt_socks[index];
    clnt_socks[index] = clnt_socks[num_user - 1]; // [4-1] 마지막 요소로 덮어쓰기
    num_user--; // [4-2] 사용자 수 감소

    printf("[삭제] 소켓 %d 삭제됨. 현재 인원: %d명\n", removed, num_user);
}

// [5] 현재 배열 중 가장 큰 소켓 번호 찾기 (select 호출에 사용 가능)
int GetMaxSockNum() {
    int max = -1;
    for (int i = 0; i < num_user; i++) {
        if (clnt_socks[i] > max)
            max = clnt_socks[i];
    }
    return max;
}

// [6] 배열 출력 함수
// 빈 공간은 [__]로 표현하여 배열의 구조를 시각적으로 확인 가능
void PrintClients() {
    printf("클라이언트 소켓 배열 상태:\n");

    for (int i = 0; i < MAX_SOCK; i++) {
        if (i < num_user)
            printf("[%2d] ", clnt_socks[i]);  // [6-1] 실제 데이터 출력
        else
            printf("[__] ");                 // [6-2] 빈 공간 출력
    }
    printf("<< 총 %d명 접속\n\n", num_user);
}

// [7] 메인 함수: 동작 테스트
int main() {
    AddClient(5);         // [7-1]
    PrintClients();

    AddClient(3);         // [7-2]
    PrintClients();

    AddClient(10);        // [7-3]
    PrintClients();

    AddClient(7);         // [7-4]
    PrintClients();

    printf("현재 최대 소켓 번호: %d\n", GetMaxSockNum());  // [7-5]

    RemoveClient(1);      // [7-6] 인덱스 1 제거 (소켓 3)
    PrintClients();

    RemoveClient(0);      // [7-7] 인덱스 0 제거 (소켓 5 → 이미 위에서 제거됨)
    PrintClients();

    printf("현재 최대 소켓 번호: %d\n", GetMaxSockNum());  // [7-8]

    return 0;
}

 

// [추가] 소켓 5 추가됨. 현재 인원: 1명
// 클라이언트 소켓 배열 상태:
// [ 5] [__] [__] [__] [__] [__] [__] [__] [__] [__] << 총 1명 접속

// [추가] 소켓 3 추가됨. 현재 인원: 2명
// 클라이언트 소켓 배열 상태:
// [ 5] [ 3] [__] [__] [__] [__] [__] [__] [__] [__] << 총 2명 접속

// [추가] 소켓 10 추가됨. 현재 인원: 3명
// 클라이언트 소켓 배열 상태:
// [ 5] [ 3] [10] [__] [__] [__] [__] [__] [__] [__] << 총 3명 접속

// [추가] 소켓 7 추가됨. 현재 인원: 4명
// 클라이언트 소켓 배열 상태:
// [ 5] [ 3] [10] [ 7] [__] [__] [__] [__] [__] [__] << 총 4명 접속

// 현재 최대 소켓 번호: 10
// [삭제] 소켓 3 삭제됨. 현재 인원: 3명
// 클라이언트 소켓 배열 상태:
// [ 5] [ 7] [10] [__] [__] [__] [__] [__] [__] [__] << 총 3명 접속

// [삭제] 소켓 5 삭제됨. 현재 인원: 2명
// 클라이언트 소켓 배열 상태:
// [10] [ 7] [__] [__] [__] [__] [__] [__] [__] [__] << 총 2명 접속

 

2. 배열 재배열 예제 - 삭제 후 나머지 요소들을 앞으로 한 칸씩 당기는 방식(O(n))

더보기
#include <stdio.h>
#include <stdlib.h>

#define MAX_SOCK 10  // [1] 최대 소켓 수

// [2] 클라이언트 소켓 번호 배열과 현재 참가자 수
int clnt_socks[MAX_SOCK];
int num_user = 0;

// [3] 클라이언트 소켓 추가 함수
void AddClient(int sock) {
    if (num_user >= MAX_SOCK) {
        printf("[오류] 최대 인원 초과! 추가 불가\n");
        return;
    }
    clnt_socks[num_user++] = sock;
    printf("[추가] 소켓 %d 추가됨. 현재 인원: %d명\n", sock, num_user);
}

// [4] 클라이언트 소켓 제거 함수 (재정렬 방식)
// 삭제한 인덱스 이후 요소들을 한 칸씩 앞으로 이동
void RemoveClient(int index) {
    if (index < 0 || index >= num_user) {
        printf("[오류] 잘못된 인덱스입니다.\n");
        return;
    }

    int removed = clnt_socks[index];

    // [4-1] 인덱스 이후 모든 요소를 한 칸 앞으로 이동
    for (int i = index; i < num_user - 1; i++) {
        clnt_socks[i] = clnt_socks[i + 1];
    }

    // [4-2] 마지막 값은 지워진 것처럼 처리
    clnt_socks[num_user - 1] = 0;
    num_user--;

    printf("[삭제] 소켓 %d 삭제됨. 현재 인원: %d명\n", removed, num_user);
}

// [5] 현재 배열에서 가장 큰 소켓 번호 찾기
int GetMaxSockNum() {
    int max = -1;
    for (int i = 0; i < num_user; i++) {
        if (clnt_socks[i] > max)
            max = clnt_socks[i];
    }
    return max;
}

// [6] 전체 배열 시각화 출력 함수
void PrintClients() {
    printf("클라이언트 소켓 배열 상태:\n");

    for (int i = 0; i < MAX_SOCK; i++) {
        if (i < num_user)
            printf("[%2d] ", clnt_socks[i]);  // [6-1] 유효한 데이터
        else
            printf("[__] ");                 // [6-2] 빈 공간
    }
    printf("← 총 %d명 접속\n", num_user);
}

// [7] 테스트용 메인 함수
int main() {
    AddClient(5);         // [7-1]
    PrintClients();

    AddClient(3);         // [7-2]
    PrintClients();

    AddClient(10);        // [7-3]
    PrintClients();

    AddClient(7);         // [7-4]
    PrintClients();

    printf("현재 최대 소켓 번호: %d\n", GetMaxSockNum());  // [7-5]

    RemoveClient(1);      // [7-6] 인덱스 1 제거 (소켓 3 → 10과 7이 앞으로 이동)
    PrintClients();

    RemoveClient(0);      // [7-7] 인덱스 0 제거 (소켓 5 → 10과 7이 앞으로 이동)
    PrintClients();

    printf("현재 최대 소켓 번호: %d\n", GetMaxSockNum());  // [7-8]

    return 0;
}
// [추가] 소켓 5 추가됨. 현재 인원: 1명
// 클라이언트 소켓 배열 상태:
// [ 5] [__] [__] [__] [__] [__] [__] [__] [__] [__] << 총 1명 접속

// [추가] 소켓 3 추가됨. 현재 인원: 2명
// 클라이언트 소켓 배열 상태:
// [ 5] [ 3] [__] [__] [__] [__] [__] [__] [__] [__] << 총 2명 접속

// [추가] 소켓 10 추가됨. 현재 인원: 3명
// 클라이언트 소켓 배열 상태:
// [ 5] [ 3] [10] [__] [__] [__] [__] [__] [__] [__] << 총 3명 접속

// [추가] 소켓 7 추가됨. 현재 인원: 4명
// 클라이언트 소켓 배열 상태:
// [ 5] [ 3] [10] [ 7] [__] [__] [__] [__] [__] [__] << 총 4명 접속

// 현재 최대 소켓 번호: 10
// [삭제] 소켓 3 삭제됨. 현재 인원: 3명
// 클라이언트 소켓 배열 상태:
// [ 5] [10] [ 7] [__] [__] [__] [__] [__] [__] [__] << 총 3명 접속

// [삭제] 소켓 5 삭제됨. 현재 인원: 2명
// 클라이언트 소켓 배열 상태:
// [10] [ 7] [__] [__] [__] [__] [__] [__] [__] [__] << 총 2명 접속