[이것이 C#이다] 10. 배열,컬렉션,인덱서

ssu_hyun·2022년 4월 19일
0

C#

목록 보기
14/22

Key point

  • 배열
  • System.Array
  • 배열의 종류
  • 컬렉션
  • 인덱서

10.1 배열

10.1.1 배열 선언

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

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

  • 선언

    데이터형식[] 배열이름 = new 데이터형식[ 용량 ];
    ex) int[] scores = new int[5];  // 용량이 5개인 int 형식의 배열
  • 데이터 저장
    배열이름[ 인덱스 ] =;
    ex) scores[0] = 80;  // scores배열의 첫번째 값 저장 (인덱스 0부터 시작)
  • 반복문, 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}");
        }
    }
}

10.1.2 배열 인덱스 & System.Index

  • 배열에 접근할 때 대괄호와 인덱스 이용
   int[] scores = new int[5];
   scores[scores.Length-1] = 34;  // scores[4] = 34;
   // 인덱스가 0부터 시작하므로 마지막 요소에 접근할 때는 1을 빼주어야 함
  • System.Index형식과 ^연산자를 이용하면 보다 쉽게 배열에 접근할 수 있다.
    • ^연산자 : 컬렉션의 마지막부터 역순으로 인덱스를 지정하는 기능
   // System.Index의 인스턴스 생성
   System.Index last = ^1; // ^1 = 배열의 마지막을 나타내는 인덱스
   scores[last] = 34; // scores[scores.Length-1] = 34;
   
   // 더 간결한 버전
   scores[^1] = 34;  // scores[scores.Length-1] = 34;

예제 프로그램

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;  // 배열 뒤에서 두번째
            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}");
        }
    }
}

10.1.3 배열 초기화

  • 컬렉션 초기자(Collection Initializer) : 배열 객체를 초기화하는 {} 블록

예제 프로그램

using System;

namespace InitializingArray
{
    class MainApp
    {
        static void Main(string[] args)
        {
        	// 방법1 : 배열 형식, 용량/길이 명시
            string[] array1 = new string[3] { "안녕", "Hello", "Halo" };

            Console.WriteLine("array1...");
            foreach (string greeting in array1)
                Console.WriteLine($" {greeting}");
			
            // 방법2 : 배열 형식만 명시 (용량/길이 생략)
            string[] array2 = new string[] { "안녕", "Hello", "Halo" };

            Console.WriteLine("\narray2...");
            foreach (string greeting in array2)
                Console.WriteLine($" {greeting}");
			
            // 방법3 : 배열 형식, 용량/길이 모두 생략
            string[] array3 = { "안녕", "Hello", "Halo" };

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



10.2 System.Array 클래스

10.2.1 System.Array 클래스

  • C#에서는 모든 것이 객체로 배열은 .NET의 CTS(Common Type System)에서 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}");
           }
       }
    }

10.2.2 Array 클래스의 주요 메소드, 프로퍼티

  • <T>
    • 형식 매개변수(Type Parameter)
    • T 대신 배열의 기반 자료형을 인수로 입력하면 컴파일러가 해당 형식에 맞춰 동작하도록 메소드를 컴파일함

예제 프로그램

using System;

namespace MoreOnArray
{
    class MainApp
    {
        private static bool CheckPassed(int score)
        {
            return score >= 60;
        }

        private static void Print(int value)
        {
            Console.Write($"{value} ");
        }

        static void Main(string[] args)
        {	
            // 배열 선언
            int[] scores = new int[]{80, 74, 81, 90, 34};
			
            // foreach문
            foreach (int score in scores)
                Console.Write($"{score} ");
            Console.WriteLine();
			
            // 정렬
            Array.Sort(scores);
            // 모든 요소에 동일한 작업 수행
            Array.ForEach<int>(scores, new Action<int>(Print)); // <int> : 배열 기반 자료형
            Console.WriteLine();
			
            // 차원 반환
            Console.WriteLine($"Number of dimensions : {scores.Rank}");
            
            // 이진 탐색
            Console.WriteLine($"Binary Search : 81 is at " +
                $"{Array.BinarySearch<int>(scores, 81)}");
            
            // 찾고자 하는 특정 데이터의 인덱스 반환
            Console.WriteLine($"Linear Search : 90 is at " +
                $"{Array.IndexOf(scores, 90)}");
			
            // 모든 요소가 지정한 조건에 부합하는지 여부 반환
            Console.WriteLine($"Everyone passed ? : " +
                $"{Array.TrueForAll<int>(scores, CheckPassed)}");
                // CheckPassed : TrueForAll 메소드는 배열과 함께 '조건을 검사하는 메소드'를 매개변수로 받음
			
            // 지정 조건에 부합하는 첫 번째 요소의 인덱스 반환
            int index = Array.FindIndex<int>(scores, (score) => score < 60);
            // 람다식 : FindIndex 메소드는 `특정 조건에 부합하는 메소드`를 매개변수로 받음 
			
            // 데이터 저장 및 변경
            scores[index] = 61;
            
            // 모든 요소가 지정한 조건에 부합하는지 여부 반환
            Console.WriteLine($"Everyone passed ? : " +
                $"{Array.TrueForAll<int>(scores, CheckPassed)}");
			
            // 지정한 차원의 길이 반환 (다차원 배열에서 유용하게 사용)
            Console.WriteLine("Old length of scores : " +
                $"{scores.GetLength(0)}");
            
            // 크기 재조정 : 배열 용량 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();
			
            // 모든 요소 초기화
            // 숫자 형식 → 0 | 논리 형식 → false | 참조 형식 → null
            Array.Clear(scores, 3, 7); // 인덱스 3~7까지 초기화
            Array.ForEach<int>(scores, new Action<int>(Print));
            Console.WriteLine();
			
            // 분할 : 배열의 일부를 다른 곳에 복사 
            int[] sliced = new int[3];
            Array.Copy(scores, 0, sliced, 0, 3);            
            Array.ForEach<int>(sliced, new Action<int>(Print));
            Console.WriteLine();
        }        
    }
}

10.3 배열 분할 : System.Range

  • ..연산자를 활용해 시작 인덱스와 마지막 인덱스를 이용해서 범위를 나타내는 방법

    • ..연산자 의 두번째 피연산자, 즉 마지막 인덱스는 배열 분할 결과에서 제외된다. (시작 연산자는 포함)

    • [..]처럼 시작과 마지막 인덱스를 모두 생략하면 배열 전체를 나타내는 System.Range 객체를 반환한다.

      // 첫 번째(0) ~ 세 번째(2) 요소
      int[] sliced3 = scores[..3];
      
      // 두 번째(1) ~ 마지막 요소
      int[] sliced4 = scores[1..];
      
      // 전체
      int[] sliced5 = scores[..];
    • System.Index 객체를 이용할 수도 있다.

      System.Index idx = ^1;
      int[] sliced5 = scores[..idx];
      
      int[] sliced6 = scores[..^1];  // ^연산자를 직접 입력하면 코드가 더 간결해짐

예제 프로그램

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]; // 90-65+1 = 26
            // Z의 ASCII 코드 = 90, A의 ASCII 코드 = 65
            for (int i = 0; i < array.Length; i++)
                array[i] = (char)('A'+i);  // array에 A부터 Z까지 입력

            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;  // Range 생성시 리터럴과 Index 객체를 함께 사용할 수 있다.
            PrintArray(array[range_5_last]); // 5번째부터 끝(^)까지      

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

10.4 2차원 배열

  • 1차원 배열(가로)을 원소로 갖는 배열
  • 2개의 차원(세로+가로)으로 원소를 배치
  • 선언
   데이터형식[,] 배열이름 = new 데이터형식[2차원길이, 1차원길이];
   ex) int[,] array = new int [2, 3];
  • 2차원 배열의 원소 접근
	// 배열이름 [두번째 차원, 첫 번째 차원]
   Console.WriteLine( array[ 0, 2 ] );
   Console.WriteLine( array[ 1, 1 ] );
  • 2차원 배열 선언 + 초기화
   // 배열의 형식과 길이 명시
   int[,] arr = new int[2, 3] {{1, 2, 3}, {4, 5, 6}};
   // 배열의 길이 생략
   int[,] arr2 = new int[,] {{1, 2, 3}, {4, 5, 6}};
   // 형식과 길이 모두 생략
   int[,] arr3 = {{1, 2, 3}, {4, 5, 6}};

예제 프로그램

using System;

namespace InitializingArray
{
    class MainApp
    {
        static void Main(string[] args)
        {
        	// 방법1 : 배열의 형식과 길이 명시 
            string[] array1 = new string[3] { "안녕", "Hello", "Halo" };

            Console.WriteLine("array1...");
            foreach (string greeting in array1)
                Console.WriteLine($" {greeting}");
			
            // 방법2 : 배열의 길이 생략
            string[] array2 = new string[] { "안녕", "Hello", "Halo" };

            Console.WriteLine("\narray2...");
            foreach (string greeting in array2)
                Console.WriteLine($" {greeting}");
			
            //방법3 : 형식과 길이 모두 생략
            string[] array3 = { "안녕", "Hello", "Halo" };

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



10.5 다차원 배열

  • 차원이 둘 이상인 배열
  • 선언 문법은 2차원 배열의 문법과 같다. 다만 차원이 늘어날수록 요소에 접근할 때 사용하는 인덱스의 수가 2개, 3개, 4개...의 식으로 늘어나는 점이 다르다.
  • 3차원 배열 : 2차원 배열을 요소로 갖는 배열

예제 프로그램

using System;

namespace _3DArray
{
    class MainApp
    {
        static void Main(string[] args)
        {
            int[, ,] array = new int[4, 3, 2] 
            { 
                { {1, 2}, {3, 4}, {5, 6} },
                { {1, 4}, {2, 5}, {3, 6} },
                { {6, 5}, {4, 3}, {2, 1} },
                { {6, 3}, {5, 2}, {4, 1} },
            };

            for (int i = 0; i < array.GetLength(0); i++)
            {
                for (int j = 0; j < array.GetLength(1); j++)
                {
                    Console.Write("{ ");
                    for (int k = 0; k < array.GetLength(2); k++)
                    {
                        Console.Write($"{array[i, j, k]} ");
                    }
                    Console.Write("} ");
                }
                Console.WriteLine();
            }
        }
    }
}



10.6 가변 배열(Jagged Array)

  • 다양한 길이의 배열을 요소로 갖는 다차원 배열
  • 들쭉날쭉한 배열
  • 선언
   데이터형식[][] 배열이름 = new 데이터형식[가변 배열의 용량][];
   ex) int[][] jagged = new int[3][];
  • 가변 배열의 요소로 입력되는 배열은 그 길이가 모두 같을 필요가 없다.
   int[][] jagged = new int[3][];
   jagged[0] = new int[5] { 1, 2, 3, 4, 5 };  // 5
   jagged[1] = new int[] { 10, 20, 30 };  // 3
   jagged[2] = new int[] { 100, 200 };  // 2
  • 가변 배열도 선언과 동시에 초기화가 가능하다.
   int[][] jagged2 = new int[2][] { 
       new int[] { 1000, 2000 }, 
       new int[4] { 6, 7, 8, 9 } };

예제 프로그램

using System;

namespace JaggedArray
{
    class MainApp
    {
        static void Main(string[] args)
        {
        	// 들쭉날쭉한 가변 배열
            int[][] jagged = new int[3][];
            jagged[0] = new int[5] { 1, 2, 3, 4, 5 };
            jagged[1] = new int[] { 10, 20, 30 };
            jagged[2] = new int[] { 100, 200 };
            

            foreach( int[] arr in jagged )
            {
                Console.Write($"Length : {arr.Length}, ");
                foreach( int e in arr)
                {
                    Console.Write($"{e} ");
                }
                Console.WriteLine("");
            }

            Console.WriteLine("");
            
            // 선언 + 초기화
            int[][] jagged2 = new int[2][] { 
                new int[] { 1000, 2000 }, 
                new int[4] { 6, 7, 8, 9 } };

            foreach (int[] arr in jagged2)
            {
                Console.Write($"Length : {arr.Length}, ");
                foreach (int e in arr)
                {
                    Console.Write($"{e} ");
                }
                Console.WriteLine();
            }
        }
    }
}



10.7 컬렉션 맛보기

  • 컬렉션(Collection) : 같은 성격을 띈 데이터의 모음을 담는 자료구조
  • 배열도 .NET이 제공하는 다양한 컬렉션 자료구조의 일부
    /* .NET의 여타 컬렉션들이 무조건 상속해야 하는 ICollection 인터페이스를
       System.Array 클래스가 상속함으로써 자신이 컬렉션 가문의 일원임을 증명하고 있다. */
    
    public abstract class Array : ICloneable, IList, ICollection, IEnumerable

10.7.1 ArrayList

  • 배열과 같이[] 연산자와 인덱스를 통해 요소에 접근 가능
  • 배열과 달리 컬렉션을 생성할 때 용량을 미리 지정할 필요 없이 필요에 따라 자동으로 그 용량이 늘어나거나 줄어든다.
  • 메소드
    • Add() : 가장 마지막에 있는 요소 뒤에 새 요소 추가
    • RemoveAt() : 특정 인덱스에 있는 요소 제거
    • Insert() : 원하는 위치에 새 요소 삽입

예제 프로그램

using System;
using System.Collections;

namespace UsingList
{
    class MainApp
    {
        static void Main(string[] args)
        {
            ArrayList list = new ArrayList();
            for (int i = 0; i < 5; i++)
                list.Add(i);

            foreach (object obj in list)
                Console.Write($"{obj} ");
            Console.WriteLine();

            list.RemoveAt(2);

            foreach (object obj in list)
                Console.Write($"{obj} ");
            Console.WriteLine();

            list.Insert(2, 2);

            foreach (object obj in list)
                Console.Write($"{obj} ");
            Console.WriteLine();

            list.Add("abc");
            list.Add("def");

            for ( int i=0; i<list.Count; i++ )
                Console.Write($"{list[i]} ");
            Console.WriteLine();
       }
    }
}

ArrayList가 다양한 형식의 객체를 담을 수 있는 이유

// Add(), Insert() 메소드의 선언
public virtual int Add( Object value )
public virtual void Insert( int index, Object value )

모든 형식은 object를 상속하므로 object 형식으로 간주될 수 있다.
그래서 Add() 메소드에 int형식의 데이터를 넣더라도
정수 형식 그대로 입력되는 것이 아닌 object 형식으로 박싱되어 입력되는 것.
반대로 ArrayList의 요소에 접근해서 사용할 때는
원래의 데이터 형식으로 언박싱이 이루어진다.

여기서 박싱과 언박싱은 오버헤드를 꽤 요구하는데
이러한 성능 저하는 데이터가 많으면 많아질수록 더욱 늘어난다.

10.7.2 Queue

  • 대기열, 즉 기다리는 (대기) 줄(열)
  • 데이터나 작업을 차례대로 입력해뒀다가 입력된 순서대로 하나씩 꺼내 처리하기 위해 사용됨
  • 먼저 들어온 것이 먼저 나가는 "선입선출"로, FIFO(First In First Out)의 구조
  • 연산
    • 삽입 연산 : Enqueue()
    • 삭제 연산 : Dequeue() (데이터를 자료구조에서 실제로 꺼내는 것)

예제 프로그램

using System;
using System.Collections;

namespace UsingQueue
{
    class MainApp
    {
        static void Main(string[] args)
        {	
        	// Queue 선언
            Queue que = new Queue();
            // 삽입
            que.Enqueue(1);
            que.Enqueue(2);
            que.Enqueue(3);
            que.Enqueue(4);
            que.Enqueue(5);

            while (que.Count > 0)
                Console.WriteLine(que.Dequeue()); // 삭제
        }
    }
}

10.7.3 Stack

  • "쌓다"라는 의미로, 데이터를 차곡차곡 쌓아 올린 형태의 자료구조
  • 가장 마지막에 삽입된 자료가 가장 먼저 삭제되는 "선입후출"로 FILO(First In Last Out)의 구조
  • 연산
    • 삽입 연산 : push()
    • 삭제 연산 : pop()

예제 프로그램

using System;
using System.Collections;

namespace UsingStack
{
    class MainApp
    {
        static void Main(string[] args)
        {
        	// 스택 선언
            Stack stack = new Stack();
            // 삽입
            stack.Push(1);
            stack.Push(2);
            stack.Push(3);
            stack.Push(4);
            stack.Push(5);

            while (stack.Count > 0)
                Console.WriteLine(stack.Pop());  // 삭제
        }
    }
}

10.7.4 Hashtable

  • 키(Key), 값(Value)의 쌍으로 이루어진 데이터를 다룰 때 사용
  • 탐색 속도가 거의 소요되지 않을 정도로 빠름
    • 해싱(Hashing) : 키를 이용해 단번에 데이터가 저장된 컬렉션 내의 주소를 계산해내는 작업

예제 프로그램

using System;
using System.Collections;
using static System.Console;

namespace UsingHashtable
{
    class MainApp
    {
        static void Main(string[] args)
        {
            Hashtable ht = new Hashtable();
            ht["하나"] = "one";
            ht["둘"]   = "two";
            ht["셋"]   = "three";
            ht["넷"]   = "four";
            ht["다섯"] = "five";

            WriteLine( ht["하나"] ) ;
            WriteLine( ht["둘"]   );
            WriteLine( ht["셋"]   );
            WriteLine( ht["넷"]   );
            WriteLine( ht["다섯"] );
        }
    }
}


10.8 컬렉션 초기화

  • 배열의 도움을 받아 초기화 수행
  • ArratList는 배열의 도움 없이 직접 컬렉션 초기자를 이용해 초기화
    • 컬렉션 초기자는 IEnumerable 인터페이스와 Add() 메소드를 구현하는 컬렉션만 지원하는데 StackQueue는 Add() 메소드를 구현하지 않아 컬렉션 초기자 사용 불가
using System;
using System.Collections;
using static System.Console;

namespace InitializingCollections
{
    class MainApp
    {
        static void Main(string[] args)
        {	
        	// 배열
            int[] arr = { 123, 456, 789 };
			
            
            // 1. 컬렉션 초기화 : 배열 이용
            ArrayList list = new ArrayList(arr);
            foreach (object item in list)
                WriteLine($"ArrayList : {item}");
            WriteLine();

            Stack stack = new Stack(arr);
            foreach (object item in stack)
                WriteLine($"Stack : {item}");
            WriteLine();

            Queue queue = new Queue(arr);
            foreach (object item in queue)
                WriteLine($"Queue : {item}");
            WriteLine();
			
            // 컬렉션 초기화 : 컬렉션 초기자 이용
            ArrayList list2 = new ArrayList() { 11, 22, 33 };
            foreach (object item in list2)
                WriteLine($"ArrayList2 : {item}");
            WriteLine();
        }
    }
}
  • Hashtable 초기화
// Hashtable 초기화 : `딕셔너리 초기자` 이용
Hashtable ht = new Hashtable()
{
	["하나"] = 1,  // ;가 아니라 ,를 이용해 항목 구분
    ["둘"] = 2,
    ["셋"] = 3
};


// Hashtable 초기화 : `컬렉션 초기자` 이용
Hashtable ht = new Hashtable()
{
	{"하나", 1},  
    {"둘", 2},
    {"셋", 3}
};

10.9 인덱서

  • 프로퍼티 : 객체 내의 데이터에 접근할 수 있도록 하는 통로
  • 인덱서 : "인덱스(Index)를 통해" 객체 내의 데이터에 접근하게 해주는 프로퍼티/통로
  • 객체를 마치 배열처럼 사용할 수 있게 해줌
  • 선언
   class 클래스이름
   {
      한정자 인덱서형식 this[형식 index]
      {
          get
          {
             // index를 이용해 내부 데이터 반환
          }
          
          set
          {
             // index를 이용해 내부 데이터 저장
          }
       }
   }

예제 프로그램

using System;
using System.Collections;

namespace Indexer
{
    class MyList
    {
        private int[] array;

        public MyList()
        {
            array = new int[3];
        }

        public int this[int index]
        {
            get
            {
                return array[index];  // 데이터 저장
            }

            set
            {
            	// 지정인덱스 > 배열크기 -> 인덱스에 맞춰 배열 크기 재조정
                if (index >= array.Length)
                {
                    Array.Resize<int>(ref array, index + 1);
                    Console.WriteLine($"Array Resized : {array.Length}"); 
                }

                array[index] = value;
            }
        }  

        public int Length
        {
            get { return array.Length; }
        }
    }

    class MainApp
    {
        static void Main(string[] args)
        {
            MyList list = new MyList();
            for (int i = 0; i < 5; i++)
                list[i] = i;

            for (int i = 0; i<list.Length; i++)
                Console.WriteLine(list[i]);
        }
    }
}

10.10 foreach가 가능한 객체

  • foreach 구문은 IEnumerable을 상속하는 형식만 지원
    = IEnumerable을 상속하면 foreach 문을 통해 요소 순회 가능
  • IEnumerable 인터페이스가 갖고 있는 메소드는 GetEnumerator()뿐이며 이는 IEnumerable 형식의 객체를 반환한다.
  • yield문을 이용하면 IEnumerable를 상속하는 클래스를 따로 구현하지 않아도 컴파일러가 자동으로 해당 인터페이스를 구현한 클래스를 생성해줌
    • yield return문은 현재 메소드 (GetEnumerator())의 실행을 일시 정지시켜놓고 호출자에게 결과를 반환
// yield 문의 도움을 받아 IEnumerator를 상속하는 클래스 구현 회피
using System;
using System.Collections// IEnumerator 상속 클래스 직접 구현 //;

namespace Yield
{
    class MyEnumerator
    {
        int[] numbers = { 1, 2, 3, 4 };
        public IEnumerator GetEnumerator()
        {
            yield return numbers[0];
            yield return numbers[1];
            yield return numbers[2];
            yield break; // GetEnumerator() 메소드 종료시킴
            yield return numbers[3];  // 이 코드 실행X
        }
    }
    class MainApp
    {

        static void Main(string[] args)
        {
            var obj = new MyEnumerator();
            foreach (int i in obj)
                Console.WriteLine(i);
        }
    }
}

// IEnumerator 상속 클래스 직접 구현 //

using System;
using System.Collections;

namespace Enumerable
{
    class MyList : IEnumerable, IEnumerator
    {
        private int[] array;
        int position = -1;  // 컬렉션의 현재 위치를 다루는 변수, 첫 번째 반복 때 0이 되어야 하므로 

        public MyList()
        {
            array = new int[3];
        }

        public int this[int index]
        {
            get
            {
                return array[index];
            }

            set
            {
                if (index >= array.Length)
                {
                    Array.Resize<int>(ref array, index + 1);
                    Console.WriteLine($"Array Resized : {array.Length}");
                }

                array[index] = value;
            }
        }

        // IEnumerator 멤버
        public object Current  // 현재 위치의 요소 반환
        {
            get
            {
                return array[position];
            }
        }

        // IEnumerator 멤버
        public bool MoveNext()  // 다음 위치의 요소로 이동
        {
            if (position == array.Length - 1)
            {
                Reset();
                return false;
            }

            position++;
            return (position < array.Length);
        }

        // IEnumerator 멤버
        public void Reset()  // IEnumerator로부터 상속받은 Reset()메소드, 요소의 위치를 첫 요소의 "앞"으로 옮김
        {
            position = -1;  
        }

        // IEnumerable 멤버
        public IEnumerator GetEnumerator()
        {
            return this;
        }
    }

    class MainApp
    {
        static void Main(string[] args)
        {
            MyList list = new MyList();
            for (int i = 0; i < 5; i++)
                list[i] = i;

            foreach (int e in list)
                Console.WriteLine(e);
        }
    }
}


연습문제

  1. 다음 배열 선언 문장 중 올바르지 않은 것을 고르세요. -> 1
    1) int[] array = new string[3] {"안녕", "Hello", "Halo"}; // int -> string
    2) int[] array = new int[3] {"안녕", "Hello", "Halo"};
    3) int[] array = new int[]{1, 2, 3}
    4) int[] array = {1, 2, 3}

  2. 두 행렬의 곱은 다음과 같이 계산합니다.

    A=[a bc d] B=[e fg h]A = {a\ b \brack c\ d}\ B = {e\ f \brack g\ h}
    A×B=[a×e+b×ga×f+b×hc×e+d×gc×f+d×h]A×B = {a×e+b×g\qquad a×f+b×h \brack c×e+d×g\qquad c×f+d×h}

    다음 두 행렬 A와 B의 곱을 2차원 배열을 이용해 계산하는 프로그램을 작성하세요.

    A=[3 21 4] B=[9 21 7]A = {3\ 2 \brack 1\ 4}\ B = {9\ 2 \brack 1\ 7}
using System;
using System.Collections;

namespace Ex_10
{

    class MainApp
    {
        static void Main()
        {
            int[,] A = { { 3, 2 }, { 1, 4 } };
            int[,] B = { { 9, 2 }, { 1, 7 } };
            int[,] array = new int[2, 2];  // 출력값을 넣을 array


            array[0, 0] = (A[0, 0] * B[0, 0]) + (A[0, 1] * B[1, 0]);
            array[0, 1] = (A[0, 0] * B[0, 1]) + (A[0, 1] * B[1, 1]);
            array[1, 0] = (A[1, 0] * B[0, 0]) + (A[1, 1] * B[1, 0]);
            array[1, 1] = (A[1, 0] * B[0, 1]) + (A[1, 1] * B[1, 1]);

            Console.Write($"array[0,0] :{array[0, 0]}"); //29
            Console.WriteLine($" array[0,1] :{array[0, 1]}"); // 20
            Console.Write($"array[1,0] :{array[1, 0]}"); // 13
            Console.WriteLine($" array[1,1] :{array[1, 1]}"); // 30
        }
    }
}

  1. 다음 코드의 출력 결과는 무엇일까요?
Stack stack = new Stack();
stack.Push(1);
stack.Push(2);
stack.Push(3);
stack.Push(4);
stack.Push(5);

while (stack.Count > 0)
    Console.WriteLine(stack.Pop());

  1. 다음 코드의 출력 결과는 무엇일까요?
Queue que = new Queue();
que.Enqueue(1);
que.Enqueue(2);
que.Enqueue(3);
que.Enqueue(4);
que.Enqueue(5);

while (que.Count > 0)
    Console.WriteLine(que.Dequeue());

  1. 다음과 같은 결과를 출력하도록 아래의 코드를 완성하세요.
회사 : Microsoft
URL : www.microsoft.com
Hashtable ht = new Hashtable();

ht["회사"] = "Microsoft";
ht["URL"] = "www.microsoft.com";

Console.WriteLine("회사 : {0}", ht["회사"]);
Console.WriteLine("URL: {0}", ht["URL"]);

업로드중..

0개의 댓글