728x90
반응형
728x90
반응형
반응형



728x90
반응형
반응형

Visual Studio 2005/2008 DLL 배포와 WinSxS의 활용법

Visual Studio 2005와 2008은 'DLL 지옥' 문제를 해결하기 위해 WinSxS(Windows Side-by-Side) 기술을 도입했습니다.

이는 .NET의 GAC(Global Assembly Cache)와 유사하게 네이티브 DLL을 버전별로 관리하고 접근할 수 있게 해줍니다.

WinSxS는 주로 Windows XP 이상 버전에서 사용됩니다.

WinSxS를 사용하지 않고 배포하려면, Visual Studio의 재배포 가능 패키지(redist) 경로에 있는 파일들을 실행 파일과 동일한 경로에 복사하는 방법이 있습니다.

예를 들어, Visual Studio 2005와 x86 시스템(32비트 Windows XP, Vista)에서는 다음과 같은 폴더를 복사해야 합니다:

  • Microsoft.VC80.ATL
  • Microsoft.VC80.CRT
  • Microsoft.VC80.MFC
  • Microsoft.VC80.MFCLOC
  • Microsoft.VC80.OPENMP

디버그 버전의 경우에는 다음 폴더도 포함됩니다:

  • Microsoft.VC80.DebugOpenMP
  • Microsoft.VC80.DebugCRT
  • Microsoft.VC80.DebugMFC

이 방법은 배포 시 보안 문제로 인해 시스템 경로 접근이 제한되는 경우 유용합니다.

그러나 서비스 팩 적용 여부에 따라 DLL 버전이 달라질 수 있으므로, 빌드한 컴퓨터의 Visual Studio 재배포 가능 패키지를 복사하는 것이 가장 정확합니다.

그렇지 않다면 WinSxS를 사용하는 것이 더 나은 방법입니다.

728x90
반응형
반응형

MFC CArchiveCString 사용 시 파일 저장 방식 이해

MFCCArchiveCString을 함께 사용할 때, 파일에 문자열이 저장되는 방식에 대해 이해하는 것이 중요합니다.

일반적으로 CArchive를 통해 CString을 파일에 저장하면, 예상과 달리 문자열의 길이 정보가 함께 기록됩니다.

예를 들어, 다음과 같은 코드를 실행하여 파일에 "hello"라는 문자열을 저장한다고 가정해봅시다.

cpp

CFile file;
file.Open(_T("example.txt"), CFile::modeCreate | CFile::modeWrite);
CArchive archive(&file, CArchive::store);
CString str = _T("hello");
archive << str;
archive.Close();
file.Close();

이 경우, 파일에는 단순히 "hello"라는 5바이트의 문자열만 저장되는 것이 아니라, 첫 바이트에 문자열의 길이(5)가 기록되고 그 뒤에 "hello"가 저장되어 총 6바이트의 파일이 생성됩니다.

이러한 동작은 CArchive<< 연산자 구현 방식에 기인합니다. 해당 연산자는 내부적으로 AfxWriteStringLength() 함수를 호출하여 문자열의 길이를 먼저 기록한 후, 실제 문자열 데이터를 저장합니다.

template< typename BaseType, class StringTraits >
CArchive& CArchive::operator<<(const ATL::CStringT<BaseType, StringTraits>& str)
{
    AfxWriteStringLength(*this, str.GetLength(), sizeof(BaseType) == sizeof(wchar_t));
    Write(str, str.GetLength()*sizeof(BaseType));
    return *this;
} 

이 함수는 문자열의 길이에 따라 기록 방식을 달리하며, 유니코드 환경에서는 추가적인 처리를 수행합니다.

void AFXAPI AfxWriteStringLength(CArchive& ar, UINT_PTR nLength, BOOL bUnicode)
{
    if (bUnicode)
    {
        // Tag Unicode strings
        ar<<(BYTE)0xff;
        ar<<(WORD)0xfffe;
    }

    if (nLength < 255)
    {
        ar<<(BYTE)nLength;
    }
    else if (nLength < 0xfffe)
    {
        ar<<(BYTE)0xff;
        ar<<(WORD)nLength;
    }
    else if (nLength < 0xffffffff)
    {
        ar<<(BYTE)0xff;
        ar<<(WORD)0xffff;
        ar<<(DWORD)nLength;
    }
    else
    {
        ar<<(BYTE)0xff;
        ar<<(WORD)0xffff;
        ar<<(DWORD)0xffffffff;
        ar<<(ULONGLONG)nLength;
    }
}

따라서, CArchiveCString을 사용하여 파일 입출력을 수행할 때는 이러한 저장 방식을 이해하고 있어야 합니다.

이는 MFC뿐만 아니라 Delphi/C++ Builder의 VCL, Qt, Boost, ACE 등 다른 프레임워크나 라이브러리에서도 유사하게 적용될 수 있으므로, 내부 소스 코드를 확인하여 정확한 동작 방식을 파악하는 것이 좋습니다.

728x90
반응형
반응형
// Exam28.cpp
// 9/21/2000 (rk)
// Last modified: 3/10/2002 (RK)
// test the routine KILL_PROC_BY_NAME to terminate a process
#include <windows.h>
#include <tlhelp32.h>
#include <iostream.h>
#ifdef BORLANDC
#include <string.h>
#include <ctype.h>
#endif
int KILL_PROC_BY_NAME(const char *);
int main(int argc,char *argv[])
{
// Terminate a running process
char szName[100]="notepad.exe"; // Name of process to terminate
int iRes;
iRes=KILL_PROC_BY_NAME(szName);
cout << "Result code=" << iRes << endl;
return 0;
}
int KILL_PROC_BY_NAME(const char *szToTerminate)
// Created: 6/23/2000 (RK)
// Last modified: 3/10/2002 (RK)
// Please report any problems or bugs to kochhar@physiology.wisc.edu
// The latest version of this routine can be found at:
// http://www.neurophys.wisc.edu/ravi/software/killproc/
// Terminate the process "szToTerminate" if it is currently running
// This works for Win/95/98/ME and also Win/NT/2000/XP
// The process name is case-insensitive, i.e. "notepad.exe" and "NOTEPAD.EXE"
// will both work (for szToTerminate)
// Return codes are as follows:
// 0 = Process was successfully terminated
// 603 = Process was not currently running
// 604 = No permission to terminate process
// 605 = Unable to load PSAPI.DLL
// 602 = Unable to terminate process for some other reason
// 606 = Unable to identify system type
// 607 = Unsupported OS
// 632 = Invalid process name
// 700 = Unable to get procedure address from PSAPI.DLL
// 701 = Unable to get process list, EnumProcesses failed
// 702 = Unable to load KERNEL32.DLL
// 703 = Unable to get procedure address from KERNEL32.DLL
// 704 = CreateToolhelp32Snapshot failed
// Change history:
// modified 3/8/2002 - Borland-C compatible if BORLANDC is defined as
// suggested by Bob Christensen
// modified 3/10/2002 - Removed memory leaks as suggested by
// Jonathan Richard-Brochu (handles to Proc and Snapshot
// were not getting closed properly in some cases)
{
BOOL bResult,bResultm;
DWORD aiPID[1000],iCb=1000,iNumProc,iV2000=0;
DWORD iCbneeded,i,iFound=0;
char szName[MAX_PATH],szToTermUpper[MAX_PATH];
HANDLE hProc,hSnapShot,hSnapShotm;
OSVERSIONINFO osvi;
HINSTANCE hInstLib;
int iLen,iLenP,indx;
HMODULE hMod;
PROCESSENTRY32 procentry;
MODULEENTRY32 modentry;
// Transfer Process name into "szToTermUpper" and
// convert it to upper case
iLenP=strlen(szToTerminate);
if(iLenP<1 || iLenP>MAX_PATH) return 632;
for(indx=0;indx<iLenP;indx++)
szToTermUpper[indx]=toupper(szToTerminate[indx]);
szToTermUpper[iLenP]=0;
// PSAPI Function Pointers.
BOOL (WINAPI *lpfEnumProcesses)( DWORD *, DWORD cb, DWORD * );
BOOL (WINAPI *lpfEnumProcessModules)( HANDLE, HMODULE *,
DWORD, LPDWORD );
DWORD (WINAPI *lpfGetModuleBaseName)( HANDLE, HMODULE,
LPTSTR, DWORD );
// ToolHelp Function Pointers.
HANDLE (WINAPI *lpfCreateToolhelp32Snapshot)(DWORD,DWORD) ;
BOOL (WINAPI *lpfProcess32First)(HANDLE,LPPROCESSENTRY32) ;
BOOL (WINAPI *lpfProcess32Next)(HANDLE,LPPROCESSENTRY32) ;
BOOL (WINAPI *lpfModule32First)(HANDLE,LPMODULEENTRY32) ;
BOOL (WINAPI *lpfModule32Next)(HANDLE,LPMODULEENTRY32) ;
// First check what version of Windows we're in
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
bResult=GetVersionEx(&osvi);
if(!bResult) // Unable to identify system version
return 606;
// At Present we only support Win/NT/2000/XP or Win/9x/ME
if((osvi.dwPlatformId != VER_PLATFORM_WIN32_NT) &&
(osvi.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS))
return 607;
if(osvi.dwPlatformId==VER_PLATFORM_WIN32_NT)
{
// Win/NT or 2000 or XP
// Load library and get the procedures explicitly. We do
// this so that we don't have to worry about modules using
// this code failing to load under Windows 9x, because
// it can't resolve references to the PSAPI.DLL.
hInstLib = LoadLibraryA("PSAPI.DLL");
if(hInstLib == NULL)
return 605;
// Get procedure addresses.
lpfEnumProcesses = (BOOL(WINAPI *)(DWORD *,DWORD,DWORD*))
GetProcAddress( hInstLib, "EnumProcesses" ) ;
lpfEnumProcessModules = (BOOL(WINAPI *)(HANDLE, HMODULE *,
DWORD, LPDWORD)) GetProcAddress( hInstLib,
"EnumProcessModules" ) ;
lpfGetModuleBaseName =(DWORD (WINAPI *)(HANDLE, HMODULE,
LPTSTR, DWORD )) GetProcAddress( hInstLib,
"GetModuleBaseNameA" ) ;
if(lpfEnumProcesses == NULL ||
lpfEnumProcessModules == NULL ||
lpfGetModuleBaseName == NULL)
{
FreeLibrary(hInstLib);
return 700;
}
bResult=lpfEnumProcesses(aiPID,iCb,&iCbneeded);
if(!bResult)
{
// Unable to get process list, EnumProcesses failed
FreeLibrary(hInstLib);
return 701;
}
// How many processes are there?
iNumProc=iCbneeded/sizeof(DWORD);
// Get and match the name of each process
for(i=0;i<iNumProc;i++)
{
// Get the (module) name for this process
strcpy(szName,"Unknown");
// First, get a handle to the process
hProc=OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,FALSE,
aiPID[i]);
// Now, get the process name
if(hProc)
{
if(lpfEnumProcessModules(hProc,&hMod,sizeof(hMod),&iCbneeded) )
{
iLen=lpfGetModuleBaseName(hProc,hMod,szName,MAX_PATH);
}
}
CloseHandle(hProc);
// We will match regardless of lower or upper case
#ifdef BORLANDC
if(strcmp(strupr(szName),szToTermUpper)==0)
#else
if(strcmp(_strupr(szName),szToTermUpper)==0)
#endif
{
// Process found, now terminate it
iFound=1;
// First open for termination
hProc=OpenProcess(PROCESS_TERMINATE,FALSE,aiPID[i]);
if(hProc)
{
if(TerminateProcess(hProc,0))
{
// process terminated
CloseHandle(hProc);
FreeLibrary(hInstLib);
return 0;
}
else
{
// Unable to terminate process
CloseHandle(hProc);
FreeLibrary(hInstLib);
return 602;
}
}
else
{
// Unable to open process for termination
FreeLibrary(hInstLib);
return 604;
}
}
}
}
if(osvi.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS)
{
// Win/95 or 98 or ME
hInstLib = LoadLibraryA("Kernel32.DLL");
if( hInstLib == NULL )
return 702;
// Get procedure addresses.
// We are linking to these functions of Kernel32
// explicitly, because otherwise a module using
// this code would fail to load under Windows NT,
// which does not have the Toolhelp32
// functions in the Kernel 32.
lpfCreateToolhelp32Snapshot=
(HANDLE(WINAPI *)(DWORD,DWORD))
GetProcAddress( hInstLib,
"CreateToolhelp32Snapshot" ) ;
lpfProcess32First=
(BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))
GetProcAddress( hInstLib, "Process32First" ) ;
lpfProcess32Next=
(BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))
GetProcAddress( hInstLib, "Process32Next" ) ;
lpfModule32First=
(BOOL(WINAPI *)(HANDLE,LPMODULEENTRY32))
GetProcAddress( hInstLib, "Module32First" ) ;
lpfModule32Next=
(BOOL(WINAPI *)(HANDLE,LPMODULEENTRY32))
GetProcAddress( hInstLib, "Module32Next" ) ;
if( lpfProcess32Next == NULL ||
lpfProcess32First == NULL ||
lpfModule32Next == NULL ||
lpfModule32First == NULL ||
lpfCreateToolhelp32Snapshot == NULL )
{
FreeLibrary(hInstLib);
return 703;
}
// The Process32.. and Module32.. routines return names in all uppercase
// Get a handle to a Toolhelp snapshot of all the systems processes.
hSnapShot = lpfCreateToolhelp32Snapshot(
TH32CS_SNAPPROCESS, 0 ) ;
if( hSnapShot == INVALID_HANDLE_VALUE )
{
FreeLibrary(hInstLib);
return 704;
}
// Get the first process' information.
procentry.dwSize = sizeof(PROCESSENTRY32);
bResult=lpfProcess32First(hSnapShot,&procentry);
// While there are processes, keep looping and checking.
while(bResult)
{
// Get a handle to a Toolhelp snapshot of this process.
hSnapShotm = lpfCreateToolhelp32Snapshot(
TH32CS_SNAPMODULE, procentry.th32ProcessID) ;
if( hSnapShotm == INVALID_HANDLE_VALUE )
{
CloseHandle(hSnapShot);
FreeLibrary(hInstLib);
return 704;
}
// Get the module list for this process
modentry.dwSize=sizeof(MODULEENTRY32);
bResultm=lpfModule32First(hSnapShotm,&modentry);
// While there are modules, keep looping and checking
while(bResultm)
{
if(strcmp(modentry.szModule,szToTermUpper)==0)
{
// Process found, now terminate it
iFound=1;
// First open for termination
hProc=OpenProcess(PROCESS_TERMINATE,FALSE,procentry.th32ProcessID);
if(hProc)
{
if(TerminateProcess(hProc,0))
{
// process terminated
CloseHandle(hSnapShotm);
CloseHandle(hSnapShot);
CloseHandle(hProc);
FreeLibrary(hInstLib);
return 0;
}
else
{
// Unable to terminate process
CloseHandle(hSnapShotm);
CloseHandle(hSnapShot);
CloseHandle(hProc);
FreeLibrary(hInstLib);
return 602;
}
}
else
{
// Unable to open process for termination
CloseHandle(hSnapShotm);
CloseHandle(hSnapShot);
FreeLibrary(hInstLib);
return 604;
}
}
else
{ // Look for next modules for this process
modentry.dwSize=sizeof(MODULEENTRY32);
bResultm=lpfModule32Next(hSnapShotm,&modentry);
}
}
//Keep looking
CloseHandle(hSnapShotm);
procentry.dwSize = sizeof(PROCESSENTRY32);
bResult = lpfProcess32Next(hSnapShot,&procentry);
}
CloseHandle(hSnapShot);
}
if(iFound==0)
{
FreeLibrary(hInstLib);
return 603;
}
FreeLibrary(hInstLib);
return 0;
}
728x90
반응형
반응형

비트 이동 연산자 (Bit Shift Operator)

비트 이동 연산자 (Bit Shift Operator) 는 C 언어에서 비트 단위의 데이터를 조작할 때 사용됩니다.

이 연산자는 특정 값을 왼쪽이나 오른쪽으로 지정된 비트 수만큼 이동시키며, 다음과 같은 형식을 가집니다:

  • 왼쪽 이동 연산자 (<<): 결과값 = 처리할값 << 이동할비트수;
  • 오른쪽 이동 연산자 (>>): 결과값 = 처리할값 >> 이동할비트수;

이때, 비트의 방향은 왼쪽 끝이 최상위 비트(MSB), 오른쪽 끝이 최하위 비트(LSB)로 정의됩니다.

따라서, 왼쪽 이동은 비트를 MSB 방향으로, 오른쪽 이동은 LSB 방향으로 이동시키는 것을 의미합니다.

예시:

c

#include <stdio.h>

int main() {
    unsigned int value = 1; // 0000 0001
    unsigned int result;

    result = value << 2; // 0000 0100
    printf("왼쪽으로 2비트 이동: %u\n", result);

    result = value >> 1; // 0000 0000
    printf("오른쪽으로 1비트 이동: %u\n", result);

    return 0;
}

위 코드에서 value는 1로 초기화되며, 이는 이진수로 0000 0001입니다.

value << 2는 비트를 왼쪽으로 2비트 이동시켜 0000 0100 이 되며, 이는 10진수로 4입니다.

반대로, value >> 1은 비트를 오른쪽으로 1비트 이동시켜 0000 0000 이 되며, 이는 10진수로 0입니다.

이러한 비트 이동 연산자는 비트 단위의 조작이 필요한 상황에서 유용하게 활용됩니다.

728x90
반응형
반응형

C++ 구조체 멤버의 오프셋(offset) 얻기

간단한 구조체라면 직관적으로 그 구조체의 멤버의 위치, 크기를 알 수 있다.

struct Hello
{
  int hello1; // size 4
  short hello2; // size 2
  double hello3; // size 8
};

그런데 문제는 아주~큰 구조체의 경우에는 이점이 쉽지 않다는 것이다. 예를 들자면 구조체 멤버가 천 개 정도인데 그 멤버들 중 일부는 또 구조체인 구조체라고 한다면 특정 멤버의 위치가 어느 정도인지 계산하기가 까다로울 수 밖에 없다.

struct BigHello
{
  int hello1;
  //
  int hello 100;
  //
  double hello 199;
  Hello hello200;
  Hello hello201;
  //
  Hello hello500;
  //
}

그럴 경우를 위해서 자신만의 아래와 같은 매크로를 만들 수도 있다.

#define OFFSETOF(a, b) ( (size_t) &((a)NULL)->b )

이 때, a 는 구조체의 포인터이고, b 는 멤버가 될 것이다.

약간 이상해 보이지만 c 의 포인터 개념을 알고 있다면 전혀 이상할 것은 없다. 임의의 구조체 대신에 NULL 을 가리키는 구조체 포인터a를 이용하여 멤버인 b가 무언지를 접근하는 매크로일 뿐이다. 실제 사용 방법은 아래와 같이 쓰면 될 것이다.

struct HelloOffset
{
  long hello1;
  long hello2;
  double hello3;
};
size_t s1 = offsetof(struct HelloOffset *, hello3); // 결과는 8 이다. (32bit OS)

그런데, offsetof() 라는 동일한 기능을 갖는 매크로가 이미 존재한다.

// #include <stddef.h>

#ifdef _WIN64

#define offsetof(s,m) (size_t)( (ptrdiff_t)&reinterpret_cast<const volatile char&>((((s *)0)->m)) )

#else

#define offsetof(s,m) (size_t)&reinterpret_cast<const volatile char&>((((s *)0)->m))

#endif

위의 OFFSETOF() 보다는 타입 변환 등이 더 C++ 표준적인 요소가 많음을 알 수 있다.

728x90
반응형
반응형

VC++ 2005로 개발된 프로그램을 배포하려면 Microsoft에서 제공하는 재배포 패키지를 설치해야 합니다. 이 패키지는 두 가지 버전이 있으며, 하나는 VC++ 2005용(x86) 이고 다른 하나는 VC++ 2005 SP1용(x86)  입니다. 설치 방법은 해당 실행 파일을 실행하면 됩니다.

 

첨부파일
다운로드

 

첨부파일
다운로드

 

 

728x90
반응형
반응형
// 출처 : MSDN
// crt_strlen.c
// Determine the length of a string. For the multi-byte character
// example to work correctly, the Japanese language support for
// non-Unicode programs must be enabled by the operating system.
#include <string.h>
#include <locale.h>
int main()
{
char* str1 = "Count.";
wchar_t* wstr1 = L"Count.";
char * mbstr1;
char * locale_string;
// strlen gives the length of single-byte character string
printf("Length of '%s' : %d\n", str1, strlen(str1) );
// wstrlen gives the length of a wide character string
wprintf(L"Length of '%s' : %d\n", wstr1, wcslen(wstr1) );
// A multibyte string: [A] [B] [C] [katakana A] [D] [\0]
// in Code Page 932. For this example to work correctly,
// the Japanese language support must be enabled by the
// operating system.
mbstr1 = "ABC" "\x83\x40" "D";
locale_string = setlocale(LC_CTYPE, "Japanese_Japan");
if (locale_string == NULL)
{
printf("Japanese locale not enabled. Exiting.\n");
exit(1);
}
else
{
printf("Locale set to %s\n", locale_string);
}
// _mbslen will recognize the Japanese multibyte character if the
// current locale used by the operating system is Japanese
printf("Length of '%s' : %d\n", mbstr1, _mbslen(mbstr1) );
// _mbstrlen will recognize the Japanese multibyte character
// since the CRT locale is set to Japanese even if the OS locale
// isnot.
printf("Length of '%s' : %d\n", mbstr1, _mbstrlen(mbstr1) );
printf("Bytes in '%s' : %d\n", mbstr1, strlen(mbstr1) );
}
//--------------------------------------------------------------
// Output
//
// Length of 'Count.' : 6
// Length of 'Count.' : 6
// Length of 'ABCァD' : 5
// Length of 'ABCァD' : 5
// Bytes in 'ABCァD' : 6
//
// 로케일을 적용하여 문자열 길이를 얻는 API 입니다. 지원은 Windows 2000/XP/2003/Vista 에서만 됩니다.
// (유닉스/리눅스는 일부만 표준 호환)
// 예제에서는 일본 로케일을 적용 하였습니다.
// 결과 중 세번째를 보시면(_mbslen) 길이가 5글자로 반환되는 것을 알 수 있습니다.
728x90
반응형
반응형

32비트 윈도우즈 자료형과 크기

32비트 윈도우즈 환경에서 사용되는 주요 자료형과 그 크기는 다음과 같습니다:

  • 1바이트 정수형:

    • char
    • unsigned char
    • signed char
    • byte
  • 2바이트 정수형:

    • short
    • unsigned short
  • 4바이트 정수형:

    • int
    • unsigned int
    • long
    • unsigned long
    • dword
  • 부동소수점형:

    • float (4바이트)
    • double (8바이트)

부호 있는 정수형의 경우, 최상위 1비트가 부호를 나타냅니다. 또한, 32비트 윈도우즈에서는 포인터의 크기가 4바이트이며, 이는 2^32 주소 공간을 의미합니다.

728x90
반응형
반응형

Windows API IsWindowUnicode 함수로 유니코드 지원 여부 확인하기

IsWindowUnicode 함수는 주어진 윈도우 핸들(HWND)이 유니코드를 지원하는지 여부를 확인하는 Windows API 함수입니다.

이 함수는 다음과 같이 정의됩니다:

BOOL IsWindowUnicode(HWND hWnd);
  • 매개변수 : hWnd는 검사할 윈도우의 핸들을 나타냅니다.
  • 반환값 : 윈도우가 유니코드를 지원하면 TRUE, 그렇지 않으면 FALSE를 반환합니다.

이 함수를 사용하면 특정 윈도우가 유니코드 기반인지 ANSI 기반인지 확인할 수 있습니다.

예를 들어, MFC의 CWindow 클래스를 활용하여 다음과 같이 사용할 수 있습니다:

CWindow myWindow;
myWindow.Attach(hWndFoo);
BOOL bUnicode = myWindow.IsWindowUnicode();

위 코드에서 myWindow 객체는 hWndFoo 핸들을 가진 윈도우와 연결되며, IsWindowUnicode() 함수를 호출하여 해당 윈도우가 유니코드를 지원하는지 확인합니다.

728x90
반응형
반응형

Windows API에서 2의 거듭제곱 여부를 확인

GNU C에는 log2() 함수가 있어 2의 거듭제곱 여부를 쉽게 확인할 수 있지만, Windows 표준 수학 함수에는 해당 함수가 없습니다.

따라서 log() 함수를 활용하여 다음과 같이 구현할 수 있습니다:

c

#include <math.h>
#include <limits.h>
#include <stdio.h>

int main() {
    for (int i = 2; i < INT_MAX; i++) {
        double t = log((double)i) / log(2.0);
        int r = (int)ceil(t);
        int p = (int)pow(2, r);

        if (i == p) {
            printf("%d\n", i); // 2의 거듭제곱 수입니다.
        }
    }
    return 0;
}

이 코드는 2부터 INT_MAX까지의 정수 중 2의 거듭제곱인 수를 찾아 출력합니다.

log() 함수를 사용하여 주어진 수의 로그 값을 계산하고, 이를 통해 2의 거듭제곱 여부를 판단합니다.

728x90
반응형
반응형

basic_string의 replace 함수로 문자열 치환하기

주어진 문자열에서 특정 문자열을 다른 문자열로 치환하는 함수를 소개합니다.

cpp

/// \brief 주어진 문자열 내에 존재하는 문자열을 다른 문자열로 치환한다.
/// \param text 원본 문자열
/// \param find_token 찾고자 하는 문자열
/// \param replace_token 치환하고자 하는 문자열
void replace(std::string& text, const std::string& find_token, const std::string& replace_token)
{
    size_t i = 0;
    while ((i = text.find(find_token)) != std::string::npos)
        text.replace(i, find_token.size(), replace_token);
}

이 함수는 text에서 find_token을 찾아 replace_token으로 모두 대체합니다.

사용 예시:

cpp

std::string str1 = "hello\tworld\r\n123\n456";
std::string strFind = "\r\n";
std::string strReplace = "";

replace(str1, strFind, strReplace); // str1 내의 "\r\n"이 모두 제거됩니다.

이 예시에서는 str1에 포함된 모든 "\r\n" 문자열이 빈 문자열로 치환되어 제거됩니다.

728x90
반응형

+ Recent posts