본문 바로가기

Programming

배열 : 쉽고 재미있는 C# Programming 의 기본

 

C# 언어에서 배열은 동일한 데이터 형식을 가진 여러 요소를 담을 수 있는 데이터 구조입니다. 배열은 고정된 크기를 가지며 인덱스를 사용하여 각 요소에 접근할 수 있습니다.

 

1. 개념

 

배열은 동일한 데이터 형식을 가진 여러 요소를 순서대로 저장하는 자료구조로, 각 요소는 고유한 인덱스를 가지고 있습니다. 배열은 선언 후에 크기를 변경할 수 없으며, 크기는 배열을 생성할 때 결정됩니다.

 

2. 형식

 

배열의 기본 문법은 아래와 같습니다.

변수타입[] 변수명 = new int[데이터를 담을 크기]

// 형식1: 데이터형[] 배열이름;
int[] myArray;

// 형식2: 배열 초기화
int[] myArray = new int[5]; // 크기가 5인 int형 배열 생성

// 형식3: 초기값을 가진 배열
int[] myArray = { 1, 2, 3, 4, 5 };

 

배열 선언법은 변수 타입에 대괄호( [ ] )를 감싸주고, 뒤에는 초기 값 대신, 객체 선언 방법과 같이 new 키워드를 써 준 후 변수 타입을 다시 명시해 주고, 얼마큼의 데이터를 담을지 배열의 크기를 지정해 줍니다.

 

3. 활용

 

3.1 배열 요소에 접근

int[] myArray = { 1, 2, 3, 4, 5 };
int element = myArray[2]; // 인덱스 2에 있는 요소에 접근 (값은 3)

 

배열은 1이 아닌 0부터 시작합니다. myArray[2]의 값은 2가 아닌 세 번째 값인 3이 됩니다.

 

3.2 배열의 길이 확인

int[] myArray = { 1, 2, 3, 4, 5 };
int length = myArray.Length; // 배열의 길이를 확인 (값은 5)

 

배열로 선언된 변수는, Length라는 함수를 제공해 줍니다. 이 함수는 배열의 크기를 알려주는 매우 중요한 함수입니다.

데이터의 크기를 5로 정했으면 5를 리턴해 주고, 10으로 정했으면 10을 리턴해 줍니다.

 

4. 사용 예

 

4.1 반복문과 함께 사용

int[] numbers = { 1, 2, 3, 4, 5 };

// for문을 사용하여 배열의 요소 출력
for (int i = 0; i < numbers.Length; i++)
{
    Console.WriteLine(numbers[i]);
}

// foreach문을 사용하여 배열의 요소 출력
foreach (int number in numbers)
{
    Console.WriteLine(number);
}

 

4.2 다차원(N차원) 배열

int[,] matrix = new int[3, 3] { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };

// 이중 for문을 사용하여 다차원 배열의 요소 출력
for (int i = 0; i < 3; i++)
{
    for (int j = 0; j < 3; j++)
    {
        Console.Write(matrix[i, j] + " ");
    }
    Console.WriteLine();
}

 

다차원 배열은 많이 사용하지는 않지만, 2차원 이상의 배열을 말합니다.

대부분 배열은 1차원으로 시작해서 2차원까지 사용하는 것을 권장합니다.

 

2차원 배열의 데이터 선언 방법은 아래와 같습니다.

변수타입[][] 변수명 = new 변수타입[X축 배열크기][Y축 배열크기];

 

1차원 배열과의 차이는 대괄호가 2개씩 묶여 있다는 것입니다. 더 많은 차원의 배열은 대괄호의 개수가 더 늘어납니다.

 

5. 배열의 간단한 예제

 

배열을 활용하여 학생들의 성적을 저장하고 평균을 계산하는 기능을 구현한 간단한 예제입니다.

using System;

class Program
{
    static void Main()
    {
        // 학생 성적을 저장할 배열
        int[] grades = new int[5];

        // 학생 성적 입력 받기
        for (int i = 0; i < grades.Length; i++)
        {
            Console.Write($"학생 {i + 1}의 성적을 입력하세요: ");
            grades[i] = Convert.ToInt32(Console.ReadLine());
        }

        // 학생 성적 출력
        Console.WriteLine("\n입력한 학생 성적:");
        for (int i = 0; i < grades.Length; i++)
        {
            Console.WriteLine($"학생 {i + 1}: {grades[i]}");
        }

        // 평균 계산
        double average = CalculateAverage(grades);
        Console.WriteLine($"\n성적 평균: {average:F2}");
    }

    // 평균 계산 함수
    static double CalculateAverage(int[] grades)
    {
        int sum = 0;

        foreach (int grade in grades)
        {
            sum += grade;
        }

        return (double)sum / grades.Length;
    }
}

 

5명의 학생 성적을 입력받고, 입력한 성적을 출력한 뒤에 그 성적의 평균을 계산하여 출력하는 간단한 예제입니다.

grade 배열을 사용하여 학생들의 성적을 저장하고 CalculateAverage 함수를 통해 배열의 평균을 계산합니다.

출력 결과는 아래와 같습니다.

학생 1의 성적을 입력하세요: 80
학생 2의 성적을 입력하세요: 90
학생 3의 성적을 입력하세요: 75
학생 4의 성적을 입력하세요: 85
학생 5의 성적을 입력하세요: 95

입력한 학생 성적:
학생 1: 80
학생 2: 90
학생 3: 75
학생 4: 85
학생 5: 95

성적 평균: 85.00

 

6. 배열 사용 시 주의점

 

  1. 인덱스 범위 확인:
    • 배열의 인덱스는 0부터 시작합니다. 따라서 유효한 인덱스는 0부터 배열의 길이보다 1 작은 값까지입니다. 인덱스를 벗어나는 접근은 예외를 발생시키므로 주의해야 합니다.
  2. 배열의 길이 고정:
    • 배열은 생성 시에 크기가 고정되기 때문에 크기를 동적으로 변경할 수 없습니다. 필요에 따라 동적 배열 또는 다른 데이터 구조를 고려해야 할 수 있습니다.
  3. Null 처리:
    • 배열은 참조 타입이기 때문에 초기화되지 않으면 기본적으로 null로 초기화됩니다. 사용 전에 배열을 명시적으로 초기화하거나 값 할당을 해야 합니다.
  4. 다차원 배열 처리:
    • 다차원 배열을 다룰 때 각 차원의 길이를 고려해야 합니다. 각 차원의 크기가 일치해야 합니다.
  5. 배열 복사:
    • 배열을 복사할 때 얕은 복사와 깊은 복사의 개념을 이해해야 합니다. Array.Copy 또는 Array.Clone 등의 메서드를 사용하여 복사할 수 있습니다.
  6. 배열의 성능 고려:
    • 배열의 크기가 크거나 배열을 자주 변경해야 하는 경우에는 성능에 영향을 줄 수 있습니다. 이러한 경우에는 다른 데이터 구조를 고려해야 할 수 있습니다.
  7. C#의 다양한 컬렉션 사용:
    • 배열 이외에도 C#은 다양한 컬렉션을 제공합니다. 필요에 따라 List<T>, Dictionary<K,V>, Queue<T>, Stack<T> 등을 고려해 보세요.
  8. 예외 처리:
    • 배열을 사용하는 코드에서 예외 처리를 고려해야 합니다. 예를 들어, 배열의 길이를 벗어난 인덱스에 접근하려고 할 때 발생하는 예외를 처리해야 합니다.

배열을 사용할 때는 위와 같은 주의점을 고려하여 안정성과 성능을 고려하는 것이 중요합니다.

 

7. Arraylist : 데이터가 얼마나 담길지 예측이 불가능한 경우

 

ArrayList은 C#에서 제공하는 동적 배열 기반의 컬렉션 클래스입니다. 배열과 달리 크기가 동적으로 조절 가능하며, 객체의 추가 및 제거가 용이합니다.

컬렉션이란, 간단히 말해 자료구조(Data Structure)입니다. 자료구조란 자료를 효과적으로 이용할 수 있도록 컴퓨터에 저장하는 방법입니다.

 

C#에서는 이러한 자료구조를 표현하는 컬렉션에는 배열(Array), 스택(Stack), 큐(Queue) 등이 있습니다.

이러한 컬렉션을 사용하기 위해서는 using 구문에 System.Collections 라는 네임스페이스 사용을 선언해 주어야 사용할 수 있습니다.

 

ArrayList는 배열처럼 인덱스를 이용하여 할당된 값을 불러올 수 있고, 값을 할당할 수 있으며, 배열과는 달리 배열의 크기를 지정할 필요 없이 값을 추가, 삭제하며 자동으로 배열의 메모리 크기를 늘렸다 줄였다 할 수 있습니다.

또한 ArrayList는 모든 타입의 변수를 담을 수 있다는 장점도 가지고 있습니다.

물론, ArrayList 뿐만 아니라 Collections 에서 제공하는 자료구조는 모든 타입의 변수를 담을 수 있습니다.

 

모든 타입을 담을 수 있는 이유는 바로 Collections에 속한 요소는 어떤 타입이든지 object 타입으로 저장되기 때문입니다.

 

7.1 개념

 

ArrayListSystem.Collections 네임스페이스에 정의된 클래스로, 가변 크기의 배열을 나타냅니다. ArrayList은 객체의 리스트를 관리하며, 배열과 유사하지만 크기가 동적으로 조절될 수 있습니다.

 

7.2 형식

ArrayList 변수명 = new ArrayList();
using System.Collections;

// ArrayList 선언
ArrayList myArrayList = new ArrayList();

// 초기값을 가진 ArrayList
ArrayList myArrayList = new ArrayList() { 1, "Hello", 3.14, true };

 

7.3 활용

 

7.3.1 요소 추가 및 제거

ArrayList myArrayList = new ArrayList();

// 요소 추가
myArrayList.Add(10);
myArrayList.Add("C#");
myArrayList.Add(3.14);

// 요소 제거
myArrayList.Remove("C#");

 

7.3.2 요소 접근

ArrayList myArrayList = new ArrayList() { 1, "Hello", 3.14, true };

// 인덱스를 사용한 요소 접근
object element = myArrayList[1];

 

7.4 사용 예

using System;
using System.Collections;

class Program
{
    static void Main()
    {
        // ArrayList 생성
        ArrayList myArrayList = new ArrayList();

        // 요소 추가 : 정수, 문자열, 실수 등 다양한 타입의 요소를 추가합니다.
        myArrayList.Add(10);
        myArrayList.Add("C#");
        myArrayList.Add(3.14);

        // 요소 출력 : foreach 문을 사용하여 ArrayList 에 있는 모든 요소를 출력합니다.
        Console.WriteLine("ArrayList 요소:");
        foreach (object element in myArrayList)
        {
            Console.WriteLine(element);
        }

        // 특정 요소 제거 : Remove 메서드를 사용하여 특정요소를 제거합니다.
        myArrayList.Remove("C#");

        // 수정된 ArrayList 출력
        Console.WriteLine("\nArrayList 수정 후:");
        foreach (object element in myArrayList)
        {
            Console.WriteLine(element);
        }
    }
}

 

ArrayList을 사용하여 요소를 추가하고 제거한 후, 결과를 출력하는 프로그램입니다.

이 예제에서는 ArrayList이 여러 데이터 형식을 가진 요소를 저장하고, 요소를 추가하고 제거하여 동적으로 변하는 특징을 보여줍니다. 그러나 주의해야 할 점은 ArrayListobject 형식을 사용하므로 요소에 접근할 때 형변환을 해야 합니다. 이로 인해 박싱과 언박싱이 발생할 수 있어 성능 저하가 있을 수 있습니다.

 

최신 C# 버전에서는 이러한 성능 이슈를 개선하기 위해 제네릭 컬렉션 (List<T>)을 사용하는 것이 권장됩니다.

 

8. ArrayList 요소 삽입과 요소의 제거

 

ArrayList 클래스에서 Insert, Remove, RemoveAt 메서드는 각각 요소의 삽입, 요소의 제거(값에 의한 제거 및 인덱스에 의한 제거)를 수행합니다.

 

8.1 Insert 메서드

 

Insert 메서드는 지정된 위치(index)에 새로운 요소를 삽입합니다. 기존의 요소들은 뒤로 이동하게 됩니다.

ArrayList myArrayList = new ArrayList() { 1, 2, 3, 4, 5 };

// 인덱스 2 위치에 10 삽입
myArrayList.Insert(2, 10);

 

위의 예제에서는 myArrayList의 인덱스 2 위치에 10을 삽입하였습니다. 결과적으로 배열은 [1, 2, 10, 3, 4, 5]가 됩니다.

 

8.2 Remove 메서드

 

Remove 메서드는 지정된 값을 가진 첫 번째 요소를 삭제합니다. 만약 같은 값이 여러 개 존재한다면, 첫 번째로 발견되는 것만 제거됩니다.

ArrayList myArrayList = new ArrayList() { 1, 2, 3, 4, 5 };

// 값 3을 가진 요소 제거
myArrayList.Remove(3);

 

위의 예제에서는 myArrayList에서 값이 3인 첫 번째 요소를 제거하였습니다. 결과적으로 배열은 [1, 2, 4, 5]가 됩니다.

 

8.3 RemoveAT 메서드

 

RemoveAt 메서드는 지정된 인덱스 위치에 있는 요소를 삭제합니다.

ArrayList myArrayList = new ArrayList() { 1, 2, 3, 4, 5 };

// 인덱스 2 위치의 요소 제거
myArrayList.RemoveAt(2);

 

위의 예제에서는 myArrayList의 인덱스 2 위치에 있는 요소를 제거하였습니다. 결과적으로 배열은 [1, 2, 4, 5]가 됩니다.

 

Reomve 는 값 매칭 (Value Matching) 이고, RemoveAT은 인덱스 매칭(Index Matching) 입니다.

즉 Remove(argument) 함수는 매개변수로 전달된 값을 찾아서(제일 먼저 찾은 인덱스) 해당 값을 제거하는 것이고, RemoveAT(number)은 매개변수로 전달된 number(인덱스)를 찾아서 해당 값을 제거하는 것입니다.

 

자료구조와 함께 박싱과 언박싱, 제네릭컬렉션에 대해서는 다음 포스팅에서 알아보겠습니다.