배열 재배열
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명 접속