프로그래밍은 CPU에서 할일은 지정해주는것이다.
할일을 지정해줄때 분기,반복등 여러 조건을 정해줄 수 있다.
중단Halt
- exit(숫자)
점프Jump
- goto,break,continue
조건분기Conditional branches
- if,switch
반복(루프)Loops
- while,do while,for
예외처리
- try,catch.throw

등이 있다.

 

중단Halt

exit(0)

#include <iostream>
#include <cstdlib>

using namespace std;

int main() 
{
	//출력 2번하는 프로그램
	cout << "test" << endl;
	//return은 return type에 맞춰서 값을줘야하지만 exit(숫자)는 상관없이 종료한다.
	exit(0);
	cout << "good" << endl;
	
	return 0;
}

조건문 if
if(bool타입){}조건으로 사용한다.
if문다음 else if()는 다음 조건을 설정할 수 있다.
else{}는 if의 조건이 안맞을때 실행된다.
논리연산자 사용이 가능하다.
return을 사용할 수 있다.

주의할점
{}(scope)을 안쓰면 아래 한줄만 동작한다.
if(조건)안에 정수가 0(false)이아니면 true로 인식한다.
논리연산자가 아닌 =을 사용하면 값을 대입하고 그값으로 if문이 작동한다.

 

#include <iostream>

using namespace std;

int main()
{
	int x,y;
	cin >> x;
	cin >> y;
	//논리연산자 사용
	if (x == y && x > 0) {
		cout << "x = y && x > 0" << endl;
	}
	
	if (x > 10) {
		cout << x << endl;
	}
	else if (x > 5) {
		cout << x << " = 10 > x > 5 " << endl;
	}
	else {
		cout << x << " < 5" << endl;
	}

	//0이 아니면 true로 본다.
	if (1) {
		cout << "if(1)" << endl;
		x = 10;
	}

	cout << x << endl;

	//return하는 if
	if (x == 10) {
		return 10;
	}
	return 0;
}

자료형을 불러올때 별명(가명) 붙여주기

typedef,using을 이용한다
예를 들어 자료형 double중에 거리에 사용되는 double형을 

별명을 붙여 사용한다면 공통으로 사용된 자료형을 관리하기 쉽다.
또 복잡한 자료형에 사용하면 보기 좋고 사용하기도 좋다.

#include <iostream>
#include <cstdint>
#include <vector>

using namespace std;


int main()
{
	typedef double distance_t;
	//고정너비 변수
	std::int8_t i(97);


	//컴파일러입장에선 같다.
	double distance;
	distance_t distance2;

	//vector<pair<string, int>> 를 줄여사용하기
	typedef vector<pair<string, int>> pairlist_t;
	//using사용
	using pairlist_t1 = vector<pair<string, int>>;

	return 0;
}

구조체struct

 

하나의 자료형으로 복잡한것(사람정보)을 구현하기 어렵다.
구조체를 이용해 하나의 사용자 정의 자료형으로 구현할 수 있다.
여러정보집합의 다수개의 정보를 저장할때도 구조체가 좋다.

 

구조체안에 함수를 구현할 수 있다.
구조체안에 구조체를 구현할 수도 있다.
구조체 대입,구조체 반환값도 가능하다.


sizeof로 사용Byte를 알수 있다(정확하진않고 조금더 추가될 수 있다).

#include <iostream>
#include <string>

using namespace std;

struct Person
{
	int id;
	double	height;
	float	weight;
	int		age;
	//기본값 정의도 가능하다.
	string	name = "me";
	//구조체안 함수 구현
	void printPersonInfo()
	{
		cout << height << endl;
		cout << weight << endl;
		cout << age << endl;
		cout << name << endl;
	}
};

void printPersonInfo(Person p)
{
	cout << p.height << endl;
	cout << p.weight << endl;
	cout << p.age << endl;
	cout << p.name << endl;
}

int main()
{

	//사람1정보구현
	double	height;
	float	weight;
	int		age;
	string	name;
	//사람2정보구현
	double	height2;
	float	weight2;
	int		age2;
	string	name2;
	
	//구조체구현이 훨씬 간단하다.
	Person person1{1, 2.0,100.0,20,"me" };
	Person person2{2, 2.0,100.0,20,"you" };

	//구조체로 묶여있어 인자로 보내기도 편하다.
	printPersonInfo(person1);
	//구조체안에 함수 구현 출력하기
	person1.printPersonInfo();

	//구조체 대입하기
	Person copyP = person1;
	cout << &person1 << " copyP addr : " << &copyP << endl;

	//사용Byte알아오기
	cout << sizeof(copyP) << endl;

	return 0;
}

열거형 enumerated types

어떤 같은 종류(색,무기종류)를 정할때 그 조건의 값을 다 기억하기는 어렵다.
그럴때 enum으로 자료형을 생성한다.
사용자 지정 자료형으로 생성된다.
내부적으로 정수 0,1,2,3순(100%integer는아님)으로 저장된다.
기본값으로 특정수를 설정하면 그 수부터 저장된다.
ex)처음 기본값을 -3으로 설정하면 -3,-2,-1,0,1순으로 된다.

enum 주의점
enum안에 선언해놓은것은 전역에서 중복될 수 없다.
캐스팅을 할 수 있다. static_cast<enum명>(정수);
cin으로 직접입력받을 수 없어 정수형,문자열으로 우회하여 받아야한다.(비추천)

#include <iostream>
#include <typeinfo>
#include <string>

using namespace std;

enum colorId {//사용자 지정 자료형
	COLOR_BLACK,
	COLOR_RED,
	COLOR_BLUE,
	COLOR_GREEN,
};

enum feelId {//사용자 지정 자료형
	HAPPY,
	JOY,
	//예를들어 colorId와 feelId의 BLUE가 이름이 같다면 에러가난다.
	BLUE,
};

int getColor(int colorId)
{
	if (colorId == 0) {
		return 1;
	}
	else if (colorId == 1) {
		return 2;
	}
}

int main()
{
	colorId apple(COLOR_RED);
	cout << apple << endl;

	//캐스팅하기
	colorId id = static_cast<colorId>(3);
	cout << id << endl;
	//string으로 입력받기(추천하지 않는다.)
	string str;
	getline(cin, str);
	if (str == "BLACK") {
		id = static_cast<colorId>(0);
	}
	cout << id << endl;

	return 0;
}

영역제한 열거형 enum class

enum으로만 생성하면 다른 enum안의 같은 순번의 데이터가

같은 숫자처럼 보일 수 있다.
enum class로 생성하게 되면 비교를 못하게 막아준다.
enum class 명 ::으로 불러온다.
같은 enum class끼리는 비교가 가능하다.
다른 enum class도 캐스팅하면 비교가 가능하긴 하다.

#include <iostream>

using namespace std;

int main()
{
	enum class Color
	{
		RED,
		BLUE,
	};
	enum class Fruit
	{
		BANANA,
		APPLE,
	};

	Color c = Color::RED;
	Color c1 = Color::RED;
	Fruit f = Fruit::BANANA;
	//두 출력 0으로 같지만 class를 선언하면 직접적으로 비교는 안된다.
	cout << static_cast<int>(c)<< " : " << static_cast<int>(f) << endl;

	//다른 enum class는 비교할 수 없다.
	/*if (c == f) {

	}*/
	//같은 class는 비교는 가능하다.
	if (c == c1) {
		cout << "같다." << endl;
	}

	return 0;
}

문자열

 

hello world같은 글을 문자열이라고 한다.
문자열을 사용할땐 string을 include해서 사용한다.
string은 기본자료형이 아닌 사람들이 만들어 놓은 사용자 정의 자료형으로 생각하면된다.
다른 기본자료형처럼 =,(),{}방식으로 정의가 가능하다.
숫자가 입력가능하지만 정수형이 아닌 문자형 ""으로 입력해야한다.
입력받을땐 다른 자료형과 같이 cin사용하는 것이 아닌 std::getline(std::cin,str);을 사용한다.
정수형(int)을 입력받고 std::getline(std::cin,str);을 사용하면 기존 버퍼에 남아있던 정수가 출력된다.
std::cin.ignore(32767,'\n');
std::cin.ignore(std::numeric_limits::max(), '\n');
을 이용해 정수입력이후 문자열을 입력받을 수 있다.
+,+=로 문자열에 문자열을 추가해줄 수 있다. append라고한다.
문자열 길이는 .length()로 확인할 수 있다.
string 문자열은 마지막에 문장마무리표시가 들어가있어 길이 1이 추가된다.

 

#include <iostream>
#include <string>
#include <limits>

using namespace std;

int main()
{
	//문자열을 출력한다.
	//아래글자는 char[12]로 출력된다.
	cout << "hello world" << endl;

	int age = 0;
	cin >> age;
	cout << age << endl;
	//cin 버퍼 초기화
	std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
	const string str = "hello world";
	cout << str << endl;
	//숫자입력
	string num = "123";


	string num2 = "";
	//문자열 입력
	std::getline(std::cin, num);
	std::getline(std::cin, num2);

	//문자열 더하기(append)
	cout << num + num2 << endl;
	num += "test";

	//문자열 길이
	cout << num.length() << endl;
	return 0;
}

형변환

 

변수 자료형 알아보는 방법
typeinfo를 사용해 자료형을 알 수 있다.
typeinfo(변수).name()형식
사용하는 이유
- 리터럴은 double지만 변수가 int형이라면 int로 저장된다.

암시적형변환
- 프로그래머가 설정하지않는데 형변환되는 경우
1. 작은것을 큰것으로 바꿀땐 적용된다.
  ex)float -> double로 변경될때 적용된다.
2. numeric conversion의 문제점
  ex)int -> char 큰자료형(작은자료형의 크기를 넘을때)에서 
             작은자료형으로 갈경우에 제대로 저장되지 않는다.
3.unsigned의 문제점도 있다.unsined int는 int보다 접근순위가 높다.

명시적형변환
- 프로그래머가 설정한 형변환   
- 대표적으로 세가지방법이 있다.
c++스타일
int i2 = int(4.0);
c스타일
i2 = (int)4.0;
다른방법
i2 = static_cast(4.0);

 

#include <iostream>
#include <cmath>
#include <typeinfo>

int main()
{
	using namespace std;

	//int형으로 저장된다.
	int a = 123.4;
	cout << a << endl;
	cout << typeid(4.0).name() << endl;

	float f = 123.4f;
	double d = f;
	d = 123.4567891011;
	f = d;

	int i = 30000;
	char c = i;
	//제대로 저장이 안된다.
	cout << static_cast<int>(c) << endl;

	//명시적형변환
	//c++스타일
	int i2 = int(4.0);
	//c스타일
	i2 = (int)4.0;
	//다른방법
	i2 = static_cast<int>(4.0);
	return 0;
}

Using
동일한 이름을 가진 변수,함수가 생길 수 있다.
클래스,namespace가 다르게 해결할 수 있다.

모호성(Ambiguity)
using namespace로 여러 namespace를 불러오면 똑같은 변수가 있을 수 있다.
그러면 namespace를 생략하고 사용할 수 없다.
namespace명::변수명 으로 사용하던지 아니면 {}영역을 구분줘서 사용해야한다.

using namespace를 선언하면 취소할 수 없다.
최대한 분리하여 사용하자.

#include <iostream>

namespace a
{
	int a1(2);
}
namespace b
{
	int a1(3);
}

int main()
{
	//std::를 생략할 수 있다.
	using namespace std;
	//아래처럼 하나만 불러와 사용할 수 있다.
	//using std::cout;

	//cout << "hello" << endl;

	//아래 두namespace에 똑같은 이름의 변수가 있다.
	//사용할려면 영역을 분리해서 사용하자
	{
		using namespace a;
		cout << a1 << endl;
	}
	{
		using namespace b;
		cout << a1 << endl;
	}
	

	return 0;
}

auto 키워드

큰프로그램을 작성하면 많은 변수를 작성하게 된다.
변수의 자료형을 프로그래머가 매번 정하면 효율이 떨어지게된다.

auto는 형추론을 통해 자동으로 자료형을 정해준다.
auto는 형추론을 해야하기해 자동화를 해주어야한다.

함수 리턴타입도 auto로 설정할 수 있다.
함수 리턴 값도 변수로 저장할때 auto로 설정가능하다.
파라미터타입은 auto로 설정할 수 없다.

파라미터타입 설정은 template로 사용할 수 있다.

#include <iostream>

//리턴타입을 auto로 설정했다.
auto add(int a, int b)
{
	return a + b;
}

//-> double방식으로 설정할 수 있다.
auto add(double a, double b) -> double
{
	return a + b;
}

int main()
{
	using namespace std;

	//int a = 123;
	//int형
	auto a = 123;
	//double형
	auto b = 23.4;

	//함수 리턴 값도 auto로 설정가능하다.
	auto result = add(1, 3);
	
	return 0;
}



전역변수(Global Variable)

cpp파일 모두에서 사용할 수 있는 변수를 전역변수(Global Variable)이라 한다.
전역변수는 가급적 사용을 하지 않아야 한다.
부득이한 경우로 사용할 상황도 생긴다.

정적변수(Static Variable)
디버깅,테스트할때 자주 사용한다.
변수 선언할때 static을 선언해 준다.
정적변수는 초기화해 사용해야 한다.

전역변수와 정적변수의 차이점

static이 없으면 일정 범위 안에서 변수가 선언될 때 메모리를 할당받고 반납하고 반복한다.
여러 함수에서 전역변수를 수정하면 문제가 생길 수 있다.

static이 있으면 영역안에 변수가 선언될 때 메모리를 할당받고 초기화하지 않는다.
변수가 선언되어있으면 재사용한다.

지역변수(local vriable),정적변수(static vriable)는 
{} 지역 안에서 사용하기 때문에 변수가 다른 곳에 영향을 주지 않는다.


내부연결
전역변수를 cpp 안에서만 사용하게 하려면 static을 선언해준다.
한 cpp파일에서만 전역변수가 사용되는 것은 내부연결(Internal Linkage)이라고 한다.

외부연결
extern선언을 이용해 여러 cpp파일에서 한 변수, 함수를 사용할 수 있다.

static : 다른 cpp 파일로부터 접근이 안된다.
const : 값을 변경 못한다.
extern : 다른 cpp파일에서 접근이 가능하다. 초기화하면 다른 곳에선 초기화를 해주면 안 된다.
extern const: 다른 cpp파일에서 접근 가능하다. 초기화해주어야 한다.

 

MyConst.h

#pragma once
//#pragma once 헤더 파일 중복 include를 막아준다.

namespace Constants
{
	//전체적으로 사용되는 상수를 선언한다.
	extern const double pi;
	extern const double grivity;

}

main.cpp

#include <iostream>
#include "MyConst.h"

using namespace std;

//전역변수 선언
int a = 123;
//정적변수 선언
void getTest()
{
	//정적변수는 꼭 초기화해야한다.
	static int a = 1;
	++a;
	cout << a << endl;
}

//다른 cpp 함수,변수 사용하기
//forward declaration
//어딘가에 있을 함수를 찾는다.
//extern 선언이 생략되어 있다.
//extern void getCppTest();
//프로그램전체에서 확인한다.
void getCppTest();
extern int a2;

int main()
{
	//전역변수(Global variabel)이 출력된다.
	cout << a << endl;
	//지역변수(local variabel)이다.
	//범위가  {}로 정해진다.
	int a = 0;

	//지역변수(Global variabel)가 출력된다.
	cout << a << endl;

	//전역연산자를 사용하면 전역변수로 출력기가능하다.
	cout << ::a << endl;

	//static을 선언해 정적변수를 사용하기 Test
	//getTest()함수를 불러오면
	//static int a를 메모리에 할당받는다.
	getTest();
	//두번째 함수 출력때 static이 있으면 변수가 선언되 있으면 재사용한다.
	getTest();

	getCppTest();

	cout << a2 << endl;
	//header에 상수를 선언해 test에서 불러오면 Constants와 메모리 주소가 다르다.
	//cpp파일을 만들어 extern header엔 정의만하고 cpp 파일에서 extern으로 정의해주면
	//같은 메모리 주소를 사용하는 걸 볼 수 있다.
	cout << "main : " << Constants::pi << " 주소: " << &Constants::pi << endl;
	return 0;
}

MyConst.cpp

namespace Constants
{
	//전체적으로 사용되는 상수를 선언한다.
	extern const double pi(3.141592);
	extern const double grivity(9.8);

}

test.cpp

#include <iostream>
#include "MyConst.h"

//초기화를 해줘야한다.
extern int a2 = 0;
void getCppTest() 
{
	using namespace std;
	cout << "test : " << Constants::pi << " 주소: " << &Constants::pi << endl;
	
}

지역변수
지역안에서 선언된 변수

범위 Scope
- 어디까지 적용되는가?
지속기간 Duration
- 메모리에 언제까지 적재되는가?


{}으로 지역을 구분한다. 

{}블록안에서 선언된 변수는 {}블록에서만 사용가능하다.
같은 블록안에서는 같은이름으로 변수를 선언하면 에러가 난다.
하지만 {{}}내부블록 안에서는 같은이름의 변수가 선언이 가능하다.
내부블록에서는 밖에 선언된 같은이름의 함수는 숨기고
내부블록안에 선언된 변수를 사용한다.

함수도 같은 이름은 불가능 하다.
하지만 파라미터가 다르다면 다른 함수로 볼 수 있다.

같은 이름의 함수를 사용하지 않는것이 좋지만
만약에 사용할려면 namespace를 사용해 사용한다.
namespace안에 namespace를 선언할 수 있다.

변수는 가급적 사용하는곳에서만 살아남게 선언한다.
객체지향프로그래밍의 기본적인 철학이다.

 

동적할당에선 범위,지속기간이 분리된다. 

#include <iostream>

using namespace std;

//만약에 같은이름의 변수와,함수를 사용하고 싶다면
//namespace를 사용한다.
namespace work1
{
	int a = 0;
	void getTest() {
		a += 1;
		cout << "work1::getTest() : " << a << endl;
	}
	
}


int a = 0;
void getTest() {
	a += 2;
	cout << "getTest() : " << a << endl;
}

int main()
{
	
	//apple변수를 선언해서 사용할 수 있게 된다.
	//OS로 부터 int메모리를 할당 받는다.
	//int main(){}안에서 사용가능 하다.
	int apple = 5;
	cout << apple << endl;
	if(true)
	{
		//{}밖에서 선언된 변수는 안 {}에서도 사용가능 하다.
		//apple변수가 위에 되어있기에 사용할 수 있다.
		//apple = 1;
		//cout << apple << endl;
		
		//같은이름으로 변수 선언이 가능하다.
		//내부 {} 안에서만 적용된다.
		//외부에 있는 apple은 같은 이름이 선언될 경우 숨긴다.
		//가급적이면 이름을 다르게 정하는것이 좋다.
		int apple = 1;
		cout << apple << endl;

		getTest();
		work1::getTest();
	}
	cout << apple << endl;

	return 0;
}

비트단위연산자
각각의 비트끼리 계산하는 연산자
int등의 계산은 타입단위 계산이다.

과거에는 메모리가 충분하지 않았다.
bool은 0,1만으로 표현되지만 1Byte를 사용해야한다.

비트단위연산자를 통해 데이터를 많이 채워 넣을 수 있다.
그리고 속도가 더빨라진다.

<<,>>,~,&,|,^ 여섯가지가 있다.
<<,>>는 cout,cin에서 사용하는 것과는 다르다.

 

#include <iostream>
//2진수로 변경해주는 라이브러리
#include <bitset>

using namespace std;

int main()
{
	//<<,>>는 cout,cin 에서 사용하는건 다른 의미이다.

	unsigned int a = 3;

	//2진수가 출력된다.
	cout << std::bitset<4>(a) << " : " << a << endl;

	//이진수를 오른쪽으로 한자리씩 보낸다. 2면 두자리 이동한다.
	//1일때 6,2일때 12,3일때 24 2제곱(연산숫자)로 계산되는걸 알 수 있다.
	//2의 제곱을 곱하고 싶을경우에 훨씬 빠르게 사용할 수 있다.
	unsigned  int b = a << 4;

	cout << std::bitset<4>(b) << " : " << b <<  endl;

	a = 1024;
	//2진수가 출력된다.
	cout << std::bitset<16>(a) << " : " << a << endl;
	//<<와 반대로 나누기가 2가된다.
	b = a >> 1;
	cout << std::bitset<16>(b) << " : " << b << endl;
	b = a >> 2;
	cout << std::bitset<16>(b) << " : " << b << endl;
	b = a >> 3;
	cout << std::bitset<16>(b) << " : " << b << endl;
	
	//~ NOT 반대로 출력된다.
	cout << std::bitset<16>(a) << " : " << a << endl;
	cout << std::bitset<16>(~a) << " : " << ~a << endl;

	//&,^,|을 확인해보자.
	//AND,OR,XOR의 조건에 맞게 출력된다.
	//2진수 출력하기
	a = 0b1100;
	b = 0b0110;

	//아래형식으로 쓸 수 있다.
	a &= b;

	cout << std::bitset<4>(a & b) << endl;
	cout << std::bitset<4>(a | b) << endl;
	cout << std::bitset<4>(a ^ b) << endl;

	return 0;
}

비트플래그

bool타입은 1Byte라 8bit를 사용한다.

생각해보면 메모리 낭비가 심하다.

1바이트는 8bit이기에 bool타입을 8가지 정보를 사용할 수 있다.

메모리를 낭비하지않고 정보를 담고 싶을때 유용하게 사용할 수 있다.
게임 아이템 정보에 많이 사용된다.

#include <iostream>
#include <bitset>

using namespace std;

int main()
{
	//4가지 아이템이 있다고 가정해보자.
	bool item1_flag = false;
	bool item2_flag = false;
	bool item3_flag = false;
	bool item4_flag = false;

	//아이템이 많아지면 bool변수를 많이 만들어야한다.
	//함수를 만들면 최대 아이템갯수가 파라미터 갯수가 될 수도 있다.
	
	//아이템은 가지고있다,없다 두가지로 생각할 수 있다.
	
	//아이템이 8가지 종류가 있다는 가정하에 char를 사용한다.
	
	const unsigned char opt0 = 1 << 0;
	const unsigned char opt1 = 1 << 1;
	const unsigned char opt2 = 1 << 2;
	const unsigned char opt3 = 1 << 3;

	cout << std::bitset<8>(opt0) << endl;
	cout << std::bitset<8>(opt1) << endl;
	cout << std::bitset<8>(opt2) << endl;
	cout << std::bitset<8>(opt3) << endl;

	unsigned char items_flag = 0;
	//00000000이 출력된다.
	//8자리의 숫자로 숫자하나당 각자 아이템 소유정보를 저장한다.
	cout << "NoItem : " << std::bitset<8>(items_flag) << endl;
	
	//|= OR를 사용해 아이템 습득 정보를 변경할 수 있다.
	//0번째 자리의 아이템을 습득했다.
	items_flag |= opt0;
	cout << "0Item Get : " << std::bitset<8>(items_flag) << endl;
	
	items_flag |= opt3;
	cout << "3Item Get : " << std::bitset<8>(items_flag) << endl;

	//&= 와 ~을 이용해 아이템 분실을 변경 할 수 있다.
	//opt0 = 00000000이다.
	//~opt0 = 11111111이다.
	//AND조건을 사용하면 둘다 1일때만 1이기에 아이템정보를 0으로 변경한다.
	items_flag &= ~opt0;
	cout << "0Item Lost : " << std::bitset<8>(items_flag) << endl;

	//아이템 보유여부 확인
	if (items_flag & opt3) {
		cout << "3번아이템 보유중" << endl;
	}

	//아이템 보유여부 확인
	if (items_flag & opt0) {
		cout << "0번아이템 보유중" << endl;
	}
	else {
		cout << "0번아이템 없음" << endl;
	}
	
	//두가지 아이템 습득할 경우
	//opt0 | opt1 는 00000011이다.
	items_flag |= (opt0 | opt1);

	if ((items_flag & opt1) && !(items_flag & opt2)) {
		items_flag ^= opt1;
		items_flag ^= opt2;
	}
	cout << std::bitset<8>(items_flag) << endl;


	unsigned int pixel_color = 0xDAA520;

	cout << std::bitset<32>(pixel_color) << endl;

	unsigned char red, green, blue;
	return 0;
}

함수보단 연산자(Operator)를 사용하는 게 편하다.
한식에 더하기,곱하기가 있으면 우선순위를 정해야 한다.

기본상식
- ()가 없어도  + 보단 *가 먼저다.
- ()가 있으면 우선순위 변경된다.

결합법칙 *,/가 있으면 우선순위가 어찌 정해질까?
*,/,%는 같은 우선순위를 가지고 있다. 
Left to Right형식으로 왼쪽부터 계산한다.

위와 같은 룰들이 있지만 ()를 통해 우선순위를 명확히 표현하는 것이 좋다.

Unary plus

*는 +보다 우선순위가 높지만 +3,-3은 우선 순위가 높다.

2^3은 2의 3제곱이아니다.
cmath를 사용해 제곱한다.

#include <iostream>
//제곱 사용
#include <cmath>
using namespace std;

int main()
{
	//함수보단 연산자(Operator)를 사용하는게 편하다.
	//한식에 더하기,곱하기가 있으면 우선순위를 정해야한다.
	//()가 없어도  + 보단 *가 먼저다.
	//()가 있으면 우선순위 변경된다.
	int x = 4 + 2 * 3;
	x = (4 + 2) * 3;

	//결합법칙 *,/가 있으면 우선순위가 어찌 정해질까?
	// *,/,% 같은 우선순위를 가지고 있다. 
	//Left to Right형식으로 왼쪽부터 계산한다.
	x = 3 * 4 / 2;

	//위와 같은 룰들이 있지만 ()를 통해 우선순위를 명확히 표현하는것이 좋다.
	
	//Unary plus
	//+3,-3은 우선 순위가 높다.
	x = +3;
	x = 3 + -3;

	//2^3은 2의 3제곱이아니다.
	//cmath를 사용해 제곱한다.
	x = std::pow(2, 3);
	cout << x << endl;

	return 0;
}

/ 는 나누기이다.
c++에서 int,float 나누기는 서로 다르다.
숫자가 하나라도 실수라면 실수로 출력된다. 

int형을 나누기 하게되면 정수이여야 하기 때문에 소수를 절삭한다.

% 나머지연산자는 왼쪽 숫자의 부호를 따른다.

#include <iostream>

int main()
{
	using namespace std;

	int x = 1;
	int y = -x;
	
	cout << y << endl;

	y = 2;

	int z = x + y;
	cout << z << endl;


	//% 는 나머지이다.
	//int,float 나머지는 서로 다르다.
	//숫자가 하나라도 실수라면 실수로 출력된다. 
	x = 7;
	y = 4;
	cout << x / y << endl;
	cout << float(x) / y << endl;

	//int형이면 정수이여야하기 때문에 0.5를 절삭한다.
	//2가 출력된다.
	cout << -5 / 2 << endl;

	//% 나머지연산자는 왼쪽숫자의 부호를 따른다.
	cout << -5 % 2 << endl;

	//x가 가르키고있는 메모리의 정보를 z가 가르키고있는 메모리에 저장한다.
	z = x;
	//z = z + y;와 같다.
	//코딩할 때 코드의 양을 줄여준다.
	//오타를 줄일 수 있다.
	//+=,*=,/=,%= 다 가능하다.
	z += y;

	return 0;
}

증감연산자

많이 쓰이고 쉽지만 실수할 때가 많다.

++,--의 특징은 앞에 붙일 수 있고 뒤에도 붙일 수 있다.

++,--가 앞에 붙으면 먼저 계산하지만 뒤에 붙으면 작업 후 마지막에 계산한다.

#include <iostream>

using namespace std;

int add(int a, int b)
{
	return a + b;
}

int main()
{

	int c = 6;

	//아래형식으로 코딩하면 안된다.
	//cout << add(c, ++c) << endl;

	int y = 2;

	cout << add(c, ++y) << endl;

	return 0;
}

sizeof
데이터형의 크기를 알고 싶을 때 사용한다.
struct, class 등 사용자가 만든 자료형도 크기를 확인할 수 있다.
Byte로 출력된다.
int = 4Byte = 32bit

sizeof는 연산자(operator)이다.

쉼표 연산자
,comma operator
주의를 하며 사용해야 한다.
int c = (++a, ++b);는
++a;
++b;
c = b;와 같다.

c = a, b;는
왼쪽 값을 메모리에 저장한다.
,는 =보다 연산자 순위가 낮다.
뒤에 값을 넣어주고 싶다면 c = (a,b);로 해준다.

for문이 아니면 풀어서 여러 줄로 사용하는 게 좋다.

조건부 연산자(삼항 연산자)
conditioanl operator
int a = 3 > 4 ? 1 : 0;
조건이 맞다면 왼쪽 값 다르다면 오른쪽 값을 메모리에 저장한다.

#include <iostream>

using namespace std;

int main()
{
	//sizeof 변수,타입 모두 넣을 수 있다.
	//struct,class등 사용자가 만든 자료형도 크기를 확인할 수 있다.
	cout << sizeof(int) << endl;
	int a = 3;
	cout << sizeof a << endl;

	int b = 10;
	/*int c = (++a, ++b);
	cout << c << endl;
	cout << a << endl;*/
	int c;
	c = a, b;
	cout << c << endl;

	bool sale = true;

	//조건부연산자.
	const int price = (sale == true) ? 10 : 100;

	cout << price << endl;

	cout << ((10 % 2 == 0) ? "GOOD" : "BAD") << endl;
	return 0;
}

관계 연산자
숫자 두 개를 비교하는 연산자이다.

실전에서 일어날 수 있는 문제점들이 있다.
== 같다.
!= 다르다.
> 왼쪽이 크다.
< 오른쪽이 크다.
>= 왼쪽이 크거나 같다.
<= 오른쪽이 크거나 같다.

float부동소수점끼리 비교는 문제점이 있다.
100 - 99.99와 10 - 9.99 두 가지를 비교하면 같지 않게 나온다.
오차의 한계를 개발자가 지정해 비교한다.

#include <iostream>
#include <cmath>

using namespace std;

int main()
{
	double d1(100 - 99.99);
	double d2(10 - 9.99);
	//0.01이 출력된다.
	cout << d1 << endl;
	//0.01이 출력된다.
	cout << d2 << endl;
	cout << d1 - d2 << endl;

	
	if (d1 == d2)
		cout << "같다" << endl;
	else
		cout << "다르다" << endl;

	//오차의 한계를 사람의 손으로 지정한다.
	const double epsilon = 1e-10;
	cout << epsilon << endl;
	cout << std::abs(d1 - d2) << endl;
	if (std::abs(d1 - d2) < epsilon)
		cout << "거의 같다" << endl;
	else
		cout << "다르다" << endl;

	return 0;
}

+ Recent posts