C와 C++는 여러 면에서 매우 유사한 언어입니다. C++에는 객체 지향 기능이 추가되어 있지만, 대부분의 C 프로그램은 C++에서도 문제없이 컴파일되고 실행됩니다. 그런데 이번에 소개할 프로그램은 C에서는 정상적으로 동작하지만, C++에서는 컴파일 오류가 발생하는 흥미로운 사례입니다.예제 코드#include<stdio.h>void myFunction() { printf(Function called\n);}int main() { myFunc
이번 글에서는 n개의 요소를 저장하면서도 모든 연산이 O(1), 즉 상수 시간 안에 수행되는 데이터 구조를 살펴보겠습니다. 상수 시간이란 입력 크기와 무관하게 연산에 걸리는 시간이 항상 일정하다는 의미입니다.이 데이터 구조는 0부터 n-1까지 총 n개의 요소를 저장하며, 요소들은 어떤 순서로든 배치될 수 있습니다. 핵심은 삽입(insertion), 삭제(deletion), 탐색(searching) 세 가지 기본 연산이 모두 O(1) 시간 복잡도를 가진다는 점입니다.이 문제를 해결하는 방법은 의외로 간단합니다. 바로 부울(Boolea
C++에서는 16비트 문자 표현(char16_t)을 사용할 수 있습니다. c16rtomb() 함수는 이러한 16비트 문자 표현을 좁은(narrow) 멀티바이트 문자 표현으로 변환하는 역할을 합니다. 이 함수는 uchar.h 헤더 파일에 정의되어 있으며, C11 표준부터 도입되었습니다.c16rtomb() 함수의 매개변수c16rtomb() 함수는 총 세 개의 매개변수를 받습니다.대상 문자열(s): 변환된 멀티바이트 문자가 저장될 문자 배열입니다.16비트 문자(c16): 변환하고자 하는 char16_t 타입의 문자입니다.mbstate_t
C/C++의 c32rtomb() 함수란?C++에서는 char32_t 타입으로 표현되는 32비트 문자(UTF-32)를 다룰 수 있습니다. 이때 c32rtomb() 함수는 32비트 문자 표현을 좁은(narrow) 멀티바이트 문자 표현으로 변환하는 역할을 담당합니다. 이 함수는 uchar.h 헤더 파일에 선언되어 있으며, C11 표준부터 도입된 유니코드 변환 함수 중 하나입니다.c32rtomb() 함수의 매개변수이 함수는 다음과 같이 세 개의 매개변수를 받습니다.변환 결과를 저장할 버퍼 : 멀티바이트 문자가 저장될 문자 배열변환할 32비
이번 글에서는 흥미로운 알고리즘 문제를 하나 살펴보겠습니다. N개의 동전이 주어졌을 때, 이 동전들을 피라미드(삼각형) 형태로 쌓을 수 있는 최대 높이를 구하는 것이 목표입니다. 여기서 피라미드는 첫 번째 층에 동전 1개, 두 번째 층에 동전 2개, 세 번째 층에 동전 3개와 같은 방식으로 층마다 하나씩 동전이 늘어나는 구조입니다.위 그림에서 볼 수 있듯이, 높이 3짜리 피라미드를 만들려면 최소 6개의 동전(1+2+3=6)이 필요합니다. 마찬가지로 높이 4짜리 피라미드를 완성하려면 10개의 동전(1+2+3+4=10)이 있어야 합니다
이번 글에서는 아래 그림과 같은 삼각형 피라미드 형태의 구조물을 만들 때 필요한 성냥개비의 개수를 구하는 방법을 알아보겠습니다. 피라미드의 밑변 크기가 주어졌을 때, 전체에 필요한 성냥개비 수를 계산하는 것이 목표입니다.예를 들어 밑변 크기가 1이면 성냥개비 3개로 하나의 삼각형을 만들 수 있고, 밑변 크기가 2이면 9개, 밑변 크기가 3이면 18개의 성냥개비가 필요합니다.계산 공식이 문제는 다음과 같은 수식을 이용하면 간단하게 해결할 수 있습니다.밑변의 크기를 x라고 할 때, 필요한 성냥개비의 총 개수는 3 × x × (x + 1
배열의 인버전(Inversion)이란? 배열의 인버전(inversion, 역전)이란 해당 배열을 정렬된 상태로 만들기 위해 필요한 교환 횟수를 의미합니다. 이미 정렬된 배열의 인버전 개수는 0이며, 반대로 역순으로 정렬된 배열에서는 인버전 개수가 최대가 됩니다. 이 문제는 두 개의 반복문을 중첩해 모든 쌍을 비교하는 단순한 방식(O(n²))보다 병합 정렬(Merge Sort)을 활용하면 O(n log n)의 시간 복잡도로 해결할 수 있습니다. 이는 대표적인 분할 정복(Divide and Conquer) 알고리즘 방식입니다. 입력
이 글에서는 정수에 포함된 세트 비트(set bit)의 개수를 확인하는 방법을 알아보겠습니다. 세트 비트란 숫자를 이진수로 표현했을 때 값이 1인 비트를 의미합니다.예를 들어 숫자 13을 이진수로 표현하면 1101이 되며, 여기에는 세트 비트가 총 3개 있습니다. 따라서 이 숫자의 세트 비트 개수는 3이 됩니다.문제 해결 방식이 문제는 다음과 같은 방식으로 해결할 수 있습니다.숫자를 오른쪽으로 한 비트씩 시프트(shift)합니다.시프트하기 전 최하위 비트(LSb)가 1이라면 카운트를 증가시킵니다.숫자가 0이 될 때까지 위 과정을 반
이 글에서는 배열 안에서 홀수 번 등장하는 숫자를 찾는 방법을 알아보겠습니다. 이 문제를 해결하는 방법은 여러 가지가 있지만, 그중 가장 간단하고 효율적인 방법 중 하나가 바로 XOR(배타적 OR) 연산을 활용하는 것입니다.XOR 연산의 원리XOR 연산에는 다음과 같은 중요한 성질이 있습니다.같은 숫자를 서로 XOR하면 결과는 0이 됩니다. (예: 5 ^ 5 = 0)0과 어떤 숫자를 XOR하면 결과는 그 숫자 자신이 됩니다. (예: 0 ^ 5 = 5)따라서 배열의 모든 요소를 차례대로 XOR하면, 짝수 번 등장한 숫자들은 서로 상쇄
이번 글에서는 간단한 C 또는 C++ 코드를 작성하여 컴퓨터 시스템을 종료하는 방법을 알아보겠습니다. 시스템 종료 절차는 운영체제(OS)마다 조금씩 다르기 때문에, 리눅스와 윈도우 환경별로 각각 살펴보겠습니다.리눅스(Linux)에서 시스템 종료하기리눅스 사용자라면 터미널에서 다음 명령어를 입력하여 시스템을 즉시 종료할 수 있습니다.shutdown -P now여기서 -P 옵션은 전원을 끄는(power off) 동작을 의미하며, now는 지체 없이 바로 실행하라는 뜻입니다.윈도우(Windows)에서 시스템 종료하기윈도우 시스템을 사용하
정수 배열이 주어졌을 때, 배열 내에서 연속된 요소들의 합 중 가장 큰 값을 찾아 출력하는 문제입니다. 이 문제는 흔히 최대 부분 배열 합(Maximum Subarray Sum) 문제라고 불리며, 동적 계획법(Dynamic Programming)을 활용하면 효율적으로 해결할 수 있습니다.접근 방식동적 계획법의 핵심 아이디어는 다음과 같습니다.현재 위치까지의 최대 합(currentMax)을 저장합니다.각 요소를 순회하면서 현재 요소만 선택하는 경우와 이전까지의 합에 현재 요소를 더하는 경우 중 더 큰 값을 currentMax로 갱신합
이 글에서는 두 수의 최대공약수(GCD)를 구하는 유클리드 호제법(Euclidean Algorithm)에 대해 알아보겠습니다. 최대공약수(Greatest Common Divisor)란 두 수를 모두 나누어 떨어지게 하는 가장 큰 정수를 의미하며, 유클리드 호제법을 활용하면 이 값을 매우 간단하고 효율적으로 구할 수 있습니다.구현 방식은 크게 두 가지가 있습니다. 하나는 반복문(loop)을 사용하는 방식이고, 다른 하나는 재귀 호출(recursion)을 사용하는 방식입니다. 여기서는 코드가 더 간결한 재귀 방식의 유클리드 알고리즘을
문제 소개 계란 던지기(Egg Dropping) 퍼즐은 컴퓨터 과학에서 가장 유명한 동적 계획법(Dynamic Programming) 문제 중 하나입니다. n층으로 된 건물과 m개의 계란이 주어졌을 때, 계란을 떨어뜨려도 깨지지 않는 안전한 층을 찾기 위해 필요한 최소 드롭 횟수를 구하는 것이 목표입니다. 풀이 전에 알아둬야 할 핵심 조건 특정 층에서 계란이 깨지지 않았다면, 그보다 낮은 어떤 층에서도 깨지지 않습니다. 특정 층에서 계란이 깨졌다면, 그보다 높은 모든 층에서도 반드시 깨집니다. 깨진 계란은 폐기해야 하며, 깨지지
매크로의 한계: 타입 검사 기능 부재C나 C++에서 매크로(Macro)는 매우 유용하게 활용되지만, 가장 큰 단점 중 하나는 타입 검사(type checking) 기능이 없다는 점입니다. 매크로는 전처리기 단계에서 단순한 텍스트 치환만 수행하기 때문에, 어떤 타입의 인수가 전달되더라도 그대로 코드에 삽입됩니다. 아래 예제를 통해 이 문제를 명확히 확인할 수 있습니다.예제#include<stdio.h> #define INCREMENT(X) ++X main() { int x = 5;
C와 C++에는 함수의 특성(property)을 컴파일러에게 알려주는 함수 지정자(function specifier)가 존재합니다. 함수 지정자를 활용하면 컴파일러가 코드를 최적화하거나, 함수의 동작 방식에 대한 중요한 단서를 얻을 수 있습니다.주요 함수 지정자의 종류C++에서는 대표적으로 inline 함수 지정자를 사용합니다. 이는 컴파일러에게 함수 호출 오버헤드를 줄이기 위해 함수 본문을 호출 지점에 직접 삽입하도록 힌트를 주는 역할을 합니다.반면 C 언어(C11 표준부터)에는 _Noreturn 함수 지정자가 도입되었습니다. 이
개요이 글에서는 역추적(Backtracking) 기법을 활용하여 n비트 그레이 코드(Gray Code)를 생성하는 방법을 살펴봅니다.n비트 그레이 코드는 0부터 2n − 1까지의 비트 패턴으로, 인접한 두 패턴 사이에 단 하나의 비트만 차이가 나는 것이 특징입니다. 예를 들어 n = 2인 경우 그레이 코드는 (00, 01, 11, 10)이며, 이를 십진수로 변환하면 (0, 1, 3, 2)가 됩니다. 아래에서 구현할 프로그램은 각 그레이 코드에 해당하는 십진수 값을 출력합니다.알고리즘generateGray(arr, n, num)재귀
이번 글에서는 흥미로운 배열 문제 하나를 살펴보겠습니다. 배열에 n개의 원소가 주어졌을 때, 각 원소가 자신의 앞 또는 뒤에 있는 원소의 개수를 나타내도록 배열을 재배치(순열)할 수 있는지 확인하는 것이 목표입니다.예를 들어 배열이 {2, 1, 3, 3}이라고 가정해 보겠습니다. 이 경우 적절한 순열은 {3, 1, 2, 3}입니다.· 첫 번째 3 → 자신 뒤에 세 개의 원소가 있음을 의미· 1 → 자신 앞에 한 개의 원소가 있음을 의미· 2 → 자신 앞에 두 개의 원소가 있음을 의미· 마지막 3 → 자신 앞에 세 개의 원소가 있음을
이진 탐색(binary search) 알고리즘이 선형 탐색(linear search)보다 뛰어나다는 것은 잘 알려진 사실입니다. O(log n)의 시간 복잡도 덕분에 방대한 데이터 속에서도 빠르게 원소를 찾아낼 수 있죠. 그런데 의외로 실무에서 작성되는 많은 이진 탐색 코드에는 치명적인 결함이 숨어 있습니다. 문제가 있는 이진 탐색 구현 int binarySearch(int array[], int start, int end, int key){ if(start <= end){ &nb
이번 글에서는 두 문자열이 서로 회전(rotation) 관계에 있는지 판별하는 프로그램을 살펴보겠습니다.문자열의 회전이란 다음과 같은 개념입니다. 예를 들어 S1 = HELLO, S2 = LOHEL이라는 두 문자열이 있다고 가정해 봅시다. HELLO를 왼쪽으로 3칸 회전시키면 LOHEL이 되므로, 이 두 문자열은 서로 회전 관계라고 할 수 있습니다.해결 아이디어이 문제는 의외로 간단하게 해결할 수 있습니다. 첫 번째 문자열을 자기 자신과 한 번 더 연결(concatenate)한 뒤, 그 결과 문자열 안에 두 번째 문자열이 포함되어
이번 글에서는 선택 정렬(Selection Sort)을 개선한 양방향 선택 정렬(Two-Way Selection Sort) 알고리즘을 살펴보겠습니다. 기존의 선택 정렬은 배열에서 최솟값 또는 최댓값 하나를 찾아 올바른 위치에 배치하는 방식으로 동작합니다. 반면 이 개선된 방식은 한 번의 순회로 최댓값과 최솟값을 동시에 찾아내고, 배열의 양쪽 끝에서부터 동시에 정렬을 진행합니다. 알고리즘을 단계별로 확인하며 더 자세히 이해해 보겠습니다.알고리즘twoWaySelectionSort(arr, n)시작 i := 0, j