Media Log


1. 배열(Array)


배열이란, 동일한 타입의 변수를 모아놓은 데이터 집합이라고 말할 수 있습니다. 예를 들어서, 우리가 각 반 학생들의 한 달 독서량을 변수에 담는다고 가정하면 아래와 같이 변수를 선언해야 합니다.

...
    int reading_1 = 4;
    int reading_2 = 9;
    int reading_3 = 1;
    int reading_4 = 0;
    int reading_5 = 21;
    int reading_6 = 12;
...

보기만 해도 비효율적이고, 만약 반에 학생이 30명 정도가 있다면 비슷한 성격의 변수를 똑같이 30번 선언해야 하며, 전체 학생의 독서량을 사용자에게 제공하려고 변수에 접근하여 값을 얻어올 때도 상당히 불편합니다. 여기서, 배열을 사용하면 이 두 문제를 한 번에 잡을 수 있으며, 익숙해지다 보면 여러 개의 데이터를 다루게 될 때 유용하게 사용할 수 있습니다. 아래는 위 문제를 배열로 구현한 예제입니다.

...
    int[] reading = new int[30]{4, 9, 1, 0, 21, 12, ..., ..., ...}
...

상당히 간편해졌죠? 그리고 배열에 접근할 때는 첨자값(index, 인덱스)으로 접근하는데 여기서 주의하실 점은 첨자값은 항상 0부터 시작한다는 사실을 기억하시고 계셔야 합니다. 아래는 첨자값으로 각 배열 요소에 접근하여 그 값을 출력시키는 예제입니다.

...
    Console.WriteLine("reading[0]={0}", reading[0]); // reading[0]=4
    Console.WriteLine("reading[1]={0}", reading[1]); // reading[1]=9
    Console.WriteLine("reading[2]={0}", reading[2]); // reading[2]=1
...

아까처럼 일일이 변수를 선언하여 접근하는 것과는 다르게 배열의 첨자값을 이용한 접근은 상당히 간단합니다. 이제는 직접 배열을 우리가 선언하고, 배운 사실을 응용하여 다른 프로그램을 만들어보도록 합시다. 아래는 배열의 선언 방법입니다.

자료형[] 배열명 = new 자료형[크기];
크기 6을 가진 int 형식의 배열 student를 선언하려면 아래와 같이 선언하시면 됩니다.
int[] student = new int[6];

student[0] = 4;
student[1] = 9;
student[2] = 1;
..

위와 같이 선언하면 아래와 같이 6개의 공간을 가진 int형 배열 구조를 형성합니다.



이제 배열에 대해 기본적인 사항은 알았으니, 배열을 직접 사용해보도록 합시다.

using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] reading = new int[6] { 4, 9, 1, 0, 21, 12 };

            for (int i = 0; i < reading.Length; i++)
                Console.WriteLine("reading[" + i + "]={0}", reading[i]);
        }
    }
}
결과:
reading[0]=4
reading[1]=9
reading[2]=1
reading[3]=0
reading[4]=21
reading[5]=12
계속하려면 아무 키나 누르십시오 . . .

코드의 12행을 보시면 reading이라는 int형 배열이 선언되었고 6개의 공간을 차지합니다. 그리고 그 공간마다 각각 4, 9, 1, 0, 21, 12란 값으로 초기화되었습니다. 11행을 보시면 for문으로 reading의 길이, 즉 크기만큼 반복하여 코드를 실행합니다. 12행에서는 0부터 5까지 접근하여 그 요소가 가지고 있는 값을 출력합니다.


여기서 9행을 다시 살펴보시면, 배열의 선언과 동시에 초기화를 하고 있는데 이방법 말고도, 배열을 선언하는 방법은 더 있습니다. 배열을 선언하고 그와 동시에 초기화를 한다면 아래와 같은 방법도 가능합니다.

int[] reading = {4, 9, 1, 0, 21, 12};

이렇게 코드를 적어도 에러가 나지 않는 이유는, 초기화 시에 배열 요소의 수로 길이가 지정되기 때문입니다. 그렇기에 크기를 생략해도 정상적으로 컴파일이 가능합니다. 위의 코드는 아래의 코드와 같습니다.

int[] reading = new int[]{4, 9, 1, 0, 21, 12};


2. System.Array


Array 클래스는 배열에 대한 다양한 기능을 제공합니다. 여기서, 클래스가 궁금하신 분들은 다음 강좌에서 'C# 강좌 10편. 클래스(Class)'를 미리 살펴보셔도 괜찮습니다. 기능이 상당히 많아, 그것을 모두 다 강좌에서 설명할 수는 없고 주로 쓰이는 메소드와 속성만 간단히 설명하도록 하겠습니다. 이것 말고도 더 궁금하신 분들은 MSDN를 방문하여 참고하시면 됩니다.


MSDN System.Array 관련 문서: http://msdn.microsoft.com/ko-kr/library/system.array.aspx


분류

이름

기능

속성

Rank

배열의 차원 수를 가져옵니다.

Length 

배열의 길이를 가져옵니다.

메소드

Clear

배열 형식에 따라 정수 형식일 경우 0, 논리 형식일 경우 false, 참조 형식일 경우 null으로 초기화됩니다.

ForEach 

지정한 배열의 각 요소에서 지정한 동작을 수행합니다.

Resize 

배열의 요소 수를 지정된 새로운 크기로 변경합니다.

indexOf 

지정한 개체를 검색하여 1차원 Array 전체에서 처음 검색된 개체의 인덱스를 반환합니다.


위의 표는 주로 사용되는 속성과 메소드를 정리한 것입니다. Rank 부터 시작하여 직접 사용하여 어떠한 기능을 하는지 알아보도록 하겠습니다. 아래 예제는 Rank, Length, Clear, ForEach, Resize, indexOf가 사용된 예제입니다.

using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] reading = new int[] { 4, 9, 1, 0, 21, 12 };

            Console.WriteLine("속성: Rank={0}, Length={1}", reading.Rank, reading.Length);
            // reading의 차원 수와 길이를 반환함

            Console.Write("Clear 메소드: ");
            Array.Clear(reading, 0, 5); // 배열 요소를 0부터 시작하여 5개의 요소를 초기화 시킴
                                        // Array.Clear(요소를 지울 배열, 시작 인덱스, 지울 요소수);
            Array.ForEach<int>(reading, new Action(ShowValue));
            // 해당 배열의 각 요소를 가지고 동작(ShowValue)를 수행함
            // Array.ForEach<데이터타입>(동작을 수행할 배열, new Action<데이터타입>(액션);
            Console.WriteLine();

            Console.Write("Resize 메소드: ");
            Array.Resize(ref reading, reading.Length + 3);
            // reading 배열의 길이를 3만큼 늘림, Array.Resize(배열의 주소값, 새 배열의 크기);
            Array.ForEach<int>(reading, new Action<int>(ShowValue));
            Console.WriteLine();

            Console.WriteLine("indexOf 메소드: {0}", Array.IndexOf(reading, 12));
            // 배열에서 12란 값을 가지고 있는 요소의 인덱스를 반환함
            // Array.IndexOf(배열, 찾고자 하는 값);
        }

        static void ShowValue(int value) // 동작, value를 받아 그 value를 출력시킴
        {
            Console.Write("{0} ", value);
        }
    }
}
결과:
속성: Rank=1, Length=6
Clear 메소드: 0 0 0 0 0 12
Resize 메소드: 0 0 0 0 0 12 0 0 0
indexOf 메소드: 5
계속하려면 아무 키나 누르십시오 . . .

결과를 보아 상당히 유용함을 알 수 있습니다. 코드에 주석을 달아놓았긴 했으나, 각 메소드의 사용 형식을 더 자세히 알고 싶으시다면 MSDN를 방문하여 참고하시기 바랍니다. 

3. 다차원 배열(Multidimensional array)

다차원 배열이란, 말 그대로 여러 개의 차원을 다루는 배열입니다. 우리가 지금까지 만나봤던 배열들은, 모두 가로로만 이루어진 1차원 배열이었습니다. 이번엔 주로 쓰이는 2차원 배열에 대해 알아보도록 하겠는데, 2차원 배열은 1차원 배열과는 달리 가로와 세로를 가지는 평면 구조의 사각형으로 이루어져 있습니다. 


만약에 student란 2차원 배열이 있고 열이 6, 행이 3인 배열이 있다고 합시다. 그렇게 되면 위와 같은 구조를 형성합니다. 1차원 배열의 요소에 접근하는 방법과 2차원 배열의 요소에 접근하는 방법은 비슷합니다. 3열 2행에 있는 값을 가져오고 싶다면, student[2][1]라고 하시면 되겠죠. 아래는 2차원 배열을 선언하는 형식입니다.

자료형[,] 배열명 = new 자료형[행, 열];

이제 2차원 배열을 직접 다루어 컴파일을 해보도록 하겠습니다. 아래 예제는 2차원 배열을 다루는 예제입니다.

using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            int[,] reading = new int[3, 6] { { 4, 9, 1, 0, 21, 12 }, { 1, 4, 6, 0, 9, 5 }, { 4, 4, 2, 4, 0, 0 } };

            for (int i = 0; i < reading.GetLength(0); i++)
                for (int j = 0; j < reading.GetLength(1); j++)
                    Console.WriteLine("reading[" + i + ", " + j + "] = {0}", reading[i, j]);
        }
    }
}
결과:

reading[0, 0] = 4

reading[0, 1] = 9

reading[0, 2] = 1

reading[0, 3] = 0

...

reading[2, 4] = 0

reading[2, 5] = 0

계속하려면 아무 키나 누르십시오 . . .


코드의 9행을 보시면 reading이라는 2차원 배열이 선언됨과 동시에 초기화를 하고 있고, 그다음에 for문의 중첩이 등장합니다. for문의 조건식에 쓰인 GetLength라는 메소드는 각 차원의 요소 수를 반환하는 메소드입니다. 즉 GetLength(0)은 3이되고, GetLength(1)은 6이 됩니다. 여기선 0부터 차원이 시작합니다. 0은 1차원, 1은 2차원을 의미합니다. 그리고 반복하면서 각 요소의 값을 출력시키고 프로그램이 종료됩니다.


  문자열 사이에 있는 + 연산자는 무엇인가요?


지금까지 배운 바로는 + 연산자는 산술 연산자라고 볼 수 있는데, 피연산자가 정수나 실수가 아닌 문자열이 등장했습니다. 우리가 나중에 배우게 될 개념이지만, 연산자 오버로딩(Operator Overloading)을 통해서 문자열 형식에 대해서도 연산이 미리 정의가 되어 있습니다.


예) "안녕, 내 이름은 " + name + "이야." -----> "안녕, 내 이름은 홍길동이야."


위와 같은 방법은 상당히 작성하기 쉽고, 보기에도 직관적입니다. + 연산자의 피연산자 중 하나가 문자열이고, 다른 하나가 숫자 형식인 경우에도 미리 정의가 되어 있기 때문에 연결할 수 있습니다. 


2차원 배열 말고도, 3차원, 4차원, 5차원.. 배열이 있으나 많이 쓰이지는 않습니다. 복잡하기 때문이죠. 만약에 3차원 배열을 선언하고 싶으시다면 아래와 같은 방법으로 선언하시면 됩니다.

자료형[,,] 배열명 = new 자료형[높이, 세로, 가로];

배열에 대한 설명은 여기서 마치도록 하겠습니다. 수고하셨습니다.


다음 강좌에서는 클래스(Class)에 대해 알아보도록 하겠습니다.

  1. need at 2012.09.16 14:05 신고 [edit/del]

    vb쪽도 써주시면 감사하겠습니다.
    강좌보고 배우고 있는데 감사합니다

    Reply
  2. C# at 2012.10.14 16:53 신고 [edit/del]

    강의 정말 잘보고 있어요
    정말 감사합니다

    Reply
  3. C# at 2012.10.14 16:53 신고 [edit/del]

    혹시 질문같은거 있으면 질문해도 될까요?

    Reply
  4. 김승현 at 2012.10.20 13:13 신고 [edit/del]

    감사합니다~

    Reply
  5. 새싹 at 2012.11.21 02:15 신고 [edit/del]

    엑시노아님 포스트 보고 프로그래밍 공부 하고 있습니다 :D
    감사합니다.

    질문 하나만 드릴게요.
    다차원 이상의 배열에서 array클래스의 속성들은 가볍게 적용이 되는데
    메소드는 어떻게 이용하나요 ''?
    'int[*,*]에서 int[]로 변환할 수 없습니다'란 경고창이 떠서 수정해보고 있는데
    잘 안돼요 _ _...

    Reply
  6. 감사합니다 at 2013.02.19 13:45 신고 [edit/del]

    다차원배열에서 3행 6열인것 같은데 오타가 나신 것 같습니다....

    헷갈릴수도 있으니 수정좀 부탁드릴께요 ㅎㅎ

    좋은 강좌 감사드립니다~

    Reply
    • 감사합니다 at 2013.02.19 13:49 신고 [edit/del]

      아 .. 저와는 다른 방식으로 행렬을 짜신거군요 ㅠㅠ

      가로의 수가 열이 되는건가요.. 순간 헷갈렸습니다 ㅎㅎ

    • BlogIcon EXYNOA at 2013.02.19 14:02 신고 [edit/del]

      3행 6열이 맞는것 같습니다. 수정했습니다. 감사합니다!

    • 고훈 at 2016.09.17 10:51 신고 [edit/del]

      좋은 글 늘 감사합니다..

      위 예제에서 2행 3열 인 '6'값을 가져오려면 이거 student[1][2] 아닌가요?

      student[2][1] 이면 '4' 값을 가죠오는거죠?

  7. ZiNee at 2013.10.14 01:02 신고 [edit/del]

    다차원 배열이 C와는 차이가 좀 있네요. 소스를 따라 코딩해보면서 강의 보고 있습니다.
    좋은 강좌 올려주셔서 감사합니다.

    Reply
  8. Yong at 2013.12.02 17:07 신고 [edit/del]

    질문이 한가지 있는데요
    C#에서는 포인터와 같은 개념이 없다고 들었습니다. 포인터는 있지만 실질적으로 잘 사용하지않는다는 이야기를 많이 들었고.. C#.net이 메모리의 크기를 자동으로 지정해준다는 이야기를 얼핏 들은 적이있습니다. 배열을 통해 유동하는 크기의 배열을 만들려면 어떻게 해야하나요??

    Reply
    • BlogIcon EXYNOA at 2013.12.02 17:39 신고 [edit/del]

      네, 그렇습니다. 아마 C#에도 포인터를 사용할 수 있지만 unsafe 키워드를 같이 사용하셔야 하는 것으로 알고 있습니다. 말씀하신 그대로, 메모리의 크기를 자동으로 지정해주며 동적 배열을 만드시려면 new 키워드를 통해 작성해주시면 됩니다.

      string[] str = new string[i];

      위와 같은 식으로 말이죠. 아니면 '유동'이 크기가 정해져 있지 않고 줄였다가 늘였다가 할 수 있는 것이라면 컬렉션을 쓰시면 될 것 같습니다. List나 ArrayList같은 자료구조를 한번 알아보시면 좋을 것 같습니다. ^-^*

  9. studyingQ at 2014.06.17 09:39 신고 [edit/del]

    안녕하세요. C#을 공부하고 있습니다. 궁금한 점이 있어 문의 드립니다.

    1) int[] reading = {4, 9, 1, 0, 21, 12}; 문장과
    2) int[] reading = new int[]{4, 9, 1, 0, 21, 12}; 이 같다고 표현하셨는데

    C++의 경우
    동적할당을 위해서는 포인터를 이용한 방식
    int* pInt= new int[]; 만 가능한 것으로 알고 있습니다.

    1) 방식과 같이 C++에서 int a[]={1,3,5}; 배열을 선언하면 동적할당이 아닌 스텍에
    할당되며 2)와 같은 방식은 선언 자체가 불가능한 것으로 알고 있습니다.

    C#에서 위와 같은 두 개의 선언이 동일한 이유(1번 형식이 스텍이 아닌 동적 할당이 이루어 지는 이유)와 제가 알고 있는 내용 중 잘못된 부분이 있다면 설명 부탁드립니다.

    감사합니다.




    Reply
    • BlogIcon EXYNOA at 2014.06.17 23:38 신고 [edit/del]

      C++와 C#를 동일시 하시면 안됩니다. 말 그대로, C#에서의 1차원 배열 초기화 방법은 대표적으로 세가지가 존재하며 그 중 두개가 1)과 2)인 것입니다. 만약 아래와 같은 예제가 있다고 생각해보세요.

      int[] reading = new int[]{4, 9, 1, 0, 21, 12};

      그런데 여기서 MSDN에 의하면 위와 같이 이니셜라이저, 즉 초기값이 주어진 경우에는 new 연산자를 생략할 수 있다고 합니다. 그렇다면, 아래와 같은 형태도 위와 같은 형태와 동일한 형태를 가집니다.

      int[] reading = {4, 9, 1, 0, 21, 12};

      또한, 1)과 2)는 정적 할당이며, 단지 크기가 명시되지 않고 컴파일러가 주어진 이니셜라이저에 따라 배열의 크기를 정해주는 것입니다. 궁금한 내용이 더 있으시다면 네이트온 혹은 메일로 남겨주시면 감사하겠습니다 ^ㅡ^*

  10. studyingQ at 2014.06.18 10:59 신고 [edit/del]

    답변 감사드립니다. ^--^

    약간의 키워드에 대한 착각이 있었습니다.
    new 키워드의 경우
    new 연산자, new 한정자, new 제약 조건의 다양한 기능을 가지고 있네요...

    C++과 착각하여 new 연산자를 동적할당이라고 착각했습니다.
    음.. 배열같은 경우에도 내부적으로 resize가 가능하고....
    그렇다면 C#에서는 동적할당이 큰 의미가 없는것인가요? 메모리 관리는 가비지컬렉터에 의해 수행되며.....

    가능하시다면 답변 부탁드립니다. ^^

    Reply
    • BlogIcon EXYNOA at 2014.06.21 19:11 신고 [edit/del]

      C#에서도 동적 메모리 할당이 물론 존재합니다. 이것도 이것대로 C#에선 나름대로의 의미를 지니고 있으며, C#에서도 동적 할당시 new 연산자가 사용되는건 마찬가지 입니다. 댓글로 의문을 풀어들이기에는 얘기가 길어질 것 같은 조짐이 보이네요..

  11. BlogIcon Siddhartha at 2014.08.09 15:59 신고 [edit/del]

    오늘도 정말 재밌게 잘 봤습니다, 감사합니다 !

    Reply
  12. ㅇㅎ at 2015.01.17 00:30 신고 [edit/del]

    [+ i +]는 무엇인가요?

    Reply
    • 안나 at 2015.01.19 14:54 신고 [edit/del]

      i는 reading[0], reading[1], reading[2] 할 때 0, 1, 2에 해당하는데
      따옴표를 사용해줘야 for문의 i값이 들어갑니다!
      따옴표를 사용하지 않으면 단순히 [i]로 찍혀나오며
      +는 i와 "를 함께 쓸 수 있게 해주는 역할로 사용 되어요
      저도 초보라 이 정도 뿐이 설명을 못드리겠네요 ㅠㅠ 죄송합니다

    • BlogIcon EXYNOA at 2017.11.26 17:00 신고 [edit/del]

      해당 질문에 관한 내용을 본문에 추가했습니다.

  13. jacoby at 2015.02.23 14:08 신고 [edit/del]

    안녕하세요 질문이 있습니다 엑시노아님 .

    "AB, AB",
    "Ab, ab",
    ",aB, ab",

    이런식으로
    (,) 쉼표를 기준으로 앞과 뒤의 단어를
    대문자 기준으로 정렬 시키고자 하는데요
    몇일 고민하다가 글을 올려 봅니다. ㅜㅜ

    Reply
  14. ThankYou at 2015.06.21 17:49 신고 [edit/del]

    너무 너무 유용한 자료입니다. 이제 막 프로그래밍을 시작했는데 가장 쉽고 알기 쉽게 알려주시네요ㅠㅠbb
    감사합니다!

    Reply
  15. 광영 at 2017.04.18 11:05 신고 [edit/del]

    new 는 깔록처럼 0으로 초기화하는군요!

    Reply
  16. 노경훈 at 2017.06.20 12:00 신고 [edit/del]

    Array.ForEach<int>(reading, new Action<int> (ShowValue));

    강의 정말 유용하게 잘 보고 있습니다.
    그런데 위의 문장을 입력하면

    The name 'ShowValue' does not exist in the current context. 라고 나오면서 진행이 안되네요
    답변 부탁드립니다.

    Reply
    • bit at 2017.06.22 14:52 신고 [edit/del]

      ShowValue 는 스크립트 하단에 보시면
      메소드 구현 되있습니다

      경훈님 코드에 ShowValue 메소드가 구현되어있는지 확인해보세요
      혹시 스펠링도 확인해보시고...

  17. 이비 at 2018.01.23 22:28 신고 [edit/del]

    showvalue를 사용할때요
    Array.ForEach<int>(reading, new Action<int>(ShowValue));
    여기서 showvalue(여기에) 매개변수값을 안넣어줬는데도 어떻게 value값이 출력으로 넘어가는건가요????
    매개변수로 따로 안넘겨준거같은데요ㅠㅠ

    Reply
    • BlogIcon EXYNOA at 2018.01.24 00:27 신고 [edit/del]

      Action<T>는 델리게이트이기 때문에 Action의 매개변수로 넘어가는 것은 메소드가 넘어갑니다. 델리게이트에 관한 내용은 19편에서 다루고 있으므로 궁금하시다면 지금 보시고 와도 괜찮습니다.

      단지 저 예제는 라이브러리에서 제공하는 다양한 기능을 보여주기 위하여 MSDN의 예제를 그대로 들고온 것이므로, 이해가 되지 않아도 전혀 상관이 없습니다.

submit

티스토리 툴바