본문 바로가기

프로그래밍226

C++ ] .ini 파일 포맷, 설정 파일 입출력 방법 .ini 파일 포맷 .ini 파일은 텍스트 파일로 주로 설정 데이터를 저장하는 데 사용된다. 그리고 각 설정은 섹션과 키-값 쌍으로 구성된다. [섹션] 키=값 [Database] ServerName=MyServer Port=5432 [User] Username=JohnDoe Password=Secret123 아래 소개할 함수들은 Windows API의 일부로 Windows.h를 포함해야 사용할 수 있으며, 설정 파일에서 구성 데이터를 읽어올 때나, 설정파일에 구성 데이터를 쓸 때 사용할 수 있다. GetPrivateProfileInt 섹션과 키를 사용하여 .INI 파일에서 설정 값을 찾으며, 설정 값을 정수(INT) 형태로 반환한다. 만약 해당 섹션이나 키를 찾지 못하면 기본값으로 설정된 nDefault.. 2023. 9. 27.
C++ ] 람다식 사용법 및 람다식으로 콜백 구현 람다식(lambda expression)을 사용하면 코드 내에서 명시적인 함수 정의 없이도 익명함수를 생성하고 사용할 수 있게 해준다. 이런 함수는 주로 한번만 사용하거나 특정 상황에서만 필요한 경우 유용하다. 람다식의 기본 구조 [캡처](매개변수) -> 반환형 { // 람다 함수 본문 // ... } [캡처] { // 람다 함수 본문 // ... } 1. [캡처] : 외부 변수를 사용하기 위해 외부 범위의 변수를 캡처할 수 있다. [ ] 안에 캡처할 변수를 지정한다. [] : 아무것도 캡처하지 않음 [변수] : 특정 변수를 값 복사로 캡처 [&변수] : 특정 변수를 레퍼런스로 캡처 [=] : 모든 외부 변수를 값 복사로 캡처 [&] : 모든 외부 변수를 레퍼런스로 캡처 2. (매개변수) : 람다 함수의.. 2023. 9. 26.
C++ ] std::thread 스레드 사용법 스레드 라이브러리 스레드를 사용하는 주요 목적은 병렬 프로그래밍을 통해 여러 작업을 동시에 실행시켜 프로그램의 효율성을 높이는 것이다. 예전에는 멀티스레드 프로그래밍을 하기 위해서든 윈도우의 경우 Win32 API를 사용하거나, 리눅스는 POSIX thread (pthread) API를 사용하었는데 C++ 11부터는 C++ 표준 라이브러리에서 스레드를 지원되기 때문에 헤더를 포함하고 std::thread 클래스를 사용하면 된다. 1. 기본 사용법 std::thread 생성자는 스레드가 시작될 때 실행할 함수를 인자로 받는다. 이 때 함수는 글로벌 함수, 멤버 함수, 람다 표현식 등 다양한 형태일 수 있는데 하나씩 살펴보자. 1.1 글로벌 함수 전달하기 #include #include using names.. 2023. 9. 25.
C++ ] 가변인자 받아서 string 또는 CString으로 출력하기 가변인자 받아서 string으로 출력하기 vsnprintf() 함수는 실제로 버퍼에 출력하지 않고도 필요한 버퍼 크기를 계산할 수 있으므로 char[] 를 사용하지 않고 string 자체의 내부 버퍼를 사용할 수 있다. vsnprintf()실제로 버퍼에 출력하지 않고도 필요한 버퍼 크기를 계산할 수 있으므로 일반적으로char[] 별도의 버퍼가 전혀 필요하지 않고 크기를 계산 std::string하고 해당 크기에 할당한 다음 std::string출력을 위해 의 자체 내부 버퍼를 사용하면 됩니다. , 예: string vString(const char* format, ...) { string line; va_list args; va_start(args, format); int len = vsnprintf(n.. 2023. 9. 24.
C++ ] std::map 자료구조 사용법 map은 키-값 쌍을 저장하고 검색하는 데 사용되는 자료구조 중 하나로 사용법은 아래와 같다. 1. map 헤더파일 포함 #include 2. map 객체 생성하기 생성시 키와 값의 자료형을 지정해야하는데 개인적으로는 문자열 키와 함수포인터 값을 가지는 map을 자주사용한다. map myMap; 3. 원소 추가하기 (insert) 원소를 추가할 때는 키-값 쌍을 pair 객체로 전달하여 추가하는데 insert 함수를 사용하는 방법도 있고 아래의 4번을 사용하는 방법도 있다. 각 키는 고유해야 하며, 각 키에 대응하는 값이 하나씩 존재하게 된다. pair 객체를 만들때는 pair로 생성하거나 make_pair 함수를 사용해도 되고 혹은 {} 중괄호를 사용하는 방법도 있다. 또한 map는 중복을 허용하지 않.. 2023. 9. 23.
C++ ] 레지스트리 등록하여 윈도우 시작시 앱 자동 실행 하기 레지스트리 등록하여 윈도우 시작시 앱 자동 실행 하기 HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run HKEY_CURRENT_USER를 사용하면 현재 로그인한 사용자의 시작 프로그램으로 등록하고, HKEY_LOCAL_MACHINE을 사용하면 모든 사용자에게 적용된다. 위 경로에서 "새 문자열 값"을 선택하고 값 이름은 프로그램을 식별할 만한 이름으로 지정하고, 값 데이터에는 실행할 프로그램의 경로를 입력하면 윈도우 부팅 시 등록한 프로그램이 자동실행된다. // 실행파일의 경로 알아내기 wchar_t exePath[MAX_PA.. 2023. 9. 22.
Windows 프로그래밍 시 OutputDebugString 사용해 디버깅 정보 출력하기 + 가변인자 받아서 디버깅 정보 출력 OutputDebugString은 Windows 프로그래밍 환경에서 디버깅 세션에 디버깅 정보를 출력하는데 사용되는 함수이다. 이 함수는 프로젝트 문자집합 설정이 멀티바이트냐 유니코드냐에 따라 OutputDebugStringW 또는 OutputDebugStringA로 정의된다. #ifdef UNICODE #define OutputDebugString OutputDebugStringW #else #define OutputDebugString OutputDebugStringA #endif // !UNICODE 먼저 Windows.h 를 포함하고 OutputDebugString 함수를 호출해 디버깅 세션에 출력할 문자열을 넘긴다. ANSI 문자열을 사용하는 경우 그냥 출력하면 되고 유니코드 문자열을 출력할 땐.. 2023. 9. 21.
C++ ] 현재 실행중인 실행파일의 경로 얻기, GetModuleFileName 현재 작업 디렉토리의 경로는 GetCurrentDirectory 함수로 확인할 수 있다. 한편 실행파일이 위치한 경로의 경우 운영체제에 따라 확인하는 방법이 다른데 윈도우에서는 Windows.h 를 포함하고 GetModuleFileName() 함수를 사용하면 현재 실행중인 실행파일의 path를 알 수있다. GetModuleFileName는 유니코드를 사용하냐 ANSI를 사용하냐에 따라 GetModuleFileNameW 또는 GetModuleFileNameA로 정의된다.  wchar_t exePath[MAX_PATH];GetModuleFileName(NULL, exePath, MAX_PATH);wchar_t* folderPath = new wchar_t[wcslen(exePath) + 1];wcscpy(f.. 2023. 9. 19.
C++ ] Winsock2의 bind 함수와 functional 헤더의 std::bind 함수 충돌 방지 Winsock2 라이브러리와 C++ 표준 라이브러리인 functional 헤더를 모두 포함에서 사용하는 경우 bind함수 때문에 충돌할 수 있다. Winsock2의 bind함수는 전역함수로 전역 네임스페이스에 속해있기 때문에 using namespace std; 를 했더라도 전역 bind 함수가 우선 호출된다. Winsock2 bind함수를 호출할 때는 ::bind로 전역 네임스페이스의 bind를 호출하고 C++표준 라이브러리의 std::bind함수를 호출할 때는 std::bind로 명시적으로 써주면 충돌을 피하고 가독성을 높일 수 있다. #include #include int main() { // Winsock2 라이브러리의 bind 함수 호출 ::bind(socket, ...); // C++ 표준 라.. 2023. 9. 17.
C++ ] 멤버 함수 포인터 사용하기 / 함수포인터 대신 std::function 사용 / using으로 별칭 사용 멤버 함수 포인터 선언 returnType (className::*pointerName)(parameterTypes); 멤버 함수 포인터에 함수 주소 대입하기 멤버 함수 포인터에 함수 주소를 대입할 때는 일반 함수포인터와는 다르게 & 연산자를 생략할 수 없다. returnType (className::*pointerName)(parameterTypes) = &className::memberFunctionName; 멤버 함수 포인터 호출하는 법 className object; // 클래스의 인스턴스 생성 (returnType)(object.*pointerName)(arguments); 만약 클래스의 멤버인 멤버 함수 포인터를 멤버 함수 내에서 호출한다면 아래처럼 하면 된다. (this->*functionP.. 2023. 9. 15.
MFC ] 사용자 지정 메시지와 메시지 처리기 만들기, SendMessage, PostMessage 메뉴에서 프로젝트 - 클래스 마법사 - -Dlg클래스 선택 - 사용자 지정 메시지 추가로 추가하는 방법도 있다. 방법 먼저 사용자 지정 메시지를 정의한다. #define MY_MSG1(WM_USER + 1) #define MY_MSG2(WM_USER + 2) Windows API에는 미리 정의된 메시지 상수가 많이 있지만, 애플리케이션의 필요에 따라 추가적인 사용자 지정 메시지를 정의할 수 있는데, 이때 WM_USER를 사용하여 사용자 지정 메시지의 베이스 값을 설정한다. WM_USER의 값은 0x0400으로 (WM_USER + n) 이런식으로 정의하면 다른 시스템 또는 프레임워크 메시지와 충돌하지 않도록 할 수 있다. 다음은 다이얼로그 헤더에 메시지 처리기를 추가한다. afx_msg LRESULT My.. 2023. 9. 15.
C] strstr 함수 구현 strstr() 함수는 substring을 찾는 함수로 str1에서 str2를 찾는다. str2의 길이가 0이면 str1을 리턴, str2를 못찾으면 NULL을 리턴, str2를 찾았으면 str1에서 str2 시작 위치의 포인터를 리턴한다. const char* my_strstr(const char* str1, const char* str2) { char* ret; int found = 0; if (*str2 == 0) { ret = str1; } else { for(; *str1 != 0; str1++) { if(*str1 == *str2) { const char *s1 = str1; const char *s2 = str2; while(*s1 == *s2 && *s2 != 0) { s1++; s2++;.. 2023. 9. 15.
MFC ] 리스트박스 스크롤 하단으로 내리는 법 // ... m_listBox.SetCurSel(m_listBox.GetCount() - 1); m_listBox.SetCurSel(-1); // ... 리스트박스의 가장 마지막 인덱스를 선택한다. 포커스를 다시 해제해 파란색으로 표시되지 않게하면 스크롤을 맨 아래로 이동하는 효과만 남는다. 2023. 9. 15.
MFC ] 다이얼로그 생성시 함수 호출 순서 처음 MFC 어플리케이션의 시작점인 WinMain()함수가 실행되고 InitInstance()함수를 호출하여 어플리케이션의 다이얼로그를 생성하고 .DoModal(); 함수를 호출하게 된다. DoModal() PreSubclassWindow() OnNcCreate() OnNcCalcSize() OnCreate() OnSize() OnMove() OnSetFont() OnInitDialog() OnWindowPosChanging() OnMove() OnWindowPosChanged() OnWindowPosChanging() OnNcActivate() OnActivate() OnShowWindow() OnWindowPosChanging() OnNcPaint() OnEraseBkgnd() OnChildNotif.. 2023. 9. 15.
Precompiled Header를 사용해 컴파일 시간 단축하기 1. 프로젝트에서 "stdafx.cpp" 파일을 만든다. stdafx는 Visual Studio에서 사용하는 미리 컴파일된 헤더 파일의 일반적인 이름으로 다른 이름을 사용해도 무방하다. 이 "stdafx.cpp" 파일은 이후 미리 컴파일된 헤더를 생성하는데 사용된다. 2. "stdafx.cpp" 파일에 아래 코드를 추가한다. #include "stdafx.h" 3. "stdafx.h" 파일을 만들고 무겁거나 자주변경되지 않을 헤더파일을 포함시킨다. #pragma once #include #include #include 4. 미리 컴파일된 헤더를 사용할 cpp파일에 아래 코드를 추가한다. #include "stdafx.h" 5. 프로젝트 우클릭 - 설정 - C/C++ - 미리 컴파일된 헤더 설정에서 "미리.. 2023. 9. 15.
MFC ] 멀티바이트 집합 사용시에도 현대적 UI 적용하기 Framework.h에 #ifdef _UNICODE, #endif 주석 처리 #ifdef _UNICODE #if defined _M_IX86 #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") #elif defined _M_X64 #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' v.. 2023. 9. 15.
C ] Data Types Range C type stdint.h type Bits Sign Range char uint8_t 8 Unsigned 0 .. 255 signed char int8_t 8 Signed -128 .. 127 unsigned short uint16_t 16 Unsigned 0 .. 65,535 short int16_t 16 Signed -32,768 .. 32,767 unsigned int uint32_t 32 Unsigned 0 .. 4,294,967,295 int int32_t 32 Signed -2,147,483,648 .. 2,147,483,647 unsigned long long uint64_t 64 Unsigned 0 .. 18,446,744,073,709,551,615 long long int64_t 6.. 2023. 9. 15.
MFC ] EditBox에서 편집하고 엔터치면 입력되게끔 하기 PreTranslateMessage(MSG* pMsg) 함수 재정의 BOOL AppDlg::PreTranslateMessage(MSG* pMsg) { // TODO: 여기에 특수화된 코드를 추가 및/또는 기본 클래스를 호출합니다. // 키보드 입력시 if (pMsg->message == WM_KEYDOWN) { // 엔터키인 경우 if (pMsg->wParam == VK_RETURN) { // 현재 다이얼로그나 윈도우에서 포커스를 가진 컨트롤(윈도우)을 반환 CWnd* pFocusWnd = GetFocus(); // 컨트롤 ID가 에딧박스인 경우 입력처리 if (pFocusWnd != nullptr && pFocusWnd->GetDlgCtrlID() == IDC_EDIT_CMD) { OnBnClicked.. 2023. 9. 15.
MFC ] 클래스 마법사 오류 CCmdTarget 파생 클래스가 아닌 이 클래스에는 명령을 추가할 수 없습니다. 프로젝트 폴더에 가서 .vs 폴더을 다른 이름으로 바꾼 뒤 다시 프로젝트를 열면 .vs 폴더가 다시 생성되면 클래스 마법사가 된다. 리소스에서 구문분석을 하지 못했습니다. 리소스뷰에 다이얼로그에가서 버튼하나 만들어주고 빌드한뒤 다이얼로그랑 Resource.h에서 만들었던 버튼 삭제하면 됨 2023. 9. 15.
char, wchar_t, TCHAR char - 1바이트 문자 또는 숫자를 저장하기 위한 자료형 wchar_t - 2바이트로 문자를 저장하기 위한 자료형 wchar_t myString[] = L"Hello, World!"; TCHAR - 컴파일 환경에 따라 char 또는 wchar_t로 매핑되는 매크로로 Visual Studio 프로젝트 - 속성 - 고급 - 문자집합에서 멀티바이트 문자집합 사용시 char로, 유니코드 문자집합 사용시 wchar_t로 처리된다. TCHAR myString[] = _T("Hello, World!"); 2023. 9. 15.
MFC ] 엔터, ESC 키 입력시 종료되지 않게하기 엔터키 입력 시 종료되지 않게하기 OnOK 함수 재정의 OnOK() 호출 주석처리 void CRwrTesterDlg::OnOK() { // TODO: 여기에 특수화된 코드를 추가 및/또는 기본 클래스를 호출합니다. //CDialogEx::OnOK(); } ESC 키 입력 시 종료되지 않게하기 OnCancel() 함수를 재정의해서 주석처리하면 Alt+F4가 눌리거나 다이얼로그의 X버튼이 눌린 경우에도 종료되지 않기 때문에 다른방법을 쓴다. PreTranslateMessage(MSG* pMsg) 함수 재정의 해당함수는 키보드 및 마우스 메시지를 번역하고 처리하기 전에 호출되는데 ESC키 입력시 바로 리턴하여 어플리케이션이 종료되지 않도록 한다. BOOL CRwrTesterDlg::PreTranslateMes.. 2023. 9. 15.
extern "C" {} extern "C" {} 는 .cpp 소스파일에서 C 스타일로 작성된 함수나 변수를 사용하기 위한 C++의 키워드로, extern "C" {} 문구를 사용하면 해당 블록 내에 있는 함수나 변수를 C 스타일로 링크하도록 지시할 수 있다. C++ 컴파일러는 C++ 언어의 특징을 따르는데, C++은 함수 오버로딩, 이름 맹글링(name mangling) 등의 기능을 지원하기 때문에 C 와는 다른 링킹 규칙을 가지고 있다. 따라서 extern "C" 키워드를 사용하면 C++ 코드에서 해당 블록 내에 선언된 C 함수나 C 변수를 호출 또는 참조할 때 C 스타일의 링킹 규칙을 따르도록 한다. extern "C" { // C 함수 extern void myCFunction(int arg); } extern "C" {.. 2023. 7. 18.
C# ] 명령프롬프트, 시스템 명령어 실행 using System; using System.Diagnostics; class Program { static void Main(string[] args) { string Command = "dir"; ProcessStartInfo startInfo = new ProcessStartInfo(); startInfo.FileName = "cmd.exe"; startInfo.Arguments = "/C " + Command; Process process = new Process(); process.StartInfo = startInfo; process.Start(); } } C++에서 system("") 함수를 사용하여 시스템 명령어를 실행할 때는 내부적으로 명령 프롬프트를 호출하는 작업이 숨겨져 있어서 간.. 2023. 7. 11.
C++ ] 시스템 명령어 실행 #include #include int main() { const char* command = "ls"; // 실행할 명령어 int result = system(command); // 명령어 실행 if (result == 0) { std::cout 2023. 7. 11.
C, C++ ] system("pause") 대신 사용할 수 있는 방법 system("pause")는 운영체제에 종속적이고 운영체제에게 "pause"라는 명령을 실행하도록 요청하므로 비슷한 기능을 구현할 다른 방법을 생각해보자. C 윈도우 환경에서만 가능한 방법 #include #include int main() { printf("Press any key to continue...\n"); while (!_kbhit()); (void)_getch(); return 0; } conio.h 는 윈도우에서만 사용 가능하다. C #include int main() { printf("Press Enter to continue...\n"); (void) getchar(); return 0; } getchar()는 표준 라이브러리이기 때문에 이식성이 좋으며, 보다 간단하게 사용자의 입력.. 2023. 7. 11.
C ] 포인터와 const const는 변수나 함수 매개변수를 선언할 때 사용되는 한정자로 값을 변경할 수 없음을 나타낸다. 변수를 상수로 취급하고자 할 때 유용하며, 많은 곳에서 참조되고 변경되는 것을 원하지 않는 정적인 정보를 보호하는데 사용된다.  포인터 형식과 const 한정자가 같이 쓰일 때 const의 위치에 따라 다음과 같은 차이가 있다.   1. 상수를 가리키는 포인터 : ptr의 역참조를 통해 값을 변경할 수 없지만, ptr이 다른 주소를 가리키도록 변경할 수 있다.const int* ptr     2. 상수 포인터 : ptr 자체를 다른 주소를 가리키도록 변경할 수 없지만, ptr의 역참조를 통해 값을 변경할 수 있다.int* const ptr     3. 상수를 가리키는 상수 포인터 : ptr이 가진 주소를 변.. 2023. 5. 30.
C ] 비트필드와 공용체 사용 #include #include typedef struct { uint32_t bit1 : 1; uint32_t bit2 : 2; uint32_t bit3 : 3; } MyBits; union MyUnion { uint32_t all; MyBits bits; }; int main() { union MyUnion myUnion; myUnion.all = 0; myUnion.bits.bit1 = 1; myUnion.bits.bit2 = 2; myUnion.bits.bit3 = 5; printf("all: %u\n", myUnion.all); printf("bit1: %u\n", myUnion.bits.bit1); printf("bit2: %u\n", myUnion.bits.bit2); printf("bit3.. 2023. 5. 29.
C++ ] Format-Hex 명령어(Hex 덤프) 직접 구현 #include #include #include #include using namespace std; namespace fs = filesystem; void printhex(char *path) { // ios::binary 플래그를 사용해 이진모드로 파일 열기 ifstream file(path, ios::binary); if (!file) { cerr 2023. 5. 29.
C++ ] Manipulator와 iomanip 헤더 iomanip 헤더에는 스트림을 제어하기 위한 다양한 Manipulator가 포함되어 있다. 스트림은 C++에서 데이터의 입력 및 출력을 처리하는 방식을 말하며, 이를 위해 "iostream" 라이브러리에서 제공하는 클래스와 함수를 사용하는데, Manipulator는 이러한 스트림을 조작하여 데이터의 포맷팅, 출력 형식을 유연하게 지정할 수 있게 한다. endl; 도 개행 문자를 출력하고 버퍼를 비우는 Manipulator이다. #include #include int main() { int number = 12345; double pi = 3.14159; // setw()를 사용하여 출력 폭(width) 지정 std::cout 2023. 5. 28.
C++ ] static_cast와 reinterpret_cast. 그 외 const_cast, dynamic_cast C++에서 C 스타일의 캐스팅은 더 이상 권장되지 않는다. C 스타일 캐스팅은 실수할 여지가 많고 의도하지 않은 형식 변환이 발생할 수 있기 때문에 C++에서는 대신 static_cast, reinterpret_cast, const_cast, dynamic_cast와 같은 명시적인 캐스팅 연산자들을 사용하는 것을 권장한다. 1. static_cast : 정적 캐스트 - 고정된 표준 형식 변환에 사용된다. - 상속 관계가 아닌 타입 간의 변환, 숫자형 타입 간의 변환, 포인터 간의 변환 등. int num = 10; double numDouble = static_cast(num); // int를 double로 변환 2. reinterpret_cast : 재해석 캐스트 - 다른 타입과 포인터 사이의 비트 패.. 2023. 5. 28.