본문 바로가기
프로그래밍/C++

[정리] C++ 데이터 처리

by Nessie! 2022. 11. 30.
본 게시글은 C++ 기초 플러스 책을 읽고 제가 필요할때마다 직접 읽어보려고 매우 대충 정리한 글입니다. (진짜 개인공부용 글임) 따라서 다른 분들이 읽으려면 읽기 어려울 수 있음 주의 ㅎㅎ

3. 데이터 처리

C++에 내장된 데이터형에는 기본형과 복합형이 있다.
기본형은 정수형, 부동 소수점형이 있다.
복합 데이터형에서는 기본형을 기초로 하여 만들어지는 배열, 문자열, 포인터, 구조체 등이 있다.

기본형에 대해 먼저 알아보자.

3.1. 간단한 변수
변수 선언을 통해 데이터를 저장할 수 있다.
int a = 5;
이렇게 저장을 하면, 메모리의 어디에 저장되는지는 알 수 없으나, &연산자를 이용하면 메모리의 주소를 알아낼 수 있다.

변수 이름을 지을 때는 여러 규칙이 있다.
각자 필요한 변수 표기법을 따르자.

변수 표기법에는 아래와 같은 종류가 있다.

1. 카멜 표기법(camel case)
- 낙타 등처럼 내려갔다 올라가는 모양이라 하여 지어진 이름
- 단어가 여러개 붙을 때, 앞 단어를 제외한 첫자를 대문자로 표기
ex) dailyUserTable

2. 파스칼 표기법(pascal case)
- 모든 단어의 앞자가 대문자로 시작(단어의 수와 상관 없음)
- 네임스페이스, 이벤트, 프로퍼티, 클레스 네임을 지정할 때 주로 사용
- 클래스 등에서 많이 사용
ex) DailyUserTable

3. 스네이크 표기법(snake case), 팟홀 표기법(pothole case)
- 모든 단어가 소문자로 표시
- 다른 의미를 갖는 단어들의 조합에서 각 단어의 구분을 위하여 언더바( _ )를 붙힘
- 단어 사이의 '_' 가 뱀처럼 보인다고 해서 유래
- 언더바 표기법 이라고도 불리움
ex) daily_user_table

4. 헝가리안 표기법
- 접두사에 자료형을 붙힘
- 마이크로소프트 개발자 중 헝가리 프로그래머가 쓰던 변수 명명법
- 현재는 자료형을 쉽게 알아 볼수 있는 다양한 방법들이 많기 때문에 권장하지 않음
ex) strDailyUserTable

​변수를 선언할때에는 [자료형 변수명] 의 형식으로 작성하며, 자료형은 소문자로 작성해야한다. 변수명은 대문자로 작성해도 상관은 없으나 추천하진 않는다. 또한 변수명은 대소문자를 구분한다.
즉, int a; 와 int A; 는 다른 변수다.
Int b; 이렇게는 선언이 안된다. 자료형에 대문자가 들어갔기 때문이다.

- 정수형
정수는 2, 10, -5663, 0 처럼 소수부가 없는 수이다.
정수형을 나타내는 여러 자료형들은 서로 다른 크기의 메모리를 사용하여 정수를 저장한다. signed 데이터형은 음수 양수를 모두 나타낼 수 있으나, unsigned 데이터형은 양수값만 나타낼 수 있다.
저장할때 사용되는 메모리의 크기를 폭이라 하는데, 메모리의 크기가 클 수 록 저장할 수 있는 범위의 폭이 넓다.

크기 순
ㄴ char, short, int, long, long long 순이다.
위와같은 기본형들은 signed와 unsigned형이 각각 따로 존재한다.

- short, ing, long, long long 정수형
컴퓨터의 메모리는 bit 단위로 이루어져있다.

C++는 데이터형들의 최소 크기만 정해서 사용할 수 있다.
short: 16bit
int: short보단 크다
long: 32비트, int만큼 크다
long long: 64비트, 최소한 long만큼 크다

bit와 byte
컴퓨터 메모리를 구성하는 기본 단위는 비트.
비트는 이진수를 생각하면 된다.
8비트 폭의 메모리는 256가지의 비트 조합을 만들 수 있다.
ㄴ 0~255, -128~127 까지의 값을 나타낼 수 있다고 보면된다.

바이트는 8비트의 메모리 단위를 의미한다.
1킬로바이트 == 1024바이트, 1메가 == 1024킬로바이트
하지만 C++에서는 이와 조금 다르게 정의한다. C++에서 바이트는 컴파일러의 기본 문자 세트를 수용할 수 있는 최소한의 연속된 비트들로 구성된다.

현재 많은 C++들이 short형을 16비트로, long형을 32비트로 사용하는 최소 보증 표준을 따르고 있다. 그러나 int형은 이 표준을 따르면서도 폭이 16, 24, 32비트가 될 수 있다. 일반적으로 IBM PC용 구식 C++에서는 int형이 16비트다. Windows XP, VISTA, 7 등 미니 PC용 C++에서는 int형이 32비트이다.

int, short, long 세 가지 데이터형은 부호가 있는 데이터형으로사. 나타낼 수 있는 양의 정수값과 음의 정수값의 범위가 거의 같다.

sizeof 연산자를 사용하면 데이터형의 크기를 알아낼 수 있다.
sizeof는 변수나 데이터형의 크기를 바이트 단위로 리턴한다.

sizeof 연산자는 데이터형 이름이나 변수 이름에 모두 사용할 수 있다. int와 같은 데이터형 이름에 sizeof 연산자를 사용할 때에는 괄호를 사용해야하며, 변수 이름에 사용할 때에는 괄호가 없어도 상관없다.

cout << sizeof (int) << endl;
cout << sizeof 변수이름 << endl;

- 초기화
초기화 문법
int owls = 101;
int wrens(432); //C++의 새로운 초기화 문법. wrens를 432로 초기화한다

변수를 초기화하지않으면, 그 변수의 값은 미확정된 상태가 된다. 미확정 상태라는 말은 그 변수가 생성되기 바로 직전에 그 메모리 위치에 우연히 남아 있던 것이 그 변수의 값으로 행세한다는 것을 의미한다.

따라서, 변수는 초기화 해주는 것이 좋으며 선언 시 한번에 값 대입까지 해주는 것이 좋다.

- C++11 에서의 초기화
int hamburgers = { 24 };
int emus{ 7 };
int rheas = { 12 };
int rocs = {}; //0으로 초기화
int psychics {};

위 방법 다 가능하다.

- unsigned형
음의 정수값을 저장할 수 없는 형이다.
short형이 -43768 ~ +32767이 범위면, unsigned short는 0부터 65535까지의 범위를 갖는다.
int, short, long, long long 전부 앞에 unsigned키워드를 붙여서 사용할 수 있다.

unsigned 만 사용하면 unsigned int랑 동일하다.

각 자료형들은 범위를 벗어나는 값이 저장되면, 그 표현 범위의 반대편에서부터 다시 시작된다.

- 어느 정수형을 사용하는 것이 좋을까?
int형은 컴퓨터가 가장 효율적으로 처리하는 정수형으로, 정수는 보통 int형을 사용한다.
int로 나타낼 수 있는 정수보다 큰 정수는 long형을 사용한다.
그보다 큰건 long long을 쓴다.
short는 메모리를 절약할 수 있다.

- 정수형 상수
정수형 상수는 212, 1776과 같이 프로그램에 직접 써 넣는 정수를 말한다.

C++에서는 정수형 상수의 처음 하나의 숫자 또는 처음 두 개의 문자가 진수를 의미한다.
처음 숫자가 1~9이면 그 수는 10진수.
처음 숫자가 0이고 두 번째 숫자가 1~7이면 그 수는 8진수
042는 8진 정수형 상수이며, 10진수로는 34다.
처음 두 개의 문자가 0x 또는 0X이면 16진수
0x42는 16진 정수형 상수이며, 10진수로 66이다.

int a = 42;
int b = 0×42;
int c = 042;

이렇게 작성하면 a는 10진, b는 16진, c는 8진 정수형 상수로 저장된것이다.

하지만 cout은 어떤 진법으로 표현되었는가는 관계없이 기본적으로 10진수로 출력된다.
이를 10진수 16진수 8진수 등으로 출력해주려면 dec, hex, oct 조정자를 사용해야한다.

cout << a << endl;
cout << hex; //이때 진법을 바꾼다. 16진수로바꾼 상태
cout << b << endl;
cout << oct; //이때 진법을 바꾼다. 8진수로바꾼 상태
cout << c << endl;

- C++가 상수의 데이터형을 결정하는 방법
C++에서는 특별한 이유가 없다면 정수형 상수를 모두 int형으로 저장한다.
특정 데이터형을 의미하는 접미어를 상수에 붙였을 때와, 값이 너무 커서 int형으로 저장할 수 없을 때에는 다르다.

접미어
상수 끝에 붙는 문자로 그 상수의 데이터형을 나타낸다.
l, L == Long
u, U == usinged int
ul == unsinged long

예를 들어, 16비트 int형과 32비트 long형을 사용하는 시스템에서 22022 는 16비트 int형으로 저장되고, 22022L은 32비트 long형으로 저장된다.

접미어가 없는 10진 정수는 int, long, long long 형 중에서 크기가 가장 작은 것으로 나타낸다.
접미어가 없는 16진 정수나 8진 정수는 int, unsigned intm long, unsinged long, long long, unsinged long long 중에서 크기가 가장 작은 것으로 나타낸다.
그 이유는 성질상 부호가 없는 메모리 주소를 일반적으로 16진수로 나타내기 때문이다.

- char형: 문자와 작은 정수
char형은 문자와 숫자를 저장하기 위한 것이다.
프로그래밍 언어들은 문자를 수치 코드로 나타냄으로써 이 문제를 해결하고 있다. 그러므로 char형은 문자를 담는다곤 하지만 실제로는 또 하나의 정수형이다.
미국에서 가장 많이 사용하는 문자 세트는 ASCII이다. 65는 문자 A, 77은 문자 M에 해당하는 코드다.

C++에서 문자 상수를 나타낼 때에는 작음따옴표를 사용, 문자열은 큰따옴표를 사용한다.

char형 변수에 M을 cin으로 입력 받으면, 실제로 메모리에는 77로 저장된다고 보면 된다. 따라서 저장된 값에 +1 하게되면, 78이 되고, 78은 N이다.

위에서 한 내용을 그대로 코드로 작성해 출력하면 N이 나온다.

- cout.put()
cout객체의 멤버함수이다. 객체에 .을 붙여서 사용할 수 있다.
이때 이 점(.)은 멤버 연산자라고 부른다.

cout.put() 함수는 << 연산자를 사용하여 문자를 출력하는 것에 대한 대안이다.

왜 있는가?
C++ Release 2.0 이전에 cout은 문자 변수들을 문자로 출력했지만 'M'이나 'N' 과 같은 문자 상수들은 수로 출력했다. 초기에는 문자 상수를 int형으로 저장했다. 즉, 문자상수 'M'에 해당하는 코드 77이 16비트나 32비트로 저장되었다.
그러나 char형 변수는 8비트만을 차지해서 같은 문자도 다르게 인식되는 문제가 있었다.
char ch = 'M'; 과 같은 구문은 문자 상수 'M'으로부터 char형 변수 ch로 8비트만을 복사했다.
문자 상수 'M'과 char형 변수 ch가 동일한 값을 가지고 있더라도 cout에게는 서로 다르게 보였다.

- char형 상수
일반적인 문자들을 나타내는 가장 간단한 방법은 작은따옴표로 그 문자를 둘러싸는 것이다. 이러한 표기는 그 문자에 해당하는 수치 코드를 나타낸다.

키보드를 통해 프로그램에 입력할 수 없는 문자들이 있다.
Enter키를 누르는 방법으로는 문자열의 일부로 입력할 수 없다. Enter키를 누르면 프로그램 에디터는 개행 문자를 입력하지 않고, 새 행을 시작하라는 뜻으로 받아들이기 때문이다.
또한 C++에서 특별한 의미를 부여하고 있는 일부 문자들도 그냥은 사용할 수 없다. 큰따옴표와 같은 것들
이러한 특수 문자들을 위해 이스케이프 시퀀스(escape sequence)라는 특별한 표기법을 사용한다.

/a : alert 문자
/n : 개행문자
/" : 인용문에 사용하는 일반 문자로서의 큰따옴표

이때 사용하는 이스케이프 시퀀스는 Q와 같은 정식 문자로 취급된다.
즉, 이스케이프 시퀀스를 문자 상수로 사용할 때에는 작은따옴표로 둘러싸야 한다.

- 유니버설 네임 코드
C++는 특정 키보드와는 무관한 국제 문자들을 표현하는 메커니즘을 가진다. 그것이 유니버설 네임 코드(universal character names)의 사용이다.

- singed char형과 unsinged char형
char형은 signed, unsigned 형으로 미리 정해져 있지 않다. char형이 어느 특별한 한 가지 행동만을 보여야 한다면 signed, usigned로 사용하여 그 행동을 명시적으로 제한할 수 있다.

확장 char형: wchar_t
1바이트로 표현할 수 없는 문자세트를 처리해야하는 경우 사용한다.
wchar_t형은 시스템에서 사용되는 가장 큰 확장 문자 세트를 나타낼 수 있을정도로 큰 비트 폭을 가진 정수형이다.

cin과 cout은 입력과 출력을 char형 문자의 스트림으로 간주하기 때문에 wchar_t형을 처리하지 못한다. iostream 헤더 파일은 wchar_t형 문자의 스트림을 처리하기 위해 wcin, wcout 객체를 제공한다.
확장 문자 상수나 확장 문자 문자열은 그 앞에 L을 붙여서 나타낸다.

wchar_t bob = L'P'; //이런식으로

unsigned 16비트형인 char16_t, unsigned 32비트형인 char32_t도 있다.
특별한 경우에 문자열을 변환할 때 길이와 부호가 고정될 필요가 있는데, wchar_t의 부호와 길이는 가변이기 때문에 문제가 발생할 수 있다. 그래서 위에 두가지가 존재한다.

char16_t는 접두사로 u를 사용
char32_t는 접두사로 U를 사용

- bool형
bool형 변수는 참이나 거짓 중 어느 한 가지 값만 가질 수 있다.
0이면 거짓, 그 외는 참으로 해석한다.
true, false로 사용도 가능.

어떠한 수치 값이나 포인터 값도 하나의 bool 값으로 묵시적으로 변환될 수 있다. 0이 아니면 true, 0이면 false로 변환된다.

3.2. const 제한자
상수를 변수로 나타내면 그 상수를 여러곳에서 사용하고 있더라도 값을 쉽게 변경할 수 있다.
#define과 비슷하게 사용이 가능하다고 볼 수 있다.

const int MONTHS = 12;

이렇게 선언한다면, 이 프로그램 내에서는 MONTHS를 숫자 12 대신 쓸 수 있는 상태가 된 것이다.

const 키워드를 붙이고 값을 초기화하면 기 값이 고정된다. 컴파일러는 이후에 값을 변경하려는 모든 시도를 불허한다.

일반적으로는 이렇게 선언하게 된다면 상수로 쓰이고 있다는 것을 쉽게 알 수 있도록 이름을 모두 대문자로 쓴다. (정해진건 아니라, 속해있는 조직에서 사용하는 방식을 따르면 될 것 같다)

const 데이터형 변수명 = 값;
기본적으로 이렇게 사용한다.

const int test = 0;
이런식으로 선언 시 한번에 초기화해야한다. 안그러면 쓰레기값이 변경할 수 없게 박혀버린다.

#define보다 좋은점은 아래와 같다.
- 데이터형을 명시적으로 지정할 수 있다
- C++의 활동 범위 규칙에 의해 그 정의를 특정 함수나 파일에서만 사용할 수 있도록 제한할 수 있다
- 배열이나 구조체와 같은 복잡한 데이터형에도 const를 사용할 수 있다.

3.3 부동 소수점수
부동 소수점형은 2.5, 3.14159 등 소수부가 있는 수들을 나타낼 수 있다.
컴퓨터는 소수부가 있는 값들은 두 부분으로 나누어 저장한다. 한 부분은 기본값을 나타내고 다른 한 부분은 기본값을 키우거나 줄이는 스케일을 나타낸다.
이게 뭔말인가 하면 34.1245와 34124.5가 있다면 이 두 수는 기본값은 같고 스케일만 다르다 라고 이해하면된다.
첫번째 수는 기본값이 0.341245이고 스케일이 100이다.
두번째 수는 기본값이 0.341245이고 스케일이 100000이다.
소주점이 스케일에 따라 자리를 옮기기 때문에 이 데이터형을 부동 소수점형이라고 부른다.
C++은 스케일 인수가 10이 아닌 2다. (2진수를 사용한다)

그냥 정수형과는 나타내는 방식이 다르다고만 알면 된다고 한다.

11.0 과 같이 소수부가 0이라 하더라도 소수점이 있기때문에 정수형이 아닌 부동 소수점형으로 표현된다.

C++가 부동 소수점수를 표기하는 방법은 두 가지이다.
1. 소수점 표기법을 그대로 따르는 것
2. 3.45E6과 같이 지수 표기를 사용하는 것
3.45E6는 3.45에 1,000,000을 곱하라는 뜻이다. E6은 10의 6제곱

float, double, long double 형이 있다.
유효 숫자의 개수와 지수의 최소 허용 범위가 다르다.
유효숫자는 어떤 수에서 의미 있는 숫자를 말한다.
234이면 유효숫자가 3개, 200 이면 유효숫자 1개라고 볼 수 있다.

유효숫자를 저장할때 float은 최소 32비트, double은 float형보다 작지 않으면서 최소 48비트, long double은 최소 double형과 같은 크기를 요구한다.
지수의 허용 범위는 최소 -37~+37 이다.

정밀도는 float이 떨어진다. (당연..?한듯)

- 부동 소수점형 상수
ㄴ 기번적으로 double형으로 저장된다.
float형으로 저장하고 싶으면 f나 F를 접미어로
long double형으로 저장하고 싶으면 l이나 L을 접미어로

- 부동 소수점수의 장단점
장점
ㄴ 정수와 정수 사이에 있는 값을 나타낼 수 있다.
ㄴ 스케일을 사용하여 매우 큰 범위의 값을 나타낼 수 있다.
단점
ㄴ 정수보다 연산이 느리다.

3.4 산술 연산자
덧셈, 뺄셈, 곱셈, 나눗셈, 나머지셈 연산자를 제공한다.

+: 두 개의 피연산자를 더한다.
-: 첫 번째 피연산자에서 두 번째 피연산자를 뺀다.
*: 두 개의 피연산자를 곱한다.
/: 첫 번째 피연산자를 두 번째 피연산자로 나눈다. 두 개의 피연산자가 모두 정수이면 결과값은 몫의 정수부이다. 남는 소수부는 버려진다.
%: 첫 번째 피연산자를 두 번째 피연산자로 나누어 나머지를 구한다. 두 피연산자는 모두 정수여야 한다.

 



피연산자는 변수를 넣어도 된다.

- 연산 순서: 우선순위와 결합 방향
ㄴ 연산순서는 일반 대수학의 우선순위 규칙을 따른다.

float logs = 120 / 4 * 5;
이런식으로 우선순위가 같은 상황이면 결합 방햐 규칙을 적용한다.
왼쪽->오른쪽 결합이면 왼쪽에 있는 연산자를 먼저 적용하고, 왼쪽<-오른쪽 결합이면 오른쪽 연산자를 먼저 적용한다.

 



- 나눗셈에 대한 보충
나눗셈 연산자를 사용하는 연산은 피연산자의 데이터형에 따라 결과가 달라진다.
모두 정수라면 정수 나눗셈이 되어 결과값은 소수부를 버리고 정수로만 나온다.
피연산자가 하나라도 부동 소수점수라면 결과는 부동 소수점수가 된다.

여러가지 데이터형을 혼합하여 사용하면, 거기에 사용도니 모든 데이터형들은 동일한 데이터형으로 변환된다.

연산자 오버로딩
동일한 연산자가 서로 다른 연산에 사용되는 것을 연산자 오버로딩이라한다.

- 나머지셈 연산자
나머지셈 연산자는 정수 나눗셈의 나머지를 리턴한다

- 데이터형 변환
자동으로 데이터형을 변환하는 상황
ㄴ 특정 데이터형의 번수에 다른 데이터형의 값을 대입했을 때
ㄴ 수식에 데이터형을 혼합하여 사용했을 때
ㄴ 함수에 매개변수를 전달할 때

그럼 데이터형 변관 규칙에 대해 알아보자.

long형의 변수에 short형 값을 대입한다하면, long형 값으로 확장하여 대입한다.
short형 값을 long형 변수에 대입하면 값은 변하지 않고 의미 없는 여분의 바이트만 추가된다.
하지만 큰 값을 작은 값에 대입하면 정밀도가 손실된다.
형변환할때 주의할 점 이다.

bool형 변수에 0을 대입하면 false로 변환되고, 0이 아닌값은 true로 변환되어 저장된다.

부동 소수점수를 정수형에 대입할 때에는 두 가지 문제가 발생한다.
첫 번째는 소수부를 버린다.
두 번째는 float형 값이 너무 클 경우 int형 변수에 온전히 들어갈 수 없다.

- 데이터형 변환자
int 형 값을 long형으로 강제로 변환하려면 아래와 같이 작성할 수 있다
(long) thorn
long (thorn)

첫 번째 형태는 C에서 사용되던 방법이고, 두 번째 형태는 C++에서만 사용된다.

static_cast<>를 사용할 수도 있다.
static_cast (thorn)
ㄴ 이런식으로 사용한다.

- C++에서의 auto 선언
C++은 초기화하는 값을 보고 변수형을 추론할 수 있다.
초기화 선언 시 데이터형을 쓰지 않고 auto키워드를 사용할 수 있다.

auto n = 100; //n은 int
auto x = 1.5; //x는 double
auto y = 1.3e12L; //y는 long double

이렇게 자동으로 자료형이 지정된다.
남발하면 좋지 않은 습관이 생길 수 있으니, STL을 사용할 때 처럼 복잡한 자료형에 쓰는게 좋다.

'프로그래밍 > C++' 카테고리의 다른 글

[정리] C++ 증감연산자와 포인터  (0) 2022.12.01
[정리] C++ 복합 데이터형  (0) 2022.11.30
메모리 구조  (0) 2022.11.22
[정리] C++ 시작하기  (0) 2022.11.21
컴파일(Compile)  (0) 2022.11.19

댓글