1. 배열의 개념
C++에서 배열은 유사한 데이터 유형의 여러 값을 연속적인 메모리 위치에 저장하는 데 사용되는 데이터 구조다.
예를 들어, 4명 또는 5명의 학생의 표시를 저장해야 한다면 5개의 다른 변수를 생성하여 쉽게 저장할 수 있지만, 100명의 학생의 표시를 저장하거나 500명의 학생이라고 한다면 같은 방식으로 진행하려 할까? 그 숫자의 변수를 생성하고 관리하는 것은 매우 어려워진다. 그런데 배열은 필요한 크기의 배열을 만들기만 하면 쉽게 수행할 수 있다.
2. 배열의 속성
① 배열은 연속적인 메모리 위치에 저장된 동일한 데이터 유형의 데이터 모음이다.
② 배열의 인덱싱은 0부터 시작한다. 첫 번째 요소는 0번째 인덱스에 저장되고, 두 번째 요소는 1번째 인덱스에 저장되는 것을 의미한다.
③ 배열의 요소는 해당 인덱스를 사용하여 액세스할 수 있다.
④ 배열이 선언되면 프로그램 전체에서 배열의 크기가 일정하게 유지된다.
⑤ 배열은 여러 차원을 가질 수 있다.
⑥ 연산자의 크기를 사용하여 배열의 요소 수를 결정할 수 있다.
⑦ 배열에 저장된 요소 유형의 크기는 인접한 주소를 빼서 구할 수 있다.
3. 배열 선언
C++에서는 데이터 유형을 먼저 지정한 다음 크기가 있는 배열의 이름을 지정하기만 하면 배열을 선언할 수 있다.
예시:
int arr[5];
int: 배열에 저장할 데이터 유형이다. char, float, double 등 다른 데이터 유형도 사용할 수 있다.
arr: 배열의 이름이다.
5: 어레이의 크기이므로, 어레이에 5개의 요소만 저장할 수 있다.
4. 배열의 초기화
C++에서는 여러 가지 방법으로 배열을 초기화할 수 있지만, 여기서는 배열을 초기화하는 가장 일반적인 방법에 대해 논의할 것이다. 우리는 배열을 선언할 때 또는 선언한 후에 초기화할 수 있다.
① 값(value)으로 배열 초기화
int arr[5] = {1, 2, 3, 4, 5};
값으로 배열을 초기화한다. 이때 중괄호 {}로 둘러싸인 값이 배열에 할당된다. 여기서 1은 ar[0]에, 2는 ar[1]에 저장된다. 여기서 배열의 크기는 5다.
② 크기(size) 없이 값으로 배열 초기화
int arr[] = {1, 2, 3, 4, 5};
여기서는 값으로 배열을 초기화했지만, 배열의 길이를 선언하지 않았다. 이때 배열의 길이는 {}에 있는 요소의 개수와 같다.
③ 선언 후 배열 초기화(루프 사용)
for (int i = 0; i < N; i++) {
arr[i] = value;
}
배열을 선언한 후 루프를 사용하여 배열을 초기화하는 것이다. 이 방법은 일반적으로 사용자로부터 입력을 받거나 배열의 각 인덱스에 요소를 하나씩 할당할 수 없을 때 사용된다. 여기서 루프 조건을 수정하거나 요구 사항에 따라 초기화 값을 변경할 수 있다.
④ 배열 부분 초기화
int partialArray[5] = {1, 2};
여기서는 크기가 5고 값이 1과 2인 배열, '부분 배열'을 선언했다. 따라서 이 값들은 처음 두 인덱스에 저장되고 나머지 인덱스들에 0이 저장된다.
⑤ 0으로 배열 초기화
int zero_array[5] = {0};
{} 안에 0을 지정하면 모든 원소를 0으로 배열을 초기화할 수 있다. 이 방법을 사용하여 2라는 다른 값으로 배열을 초기화하려고 하면, 2는 0번째 인덱스에만 저장될 것이다.
5. 배열의 구성요소 액세스
① 배열의 요소는 배열의 이름을 지정한 다음, 배열 첨자 연산자 []에 포함된 요소의 인덱스를 지정하여 액세스할 수 있다. 예를 들어 arr[i]가 있다.
예시:
// C++ Program to Illustrate How to Access Array Elements
#include <iostream>
using namespace std;
int main()
{
int arr[3];
// Inserting elements in an array
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;
// Accessing and printing elements of the array
cout << "arr[0]: " << arr[0] << endl;
cout << "arr[1]: " << arr[1] << endl;
cout << "arr[2]: " << arr[2] << endl;
return 0;
}
출력:
arr[0]: 10
arr[1]: 20
arr[2]: 30
한편, 배열의 요소를 업데이트하려면 배열 첨자 연산자 내에 포함된 업데이트할 인덱스를 사용하고, 새 값을 할당할 수 있다:
arr[i] = new_value;
② 또한, 우리는 인덱싱을 사용하여 루프의 도움으로 배열을 순회할 수 있다. 먼저, 우리는 2의 배수로 table_of_two 배열을 초기화한다. 그 후, 배열의 인덱싱은 0부터 시작하기 때문에 0부터 9까지 for 루프를 실행한다. 따라서 인덱스를 사용하여 어레이에 저장된 모든 값을 프린트한다.
예시:
// C++ Program to Illustrate How to Traverse an Array
#include <iostream>
using namespace std;
int main()
{
// Initialize the array
int table_of_two[10]
= { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 };
// Traverse the array using for loop
for (int i = 0; i < 10; i++) {
// Print the array elements using indexing
cout << table_of_two[i] << " ";
}
return 0;
}
출력:
2 4 6 8 10 12 14 16 18 20
③ 그리고 배열 크기를 찾는 자바의 길이 함수는 없지만, size of() 연산자 트릭을 사용하여 배열의 크기를 계산할 수 있다. 먼저 메모리에서 전체 배열이 차지하는 크기를 찾은 다음, 배열에 저장된 요소 유형의 크기로 나눈다. 그러면 배열에 저장된 요소의 수를 알 수 있다.
예시:
// C++ Program to Illustrate How to Find the Size of an
// Array
#include <iostream>
using namespace std;
int main()
{
int arr[] = { 1, 2, 3, 4, 5 };
// Size of one element of an array
cout << "Size of arr[0]: " << sizeof(arr[0]) << endl;
// Size of array 'arr'
cout << "Size of arr: " << sizeof(arr) << endl;
// Length of an array
int n = sizeof(arr) / sizeof(arr[0]);
cout << "Length of an array: " << n << endl;
return 0;
}
출력:
Size of arr[0]: 4
Size of arr: 20
Length of an array: 5
④ 한편, C++에서 배열과 포인터는 서로 밀접한 관계가 있다. 배열 이름은 배열의 첫 번째 원소의 메모리 주소를 저장하는 포인터로 취급된다. 앞서 말했듯, 배열의 원소는 연속된 메모리 위치에 저장되므로, 배열 이름을 사용하여 배열의 모든 원소에 접근할 수 있다.
// C++ Program to Illustrate that Array Name is a Pointer
// that Points to First Element of the Array
#include <iostream>
using namespace std;
int main()
{
// Defining an array
int arr[] = { 1, 2, 3, 4 };
// Define a pointer
int* ptr = arr;
// Printing address of the arrary using array name
cout << "Memory address of arr: " << &arr << endl;
// Printing address of the array using ptr
cout << "Memory address of arr: " << ptr << endl;
return 0;
}
출력:
Memory address of arr: 0x7fff2f2cabb0
Memory address of arr: 0x7fff2f2cabb0
위 코드에서 먼저 배열 arr을 정의한 다음 포인터 ptr을 선언하고 배열 arr을 할당한다. 역서 arr도 포인터이기 때문에 ptr에 arr을 할당할 수 있다. 그 후 참조 연산자 &를 사용하여 arr의 메모리 주소를 프린트하고, 포인터 ptr에 저장된 주소를 프린트하고 arr과 ptr을 볼 수 있으며, 둘 다 동일한 메모리 주소를 저장한다.
⑤ 우리는 일반적으로 인덱싱을 사용하여 배열 요소에 액세스하고 프린트한다. 예를 들어 첫 번째 요소에 액세스하려면 array_name[0]을 사용한다. 배열 이름은 첫 번째 요소의 주소를 저장하는 포인터이며, 배열 요소는 연속된 위치에 저장된다고 앞서 기술했다. 이제는 배열 이름만 사용하여 배열의 요소에 액세스할 것이다.
예시:
// C++ Program to Print Array Elements without Indexing
#include <iostream>
using namespace std;
int main()
{
// Define an array
int arr[] = { 11, 22, 33, 44 };
// Print elements of an array
cout << "First element: " << *arr << endl;
cout << "Second element: " << *(arr + 1) << endl;
cout << "Third element: " << *(arr + 2) << endl;
cout << "Fourth element: " << *(arr + 3) << endl;
return 0;
}
출력:
First element: 11
Second element: 22
Third element: 33
Fourth element: 44
6. 함수로 배열을 전달
배열을 효율적으로 사용하려면 배열을 함수에 전달하는 방법을 알아야 한다. 변수를 함수에 전달하는 것과 마찬가지로, 배열을 함수에 전달할 수 있지만, 배열 이름이 이 개념을 사용하여 포인터로 처리된다는 것을 알고 있다. 우리는 배열을 함수에 전달한 다음, 포인터를 사용하여 배열의 모든 요소에 접근할 수 있을 것이다.
따라서 궁극적으로 배열은 항상 함수의 포인터로 전달된다. 주로 사용되는 함수에 배열을 전달하는 방법에는 3가지가 존재한다.
① 배열을 포인터로 전달
단순히 배열 이름을 함수 호출에서 전달하는데, 이는 배열의 첫 번째 요소에 주소를 전달한다는 것을 의미한다. 이 방법에서는 함수 내의 배열 요소를 수정할 수 있다.
구문:
return_type function_name ( data_type *array_name ) {
// set of statements
}
② 배열을 크기가 지정되지 않은 배열로 전달
이 방법에서 함수는 크기가 없는 단순 배열 선언을 인수로 사용하여 배열을 받아들인다.
구문:
return_type function_name ( data_type array_name[] ) {
// set of statements
}
③ 배열을 크기가 지정된 배열로 전달
이 방법에서 함수는 크기를 인수로 하는 간단한 배열 선언을 사용하여 배열을 받아들인다. 배열의 크기를 나타내기 위해 배열의 크기를 조정하여 이 방법을 사용한다.
구문:
return_type function_name(data_type array_name[size_of_array]){
// set of statements
}
예시:
#include <iostream>
using namespace std;
// passing array as a sized array argument
void printArraySized(int arr[3], int n)
{
cout << "Array as Sized Array Argument: ";
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
cout << endl;
}
// passing array as an unsized array argument
void printArrayUnsized(int arr[], int n)
{
cout << "Array as Unsized Array Argument: ";
for (int i = 0; i < n; i++) {
cout << *(arr + i) << " ";
}
cout << endl;
}
// Passing array as a pointer argument
void printArrayPointer(int* ptr, int n)
{
// Print array elements using pointer ptr
// that store the address of array passed
cout << "Array as Pointer Argument: ";
for (int i = 0; i < n; i++) {
cout << ptr[i] << " ";
}
}
// driver code
int main()
{
int arr[] = { 10, 20, 30 };
// Call function printArray and pass
// array and its size to it.
printArraySized(arr, 3);
printArrayUnsized(arr, 3);
printArrayPointer(arr, 3);
return 0;
}
출력:
Array as Sized Array Argument: 10 20 30
Array as Unsized Array Argument: 10 20 30
Array as Pointer Argument: 10 20 30
7. 다차원 배열
하나 이상의 차원으로 선언된 배열을 다차원 배열이라 한다. 가장 널리 사용되는 다차원 배열은 2D 배열과 3D 배열이다. 이러한 배열은 일반적으로 행과 열의 형태로 표현된다.
구문:
Data_Type Array_Name[Size1][Size2]...[SizeN];
Data_Type: 배열에 저장할 데이터 유형
Array_Name: 배열의 이름
Size1, Size2,…, SizeN: 각 차원의 크기
① 2차원 배열
2차원 배열은 행과 열로 배열된 요소들의 그룹이다. 각 요소들은 테이블이나 그리드로 쉽게 시각화할 수 있도록 행과 열의 두 가지 인덱스를 사용하여 접근된다.
구문:
data_Type array_name[n][m];
여기서 n이 행, m이 열이 된다.
2차원 배열 설명 예시:
// c++ program to illustrate the two dimensional array
#include <iostream>
using namespace std;
int main()
{
// Declaring 2D array
int arr[4][4];
// Initialize 2D array using loop
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
arr[i][j] = i + j;
}
}
// Printing the element of 2D array
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
cout << arr[i][j] << " ";
}
cout << endl;
}
return 0;
}
출력:
0 1 2 3
1 2 3 4
2 3 4 5
3 4 5 6
위의 코드에서 4개의 행과 4개의 열로 구성된 2D 배열을 선언한 후, 모든 반복 루프에서 (i+j) 값으로 배열을 초기화했다. 그런 다음, 중첩 루프를 사용하여 2D 배열을 프린트하고 아래 출력에서 4개의 행과 4개의 열이 있음을 볼 수 있다.
② 3차원 배열
3D 배열은 3차원을 사용한다. 그것을 표현하기 위해 다양한 2차원 배열의 집합체를 사용할 수 있다. 3D 배열의 각 요소를 고유하게 식별하기 위해 행 인덱스, 열 인덱스, 깊이 인덱스의 세 가지 인덱스가 사용된다.
구문:
Data_Type Array_Name[D][R][C];
Data_Type: 각 요소에 저장할 데이터 유형
Array_Name: 어레이의 이름
D: 2D 배열의 개수 또는 배열의 깊이
R: 각 2D 배열의 행 개수
C: 각 2D 배열의 열 개수
예시:
int array[3][3][3];
3차원 배열 설명 예시:
// C++ program to illustrate the 3d array
#include <iostream>
using namespace std;
int main()
{
// declaring 3d array
int arr[3][3][3];
// initializing the array
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
for (int k = 0; k < 3; k++) {
arr[i][j][k] = i + j + k;
}
}
}
// printing the array
for (int i = 0; i < 3; i++) {
cout << i << "st layer:" << endl;
for (int j = 0; j < 3; j++) {
for (int k = 0; k < 3; k++) {
cout << arr[i][j][k] << " ";
}
cout << endl;
}
cout << endl;
}
return 0;
}
출력:
0st layer:
0 1 2
1 2 3
2 3 4
1st layer:
1 2 3
2 3 4
3 4 5
2st layer:
2 3 4
3 4 5
4 5 6
위 코드에서는 3D 배열을 선언한 다음 루프에 대해 3개의 중첩을 사용하여 초기화했다. 그 후 출력에서 볼 수 있듯이 루프에 대해 3D 배열의 모든 층을 다시 3개의 중첩을 사용하여 프린트했다.
'C++' 카테고리의 다른 글
C++ 새로운 연산자를 사용해 2D 배열을 동적 선언하는 방법 (0) | 2024.05.28 |
---|---|
C++ 다차원 배열 총정리 (0) | 2024.05.26 |
C++ 레퍼런스(참조, Reference) 총정리 (0) | 2024.05.18 |
C++ 포인터 응용 (0) | 2024.05.17 |
C++ 댕글링, 보이드, 널, 와이드 포인터 (0) | 2024.05.16 |