Skip to content

Latest commit

 

History

History
254 lines (206 loc) · 8.01 KB

211025.md

File metadata and controls

254 lines (206 loc) · 8.01 KB

Day 24

Review C

배열 선언 및 접근

자료형 배열이름[크기];
자료형 배열이름[크기] = {값1, 값2, 값3};

  • 이 방법은 이미 선언된 배열에는 사용할 수 없다.
  • 이 방법에서 크기를 생략할 수 있고, 크기는 자동으로 인자 수만큼 할당된다.
int numArr1[2] = {1, 2};

접근을 하려면 배열 뒤에 [인덱스]를 사용한다.

numArr[0]; // 0번 인덱스에 접근

배열의 인덱스는 0부터 시작

배열의 모든 요소를 0으로 초기화

자료형 배열이름[크기] = {0,};

int numArr[10] = {0, }; // 배열의 요소를 모두 0으로 초기화

배열의 요소에 값 할당

배열[인덱스] = 값;

int numArr[10];

numArr[0] = 11;
numArr[4] = 22;

배열의 범위를 벗어난 인덱스에 접근하면 쓰레기 값이 출력되며, 이는 배열이 아닌 다른 메모리 공간에 접근한 것이다.

배열의 크기

int numArr[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; // 크기 10인 int형 배열 선언 및 초기화

printf("%d", sizeof(numArr)); // 40 출력, 4바이트인 int형 요소가 10개이므로 40이 됨
printf("%d", sizeof(numArr) / sizeof(int)); // 10 출력, 전체 공간을 요소 크기로 나눠준다.

배열을 포인터에 넣기

배열은 첫 번째 요소의 주솟값만 담고 있다.

int numArr[3] = {1, 2, 3};
int *numPtr = numArr; // 포인터에 int형 배열 할당

printf("%d", *numPtr); // 1 출력, 배열의 주소가 들어있는 포인터를 역참조하면 배열의 첫 번째 요소에 접근
printf("%d", *numArr); // 1 출력, 배열 자체를 역참조해도 마찬가지
printf("%d", numPtr[2]); // 3 출력, 배열의 주소가 들어있는 포인터는 인덱스로 접근이 가능하다.
printf("%d", sizeof(numArr)); // 12 출력, sizeof로 배열의 크기를 구하면 배열이 메모리에 차지하는 공간이 출력
printf("%d", sizeof(numPtr)); // sizeof로 배열의 주소가 들어있는 포인터의 크기를 구하면 포인터의 크기가 출력됨

단, 자료형이 같고, 1차원 배열이라면 단일 포인터여야 한다.

2차원 배열의 선언과 접근

가로 * 세로 형태로 이루어진 배열, 평면 구조
자료형 배열이름[세로크기][가로크기];
자료형 배열이름[세로크기][가로크기] = {{값1, 값2, 값3}, {값4, 값5, 값6}};

int numArr[3][4] = {
    {1, 2, 3, 4},
    {5, 6, 7, 8},
    {9, 10, 11, 12}
};

printf("%d", numArr[0][1]); // 2 출력

2차원 배열의 요소를 0으로 초기화

int numArr[3][4] = {0, };

2차원 배열의 크기

int numArr[3][4] = {
    {1, 2, 3, 4},
    {5, 6, 7, 8},
    {9, 10, 11, 12}
};

printf("%d", sizeof(numArr)); // 48 출력, 4바이트가 12개이므로 48

int col = sizeof(numArr[0]) / sizeof(int); // 4 출력, 가로 한줄의 크기를 요소의 크기로 나눠주면 가로 크기

int row = sizeof(numArr) / sizeof(numArr[0]); // 3 출력, 배열이 차지하는 전체 공간을 가로 한 줄의 크기로 나눠주면 세로 크기

2차원 배열과 이중 포인터

자료형 (*포인터이름)[가로크기];

int (*numPtr)[4];

괄호의 유무에 따른 차이

  • int (*numPtr)[4] : 배열을 가리키는 배열 포인터
  • int *numPtr[4] : 포인터를 여러 개 담는 포인터 배열

이차원 배열을 포인터에 할당

int numArr[3][4] = {
    {1, 2, 3, 4},
    {5, 6, 7, 8},
    {9, 10, 11, 12}
};

int (*numPtr)[4] = numArr;

printf("%p", *numPtr); // 세로 첫 번째 주소 출력 
printf("%p", *numArr); // 세로 첫 번째 주소 출력
printf("%d", numPtr[2][1]); // 10 출력
printf("%d", sizeof(numArr)); // 48 출력
printf("%d", sizeof(numPtr)); // 포인터의 크기 출력

3차원 배열

높이 * 가로 * 세로 형태
자료형 배열이름[높이][세로크기][가로크기];

int num[2][3][4] = {
    {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}
    },
    {
        {13, 14, 15, 16},
        {17, 18, 19, 20},
        {21, 22, 23, 24}
    }
};

포인터에 할당된 메모리를 배열처럼 사용하기

자료형 *포인터이름 = malloc(sizeof(자료형) * 크기);

int *numPtr = malloc(sizeof(int) * 10); // int 10개 크기만큼 동적 메모리 할당

numPtr[0] = 10; // 배열처럼 인덱스로 접근 가능

free(numPtr); // 메모리 해제

포인터에 할당된 메모리를 2차원 배열처럼 사용하기

자료형 **포인터이름 = malloc(sizeof(자료형 *)* 세로크기);

  • 반복문으로 포인터[i] = malloc(sizeof(자료형) * 가로크기);와 같이 가로 공간 메모리 할당
  • 반복문으로 free(포인터[i]); 와 같이 가로 공간 메모리 해제
  • free(포인터);와 같이 세로 공간 메모리 해제
int **m = malloc(sizeof(int *)*3); // 이중 포인터에 (int 포인터 크기 * 세로 크기)만큼 동적 메모리 할당, 배열의 세로

for (int i = 0; i < 3; i++) // 세로 크기만큼 반복
{
    m[i] = malloc(sizeof(int) * 4); // (int 크기 * 가로 크기)만큼 동적 메모리 할당, 배열의 가로
}

m[0][0] = 1;

for (int i = 0; i < 3; i++) // 세로 크기만큼 반복
{
    free(m[i]); // 2차원 배열의 가로 공간 메모리 해제
}
free(m); // 2차원 배열의 세로 공간 메모리 해제

문자와 문자열 포인터

문자열은 따로 자료형이 없다.

char *변수이름 = "문자열";

char *s1 = "Hello"; // 포인터에 문자열 "Hello"의 주소 저장

printf("%s", s1);

문자열의 마지막에 항상 NULL 문자가 붙는다.
문자열의 끝을 나타내며, printf는 문자열을 출력할때 NULL에서 출력을 끝낸다.

문자열 포인터에서 인덱스로 문자에 접근하기

char *s1 = "Hi";

printf("%c", s1[1]); // i 출력, 1번 인덱스 출력

배열로 문자열 선언하기

char 배열이름[크기] = "문자열";

char s1[10] = "Hi"; // 크기가 10인 char형 배열 선언하고 문자열 할당

printf("%s", s1);

배열에 문자열과 NULL을 저장하고 남은 공간은 보통 NULL로 채워짐
선언과 동시에 문자열로 초기화해야함
문자열을 배열로 선언할 때 반드시 NULL 값을 생각해서 크기를 정할 것
인덱스를 이용해서 문자에 접근이 가능하다.

문자열 입력받아 배열에 저장

scanf("%s", 배열);

  • 성공하면 가져온 갑의 개수를 반환, 실패하면 EOF(-1) 반환
char s1[10];

scanf("%s", s1); // 배열은 scanf에서 &를 붙이지 않는다. 배열이 주소를 담고있기 때문

scanf("%[^\n]s", s1) // 공백까지 포함하여 문자열 입력받음

문자열 입력받아 포인터에 저장

char *s1 = malloc(sizeof(char) * 10); // char 10개 크기만큼 동적 메모리 할당

scanf("%s", s1); // 표준 입력을 받아서 메모리가 할당된 문자열 포인터에 저장

free(s1);

여러 개의 문자열 입력받기

scanf("%s%s...", 배열1, 배열2, ...);
scanf("%s%s...", 포인터1, 포인터2, ...);

scanf("%s %s", s1, s2); // 공백으로 구분된 문자열 두 개 입력받음

문자열 길이 구하기

strlen 함수 사용, string.h에 선언
strlen(문자열포인터 or 문자배열);

  • 문자열의 길이를 반환
char *s1 = "Hi";

printf("%d", strlen(s1)); // 2 출력

strlen은 순수한 문자열의 길이만 구해서, NULL은 포함하지 않는다.

문자열 비교

strcmp 함수 사용, string.h에 선언
strcmp(문자열1, 문자열2);

  • 문자열 비교 결과를 반환
char s1[10] = "Hi";
char *s2 = "Hi";

int result = strcmp(s1, s2)

printf("%d", result); // 0 출력, 두 문자열이 같으면 0 반환

반환값

  • -1 : ASCII 코드 기준으로 문자열2가 클 때
  • 0 : ASCII 코드 기준으로 두 문자열이 같을 때
  • 1 : ASCII 코드 기준으로 문자열1이 클 때

그냥 사전 순으로 뒤에 있는 것이 크고 앞에 있는 것이 작음

리눅스에서는 반환값이 ASCII 코드값의 차이를 반환, 즉 음수, 0, 양수로 판별하면 됨