같은 형식의 복수 인스턴스를 저장할 수 있는 형식
참조형식으로써 연속된 메모리 공간을 가리킴
선언
데이터형식[] 배열이름 = 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}");
}
}
}
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}");
}
}
}
{}
블록예제 프로그램
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}");
}
}
}
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}");
}
}
}
<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();
}
}
}
..연산자
를 활용해 시작 인덱스와 마지막 인덱스를 이용해서 범위를 나타내는 방법
..연산자
의 두번째 피연산자, 즉 마지막 인덱스는 배열 분할 결과에서 제외된다. (시작 연산자는 포함)
[..]
처럼 시작과 마지막 인덱스를 모두 생략하면 배열 전체를 나타내는 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번째까지
}
}
}
데이터형식[,] 배열이름 = new 데이터형식[2차원길이, 1차원길이];
ex) int[,] array = new int [2, 3];
// 배열이름 [두번째 차원, 첫 번째 차원]
Console.WriteLine( array[ 0, 2 ] );
Console.WriteLine( array[ 1, 1 ] );
// 배열의 형식과 길이 명시
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}");
}
}
}
예제 프로그램
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();
}
}
}
}
데이터형식[][] 배열이름 = 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();
}
}
}
}
/* .NET의 여타 컬렉션들이 무조건 상속해야 하는 ICollection 인터페이스를
System.Array 클래스가 상속함으로써 자신이 컬렉션 가문의 일원임을 증명하고 있다. */
public abstract class Array : ICloneable, IList, ICollection, IEnumerable
[]
연산자와 인덱스를 통해 요소에 접근 가능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의 요소에 접근해서 사용할 때는
원래의 데이터 형식으로 언박싱이 이루어진다.
여기서 박싱과 언박싱은 오버헤드를 꽤 요구하는데
이러한 성능 저하는 데이터가 많으면 많아질수록 더욱 늘어난다.
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()); // 삭제
}
}
}
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()); // 삭제
}
}
}
예제 프로그램
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["다섯"] );
}
}
}
ArratList
는 배열의 도움 없이 직접 컬렉션 초기자
를 이용해 초기화Stack
과 Queue
는 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 ht = new Hashtable()
{
["하나"] = 1, // ;가 아니라 ,를 이용해 항목 구분
["둘"] = 2,
["셋"] = 3
};
// Hashtable 초기화 : `컬렉션 초기자` 이용
Hashtable ht = new Hashtable()
{
{"하나", 1},
{"둘", 2},
{"셋", 3}
};
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]);
}
}
}
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) 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}
두 행렬의 곱은 다음과 같이 계산합니다.
다음 두 행렬 A와 B의 곱을 2차원 배열을 이용해 계산하는 프로그램을 작성하세요.
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
}
}
}
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());
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());
회사 : 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"]);