배열
이란? 다수의 데이터를 저장하고 처리하는 경우에 유용하게 사용할 수 있는 것이다.
1차원 배열의 선언에 필요한 것은 배열이름
, 자료형
, 길이정보
이다.
배열은 일반적인 변수와 달리 여러 개의 값을 저장할 수 있다.
여러 개의 변수가 모여서 배열을 이루기 때문이다.
이러한 배열 중에서 1차원 배열은 다음과 같이 선언한다.
int oneDimArr[4];
위 문장을 이루는 요소 세 가지는 다음과 같다.
👉int형 변수 4개로 이루어진 배열을 선언하되, 그 배열의 이름은 'oneDimArr'이다.
이 외에도 다양한 자료형의 다양한 길이의 1차원 배열을 선언할 수 있다.
int arr1[7]; // 길이가 7인 int형 1차원 배열 arr1
float arr2[10]; // 길이가 10인 float형 1차원 배열 arr2
double arr3[12]; // 길이가 12인 double형 1차원 매열 arr3
배열의 길이정보는 상수로 주기 때문에 변수를 통한 배열의 길이 선언이 가능하다. 다만 범용적인 컴파일을 위해서는 가급적 배열의 길이정보를 상수로 지정해야한다.
배열의 접근은 아래와 같은 형태로 접근한다.
int arr[3]; // 길이가 3인 int형 1차원 배열 arr
arr[0] = 10; // 배열 arr의 첫 번째 요소에 10 저장.
arr[1] = 12; // 배열 arr의 두 번째 요소에 12 저장.
arr[2] = 25; // 배열 arr의 세 번째 요소에 25 저장.
👉 arr[idx] = n; // 배열 arr의 idx+1 번째 요소에 n 저장.
이를 통해 배열의 위치 정보를 명시하는 인덱스 값은 1이 아닌 0에서부터 시작한다.
예제를 통해 배열의 선언과 배열 요소의 접근에 대해 이해해보자.
#include<stdio.h>
int main()
{
int arr[5];
int sum = 0, i;
arr[0] = 10, arr[1] = 20, arr[2] = 30, arr[3] = 40, arr[4] = 50;
for (i = 0; i < 5; i++)
sum += arr[i];
printf("배열요소에 저장된 값의 합: %d \n\n", sum);
return 0;
}
> 출력
배열요소에 저장된 값의 합: 150
예제를 통해 배열의 선언, 배열 요소의 접근 뿐만 아니라 배열의 모든 요소는 반복문을 이용해서 순차적으로 접근하는 것이 가능하다는 것을 알 수 있다.
기본 자료형 변수들은 선언과 동시에 초기화가 가능하다.
배열도 선언과 동시에 원하는 값으로 초기화를 할 수 있다.
초기화 방법은 총 3가지로 구분 가능하다.
1. 중괄호 사용
int arr1[5] = {1, 2, 3, 4, 5};
위와 같이 중괄호 내에 초기화 할 값들을 나열하면 해당 값들이 순서대로 저장된다.
배열의 초기화를 목적으로 선언된, 중괄호로 묶인 부분을 '초기화 리스트'라 한다.
2. 길이정보 생략
int arr2[ ] = {1, 2, 3, 4, 5, 6, 7};
위와 같이 배열의 길이 정보를 생략하고 초기화 및 선언하게 되면 컴파일러가 초기화 리스트의 수를 참고하여 길이정보를 7로 채워준다.
3. 부분 채우기
int arr3[5] = {1, 2};
배열의 길이를 다 채운 만큼의 초기 값이 선언되지 않은 경우 채울 값이 존재하지 않는 요소들은 0으로 채워진다.
예제를 통해 더 알아보자. sizeof 연산도 함께 알아보자.
#include<stdio.h>
int main()
{
int arr1[5] = { 1, 2, 3, 4, 5 };
int arr2[] = { 1, 2, 3, 4, 5, 6, 7 };
int arr3[5] = { 1, 2 };
int ar1Len, ar2Len, ar3Len, j;
printf("배열 arr1의 크기: %d \n", sizeof(arr1));
printf("배열 arr2의 크기: %d \n", sizeof(arr2));
printf("배열 arr3의 크기: %d \n", sizeof(arr3));
ar1Len = sizeof(arr1) / sizeof(int); // 배열 arr1의 길이 계산.
ar2Len = sizeof(arr2) / sizeof(int); // 배열 arr2의 길이 계산.
ar3Len = sizeof(arr3) / sizeof(int); // 배열 arr3의 길이 계산.
for (j = 0; j < ar1Len; j++)
printf("%d ", arr1[j]);
printf("\n");
for (j = 0; j < ar2Len; j++)
printf("%d ", arr2[j]);
printf("\n");
for (j = 0; j < ar3Len; j++)
printf("%d ", arr3[j]);
printf("\n\n");
return 0;
}
> 출력
배열 arr1의 크기: 20
배열 arr2의 크기: 28
배열 arr3의 크기: 20
1 2 3 4 5
1 2 3 4 5 6 7
1 2 0 0 0
배열의 이름을 대상으로 하는 sizeof 연산의 결과로는 '바이트 반위의 배열크기'가 반환된다.
따라서 배열의 크기로 반환하고 싶다면 자료형의 사이즈로 나눠줘야한다.
char형의 배열을 이용하면 문자열의 저장뿐만 아니라 문자열의 변경도 가능해진다.
즉, 변수형태의 문자열 선언이 가능해진다.
C언어에서는 큰 따옴표를 이용해 문자열을 표현한다.
char str[14] = "Good morning!";
위 선언을 통해서 메모리 공간에는 char형 배열이 할당되고, 이 배열에는 다음의 형태로 문자열이 저장된다.
문자열의 저장을 목적으로 char형 배열을 선언할 경우에는 특수문자 \0
이 저장될 공간까지 고려해서 배열의 길이를 결정해야한다.
문자열의 끝에 자동으로 삽입되는 문자 \0
을 가리켜 널(null)
문자라 한다.
예제를 통해 '널 문자'가 자동으로 삽입되는지 확인해보자.
#include<stdio.h>
int main()
{
char str[] = "Good morning!";
printf("배열 str의 크기: %d \n", sizeof(str));
printf("널 문자 문자형 출력: %c \n", str[13]);
printf("널 문자 정수형 출력: %d \n", str[13]);
str[12] = '?'; // 배열 str에 저장된 문자열 데이터 변경 가능
printf("문자열 출력: %s \n\n", str);
// 추가
char nu = '\0'; // 널 문자 저장
char sp = ' '; // 공백 문자 저장
printf("%d %d\n\n", nu, sp); // '0 32' 출력
return 0;
}
> 출력
배열 str의 크기: 14
널 문자 문자형 출력:
널 문자 정수형 출력: 0
문자열 출력: Good morning?
0 32
'널 문자'의 아스키 코드 값은 0이다. 이를 문자의 형태로 출력할 경우 아무런 출력이 발생하지 않는다.
'널 문자'와 '공백 문자'를 혼동할 수 있는데 추가 예제를 보면 아스키 코드 값이 다르므로 이 차이를 확인할 수 있다.
그리고 배열에 저장되어 있는 문자열 데이터 값도 변경 가능하다.
printf 함수
를 이용해서 문자열을 출력할 때 서식문자 %s
를 사용하듯 scanf 함수
에서도 서식문자 %s
를 이용해 문자열을 입력 받는다.
#include<stdio.h>
int main()
{
char Str[50];
int idx = 0;
printf("문자열 입력: ");
scanf_s("%s", Str, 50); // 문자열을 입력 받아서 배열 str에 저장!
printf("입력 받은 문자열: %s \n", Str);
printf("문자 단위 출력: ");
while (Str[idx] != '\0')
{
printf("%c", Str[idx]);
idx++;
}
return 0;
}
> 출력
문자열 입력: Simple
입력 받은 문자열: Simple
문자 단위 출력: Simple
VSC에서 scanf 함수
를 이용해서 문자열을 입력받을 때 그 크기를 뒤에 적어줘야한다.
문자열을 입력 받는 배열의 이름 앞에는 연산자 &
를 붙이지 않는다.
변수 이름 앞에는 반드시 붙여야하지만 배열의 이름 앞에는 붙이지 않는다.⭐
그리고 문자열을 구성하는 문자 하나하나를 출력하는 반복문을 보면 scanf 함수를 통해서 입력 받는 문자열의 끝에도 널 문자가 삽입되어 있다는 것을 알 수 있다.
C언어에서 표현하는 모든 문자열의 끝에는 널 문자가 자동으로 삽입된다.
널 문자의 존재는 굉장히 중요하다.
널 문자가 존재하면 문자열이고,
널 문자가 존재하지 않으면 문자열이 아니다.
char arr1[ ] = {'H', 'i', '~'};
위와 같이 선언된 배열은 문자열이라 할 수 없다.
메모리상에서 문자열의 이진 데이터로 저장되기 때문에 문자열의 시작과 끝이 표시되어 있지 않다면 문자열을 구분하는 것이 불가능하다. 널 문자를 이용해서 문자열의 끝을 표시하는 것이다.
#include<stdio.h>
int main()
{
char string[50] = "I like C programming";
printf("string: %s \n", string);
string[8] = '\0';
printf("string: %s \n", string);
string[6] = '\0';
printf("string: %s \n", string);
string[1] = '\0';
printf("string: %s \n\n", string);
return 0;
}
> 출력
string: I like C programming
string: I like C
string: I like
string: I
문자열 중간에 널 문자를 삽입하여 문자열의 끝을 변경하고 있다. 변경된 끝을 기준으로 문자열이 출력됨을 알 수 있다.
string[8] = '\0';
는 널 문자가 아스키 코드 값 0이므로 string[8] = 0;
으로 동일하게 표현할 수 있다.
공백을 포함한 문자열을 입력할 경우 공백은 scanf 함수가 데이터를 구분 짓는 기준이기 때문에 입력한 문장을 전부 출력하지 않는다.
추후 공백을 포함하는 하나의 문장을 통째로 입력 받을 때 호출하는 함수를 별도로 소개한다.
이번 Chapter가 1차원 배열인 이유는 배열이 모두 일렬로 나열된 배열만 다뤘기 때문이다. 1차원은 선에 해당한다.
추후 2차원 배열, 3차원 배열에서는 면, 입체에 해당하는 배열을 공부할 것이다.
<Review>
오랜만에 게시글을 올리는 것 같다.
그동안 여름 휴가를 놀러갔다 왔기 때문,,,!
(그리고 내가 다녔던 부트캠프에서 조교 제안과 마이다스 아이티 지원이 맞물려 갑작스럽게 취업 준비를 하다보니,,, 쿨럭)
C언어를 다시 배우니 언어의 근본을 다시 배우는 느낌이라 좋았다.
다음에 배울 포인터도 매우 기대가 된다! (이미 한번 한적은 있지만 ㅎㅎ)