1. 간결하게
- 예를 들어 정렬되지 않은 정수 배열에 중복 원소가 존재하는지 하는 함수가 있다고 하자
bool hasDuplicate(const vector<int>& array) {
for(int i = 0; i < array.size(); ++i)
for(int j = 0; j < i; ++j)
if(array[i] == array[j])
return true;
return false;
}
- 매크로를 사용하여 다음과 같이 코드 변경 가능
#define FOR(i, n) for(int i = 0; i < (n); ++i)
bool hasDuplicate(const vector<int>& array) {
FOR(i, array.size())
FOR(j, i)
if(array[i] == array[j])
return true;
return false;
}
2. 전역 변수 X
=> 프로그램 흐름 파악 어려움
3. 적극적으로 코드 재사용
=> 반복되는 기능이라면 함수나 클래스로 분리해 사용
4. 표준 라이브러리 사용
=> queue, stack, algorithm, vector, map 과 같은 표준 라이브러리 적극 활용
5. 일관적이고 명료한 명명법 사용
=> bool judge(int y, int x) 보다
bool isInsideCircle(int y, int x) 와 같이 작성
6. 코드와 데이터를 분리하기
ex)
string getMonthName(int month) {
if(month == 1) return "January";
if(month == 2) return "February";
} ... (X)
const string monthName[] = { "January", "February", ... } 와 같이 작성
x, y 좌표 이동하는 경우
const int moveX = { 1, 1, -1, -1}
const int moveY = { 1, -1, 1, -1}
와 같이 작성
7. 일관된 범위 표현 방식 사용
=> 대부분 반 열린 구간 사용 [a, b) (a <= n < b)
- 위와같이 사용 시 두 구간이 연속해 있는지 확인하기 쉬움
ex) [a, b) , [c, d) 두 구간이 연속해있는지 보려면 b == c 인지 또는 a == d인지만 확인하면 됨
구간의 크기도 b - a로 찾기 쉬움
8. Off-by-one 오류
=> 하나가 모자라거나 하나가 더 많은 경우
ex) 100미터 담장에 10미터 간격으로 울타리 기둥 세우기는
기둥이 10개가 아니라 11개 필요함에 유의
9. 오버플로 피해가기
ex) lcm(a, b) = a x b / (gcd(a, b) 이다.
코드로 옮기면
ex)
int gdc(int a, int b);
int lcm(int a , int b ) {
return (a * b) / gcd(a , b);
}
인데 a, b가 50000, 100000 일 경우 인간은 답을 구하기 쉽지만,
만약 a, b 가 int 형일 경우 32비트를 넘어 오류가 난다.
그러니 해당 수식에서 a와 b중 하나를 64비트 정수형으로 캐스팅 해주거나
ex)
int lcm(int a , int b ) {
return (a * (long long) b) / gcd(a , b);
}
곱셈 순서를 바꿔보자. b는 gcd(a, b)로 무조건 나누어 지므로 b / gcd(a, b)연산을 먼저 하면
비트수로 인한 오버플로우를 막을 수 있다.
ex)
int lcm(int a , int b ) {
return (a * (b / gcd(a , b);
}
10. 자료형의 프로모션
=> 사칙연산, 비교 등은 보통 두 개의 피연산자를 받는데
만약 피연산자들의 자료형이다르거나 자료형의 범위가 너무 작은 경우,
컴파일러가 이들을 같은 자료형으로 변환하여 계산한다.
이를 프로모션이라고 한다.
ex)
bool isSorted(const vector<int>& seq) {
for(int i = 0; i < seq.size()-1; ++i)
if(seq[i] > seq[i+1])
return false;
return true;
}
위의 코드인 경우 문제가 없어 보이지만 seq.size()는 unsigned int(size_t)를 반환한다.
프로모션 규칙에 의해 seq.size()-1이 size_t로 강제 변환되면
2^32 - 1 값으로 자동 변환 되기 때문에 에러가 발생한다.
이를 막기 위해 seq[]가 비어있는 경우를 처음에 예외처리 해주거나,
seq.size()를 int 형으로 변환하거나
i를 1부터 시작하도록 바꿔야 한다.
'ETC' 카테고리의 다른 글
화면보호기 방지 (0) | 2024.04.26 |
---|---|
Smilegate Unsmile AI 사용법 (0) | 2023.05.08 |
유용한 VSCode Extension 및 hot key (0) | 2022.07.08 |
코드 최적화 팁 [c++] (0) | 2022.06.29 |