#1. strcpy_s

-> 문자열 복사 함수

( c에서는 strcpy로 사용을 하였지만 c++로 넘어오면서 strcpy_s로 바뀌었다.)

 

strcpy_s(목적지, 크기, 출발지)

 

목적지

-> 어디에 복사를 할 것인지 복사 받을 메모리의 시작 주소를 전달

 

크기

-> 얼마만큼 복사를 수행할 것인지 크기를 전달(byte 단위)

 

출발지

-> 어디에 있는 데이터를 복사할지 시작 주소를 전달

#2. strcat_s

-> 문자열 결합

-> 기존 문자열 뒤에 문자를 이어 붙인다.

 

strcat_s(목적지, 크기, 출발지)

 

목적지

-> 이어붙일 메모리의 시작 주소

 

크기

-> 얼마만큼 수행할 것인지 크기를 전달(byte 단위)

 

출발지

-> 어디에 있는 데이터를 이어붙일지 시작 주소를 전달

	char szDst[20] = "Hello";
	char szSrc[20] = "World";

	cout << szDst << endl;
	cout << szSrc << endl;
	cout << "-------------------------" << endl;
	strcat_s(szDst, 20, szSrc);
	cout << szDst << endl;
	cout << szSrc << endl;

 

#3. strlen

-> 문자열의 길이를 반환하는 함수.

-> 단, NULL문자를 제외한 순수 문자열의 길이만 반환

	char	szBuff[20] = "Hello";
	
	cout << "sizeof: " << sizeof(szBuff) << endl;
	cout << "strlen: " << strlen(szBuff) << endl;

-> NULL문자를 포함하여 문자열의 길이를 반환하는 방법

void Func(char* m_pBuff)
{
   strlen(m_pBuff) + 1;
}

-> strlen을 사용하지 않고 문자열의 길이를 알아내는 방법은 다음과 같다.

int _len = 0;
while (_szBuff[_len] != '\0')
		_len++;

위와 같이 선언을 하게되면 해당 문자열에서 NULL문자가 나올때까지 비교를 하면서 문자열의 길이를 파악할 수 있다.

 

 

#4. strcmp

-> 두 문자열이 같은지를 비교하는 함수.

-> 두 문자가 같으면 0, 다르면(대소문자도 포함) 0이 아닌 값

(두 문자의 아스키코드 값이 같아도 동일하게 0이 나온다.)

char	szDst[20] = "Hello";
char	szSrc[10] = "Hello";

if (!strcmp(szDst, szSrc)) // strcmp(szDst, szSrc)의 값이 1이 아닐 경우
	cout << "같다" << endl;
else
	cout << "다르다" << endl;
    
cout << !strcmp(szDst, szSrc) << endl;

char	szDst[20] = "Hello";
char	szSrc[10] = "HellO";

if (!strcmp(szDst, szSrc)) // strcmp(szDst, szSrc)의 값이 1이 아닐 경우
	cout << "같다" << endl;
else
	cout << "다르다" << endl;
    
cout << !strcmp(szDst, szSrc) << endl;

'Programming > C++ Basic' 카테고리의 다른 글

C++ 구조체와 포인터  (0) 2020.08.31
C++ 구조체(Struct)  (0) 2020.08.31
C++ 문자 배열과 문자열 상수  (0) 2020.08.28
C++ 2차원 배열  (0) 2020.08.28
C++ 배열과 포인터  (0) 2020.08.28

문자 배열의 선언

char ch[10];

문자 배열의 초기화

-> 배열의 초기화는 {}를 사용했다.

-> 하지만 문자 배열의 초기화는 ""를 사용한다.

 

문자 배열은 배열 한칸 당 문자 하나씩 삽입이 된다.

마지막 문자가 삽입 된 후 다음 칸에는 자동으로 NULL문자가 삽입 된다.

 

NULL문자가 삽입되는 이유

-> NULL문자는 컴퓨터에게 해당 문자의 마지막 부분까지 읽으라고 명령을 하는 것이다.

 

예를 들어보자.

처음에 Hello라는 문자 배열을 선언하면 H, e, l, l, o 5개의 문자가 만들어진다.

여기서 H 부터 o까지 읽고 그 다음엔 NULL문자가 삽입이 된다.

 

NULL문자는 찾을 수 없을 경우 다음과 같이 알 수 없는 문구로 표시가 되는데,

원래는 빈 공간으로 표시가 된다.

배열의 이름은 주소이다.

-> cout 으로 배열의 이름을 전달하면 주소가 나온다.

-> 문자 배열은 같은 배열인데 주소가 나오는 것이 아니라 문자가 출력이 된다.

-> cout은 객체이다.

-> 단, 해당 주소가 char*일 경우에는 주소로 출력하는 것이 아닌 해당 주소에 있는 문자를 출력해준다.

 

문자 배열의 원소 접근

-> 배열처럼 인덱스 접근을 통한 읽기/쓰기가 가능하다.

char	ch[30] = "Hello";

	ch[2] = 'L';
	cout << "\t" << ch[2] << endl;
	cout << "\t" << ch << endl;

NULL문자의 중요성

-> 문자 배열의 크기를 설정할 때 NULL문자를 고려해서 크기를 설정해야된다.

 

예를 들어보자.

 

1byte 5개를 준비하고 6개의 문자를 넣으려고 시도한다.

이 경우 마지막에 들어갈 NULL문자는 할당한 메모리 공간이 아니다!!
-> 사용자가 할당하지 않은 메모리 공간의 접근 시도로 인해서 오류가 발생한다.


하지만 1byte 6개를 준비하고 Hello를 선언하면?

문제없이 잘 작동한다.

6byte로 만들어진 문자 배열 같은 경우는

첫 번째 문자부터 0, 1, 2, 3, 4, NULL 순서대로 읽으면 된다.

문자열 상수

-> 문자열 상수는 Data 영역에 할당이 된다.

(Data 영역에 배열의 형태로 공간을 만든다.)

-> 이후 문자 하나씩 대입하고, 마지막에는 NULL문자를 대입한다.

-> 메모리 할당이 완료되면 할당된 공간의 시작 주소를 반환한다.

cout << "Hello" << endl;

위에 Hello를 출력한 것은 Data 영역의 주소를 출력하는 것과 같은 말이다.

 

 

문자열 상수를 다루는 방법

-> 문자열 상수는 Data 영역의 주소를 반환하니, 주소를 저장할 변수를 만들어 사용한다.

char*	ch = "Hello";

 

원소 접근

-> Data 영역에 등록된 문자는 상수의 성질을 가진다.

	char*	ch = "Hello";
	ch[2] = 'L';		// 오류 발생
	cout << ch[2] << endl;

문자 배열과 문자열 상수의 차이점

#1 문자 배열

-> const가 *(에스크리터) 뒤에 붙는 경우와 동일하다.

-> 역참조를 통한 값 변경은 가능

-> 배열의 이름은 상수포인터이기 때문에 주소 값 변경은 불가능

 

#2 문자열 상수

-> const가 *(에스크리터) 앞에 붙는 경우와 동일하다.

-> 역참조를 통한 값 변경은 불가능

-> 주소 값 변경은 가능

 

문자 배열의 초기화

-> 컴퓨터가 문자 배열의 선언과 동시에 초기화 시 문자를 하나하나 대입해준다.

char	ch[10] = "Hello";

초기화 후 대입

-> ch는 주소를 가지는 포인터 변수

-> "Hello" 는 Data 영역의 주소

 

 

 

'Programming > C++ Basic' 카테고리의 다른 글

C++ 구조체(Struct)  (0) 2020.08.31
C++ 문자열 함수  (0) 2020.08.31
C++ 2차원 배열  (0) 2020.08.28
C++ 배열과 포인터  (0) 2020.08.28
C++ const와 포인터  (0) 2020.08.28

2차원 배열

-> 배열의 원소로 배열을 가지는 것.

-> 2차원 배열은 뒤에서부터 읽으면 편하게 읽을 수 있다.

 

 

2차원 배열의 형태

자료형 변수명[행][열]

int iArr[2][3];

 

2차원 배열의 초기화

1차원 배열의 초기화와 같다.

int iArr[2][3] = 
{
  { 1, 2, 3 },
  { 4, 5, 6 }
};

 

2차원 배열의 모든 원소 접근

for (int i = 0; i < 2; ++i)
{
	for (int j = 0; j < 3; ++j)
		cout << iArr[i][j] << '\t';
	cout << endl;
}

 

2차원 배열의 시작 주소

int iArr[2][3] = { 1, 2, 3, 4, 5, 6 };

cout << iArr << endl;

 

2차원 배열의 첫 번째 원소(배열)의 값

-> 배열의 값은 == 배열의 시작 주소

-> 첫 번째 배열의 시작 주소

cout << iArr[0] << endl;

 

2차원 배열의 두 번째 원소의 값

-> 두 번째 배열의 시작 주소

cout << iArr[1] << endl;

 

매개 변수의 int* _iArr 와 int _iArr[]는 같은 의미이다.

void Func(int _iArr[]) == void Func(int* _iArr)

같은 의미를 갖는 이유는 해당 매개 변수가 포인터인지 배열인지 구분을 하기 위해서이다.

 

배열을 함수 인자로 전달하는 방법

int iArr1[5] = { 1, 2, 3, 4, 5 };
int iArr2[10] = { 1, 2, 3, 4, 5 };

Func(iArr1, 5);
Func(iArr2, 10);

 

1차원 배열을 2차원 배열처럼 출력하기

int iArr[25] = {};

for (int i = 0; i < 25; ++i)
{
	iArr[i] = i + 1;
}

for (int i = 0; i < 5 ; ++i)
{
	for (int j = 0; j < 5 ; ++j)
		cout << iArr[j + (i * 5)] << '\t';
	cout << endl;
}

2차원 배열 포인터 형

int iArr[2][3] = { 1, 2, 3, 4, 5, 6 };

cout << iArr << endl; // 2차원 배열의 시작 주소 
cout << iArr[0] << endl; // 2차원 배열의 첫 번째 원소 -> 1차원 배열 -> 주소 
cout << *iArr << endl; 
cout << **iArr << endl;

역참조 연산자를 2번 사용하니, 포인터 변수에 에스크리터 2개를 추가하여 대입이 가능한가?

2차원 배열은 2중 포인터가 아니기때문에 불가능하다.

2중 포인터가 아닌 이유는 포인터 연산 증가 값의 차이점을 통해 알아보자.

 

ptr이 100번지라고 가정할 경우

ptr + 1은 몇 번지를 가리킬까?

ptr은 주소를 저장한다.

 

double*의 주소를 저장한다.

double*는 4byte의 크기를 가진다.

(증가는 4byte 만큼만 증가 한다.)

double** ptr = nullptr;

ptr + 1

2차원 배열의 증가 값은

-> 자료형 * 열의 개수 만큼 증가한다.

int iArr[2][3] = { 1, 2, 3, 4, 5, 6 };

	cout << iArr << endl;
	cout << iArr + 1 << endl;

이중 포인터와 2차원 배열은 증가 값이 다르다

-> 이중 포인터에 2차원 배열의 주소를 저장 할 수 없다.

 

2차원 배열의 포인터형

-> int형 주소를 저장할 공간 3개를 만들고, 포인터 변수에 해당 공간을 대입해보자.

빨간줄이 뜬 이유?

-> 2차원 배열의 포인터 형은 기존의 배열이랑 똑같이 선언을 하게되면 오류가 발생한다.

2차원 배열의 포인터 형은 다음과 같다.

기존 방식에서 *ptr 부분을 가로로 감싸주면 끝이다.

 

3차원 배열

-> 3차원 배열은 대부분 사용을 하지 않는다고 한다.

-> 그러므로 사용 방법만 간단하게 적어보자.

int	iArr[2][3][4] = 
{
  {
	{ 11, 12, 13, 14 },
	{ 15, 16, 17, 18 },
	{ 19, 20, 21, 22 }
  },
  {
	{ 23, 24, 25, 26 },
	{ 27, 28, 29, 30 },
	{ 31, 32, 33, 34 }
  }
};

'Programming > C++ Basic' 카테고리의 다른 글

C++ 문자열 함수  (0) 2020.08.31
C++ 문자 배열과 문자열 상수  (0) 2020.08.28
C++ 배열과 포인터  (0) 2020.08.28
C++ const와 포인터  (0) 2020.08.28
C++ 포인터  (0) 2020.08.26

배열

-> 동일한 특성을 가지며, 일정한 규칙에 따라 나열되어 있는 데이터 집합

동일한 특성 : 자료형

일정한 규칙 : 연속된 메모리

 

배열의 형태

자료형 변수명 [ 배열의 수]

int iArr[5];

int형을 사용하는 변수 5개를 만든다는 의미.

 

배열의 길이

int iArr[] = {1,2,3,4,5};
cout << sizeof(iArr) / sizeof(int) << endl;

 

배열의 초기화

-> 다음과 같이 선언을 하게되면 5개의 변수가 모두 쓰레기 값으로 초기화가 진행된다.

int iArr[5];

배열의 초기화 방법

int iArr[5] = {}

{} 안에 명시한 값들이 순차적으로 채워진다.

int iArr[5] = { 1, 2, 3, 4, 5 };

1 > 2 > 3 > 4 > 5

 

만약 다음과 같이 선언 했을 경우 {} 안에 명시한 값들이 순차적으로 채워지고 뒤에 나머지 값들은 0으로 채워진다.

int iArr[5] = { 1, 2, 3 };

배열의 원소 접근

-> 변수명 [ 인덱스 ]

-> 배열 선언 시 사용한 []는 배열의 크기를 설정하는 것 (1부터시작)

-> 배열 선헌 후 사용한 []는 원소에 접근하는 것. (0부터시작)

int iArr[5] = { 1, 2, 3, 4, 5 };

for (int i = 0; i < 5; ++i)
		cout << iArr[i] << endl;

배열을 사용하다보면 {1, 2, 3, 4, 5} 처럼 원소를 일일이 지정하기 귀찮을 때가 있다.

이럴 때는 for문을 활용하면 좀 더 간편하게 원소를 지정할 수가 있다.

int iArr[5] = {};

for(int i = 0; i < 5; ++i)
{
   iArr[i] = i + 1;
}

 

배열의 크기는 상수로만 설정이 된다.

-> 변수로는 설정이 불가능하다.

이는 정적 배열을 뜻한다.

 

다음과 같이 입력을 통해 배열의 크기를 직접 설정하는 것은 불가능하다.

int iSize = 0;
 cin >> iSize;

 int iArr[iSize]; // 불가능

 

배열의 변수명만 출력할 경우 주소가 나온다.

-> 이 주소는 첫 번째 원소의 주소와 같다.

배열의 이름은 시작 주소를 저장하고 있다. 즉, 시작 주소를 저장하는 포인터라고 할 수 있다.

int iArr[5] = { 1, 2, 3, 4, 5 };
	cout << iArr << endl;
	cout << "==============================" << endl;
	for (int i = 0; i < 5; ++i)
		cout << &iArr[i] << endl;

포인터 연산

-> 주소를 대상으로 + 연산을 수행한다.

-> 단, 포인터 연산 시 연속 된 메모리를 사용해야만 한다.

-> 포인터 연산 시 증가 값은 자료형의 크기만큼 증가한다.

int	iArr[5] = { 1, 2, 3, 4, 5 };
int*	ptr = iArr;

인덱스 연산자는 *( + n)와 같은 말이다.

예)

*(ptr + 0) == iArr[0] 
*(ptr + 1) == iArr[1]
*(ptr + 2) == iArr[2]
*(ptr + 3) == iArr[3]
*(ptr + 4) == iArr[4]

 

인덱스 연산자는 주소 값을 대상으로 포인터 연산을 수행 후 역참조를 사용한다.

cout << ptr[3] << endl;

-> 만약, 해당 연산이 성립할 경우 iArr가 할당된 공간을 잃어버리게 된다.

-> 배열의 시작 주소를 잃어버리면 배열에 접근을 할 수가 없게 된다.

-> 이를 안전하게 사용하게 하기 위해 배열의 이름은 상수 포인터로 설정되어 있다.

 

배열로 매개변수 선언

void Func(int* _ptest)   // 포인터
void Func(int  _ptest[]) // 배열

-> 포인터 형식으로 선언을 해도 배열을 참조할 수가 있다.

-> 작업을 하면서 해당 매개변수가 포인터인지 배열인지 구분을 하기위해 나눠져 있다.

'Programming > C++ Basic' 카테고리의 다른 글

C++ 문자 배열과 문자열 상수  (0) 2020.08.28
C++ 2차원 배열  (0) 2020.08.28
C++ const와 포인터  (0) 2020.08.28
C++ 포인터  (0) 2020.08.26
C++ 재귀 함수  (0) 2020.08.25

+ Recent posts