0️⃣ New Knowledge
▪ accumulate(반복 시작, 반복 끝, 합의 초깃값)
accumulate의 반환값은 합의 초깃값 타입을 따라감
vector<int> vec = { 5'000'000'000, 7'000'000'000 };
long long sum = accumulate(vec.begin(), vec.end(), 0);
//long long으로 받아도 0으로 설정해서 int로 반환 -> 오버플로우 발생 (0대신 0LL 사용)
cout << sum << '\n'
▪ “” ‘’
char 변수 = ‘작은 따옴표’
string 변수 = “큰 따옴표 ”
서로 바뀌면 에러 발생
▪ 문자열 리터럴은 const char[] 타입
1️⃣ 2주차 과제 풀이
🔹 Vector 템플릿 구현
GitHub - swehio/241231_TempleteVector: implement Vector Templete
implement Vector Templete. Contribute to swehio/241231_TempleteVector development by creating an account on GitHub.
github.com
💭자아성찰
▪ 값만 반환하는 함수는 const 적어주기
▪ 복사 생성자에서 Capacity만 재할당하고 근본적으로 data 재생성 및 이전 데이터 복사 안함
▪ resize도 동일
🔹도서관 시스템 구현
GitHub - swehio/250102_LibrarySystem
Contribute to swehio/250102_LibrarySystem development by creating an account on GitHub.
github.com
💭자아성찰
▪ BorrowManager 기능을 BookManager로 다 옮겨서 SOLID를 지키지 못함
▪ const 레퍼런스로 받아오기 -> 다이어그램대로 만들 필요가 없구나..!
2️⃣ 추가 공부
🔹 LValue와 RValue
- LValue :
- 표현식 이후에도 사라지지 않는 이름을 지니는(메모리 주소를 가지는) 객체(보통 등호의 왼쪽)
- RValue
- 표현식 이후에는 사라지는 값으로 메모리 주소를 가지지 않는 임시 객체(보통 등호의 오른쪽)
- 리터럴 상수/포인터(주소값)/(일반적인)함수 리턴 값 등이 해당
💡할당 연산자
등호 왼쪽(피연산자)에는 LValue가 와야 함
//예외 int main(){ setAge(age) = 40; //함수가 lvalue인 참조를 반환하므로 가능 return 0; } int& setAge(int& age) { return age; }
💡주소 연산자
▪ &
LValue 레퍼런스
LValue를 인수로 받아 RValue(주소값) 반환
메모리를 가지는 변수들만 대입 가능 → &(RValue)는 에러
▪ &&
RValue 레퍼런스
int&& ten = 10;
메모리 위치가 명확한 LValue에 대한 참조 불가능 RValue만 가능
💡a++
1. a의 값을 카피하여 임시변수(RValue)에 저장
2. 원래 a(LValue)의 값을 변경한 후 임시 변수를 계산에 사용
따라서 ++앞에 있는 변수 a는 RValue
💡산술연산자
더하기 연산자의 경우 두 개의 RValue를 취해서 RValue의 결과 반환
→ 변수(LValue)도 가능한데 이는 암시적으로 LValue를 RValue로 변환
💡LValue와 RValue 간의 변환
▪ LValue → RValue 가능
위의 산술연산자 예시
▪ RValue → LValue 불가능
참조를 통해 숫자 상수의 값 변경을 막기 위해서
💡함수 매개변수 참조 시
func1(10); //에러rvalue를 lvalue로 변환할 수 없으니까 func2(10); void func1(int& x) { } void func2(const int& x) { //참조 자체를 상수로 만들면 수정할 수 없게되니까 //리터럴 상수 넘길 수 있음 }
- 내부적으로는 컴파일러가 숨겨진 변수(lvalue)를 생성해서 참조에 바인딩한 것
- 임시 개체의 불필요한 복사와 생성을 방지
🔹비트 연산
#include <iostream>
using namespace std;
int main() {
int A = 10; // 1010
int B = 12; // 1100
//1. AND 연산(&)
//두 비트가 모두 1일 때만 결과가 1
cout << (A & B) << endl; // 출력: 8 (1000)
//2. OR 연산(|)
//두 비트 중 하나라도 1이면 결과가 1
cout << (A | B) << endl; // 출력: 14 (1110)
//3. XOR 연산(^)
//두 비트가 서로 다를 때만 결과가 1
cout << (A ^ B) << endl; // 출력: 6 (0110)
//4. NOT연산(~)
//비트를 반전 (0 → 1, 1 → 0)
cout << (~A) << endl; // 출력: -11 (컴퓨터에서 2의 보수로 표현)
return 0;
}
a. 왼쪽 시프트(<<)
비트를 왼쪽으로 이동, 오른쪽은 0으로 채움(A×2^n)
#include <iostream> using namespace std; int main() { int A = 10; // 1010 cout << (A << 2) << endl; // 출력: 40 (101000) return 0; }
b. 오른쪽 시프트(>>)
비트를 오른쪽으로 이동, 왼쪽은 부호 비트로 채움(A÷2^n)
🔹진법 변환
1. 10진수 -> 다른 진법
- 변환하려는 진법으로 계속 나누기
- 나머지 기록
- 나눈 몫이 0이 될 때까지 반복한 후, 나머지를 역순으로 읽기
2. 다른 진법 -> 10진수
자리값에 기수를 곱하고 합산
3. 진법 A -> 진법 B
a. 진법 A → 10진수로 변환
b. 10진수 → 진법 B로 변환
4. 프로그래밍 진법 변환
- 입출력 조직자 활용
#include <iostream>
#include <bitset>
using namespace std;
int main() {
int num;
cout << "10진수를 입력하세요: ";
cin >> num;
cout << "2진수: " << bitset<32>(num) << endl; // 32비트 기준
cout << "8진수: " << oct << num << endl;
cout << "16진수: " << hex << num << endl;
return 0;
}
- 문자열 사용
#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
using namespace std;
// 16진수를 10진수로 변환
int fromBase(const string& num, int base) {
int result = 0;
int power = 0;
for (int i = num.size() - 1; i >= 0; --i) {
char digit = num[i];
int value = isdigit(digit) ? digit - '0' : toupper(digit) - 'A' + 10;
result += value * pow(base, power++);
}
return result;
}
// 10진수를 2진수로 변환
string toBase(int num, int base) {
string result = "";
string digits = "0123456789ABCDEF";
while (num > 0) {
result += digits[num % base];
num /= base;
}
reverse(result.begin(), result.end());
return result;
}
int main() {
string num = "FF";
int fromBaseValue = 16; // 시작 진법
int toBaseValue = 2; // 변환할 진법
int decimal = fromBase(num, fromBaseValue);
string binary = toBase(decimal, toBaseValue);
cout << num << " (16진수) → " << binary << " (2진수)" << endl;
return 0;
}
🔹유클리드 호제법
- 목적: 두 수 a와 b의 최대공약수(GCD)를 구함.
- 아이디어: a를 b로 나눈 나머지 r과 b의 최대공약수와 같음 즉, GCD(a,b)=GCD(b,r) 여기서 r=a%b
- 반복 조건: 나머지 r이 0이 될 때 b가 최대공약수
1. 알고리즘 단계:
- 두 수 a와 b를 나눈 나머지 r을 계산(r=a%b).
- a에 b, b에 r 대입
- b가 0이 될 때까지 반복
- b가 0이 되었을 때, 그 직전의 b 값이 최대공약수
2. 최대 공배수:
관계: LCM(a,b)와 GCD(a,b)의 관계
최대공약수를 먼저 구한 뒤 위 공식을 사용하면 최소공배수를 쉽게 계산 가능
#include <iostream>
using namespace std;
// 최대공약수(GCD)를 구하는 함수
int gcd(int a, int b) {
while (b != 0) {
int r = a % b; // a를 b로 나눈 나머지
a = b;
b = r;
}
return a; // 마지막에 b가 0이 되었을 때, a가 GCD
}
// 최소공배수(LCM)를 구하는 함수
int lcm(int a, int b) {
return (a * b) / gcd(a, b); // LCM 공식
}
int main() {
int a, b;
cout << "두 정수를 입력하세요: ";
cin >> a >> b;
cout << "최대공약수(GCD): " << gcd(a, b) << endl;
cout << "최소공배수(LCM): " << lcm(a, b) << endl;
return 0;
}
3. 유클리드 호제법의 시간복잡도
- 시간복잡도: O(log(min(a,b)))
- 나머지가 반복적으로 계산될 때 a와 b의 크기가 빠르게 줄어들기 때문
'TIL' 카테고리의 다른 글
[250107 TIL] 패턴 매칭, 문자열 검색, 치환 등의 작업에 유용한 regex (0) | 2025.01.07 |
---|---|
[250106 TIL] 정적/동적 배열과 벡터, 생성자와 소멸자에서 놓쳤던 부분 (0) | 2025.01.06 |
[250102 TIL] switch반복문에 열거형 입력 (0) | 2025.01.02 |
[241231 TIL] 언리얼 C++ 한글 폰트 깨짐 (1) | 2024.12.31 |
[241230 TIL] C++ 공부_객체 선언, 포인터와 참조 등 (0) | 2024.12.30 |