RSA(Rivest–Shamir–Adleman)는 공개 키(Public Key)와 개인 키(Private Key), 두 개의 키를 사용하는 대표적인 비대칭 암호화 알고리즘입니다. 공개 키로 암호화한 데이터는 짝이 되는 개인 키로만 복호화할 수 있기 때문에, 네트워크를 통해 안전하게 정보를 주고받아야 하는 환경에서 널리 활용됩니다. 이번 글에서는 RSA 알고리즘의 동작 원리를 단계별로 살펴보고, 이를 C++로 구현한 예제 코드와 실제 실행 결과까지 함께 확인해 보겠습니다. RSA 알고리즘의 동작 단계 시작 1. 두 개의 소수
힐 암호(Hill Cipher)는 선형대수학(linear algebra)에 기반한 다중 문자 치환 암호(polygraphic substitution cipher)입니다. 1929년 Lester S. Hill이 고안한 이 암호는 평문과 키를 행렬 형태로 변환한 뒤 행렬 곱셈과 모듈러 연산을 통해 암호화·복호화를 수행하는 것이 특징입니다.힐 암호의 동작 원리암호화(Encryption)키 문자열과 메시지 문자열을 각각 행렬 형태로 변환합니다. 두 행렬을 곱한 결과에 모듈로 26(알파벳 개수)을 적용하면 암호문이 생성됩니다. 이때 복호화를
비제네르 암호(Vigenère Cipher)는 알파벳 텍스트를 암호화하는 다중 치환(polyalphabetic substitution) 방식의 암호 기법입니다. 이 방식에서는 A부터 Z까지의 알파벳을 26개의 행으로 배열한 비제네르 암호표(Vigenère Cipher Table)를 사용하여 암호화와 복호화를 수행합니다.암호화(Encryption)키(Key): WELCOME평문(Message): Thisistutorialspoint먼저 주어진 키를 반복하여 그 길이가 원래 메시지의 길이와 같아질 때까지 확장합니다.암호화할 때는 메시지
아핀 암호(Affine Cipher)는 알파벳의 각 문자를 숫자 값에 매핑하는 단일 치환 암호(monoalphabetic substitution cipher)의 한 종류입니다. 암호화는 간단한 수학 함수를 통해 이루어지며, 그 결과는 다시 문자로 변환됩니다. 아핀 암호에서는 크기가 m인 알파벳의 문자들이 먼저 0부터 m-1까지의 정수 범위에 매핑됩니다. 아핀 암호의 키(key)는 a와 b라는 두 개의 숫자로 구성되며, 이때 a는 반드시 m과 서로소(relatively prime) 관계여야 합니다. 암호화(Encryption) 암호
카데인 알고리즘(Kadanes Algorithm)은 정수 배열에서 최대 부분 배열 합(maximum subarray sum)을 효율적으로 찾기 위한 대표적인 동적 계획법(Dynamic Programming) 기반 알고리즘입니다. 연속된 요소들의 합이 가장 커지는 구간을 O(n)의 시간 복잡도로 한 번의 순회만으로 구할 수 있다는 점이 큰 장점입니다.이 글에서는 카데인 알고리즘의 동작 원리를 살펴보고, 이를 구현한 C++ 프로그램을 예제와 함께 소개하겠습니다.알고리즘 동작 원리카데인 알고리즘은 두 개의 변수를 유지하며 배열을 한 번만
이 글에서는 여러 개의 문자열(시퀀스) 집합이 주어졌을 때, 모든 시퀀스에 공통적으로 포함되는 가장 긴 부분 시퀀스를 찾는 C++ 프로그램을 소개합니다. 이 문제는 널리 알려진 최장 공통 접두사(Longest Common Prefix) 문제와 본질적으로 같으며, 첫 번째 문자열을 기준으로 삼아 나머지 문자열들과 순서대로 비교하면서 공통된 앞부분을 점차 좁혀 가는 방식으로 해결할 수 있습니다. 알고리즘 시작 문자열 배열을 입력받는다. 함수 matchedPrefixtill(): 두 문자열 s1과 s2 사이의 일치하는 접두사를 찾는다
이 글에서는 두 개 이상의 시퀀스(문자열)를 부분 시퀀스(subsequence) 형태로 모두 포함하면서 길이가 가장 짧은 최단 슈퍼 시퀀스(Shortest Supersequence)를 찾는 C++ 프로그램을 살펴봅니다.최단 슈퍼 시퀀스란?최단 슈퍼 시퀀스란 주어진 두 문자열 A와 B를 각각 부분 시퀀스로서 모두 포함하는 문자열 중 길이가 가장 짧은 것을 말합니다. 이 문제는 최장 공통 부분 시퀀스(LCS)와 밀접한 관련이 있으며, 최단 슈퍼 시퀀스의 길이는 a + b - LCS(A, B)로 계산할 수 있습니다. 아래에서는 동적 계획
이 글에서는 여러 개의 문자열로 이루어진 집합에서 모든 문자열에 공통으로 나타나는 가장 긴 접두사(Longest Common Prefix)를 찾는 C++ 프로그램을 살펴보겠습니다. 이 기법은 파일 경로 비교, 자동완성 기능 구현 등 다양한 분야에서 활용될 수 있습니다.알고리즘핵심 아이디어는 간단합니다. 첫 번째 문자열을 기준 접두사로 설정한 뒤, 나머지 문자열들과 하나씩 비교하면서 공통 부분만 남기는 방식입니다.Begin Take the array of strings as input. function matchedPrefixtill
이 글에서는 하나의 단어(문자열)를 여러 조각으로 나누되, 모든 조각이 회문(Palindrome)이 되도록 분할하는 방법이 총 몇 가지인지 구하는 C++ 프로그램을 살펴봅니다. 회문이란 앞에서 읽으나 뒤에서 읽으나 동일한 문자열을 뜻합니다. 예컨대 tut, o, a처럼 짧은 문자열도 회문에 해당합니다. 재귀 호출과 백트래킹을 활용하면 주어진 문자열에서 가능한 모든 회문 분할 조합을 체계적으로 탐색할 수 있습니다. 알고리즘 단어를 입력으로 받습니다. partitionadd 함수는 현재 위치(index)부터 한 글자씩 이어 붙여 임
이 글에서는 트라이(Trie) 자료구조를 구현하는 C++ 프로그램을 살펴봅니다. 트라이는 트리 기반의 자료구조로, 대량의 문자열 데이터 집합에서 특정 키(key)를 매우 효율적으로 검색하기 위해 사용됩니다. 트라이는 문자열을 한 글자씩 노드로 연결해 저장하며, 각 노드는 알파벳(A~Z) 개수만큼의 자식 포인터를 가질 수 있습니다. 이러한 구조 덕분에 검색 시간은 키의 길이에 비례하여 O(L)(L은 키의 길이)로 매우 빠릅니다. 사전(단어장), 자동완성, 접두사 검색 등에 널리 활용됩니다. 주요 함수와 의사 코드 트라이 구현에는
qsort() 함수란?C 언어에서는 stdlib.h 헤더 파일을 통해 qsort() 함수를 제공합니다. 이 함수는 퀵 정렬(quicksort) 알고리즘을 기반으로 배열을 정렬하며, 정수 배열은 물론 구조체 배열 등 어떤 타입의 배열이든 정렬할 수 있도록 범용적으로 설계되었습니다.qsort()를 사용하려면 반드시 비교 함수(comparator)를 함께 전달해야 합니다. 비교 함수는 두 개의 인자를 받아 두 요소 사이의 상대적인 순서를 판단하는 역할을 합니다. 이때 두 인자는 모두 포인터이며, const void* 타입으로 형 변환되어
C나 C++로 프로그래밍을 하다 보면 다양한 종류의 오류(error)와 마주하게 됩니다. 이러한 오류는 크게 다섯 가지 유형으로 분류할 수 있습니다.구문 오류(Syntax Error)런타임 오류(Run-Time Error)링커 오류(Linker Error)논리 오류(Logical Error)의미 오류(Semantic Error)지금부터 각 오류 유형이 언제 발생하고 어떻게 해결해야 하는지 하나씩 자세히 살펴보겠습니다.1. 구문 오류 (Syntax Error)구문 오류는 C++ 작성 규칙이나 문법(syntax)을 위반했을 때 발생합니
개요getopt()는 C 프로그램에서 명령줄 옵션(command line options)을 손쉽게 처리할 수 있도록 해주는 표준 라이브러리 함수입니다. unistd.h 헤더에 선언되어 있으며, 프로그램 실행 시 전달된 인수 중에서 하이픈(-)으로 시작하는 옵션 플래그를 하나씩 순서대로 읽어 들입니다.함수의 기본 구문은 다음과 같습니다.getopt(int argc, char *const argv[], const char *optstring)여기서 argc와 argv는 main() 함수가 받은 인수 개수와 인수 배열이며, optstri
mbrtowc() 함수는 C/C++에서 멀티바이트(multibyte) 문자 시퀀스를 와이드 문자(wide character)로 변환하는 데 사용되는 표준 라이브러리 함수입니다. 함수 이름에서 알 수 있듯이 multibyte restartable to wide character의 약자로, 변환 상태(conversion state)를 유지하면서 멀티바이트 문자열을 하나씩 안전하게 해석할 수 있다는 특징이 있습니다.이 함수는 성공적으로 변환된 멀티바이트 문자가 차지하는 바이트 수를 반환합니다. 기본 문법은 다음과 같습니다.mbrtowc
세그멘테이션 오류(Segmentation Fault)는 대표적인 런타임 오류 중 하나로, 잘못된 메모리 접근으로 인해 발생합니다. 예를 들어 유효하지 않은 배열 인덱스에 접근하거나, 접근이 제한된 메모리 주소를 포인터가 가리키는 경우 등이 대표적입니다. 이 글에서는 GDB(GNU Debugger) 도구를 사용해 이러한 오류의 발생 위치를 효과적으로 찾아내는 방법을 알아보겠습니다.오류가 발생하는 코드 예제먼저 의도적으로 세그멘테이션 오류를 일으키는 간단한 코드를 살펴봅시다.#include <stdio.h> main() {
C/C++에서 코드의 실행 시간을 아주 정밀하게 측정해야 할 때가 있습니다. 이럴 때 유용한 것이 바로 C++11부터 표준에 포함된 chrono 라이브러리입니다.chrono 라이브러리란?chrono는 시간 관련 기능을 다루는 C++ 표준 라이브러리로, 그중 high_resolution_clock은 운영체제가 제공하는 가장 높은 해상도의 클럭입니다. 이 클럭은 나노초(nanosecond) 단위까지 측정할 수 있어, 짧은 코드 구간의 성능을 분석하는 데 적합합니다.측정 원리측정 방식은 간단합니다. 측정하려는 코드가 시작되기 직전에 현재
C 언어에서 지정된 범위 내의 난수를 생성하는 방법을 알아보겠습니다. 이 문제를 해결하기 위해 srand() 함수를 사용하며, 현재 시간을 시드(seed) 값으로 활용합니다.rand() 함수는 임의의 범위를 지정할 수 없고 0부터 특정 값 사이의 숫자만 생성한다는 한계가 있습니다. 따라서 간단한 트릭이 필요합니다. 먼저 0부터 (상한값 − 하한값 + 1) 사이의 난수를 생성한 뒤, 하한값을 더해 오프셋(offset)을 적용하면 원하는 범위의 난수를 얻을 수 있습니다.예제 코드#include <stdio.h> #includ
C++11에서 람다(lambda)가 처음 도입되었습니다. 람다는 다른 함수 호출문 안에 중첩하여 작성할 수 있는 코드 조각으로, auto 키워드와 함께 사용하면 변수에 저장해 두었다가 나중에 재사용할 수 있습니다.C++14에서는 이러한 람다 표현식이 한층 발전하여 일반화된 람다(generalized lambda)를 지원하게 되었습니다. 예를 들어, 하나의 람다로 정수 덧셈, 실수 덧셈, 심지어 문자열 연결까지 모두 처리하고 싶다면 일반화된 람다를 활용해야 합니다.일반화된 람다의 문법일반화된 람다 표현식의 기본 문법은 다음과 같습니다
이번 글에서는 C 언어로 자기 파괴 코드(self-destructing code)를 만드는 방법을 살펴보겠습니다. 자기 파괴 코드란 프로그램을 실행한 뒤, 실행이 끝나면 자신의 실행 파일을 스스로 삭제하는 코드를 말합니다.구현 자체는 매우 간단합니다. 파일을 삭제하려면 우선 실행 파일의 이름을 알아내야 하는데, 이는 명령줄 인자(command line arguments)를 통해 얻을 수 있습니다. 배열 argv[0]에는 항상 실행 파일의 이름이 저장되므로, 표준 라이브러리의 remove() 함수에 이 값을 넘겨주면 해당 파일을 손쉽
세마포어란 무엇인가? 세마포어(Semaphore)는 여러 프로세스나 스레드가 공유 자원에 동시에 접근하지 못하도록 제어하는 동기화(Synchronization) 도구입니다. 운영체제에서 매우 중요한 개념이며, 실제 프로그램에서 어떻게 활용되는지 이번 글에서 살펴보겠습니다. POSIX 세마포어 준비하기 리눅스 시스템에서는 POSIX 세마포어 라이브러리를 기본으로 제공합니다. 이를 사용하려면 소스 코드에 semaphore.h 헤더 파일을 포함해야 하며, 컴파일할 때 아래와 같이 -lpthread와 -lrt 옵션을 함께 지정해야 합니다