오늘의 TIL 목차 (22.08. 11)
- 메모리 함수 ( memset, memcpy, memmove )
- 입출력 ( feat. stream )
메모리 함수
1. memset ( = ZeroMemory ) 2. memcpy 3. memmove
[ 메모리 함수 ]
: 메모리 대 메모리로 단위로 데이터들을 변경하는 기능의 함수
[ memset ] = [ ZeroMemory ]
: 메모리 초기화 함수
#include <windows.h> // ZeroMemory 함수 사용 시 <windows.h> 헤더파일 포함
memset(void* _Dst, int _Val, size_t _Size);
//(초기화하는 메모리 공간의 주소 값, 어떤 값으로 초기화 할 것인가, 얼마만큼의 메모리 크기를 초기화 할 것인가)
ZeroMemory(void* _Dst, size_t _Size);
// (초기화하는 메모리 공간의 주소 값, 초기화할 메모리 크기)
■ 기능 / 주의
- ZeroMemory() 함수 사용 시 <windows.h> 헤더파일을 포함시켜야 한다.
- memset은 초기값이 0, -1만 가능
- ZeroMemory는 초기값 0 고정 ( 매개변수에 초기값 할당 X )
■ 예시
int iArray[5] = { 1,2,3 };
int iArray2D[][2] = { 10, 11, 12, 13, 14, 15 };
cout << iArray1 << endl;
cout << iArray2D[0][1] << endl;
cout << iArray2D[1][0] << endl;
cout << "memset = ZeroMemory" << endl;
memset(iArray, 0, 4); // 초기값은 0과 -1만 가능
cout << sizeof(iArray2D) / sizeof(int) << endl;
ZeroMemory(iArray2D, 5); // int형이므로 4당 원소 하나 초기화
cout << iArray2D[0][0] << endl << iArray2D[0][1] << endl;
cout << iArray[1] << endl;
/*for (int i = 0; '\0' != i; ++i)
{
cout << iArray[i] << endl;
}*/
※ 주의사항
- memset ( 주소, 초기값, 초기화할 메모리 크기 )
- 복사할 메모리 크기가 5이면 int형 2차원 배열 iArray2D를 기준으로 원소 5개가 초기화되는 것이 아니라 원소 1개 = 4byte이므로 4byte + 1byte로 총 2개의 원소가 초기화된다.
[ memcpy ]
: 메모리 복사 함수
memcpy(void* _Dst, void const* _Src, size_t _Size);
//(복사 받을 변수의 메모리 공간의 주소, 복사 할 원본 메모리 공간의 주소, 복사할 메모리 크기)
■ 예시
int iArray[5] = { 1,2 }; // 나머지 3개는 자동 0 초기화
int iArray2D[][2] = { 10, 11, 12, 13, 14, 15 };
// 크기는 4byte만큼 변경이므로 iArray2D[1]행의 0번째부터 12byte(int형 4byte * 3)인 3개 원소가 iArray값으로 대체
memcpy(iArray2D[1], iArray, 12);
for (int i = 0; sizeof(iArray2D)/sizeof(int)>i; ++i)
cout << *(*iArray2D + i) << "\t"; // 2차원 배열에서 *iArray2D + i는 시작주소부터 열단위로 i만큼 주소 이동
memcpy(iArray, iArray2D[2], sizeof(iArray));
cout << iArray[0] << "\t" << iArray[1] << endl;
출력 결과:
10 11 1 2 0 15
0 15 // iArray2D 2행이 iArray 크기 (4byte * 원소 개수)만큼 iArray에 복사된다.
※ 주의사항
- memcpy ( 주소, 주소, 복사할 메모리 크기 )
- sizeof(iArray) 해야 전체 배열 원소 변경, sizeof(iArray) / sizeof(int)를 해버리면 원소 개수인 5가 되면서 5byte 크기만큼 총 원소 2개만 복사 변경 된다.
[ memmove ]
: 메모리 이동 함수, 동작은 memcpy와 같지만 내부 동작이 다름 ( memcpy는 속도, memmove는 안전성 )
memmove(void* _Dst, void const* _Src, size_t _Size);
//(복사 받을 변수의 메모리 공간의 주소, 복사 할 원본 메모리 공간의 주소, 복사할 메모리 크기)
■ 예시
char cArray[] = "DainnGoHome";
char cDest1[] = "abcdefghijklmnop";
char cDest2[] = "abcdefghijklmnop";
char cDest3[] = "abcdefghijklmnop";
cout << sizeof(cArray) << endl; // 널 포함 문자열 길이
memmove(cDest1, cArray, sizeof(cArray) - 1); // 널 제외 문자열 길이칸큼 복사
memmove(cDest2, cArray, sizeof(char) * sizeof(cArray)); // 널 포함 문자열 길이만큼 복사
// 널 포함 복사 시 널까지만 출력
memmove(cDest3 + 5, cArray, sizeof(char) * 5); // cDest의 5 글자 뒤부터 5크기만큼 복사
cout << cDest1 << "\t" << cDest2 << "\t" << cDest3 << endl;
출력 결과:
12
DainnGoHomelmnop DainnGoHome abcdeDainnklmnop
※ TIP
- 널 제외 복사 시 복사받은 문자열에서 복붙하고 남은 문자열은 이어서 출력
- 널 포함 복사 시 널까지만 출력
입출력 ( feat. stream )
1. 콘솔 입출력 2. 파일 입출력
[ 콘솔 입출력 ]
- 텍스트 모드 : 문자열 단위로 수행하는 작업
- 바이너리 모드 : 2진 코드 단위로 수행하는 작업
[ stream ]
: 전달 통로(매개체), 프로그램을 드나드는 데이터를 바이트의 흐름으로 표현한 단어
- stdin : 표준 입력 스트림, 기본 키보드 대상
- stdout : 표준 출력 스트림, 기본 모니터 대상
- stderr : 표준 에러 스트림, 기본 모니터 대상, 우리가 사용하지 않음
※ 표준 입출력
: 어떤 프로그램에 있어 사용자가 명시하지 않는 이상 프로그램 개발 시
기본적으로 사용할 입출력 대상을 '표준 입출력' 이라고 한다.
우리 프로그램은 키보드 입력을 표준 입력, 모니터 콘솔 출력을 표준 출력으로 한다.
■ 단일 문자 출력 함수 ( 텍스트 모드 함수 )
[ putchar ]
: stdout으로 스트림 고정(=콘솔 출력 고정)
putchar(값); // 값은 숫자 또는 문자 혹은 변수
[ fputc ]
: 파일 또는 콘솔에 값 추가
fputc(값, 파일 주소 또는 stdout) // 값은 파일에 넣을 숫자 또는 문자, 파일 주소는 stdout
■ 문자열 출력 함수
[ puts ]
: stdout으로 스트림 고정(= 콘솔 출력 고정)
puts("문자열"); // stdout으로 스트림 고정, 자동 개행을 제공
[ fputs ]
: 파일 또는 콘솔에 출력
fputs("문자열", 파일 주소 또는 stdout); // 자동 개행을 제공하지 않음
■ 단일 문자 입력 함수
[ getchar ]
: 문자열 배열 입력 시, 널 값을 제외한 [크기]만큼 단문자를 받는 함수
int ch = getchar(); // 띄어쓰기까지 입력 받음
#Define Size 3
char arr[3] = {};
int i = 0;
for (i = 0; sizeof(arr) / sizeof(char) > i ; ++i)
{
fgets(arr, sizeof(arr), stdin);
arr[i] = getchar();
cout << arr[i];
}
[ fgetc ]
: 문자 단위로 읽어들이는 함수, 파일의 단일 문자를 읽어들임
fgetc(파일 포인터명);
■ 문자열 입력 함수
[ gets_s ]
: stdin으로 스트림 고정(=키보드 입력 고정)
get_s(저장할 배열, 크기); // 공백(스페이스)를 읽어들임
char szName[8] = "";
get_s(szName, sizeof(szName)); // szName의 문자열 길이만큼 해당 배열에 저장
puts(szName); // 콘솔 출력 ; puts는 stdout 고정
[ fgets ]
: 파일에서 행 단위로 취득하고 싶은 경우 사용, 스트림을 직접 지정 가능(=파일 또는 콘솔에 입력),
fgets(저장할 배열, 크기, 파일주소 또는 stdin); // 크기는 1행 최대 문자수
char szName[8] = "";
fgets(szName, sizeof(szName), stdin); // 키보드 입력으로 szName 길이만큼 szName에 입력
puts(szName); // 콘솔 출력 ; puts는 stdout 고정
※ fgets와 gets_s 중 fgets 사용 권장
→ 공통점 : 성공 시 입력 받은 문자열의 시작 주소 반환, 실패 또는 파일의 끝에 도달할 경우 null 반환
- fgets_s는 enter(\n) 읽어들이고 '\0' 문자를 고려하여 읽어들이기가 가능하다. 널까지만 입력하며 선언한 배열의 크기만큼 널을 포함해서 읽어들인다. ( 입력한 크기가 배열의 크기를 초과하면 배열의 크기 - 1만큼 받고, 자동으로 널을 넣는다. )
- gets_s는 선언한 배열의 크기보다 입력한 크기가 커도 입력이 되고 논리적 오류가 뜨기 때문에 오버로드가 발생한다.
[ EOF ] End of FIle
: 파일의 끝을 표현하기 위한 상수로 -1 이다.
char text = 0;
while (text != EOF)
{
text = getchar();
putchar(text);
}
※ 콘솔 입출력에서는 ctrl + z를 이용하여 입력 버퍼에 EOF를 삽입할 수 있다.
'C++' 카테고리의 다른 글
| [TIL 16장] 레퍼런스 (0) | 2022.08.18 |
|---|---|
| [TIL 15장] 파일 입출력(feat. errno_t, 경로) 및 지원함수 텍스트 모드(.txt) & 바이너리 모드(.dat) (0) | 2022.08.16 |
| [TIL 13강] 열거체, C언어 동적할당(feat. Heap) (0) | 2022.08.12 |
| [TIL 12장] 문자열 함수, 구조체(feat. 포인터 사용), 공용체 (0) | 2022.08.10 |
| [TIL 11장] 문자열, 함수 포인터 (0) | 2022.08.08 |