본문 바로가기
전공/C# 프로그래밍

8강. 배열 (1)

by 임 낭 만 2023. 4. 19.

배열

배열 (Array)

  • 같은 데이터 형의 다수의 데이터를 한번에 다뤄야 하는 경우
    • 각각의 데이터에 대한 변수를 선언한다면 코드의 양 증가
  • 배열 변수 한 개로 다수의 데이터 관리 가능

같은 성격을 띤 다수의 데이터를 한 번에 다뤄야 하는 경우 : 수많은 변수 대신 그만큼의 용량을 가진 변수 하나로 해결한다면?

같은 형식의 복수 인스턴스를 저장할 수 있는 형식

참조 형식으로써 연속된 메모리 공간을 가리킴

반복문, 특히 for/foreach문과 함께 사용하면 효율 향상

꺽쇠 가로 [ ] 안에 배열의 크기를 지정하여 다음과 같이 선언

배열의 출력과 연산

  • 다수의 변수 선언과 배열 사용의 비교

using System;

namespace ArraySample
{
    class MainApp
    {
        static void Main(string[] args)
        {
            int[] scores = new int[5];
            scores[0] = 80;
            scores[1] = 74;
            scores[2] = 81;
            scores[3] = 90;
            scores[4] = 34;

            foreach (int score in scores)
                Console.WriteLine(score);

            int sum = 0;
            foreach (int score in scores)
                sum += score;

            int average = sum / scores.Length;
            //배열 객체의 Length 프로퍼티는 배열의 크기를 나타냅니다.

            Console.WriteLine($"Average Score : {average}");
        }
    }
}

Index from end (^) 연산자

  • C# 8.0 부터 System.Index 형식과 ^ 연산자 지원
    • 배열의 마지막부터 역순으로 인덱스를 지정
    • ^1 은 배열의 마지막 요소를 나타내는 인덱스
    • ^2 은 배열의 마지막에서 두번째 요소를 나타내는 인덱스
    • ^ 연산자의 연산 결과는 System.Index 형식의 인스턴스로 나타냄

using System;

namespace ArraySample2
{
    class MainApp
    {
        static void Main(string[] args)
        {
            int[] scores = new int[5];
            scores[0] = 80;
            scores[1] = 74;
            scores[2] = 81;
            scores[^2] = 90;  // 배열의 마지막-1
            scores[^1] = 34;  // 배열의 마지막

            foreach (int score in scores)
                Console.WriteLine(score);

            int sum = 0;
            foreach (int score in scores)
                sum += score;

            int average = sum / scores.Length;

            Console.WriteLine($"Average Score : {average}");
        }
    }
}

배열 초기화하는 세 가지 방법

  • 배열의 원소 개수 명시, 중괄호로 둘러싸인 블록을 붙인 뒤, 블록 사이에 배열의 각 원소에 입력될 데이터를 입력

배열 크기를 명시하고 컬렉션 초기자를 사용

  • 첫 번째 방법에서 배열의 용량을 생략

배열 크기를 명시하지 않고 컬렉션 초기자 사용

  • 첫 번째 방법에서 new 연산자와 형식과 대괄호 [ ], 배열의 용량 모두 생략

컬렉션 초기자만 사용

using System;

namespace InitializingArray
{
    class MainApp
    {
        static void Main(string[] args)
        {
            string[] array1 = new string[3]{ "안녕", "Hello", "Halo" };

            Console.WriteLine("array1...");
            foreach (string greeting in array1)
                Console.WriteLine($" {greeting}");

            string[] array2 = new string[] { "안녕", "Hello", "Halo" };

            Console.WriteLine("\narray2...");
            foreach (string greeting in array2)
                Console.WriteLine($" {greeting}");

            string[] array3 = { "안녕", "Hello", "Halo" };

            Console.WriteLine("\narray3...");
            foreach (string greeting in array3)
                Console.WriteLine($" {greeting}");
        }
    }
}


System.Array 클래스

System.Array 클래스

모든 배열의 기반 클래스이며 배열 그 자체를 나타냄.

배열을 보다 편리하게 다룰 수 있게 도와주는 유틸리티 메소드 제공

정렬, 탐색, 크기 조정 등의 기능 제공

  • .NET의 CTS (Common Type System)에서 배열은 System.Array 클래스에 대응
    • 아래 예제는 int 기반의 배열이 System.Array 형식에서 파생되었음을 보여줌
using System;

namespace DerivedFromArray
{
    class MainApp
    {
        static void Main(string[] args)
        {
            int[] array = new int[] { 10, 30, 20, 7, 1 };
            Console.WriteLine($"Type Of array : {array.GetType()}");
            Console.WriteLine($"Base type Of array : {array.GetType().BaseType}");
        }
    }
}

System.Array의 메소드와 프로퍼티

이를 사용한 예제 (아래)

using System;

namespace MoreOnArray
{
    class MainApp
    {
        private static void Print(int value)
        {
            Console.Write($"{value} ");
        }
        static void Main(string[] args)
        {
            int[] scores = new int[]{80, 74, 81, 90, 34};

            foreach (int score in scores)
                Console.Write($"{score} ");
            Console.WriteLine();

            Array.Sort(scores);
            Array.ForEach<int>(scores, new Action<int>(Print));
            Console.WriteLine();
        }        
    }
}

이를 사용한 예제 (아래)

using System;

namespace MoreOnArray
{
    class MainApp
    {
        static void Main(string[] args)
        {
            int[] scores = new int[]{80, 74, 81, 90, 34};
            Array.Sort(scores);

            Console.WriteLine($"Number of dimensions : {scores.Rank}");
            
            Console.WriteLine($"Binary Search : 81 is at " +
                $"{Array.BinarySearch<int>(scores, 81)}");
            
            Console.WriteLine(($"Binary Search : 90 is at " +
                $"{Array.IndexOf(scores, 90)}");
        }        
    }
}

이를 사용한 예 (아래)

using System;

namespace MoreOnArray
{
    class MainApp
    {
        private static bool CheckPassed(int score)
        {
            return score >= 60;
        }
        static void Main(string[] args)
        {
            int[] scores = new int[] { 80, 74, 81, 90, 34 };
            Array.Sort(scores);

            // TrueForAll 메소드는 배열과 함께 조건을 검사하는 메소드를 매개변수로 받음
            Console.WriteLine($"Everyone passed ? : "
            + $"{Array.TrueForAll<int>(scores, new Predicate<int>(CheckPassed))}");
        }
    }
}

이를 사용한 예제 (아래)

using System;

namespace MoreOnArray
{
    class MainApp
    {
        private static bool CheckPassed(int score)
        {
            return score >= 60;
        }
        static void Main(string[] args)
        {
            int[] scores = new int[] { 80, 74, 81, 90, 34 };
            Array.Sort(scores);

            // FindIndex 메소드는 특정 조건에 부합하는 메소드를 매개변수로 받음
            // 메소드는 람다식으로 구현
            int index = Array.FindIndex<int>(scores, new Predicate<int>((score) => score < 60));
           
            scores[index] = 61;
            Console.WriteLine($"Everyone passed ? : "
            + $"{Array.TrueForAll<int>(scores, CheckPassed)}");
        }
    }
}

이를 사용한 예제 (아래)

using System;

namespace MoreOnArray
{
    class MainApp
    {

        private static void Print(int value)
        {
            Console.Write($"{value} ");
        }
        static void Main(string[] args)
        {
            int[] scores = new int[] { 80, 74, 81, 90, 34 };
            Array.Sort(scores);

            int index = Array.FindIndex<int>(scores, (score) => score < 60);

            scores[index] = 61;

            Console.WriteLine("Old length of scores : "
                + $"{scores.GetLength(0)}");

            // 5 였던 배열 용량을 10으로 재조정
            Array.Resize<int>(ref scores, 10);
            Console.WriteLine($"New length of scores: {scores.Length}");
            Array.ForEach<int>(scores, new Action<int>(Print));
            Console.WriteLine();

            int[] sliced = new int[3];
            // scores 배열의 0번째부터 3개 요소를 sliced 배열의 0번째~2번째 요소로 복사
            Array.Copy(scores, 0, sliced, 0, 3);
            Array.ForEach<int>(sliced, new Action<int>(Print));
        }
    }
}


배열 분할하기

배열 분할하기

  • C# 8.0에서 System.Range 형식 도입하여 범위를 나타냄
    • 시작 인덱스와 마지막 인덱스를 이용해서 범위를 나타
    • “..” 연산자 왼쪽에는 시작 인덱스, 오른쪽에는 마지막 인덱스 위치

  • .. 연산자의 오른쪽 마지막 인덱스는 분할 결과에 제외
    • 왼쪽 시작 인덱스는 분할 결과에 포함
  • .. 연산자의 두 피연산자는 생략 가능
    • 시작 인덱스를 생략하면 배열의 첫 번째 요소의 위치를 시작 인덱스로 간주
    • 마지막 인덱스를 생략하면 마지막 요소의 위치를 마지막 인덱스로 간주
    • 시작과 마지막 인덱스를 모두 생략하면 배열 전체를 나타냄

using System;

namespace Slice
{
    class MainApp
    {
        static void PrintArray(System.Array array)
        {
            foreach (var e in array)
                Console.Write(e);
            Console.WriteLine();
        }

        static void Main(string[] args)
        {
            char[] array = new char['Z' - 'A' + 1]; // 대문자 알파벳 개수
            // arrary에 'A'부터 'Z'까지 입력
            for (int i = 0; i < array.Length; i++)
                array[i] = (char)('A' + i);

            PrintArray(array[..]);    // 0번째부터 마지막까지
            PrintArray(array[5..]);   // 5번째부터 끝까지

            Range range_5_10 = 5..10;
            PrintArray(array[range_5_10]); // 5번째부터 9(10-1)번째까지      

            Index last = ^0;
            Range range_5_last = 5..last;
            PrintArray(array[range_5_last]); // 5번째부터 끝(^)까지      

            PrintArray(array[^4..^1]);  // 끝에서 4번째부터 끝(^)에서 1번째까지      
        }
    }
}

댓글