본문 바로가기

프로그래밍226

C ] TUI ARINC429 비행 고도/속도 송신 앱 (Text-based User Interface) 개발 배경 :콘솔 창에 그래픽 요소를 추가하여 사용자 친화적인 인터페이스를 구현한 형태를 TUI(Text-based UI) 또는 CUI(Console UI)라고 한다. 사용자로부터 키보드 입력을 받아 프로그램을 제어하고 데이터를 시각적으로 구분하기 위해 박스나 테두리를 활용하고 색상을 입혀 데이터를 강조한다.이런 TUI 앱을 언젠가 한번 만들어봐야지 하고 생각했었는데 마침 적당한 사례를 발견해서 업무상 굳이 필요는 없었지만 개인 시간을 들여 한번 만들어 봤다.  어플리케이션 설명 :이 어플리케이션은 대기 자료 컴퓨터(Air Data Computer)를 시뮬레이션하기 위한 도구로 비행고도(Altitude)와 비행속도(Airspeed) 정해진 주기로 송신하도록 제어할 수 있다. 현재 송신하고 있는 데이터를 .. 2025. 1. 7.
C] 콘솔 프로그램 플리커 현상 개선하기 (더블 버퍼링 & 오프스크린 버퍼) 콘솔 화면을 주기적으로 갱신하는 프로그램을 개발 시 화면이 깜빡이는 플리커(flicker) 현상이 발생할 수 있다. 이번 글에서는 이런 플리커 현상을 개선하기 위한 전략을 알아보자.  먼저 대략 60fps로 7세그먼트 형식의 디지털시계를 출력하는 C언어 프로그램을 작성해보았다. 프로그램을 실행시키면 아래 이미지 처럼 화면이 깜빡이면서 출력되는 것을 볼 수 있다.    플리커 현상의 원인은? 플리커 현상은 화면 갱신 과정에서 발생하는 중간 상태가 사용자에게 노출되면서 발생한다. 아래 코드를 보면 system("cls")를 사용해 화면을 완전히 지운 후, 초기화된 화면에 새로운 데이터를 출력하고 있다. 이 과정이 빠르게 반복되면서 빈 화면과 새 데이터를 그리는 중간 상태가 짧은 시간 동안 화면에 보여지게 되.. 2025. 1. 5.
inet_addr, inet_aton, inet_pton, inet_ntoa, inet_ntop 1. 문자열 형식의 IP 주소를 uint32_t 형식으로 변환하는 함수 :inet_addr, inet_aton, inet_pton  - inet_addr문자열 형식의 IPv4 주소를 uint32_t로 변환.반환된 값이 네트워크 바이트 순서로 저장됨.Deprecated(더 이상 권장되지 않으며, 향후 버전에서 제거될 가능성이 있으니 사용을 자제해야하는 함수) 이므로 최신 코드에서는 inet_aton 또는 inet_pton을 사용하는 것이 권장됨.#include #include #if defined(_WIN32) || defined(_WIN64)#pragma comment(lib,"ws2_32")#include #else#include #endifint main() { const char* ip_str = .. 2024. 12. 17.
C++ ] <random> 헤더 사용 난수 생성 C++ 헤더를 사용해 난수 생성하는 방법 1. 헤더 파일 포함#include    2. 시스템 기반 난수 시드 생성시스템에서 제공하는 하드웨어 기반 난수 시드를 가져온다.std::random_device rd;   3. 난수 생성 엔진 초기화시드를 사용해 난수 생성 엔진을 초기화한다. 보통은 Mersenne Twister 알고리즘을 사용한 std::mt19937 엔진을 많이 사용한다.std::mt19937 gen(rd()); // Mersenne Twister 엔진에 시드 할당   4. 분포 정의 (범위와 형식 설정)난수가 발생할 범위와 형식은 분포(distribution)를 통해 정의한다.  정수형 균등 분포, 범위 내의 모든 값이 동일한 확률로 선택된다.std::uniform_int_distribu.. 2024. 12. 3.
C++ ] CLI Loading indicator와 Progress bar 사용자에게 작업이 진행중임을 알리는 간단한 로딩 인디케이터와 프로그레스 바 만들어보기   로딩 인디케이터 #include #include using namespace std;bool running = true;void loading_indicator() { const char* states[] = {" ", ". ", ".. ", "... ", ".... ", "....."}; int index = 0; while (running) { cout      프로그레스 바 #include #include #include using namespace std;class ProgressBar {private: int barWidth; int progress;.. 2024. 10. 28.
C++ ] 가변 인자 템플릿(Variadic Templates) 활용 C++ 11에서 도입된 가변 인자 템플릿이란 함수가 불특정 다수의 여러 인자를 받을 수 있게 해주는 기능이다. 가변 인자 템플릿은 C의 stdarg.h에 있는 가변 인자 매크로들과 비슷한 역할을 한다고 볼 수 있는데 그 사용법에 있어서는 큰 차이가 있다. 이에 대해 한번 알아보자.   1. 템플릿(Templates)이란?템플릿은 C++에서 함수나 클래스를 정의할 때 그 타입을 일반화하여 코드 재사용성을 높이는 기능이다. 템플릿을 사용하면 특정 데이터 타입에 종속되지 않고, 다양한 타입에 대해 동일한 코드 구조를 사용할 수 있다. 템플릿을 선언할 때는 다음과 같은 구문을 사용한다. 여기서 T는 타입 매개변수로 함수나 클래스가 다양한 데이터 타입에 대해 동작하도록 일반화할 수 있게 해준다. template .. 2024. 9. 2.
Python ] os.path 모듈 파이썬의 표준 라이브러리인 os 모듈의 서브모듈인 os.path 모듈은 경로, 파일, 디렉토리에 관련된 유용한 함수들을 제공해준다.   os 모듈 import os.path 서브모듈을 사용하기 위해 os 모듈을 import 한다.import os   경로를 다룰 때 자주 사용하는 함수   os.path.join 플랫폼에 따라 올바른 경로 구분자를 사용해 여러 경로 조각을 결합해 하나의 경로를 생성한다.path = os.path.join("folder", "subfolder", "file.txt")print(path)# 리눅스에서 결과: "folder/subfolder/file.txt"# Windows에서 결과: "folder\subfolder\file.txt"    os.path.exist 주어진 경로가.. 2024. 8. 30.
PyInstaller ] 파이썬 스크립트(.py)를 실행파일(.exe)로 만들기 PyInstaller는 파이썬 스크립트를 파이썬 인터프리터가 설치되지 않은 환경에서도 실행이 가능하도록 실행 파일로 만들어 배포할 수 있게 해주는 패키지이다.      PyInstaller 설치 pip install pyinstaller    PyInstaller 기본 사용법 실행 파일로 만들려는 파이썬 스크립트를 지정하여 PyInstaller를 실행한다.pyinstaller example.py      PyInstaller로 생성되는 주요 폴더와 파일 project_root/├── example.py # PyInstaller로 패키징할 Python 스크립트├── build/ # 빌드 과정에서 생성된 임시 파일들│ └── ..... 2024. 8. 12.
winmm API 사용하여 WAV 파일 재생하기 winmm 은 Windows Multimedia의 약자로 해당 라이브러리의 API를 사용해 WAV 형식의 오디오 파일을 재생할 수 있다.  #include #include // mmsystem.h 포함#include // winmm.lib 링크#pragma comment(lib, "winmm.lib")int main() { // wav 파일 경로 const char* filePath = "C:\\Users\\jo\\Downloads\\warning.wav"; // wav 파일 동기식 재생 MMRESULT result = PlaySound(filePath, NULL, SND_FILENAME); if (!result) { printf("PlaySound Error\n"); return 1; } print.. 2024. 7. 4.
POSIX thread, mutex 사용법 Pthread는 모든 유닉스 계열 POSIX 시스템에서, 일반적으로 이용되는 라이브러리로 병렬적으로 작동하는 소프트웨어 작성을 위해 사용할 수 있다. 소스코드에선 #include 로 헤더를 포함하고 컴파일 시 -pthread 옵션을 붙여 컴파일 한다.   주요 thread 함수  pthread_create새로운 스레드를 생성하고 지정된 함수 start_routine을 실행한다.int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);pthread_t *thread: 생성된 스레드의 식별자를 저장할 포인터, 해당 식별자를 통해 이후 스레드를 제어할 수 있다.const .. 2024. 6. 26.
C] epoll 사용법 epoll이란?epoll은 리눅스 커널 2.5.44부터 도입된 Multiplexing IO 함수로 다수의 파일 디스크립터를 모니터링 할 때 효율적이다. epoll은 epoll_event 구조체와 다음의 세 가지 주요 함수로 구성된다.epoll_create : epoll 파일 디스크립터 저장소 생성epoll_ctl : 저장소에 파일 디스크립터 등록 및 삭제epoll_wait : 파일 디스크립터의 변화를 대기   select와의 차이점select의 경우 매번 호출할 때마다 파일 디스크립터 집합을 사용자 공간에서 커널 공간으로 복사해야 하지만 epoll는 한 번 설정한 파일 디스크립터 집합을 커널 공간에서 유지하여 불필요한 복사를 방지한다. 따라서 많은 수의 파일 디스크립터를 다룰 때 epoll이 더욱 효율적.. 2024. 6. 24.
C++ ] 문자열 탐색 및 조작 함수, find() 외 문자열 탐색 함수 find : 문자열/문자의 처음 등장 위치 찾기rfind : 문자열/문자의 마지막 등장 위치 찾기find_first_of : 문자 집합 중 하나라도 처음으로 등장하는 위치 찾기find_last_of : 문자 집합 중 하나라도 마지막으로 등장하는 위치 찾기find_first_not_of : 주어진 문자 집합에 없는 첫번째 문자 위치 find_last_not_of : 주어진 문자 집합에 없는 마지막 문자 위치 찾기 ✔️ 위의 문자열 탐색함수는 문자열 내에서 특정 조건을 만족하는 요소를 찾지 못했을 경우 string::npos를 반환한다. string::npos는 상수값으로 size_t 타입의 최대값이다.✔️ find와 rfind 함수는 주어진 문자열에서 특정 문자열 뿐만 아니라 단일 문자를.. 2024. 6. 11.
Tkinter ] Python GUI 프로그래밍 Tkinter는 파이썬 설치시 기본적으로 내장된 표준 라이브러리로 별도의 설치 없이 바로 GUI 개발을 시작할 수 있다는 장점이 있다.  Tkinter의 주요 구성 요소Tk 객체 : GUI 애플리케이션의 메인 윈도우를 생성하는 핵심 객체이다. Tk()를 통해 생성된다.위젯(Widgets) : 사용자 인터페이스를 통해 상호작용할 수 있도록 도와주는 각종 UI 요소이다.Label : 텍스트나 이미지를 표시한다.Button : 사용자가 누를 수 있는 버튼을 제공한다.Entry : 한 줄의 텍스트를 입력받는 입력 필드이다.Text : 여러 줄의 텍스트를 입력받는 필드이다.Frame : 다른 위젯들을 그룹핑하고 레이아웃을 관리하는 컨테이너이다.배치 관리자(Layout Managers) : 위젝을 윈도우 또는 프레.. 2024. 6. 9.
Pyside6 ] 개발 환경 설정 with VSCode pyside6 설치 pip install pyside6       VScode에서 Qt for Python 익스텐션 설치        test.py를 만들고 공식문서에서 제공한 코드를 복붙한 후 콘솔에서 python test.py로 실행한다. https://doc.qt.io/qtforpython-6/tutorials/basictutorial/widgets.htmlimport sysfrom PySide6.QtWidgets import QApplication, QLabelapp = QApplication(sys.argv)label = QLabel("Hello World!")label.show()app.exec()    한줄 씩 살펴보면 다음과 같다.# command line arguments에 접근하기 위해.. 2024. 6. 8.
Python ] 코드 실행 시간 ms 단위로 측정하기 + datetime 모듈 사용법 1. time 모듈 사용하기 import timestart_time = time.time()for i in range(1, 10000000): passend_time = time.time()elapsed_time = (end_time - start_time) * 1000print(f"start_time : {start_time}")print(f"end_time : {end_time}")print(f"elapsed_time : {elapsed_time} ms")  time 모듈은 아래와 같이 import하여 사용할 수 있고 현재시간을 초단위로 반환하는 time() 함수와 시간 지연을 생성하는 sleep() 함수가 많이 쓰인다.import time time 모듈에서 시간은 UNIX time을 기준으로 .. 2024. 6. 3.
Python 기본 문법 1. 파이썬의 특징  ✔️ 동적인 자료형 결정변수에 값이 할당되는 시점에 데이터 타입이 동적으로 결정됨a = 1b = 1.0c = 'hello'print(type(a))print(type(b))print(type(c))   ✔️ 자동 메모리 관리개발자가 직접 메모리를 관리할 필요 없고, 자료형의 범위 또한 필요에 따라 자동으로 확장되기 때문에 일반적으로 고려할 필요 없다.    ✔️ 체이닝체이닝은 특히 메서드나 연산자를 연속적으로 연결하는 것을 의미한다.# strip() 함수는 공백을 제거하거나 특정 문자 또는 문자열을 제거함result = " Hello, World! ".strip().lower().replace("hello", "hi").strip('!')print(result)# 논리 연산자 체이닝.. 2024. 6. 1.
C++ ] std::condition_variable 사용법 std::condition_variable은 C++에서 스레드 간의 동기화를 위해 사용되는 매커니즘 중 하나로, 한 스레드가 특정 조건이 충족될 때까지 대기하도록 하고, 다른 스레드가 그 조건을 충족시켰을 때 대기 중인 스레드를 깨우는 방식으로 사용한다. std::condition_variable은 주로 std::mutex와 함께 사용되며, 뮤텍스의 소유권을 관리하기 위해 std::unique_lock 클래스와 결합하여 사용된다. std::condition_variable 사용 패턴 스레드는 std::unique_lock를 사용하여 뮤텍스를 잠근다. 스레드는 std::condition_variable의 대기 함수(wait, wait_for, wait_until)를 호출하여 특정 조건이 충족될 때까지 대기.. 2024. 5. 12.
C++ ] std::unique_lock과 std::lock_guard의 차이 std::unique_lock과 std::lock_guard의 차이 std::unique_lock과 std::lock_guard 모두 스코프 기반의 락 관리를 제공한다. 객체가 스코프에 진입할 때 자원을 획득(락을 잠금)하고, 스코프를 벗어날 때 소멸자를 호출해 자동으로 자원을 해제(락을 해제)하는 방식이다. 사용자가 { }를 사용하여 직접 스코프를 지정하는 패턴으로 사용할 수도 있다. 둘의 차이점은 다음과 같다. std::lock_guard : 생성될 때 자동으로 락을 획득하고 소멸될 때 락을 해제한다. 도중에 수동으로 락을 잠그거나 풀 수 있는 기능을 제공하지 않는다. std::unique_lock : 생성될 때 자동으로 락을 획득하고 소멸될 때 락을 해제하며 lock(), unlock() 메소드를 .. 2024. 5. 4.
C++ ] std::unordered_map과 std::map의 차이, unordered_map의 사용법 std::unordered_map unordered_map은 STL에서 제공하는 해시 테이블 기반의 키-값 쌍을 저장하는 컨테이너로, 사용법은 map과 유사하지만 몇 가지 차이점이 있다.  내부 구현: map은 균형 이진 검색 트리(레드-블랙 트리)를 사용하여 요소를 저장한다.unordered_map은 해시 테이블을 사용하여 요소를 저장한다. 접근 시간: map에서 키-값 쌍에 접근하는 데 걸리는 시간은 O(log n)이다.unordered_map은 평균적으로 상수 시간 O(1)에 키-값 쌍에 접근할 수 있다. 단, 해시 충돌이 발생할 경우 최악의 경우 시간 복잡도는 O(n)에 수렴한다. 정렬: map은 키에 대해 unordered_map은 입력된 순서나 키에 대한 정렬을 유지하지 않고, 해시 함수의 결.. 2024. 4. 26.
C++ ] std::set 사용법 std::set STL에 포함되는 std::set은 중복이 없이 정렬된 데이터를 쉽게 관리할 수 있게 해주는 컨테이너로 내부적으로는 균형 이진 검색 트리(레드-블랙 트리)를 사용하여 요소를 저장한다. 가장 큰 특징은 중복을 허용하지 않으므로 모든 요소는 유일하며, 요소를 추가, 삭제, 검색할 때 std::set은 O(log n)을 보장한다. 1. set에 요소 추가하기 set에 요소를 추가할 때는 .insert() 메소드를 사용한다. 삽입 시도 시 중복 요소가 없으면 성공적으로 추가되고, 중복 요소가 있으면 추가되지 않는다. #include #include int main() { std::set mySet; // 요소 추가 mySet.insert(3); mySet.insert(1); mySet.inser.. 2024. 4. 22.
C++ ] std::iota 사용법 처음엔 itoa의 오타인 줄 알았다. std::iota는 헤더에 정의된 C++ 표준 라이브러리 함수로 배열이나 컨테이너에 연속적 숫자를 할당한다. 시작 반복자, 종료 반복자, 그리고 초기 값의 세 개의 매개변수를 받는다. #include #include std::vector v(10); std::iota(v.begin(), v.end(), 0); // v는 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}로 초기화됨 for 반복문을 사용해서 동일한 작업을 수행할 수 있다. 둘 다 O(n) 시간 복잡도를 가지며 유의미한 성능차이는 없을 것 같다. std::vector v(10); for(int i = 0; i < v.size(); ++i) { v[i] = i; } 2024. 4. 19.
__DATE__ 에서 필요한 정보를 추출하여 원하는 포맷으로 출력하기 __DATE__, __TIME__ 은 ANSI/ISO 표준으로 정의되고 C 컴파일러 전처리기가 제공하는 특수한 매크로로 소스파일이 컴파일 시점의 날짜와 시간 정보를 나타내는 문자열 리터럴이다. 보통 __TIME__ 의 경우는 우리가 자주 사용하는 형태와 동일하기 때문에 따로 손댈게 없다. 하지만 __DATE__ 의 경우 월, 일, 년도 순이고 월은 영문에 일은 한자리 수 인경우 앞이 공백이여서 그대로 쓰기엔 애매하다. 따라서 __DATE__를 원하는 형태의 formatted string으로 출력하기 위해 다음의 두가지 방법이 있다. 첫번째 방법 yyyy-mm-dd 로 출력하고자 하는 경우 해당 digit Character를 추출해서 조합하는 형태 #include #define BUILD_YEAR_CH0 .. 2024. 4. 17.
C++ ] leetCode 3005 - Count Elements With Maximum Frequency 리트코드 3005 문제 You are given an array nums consisting of positive integers. Return the total frequencies of elements in nums such that those elements all have the maximum frequency. The frequency of an element is the number of occurrences of that element in the array. Example 1: Input: nums = [1,2,2,3,1,4] Output: 4 Explanation: The elements 1 and 2 have a frequency of 2 which is the maximum frequ.. 2024. 4. 16.
C++ ] std::stack 사용법 C++의 std::stack은 STL(Standard Template Library)의 일부로 후입선출(LIFO: Last In, First Out) 방식을 따르는 자료구조이며 데이터의 삽입(push)과 삭제(pop)가 한 쪽 끝에서만 이루어지는 특징을 가지고 있다. 1. stack 헤더 파일 포함 #include 2. stack 객체 생성 std::stack myStack; 3. 요소 삽입 (push) myStack.push(10); 4. 요소 제거 (pop) myStack.pop(); 5. 최상위 요소 접근 (top) std::cout 2024. 3. 20.
C++ ] std::pair 사용법 C++에서 pair는 두 개의 값을 하나의 단위로 묶을 때 유용한 STL(Standard Template Library)의 일부이다. pair를 사용하면 문자열과 정수, 정수와 정수 등 다양한 데이터 타입의 두 값을 쌍으로 묶어 쉽게 관리할 수 있다. 1. std::pair 사용을 위한 헤더 포함 #include std::pair는 utility 헤더를 포함시키면 사용할 수 있지만 이미 vector나 map, algorithm 같이 자주쓰는 헤더에 utility 헤더가 포함되어 있기 때문에 별도로 utility 헤더를 포함시키지 않아도 쓸 수 있는 경우가 많다. 2. pair 생성하고 요소에 접근하기 #include #include #include using namespace std; int main().. 2024. 3. 1.
C++ ] std::sort 사용법 with 람다식 C++에서 제공하는 표준 라이브러리 함수 std::sort는 벡터, 리스트, 배열 등 다양한 컨테이너를 정렬하는 데 사용된다. 1. algorithm 헤더 포함 #include 2. std::sort 함수 원형 template void sort(RandomIt first, RandomIt last); template void sort(RandomIt first, RandomIt last, Compare comp); first: 정렬을 시작할 범위의 첫 번째 요소를 가리키는 반복자 last: 정렬을 종료할 범위의 마지막 다음 요소를 가리키는 반복자 comp: (optional) 정렬 기준을 제공하는 함수나 함수 객체로 람다식으로 표현될 수 있다 만약 비교함수 comp가 사용자에 의해 제공되지 않은 경우 기.. 2024. 2. 20.
C++ ] string -> char *, char * -> string 변환 C스타일 문자열 char *에서 string으로 변환하거나 반대로 변환하는 법 char * to string const char *pChar ="hello"; string str = pChar; 또는 string str(pChar); char *에서 string으로 바꾸는건 간단하다. = 연산자를 통해 초기화하거나 생성자를 통해 초기화하면 된다. sring to char * string str = "hello"; const char *pChar = str.c_str(); 또는 char buf[str.length() + 1]; strcpy(buf, str.c_str()); string에서 char *로 변환할 때는 string의 수명에 주의해야한다. 위의 변환 방법 중 첫번째 방법의 경우 string 변수.. 2024. 2. 18.
C++ 에서 구조체와 클래스의 차이 아래에서 보듯이 C++에서 구조체와 클래스는 사용방법과 기능이 매우 유사하다. C++의 구조체는 멤버함수를 추가할 수도 있으며, 명시적으로 생성자/소멸자를 추가할 수 있고 명시적으로 정의하지 않으면 수명주기에 따라 호출되는 기본 생성자/소멸자가 컴파일러에 의해 제공된다는 점이 클래스와 동일하다. 반면 구조체와 클래스의 주요 차이는 접근제어 지시자의 기본값이 다르다는 것이다. 접근제어 지시자를 따로 명시하지 않고 정의한 경우 구조체는 기본적으로 public 이고, 클래스는 기본적으로 private이다. #include using namespace std; struct Point { int x; int y; Point(int _x, int _y) : x(_x), y(_y) { cout 2024. 2. 14.
C++ ] 벡터의 최대값과 최소값 찾기, max_element, min_element C++에서는 헤더에 포함된 std::max_element와 std::min_element 함수를 사용하여 벡터의 최대값과 최소값을 찾을 수 있다. 리턴값은 가장 큰 또는 가장 작은 원소의 iterator이고 애스터리스크를 붙여 역참조해서 값을 가져올 수 있다. max_element 함수 사용 예시 #include #include #include int main() { std::vector numbers = {10, 5, 8, 3, 12, 7}; auto max_iterator = std::max_element(numbers.begin(), numbers.end()); int max_value = *max_iterator; std::cout 2024. 2. 10.
C언어 ] qsort (Quick Sort, 퀵정렬) 함수 사용법 C언어 표준 라이브러리에 포함된 qsort 함수는 퀵 정렬(Quick Sort) 알고리즘을 사용하여 배열을 정렬하는 데에 사용된다. 아래는 qsort 함수의 사용법에 대한 예시이다. 1. 헤더 파일 include qsort 함수를 사용하려면 stdlib.h 헤더 파일을 포함해야 한다. #include 2. 비교 함수 작성 qsort 함수를 사용하기 위해선 정렬을 위해 사용할 비교 함수를 만들어야 하며, 이 함수는 두 요소를 받아들여 비교한 결과를 반환해야 한다. 반환값이 음수, 0, 양수인지에 따라 정렬의 순서가 결정된다. 비교 함수의 반환값이 양수면, qsort 함수는 두 요소의 순서를 바꾼다. int compare(const void *a, const void *b) { // 비교 로직 작성 retu.. 2024. 1. 30.