본문 바로가기
C#/C# 문법

c# 배열과 컬렉션

by GREEN나무 2025. 6. 13.
728x90

01. 배열

1) 1차원 배열

  • 동일한 데이터 유형을 가지는 데이터 요소들을 한 번에 모아서 다룰 수 있는 구조
  • 인덱스를 사용하여 요소에 접근 가능
  • 선언된 크기만큼의 공간을 메모리에 할당받음
// 배열 선언
데이터_유형[] 배열_이름;

// 배열 초기화
배열_이름 = new 데이터_유형[크기];

// 배열을 한 줄로 선언 및 초기화
데이터_유형[] 배열_이름 = new 데이터_유형[크기];

// 배열 요소에 접근
배열_이름[인덱스] = 값;
값 = 배열_이름[인덱스];
int[] array1 = new int[5];       // 크기가 5인 int형 배열 선언
string[] array2 = new string[3]; // 크기가 3인 string형 배열 선언
int num = 0;

// 배열 초기화
array1[0] = 1;
array1[1] = 2;
array1[2] = 3;
array1[3] = 4;
array1[4] = 5;

num = array1[0];
int[] itemPrices = { 100, 200, 300, 400, 500 };
int totalPrice = 0;

for (int i = 0; i < itemPrices.Length; i++)
{
    totalPrice += itemPrices[i];
}

Console.WriteLine("총 아이템 가격: " + totalPrice + " gold");

2) 게임 캐릭터의 능력치 배열 만들기

int[] playerStats = new int[4]; 
Random rand = new Random();
for (int i = 0; i < playerStats.Length; i++)
{
    playerStats[i] = rand.Next(1, 11);
}

Console.WriteLine("플레이어의 공격력: "  + playerStats[0]);
Console.WriteLine("플레이어의 방어력: "  + playerStats[1]);
Console.WriteLine("플레이어의 체력: "    + playerStats[2]);
Console.WriteLine("플레이어의 스피드: "  + playerStats[3]);

3) 학생들의 성적 평균 구하기

int[] scores = new int[5];
for (int i = 0; i < scores.Length; i++)
{
    Console.Write("학생 " + (i + 1) + "의 성적을 입력하세요: ");
    scores[i] = int.Parse(Console.ReadLine());
}

int sum = 0;
for (int i = 0; i < scores.Length; i++)
{
    sum += scores[i];
}

double average = (double)sum / scores.Length;
Console.WriteLine("성적 평균은 " + average + "입니다.");

4) 배열을 활용한 숫자 맞추기 게임

Random random = new Random();
int[] numbers = new int[3];

for (int i = 0; i < numbers.Length; i++)
{
    numbers[i] = random.Next(1, 10);
}

int attempt = 0;
while (true)
{
    Console.Write("3개의 숫자를 입력하세요 (1~9): ");
    int[] guesses = new int[3];

    for (int i = 0; i < guesses.Length; i++)
    {
        guesses[i] = int.Parse(Console.ReadLine());
    }

    int correct = 0;
    for (int i = 0; i < numbers.Length; i++)
    {
        for (int j = 0; j < guesses.Length; j++)
        {
            if (numbers[i] == guesses[j])
            {
                correct++;
                break;
            }
        }
    }

    attempt++;
    Console.WriteLine("시도 #" + attempt + ": " + correct + "개의 숫자를 맞추셨습니다.");

    if (correct == 3)
    {
        Console.WriteLine("축하합니다! 모든 숫자를 맞추셨습니다.");
        break;
    }
}

5) 다차원 배열

int[,] array3 = new int[2, 3];
array3[0, 0] = 1;
array3[0, 1] = 2;
array3[0, 2] = 3;
array3[1, 0] = 4;
array3[1, 1] = 5;
array3[1, 2] = 6;

int[,] array2D = new int[3, 4] { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } };

int[,,] array3D = new int[2, 3, 4] 
{
    { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } },
    { { 13, 14, 15, 16 }, { 17, 18, 19, 20 }, { 21, 22, 23, 24 } }
};

int[,] map = new int[5, 5];
for (int i = 0; i < 5; i++)
{
    for (int j = 0; j < 5; j++)
    {
        map[i, j] = i + j;
    }
}

for (int i = 0; i < 5; i++)
{
    for (int j = 0; j < 5; j++)
    {
        Console.Write(map[i, j] + " ");
    }
    Console.WriteLine();
}

6) 2차원 배열을 사용하여 게임 맵 구현

int[,] map = new int[5, 5] 
{ 
    { 1, 1, 1, 1, 1 }, 
    { 1, 0, 0, 0, 1 }, 
    { 1, 0, 1, 0, 1 }, 
    { 1, 0, 0, 0, 1 }, 
    { 1, 1, 1, 1, 1 } 
};

for (int i = 0; i < 5; i++)
{
    for (int j = 0; j < 5; j++)
    {
        if (map[i, j] == 1)
        {
            Console.Write("■ ");
        }
        else
        {
            Console.Write("□ ");
        }
    }
    Console.WriteLine();
}

✅배열(Array)과 리스트(List<T>)

1. C#에서 배열(Array)과 리스트(List<T>)의 차이

항목 배열 (Array)  리스트 (List)
크기 고정 (생성 시 결정) 가변 (필요시 자동 확장)
기능 값 저장/조회만 지원 요소 추가, 삭제, 검색 등 다양한 메서드 제공
선언 방법 int[] arr = new int[5]; List<int> list = new List<int>();
메모리 구조 연속된 메모리 공간 내부적으로 배열 기반이지만 동적 확장
성능 고정 크기라서 반복 처리에 빠름 추가/삭제 편리하지만 확장 시 복사 발생
실전 용도 고정된 데이터 개수, 성능 중시 데이터 수가 유동적일 때 유리

💡 핵심 요약

  • 배열: 고정된 크기의 데이터 저장용
  • 리스트: 유연한 크기 조정과 다양한 조작이 필요한 경우

✅ 2. [ ]와 { }의 의미와 차이

int[,] array3 = new int[2, 3];
int[] itemPrices = { 100, 200, 300, 400, 500 };

1️⃣ [ ]의 의미

  • [ ]는 '배열의 타입 및 인덱스 접근'을 나타내는 문법입니다.

예시 설명:

int[] arr = new int[5]; // 1차원 배열
int[,] arr2D = new int[2,3]; // 2차원 배열 (행, 열)
  • [ ] 안에 숫자를 넣으면 배열의 크기를 지정
  • 또는 arr[0]처럼 특정 요소에 접근

2️⃣ { }의 의미

  • { }는 배열이나 컬렉션을 '초기화'할 때 사용하는 문법입니다.

예시 설명:

int[] itemPrices = { 100, 200, 300 }; // 배열 생성 + 초기화
  • 내부적으로는 아래와 동일합니다:
int[] itemPrices = new int[3];
itemPrices[0] = 100;
itemPrices[1] = 200;
itemPrices[2] = 300;

3️⃣ 왜 둘 다 필요한가?

문법 목적 예시
[ ] 배열의 크기와 타입 정의, 요소 접근 int[], arr[0]
{ } 배열의 초기값 지정 { 1, 2, 3 }

✅ 정리

// 선언 + 크기 지정 + 나중에 값 넣음
int[] scores = new int[3];
scores[0] = 90;
scores[1] = 80;
scores[2] = 70;

// 선언과 동시에 초기화 (축약형)
int[] scores2 = { 90, 80, 70 };

// 2차원 배열
int[,] grid = new int[2, 3]; // 2행 3열

02. 컬렉션

  • 배열과 비슷한 자료 구조지만, 크기가 가변적
  • 다양한 종류의 컬렉션을 제공
  • 사용 전 System.Collections.Generic 네임스페이스 필요

1) List

List<int> numbers = new List<int>();
numbers.Add(1);
numbers.Add(2);
numbers.Add(3);
numbers.Remove(2);

foreach(int number in numbers)
{
    Console.WriteLine(number);
}

2) Dictionary

Dictionary<string, int> scores = new Dictionary<string, int>();
scores.Add("홍길동", 95);
scores.Add("김철수", 88);

foreach (var kvp in scores)
{
    Console.WriteLine(kvp.Key + "의 점수: " + kvp.Value);
}

3) Queue와 Stack 

  • Queue: FIFO(선입선출) 방식
  • Stack: LIFO(후입선출) 방식
Queue<string> queue = new Queue<string>();
queue.Enqueue("A");
queue.Enqueue("B");
Console.WriteLine(queue.Dequeue()); // A

Stack<string> stack = new Stack<string>();
stack.Push("A");
stack.Push("B");
Console.WriteLine(stack.Pop()); // B

 

 


+

1. 예외 처리 및 안전성을 위한 가드 (Guard Clause)

  • IndexOutOfRangeException 방지를 위한 안전 코드
if (index < 0 || index >= array.Length)
{
    Console.WriteLine("잘못된 인덱스입니다.");
    return;
}
  • 사용자 입력 시, int.TryParse 사용으로 파싱 실패 대비
Console.Write("숫자를 입력하세요: ");
if (!int.TryParse(Console.ReadLine(), out int value))
{
    Console.WriteLine("유효한 정수가 아닙니다.");
    return;
}

2. 컬렉션 활용 예시 확장

  • HashSet
    • 중복 없이 데이터 저장, 집합 연산 예시
HashSet<string> set = new HashSet<string>();
set.Add("apple");
set.Add("banana");
set.Add("apple");  // 중복 무시됨
Console.WriteLine($"요소 수: {set.Count}");
  • LinkedList
    • 중간 삽입/삭제 시 유리한 구조
LinkedList<int> link = new LinkedList<int>(new[] {1, 3, 5});
link.AddAfter(link.First, 2);  // 1 다음에 2 삽입
  • ObservableCollection
    • UI 바인딩 컬렉션 예시 (WPF, Xamarin 등)
ObservableCollection<string> obs = new ObservableCollection<string>();
obs.CollectionChanged += (s, e) => Console.WriteLine("변경됨");
obs.Add("hello");

3. 배열 ↔ 리스트 간 변환

int[] arr = {1,2,3};
List<int> list = arr.ToList();         // 배열 → 리스트
int[] arr2 = list.ToArray();           // 리스트 → 배열

4. 반복문 심화

  • foreach와 for 비교, 성능 이슈 및 변경 불가 특징
  • 컬렉션에서는 for말고 foreach 권장
foreach (var item in list)
{
    Console.WriteLine(item);
}

5. 성능 팁 비교 정리 표

  

항목 배열 (Array) 리스트 (List)
크기 고정 가변
메모리 구조 단일 블록 동적 동적 배열
인덱스 접근 속도 매우 빠름 (O(1)) 빠름 (O(1)), 다만 리사이즈 시 복사 발생
추가/삭제 비용 불가 또는 O(n) 전체 복사 보통 O(1), 중간 삽입/삭제 O(n)
일반 사용 추천 크기 고정 데이터, 루프 내 반복 사용 동적 데이터 추가/삭제 필요 시 사용

6. 실습 예제: 컬렉션 합치기

List<int> listA = new List<int>{1,2,3};
List<int> listB = new List<int>{3,4,5};
List<int> merged = listA.Union(listB).ToList();
Console.WriteLine(string.Join(", ", merged));  // 1,2,3,4,5

 

'C# > C# 문법' 카테고리의 다른 글

c# 메서드와 구조체  (0) 2025.07.08
C# 실습 예제 -  (0) 2025.05.24
c# 프로그래밍 기본 요소  (0) 2025.05.24
C#에서 자주 사용되는 코드  (1) 2025.05.22
C# 환경설정, 프로젝트 생성  (2) 2025.05.21