반응형
🔖 INDEX
정규 표현식 라이브러리: std::regex
C++11에서 도입된 std::regex 라이브러리는 정규 표현식의 파싱, 검색, 그리고 문자열 조작을 위한 강력한 도구들을 제공합니다. 아래에 이 라이브러리의 주요 내용을 요약하여 설명하겠습니다.
주요 컴포넌트
- std::regex: 정규 표현식 객체입니다. 이 객체는 정규 표현식 패턴을 나타냅니다.
- std::smatch: 문자열 검색의 결과로 반환되는 match 객체입니다.
- std::regex_iterator: 주어진 문자열에서 정규 표현식과 일치하는 부분을 반복적으로 검색하는 반복자입니다.
- std::regex_token_iterator: 반복자와 유사하나, 정규 표현식의 서브매치나 토큰을 반복적으로 검색합니다.
주요 함수
- std::regex_match: 주어진 문자열이 정규 표현식과 전체적으로 일치하는지 확인합니다.
- std::regex_search: 주어진 문자열에서 정규 표현식과 일치하는 부분이 있는지 검색합니다.
- std::regex_replace: 문자열에서 정규 표현식과 일치하는 부분을 다른 문자열로 교체합니다.
사용 예제
#include <iostream>
#include <regex>
#include <string>
int main() {
std::string input = "My email is example@gmail.com and my friend's email is friend@yahoo.com";
// Email 정규 표현식 패턴
std::regex email_pattern(R"(\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,7}\b)");
// 문자열에서 email 패턴과 일치하는 모든 부분을 찾아 출력
std::sregex_iterator begin = std::sregex_iterator(input.begin(), input.end(), email_pattern);
std::sregex_iterator end;
for (std::sregex_iterator i = begin; i != end; ++i) {
std::smatch match = *i;
std::string match_str = match.str();
std::cout << "Found email: " << match_str << '\n';
}
// Email 주소를 [REDACTED]로 교체
std::string replaced = std::regex_replace(input, email_pattern, "[REDACTED]");
std::cout << "Replaced string: " << replaced << '\n';
return 0;
}
주의 사항
- std::regex는 일부 구현에서 성능 문제가 있을 수 있습니다. 특히 복잡한 패턴이나 큰 입력 문자열에서는 성능 이슈가 나타날 수 있으므로, 실제 사용 시에는 성능 테스트를 통해 확인해야 합니다.
- 정규 표현식 자체가 복잡하므로, 의도한 대로 동작하는지 항상 확인해야 합니다.
Type Traits
타입 특성(Type Traits)는 C++ 표준 라이브러리의 일부로, 타입에 대한 정보를 컴파일 시간에 조회하거나 타입 변환을 수행하는 역할을 합니다. 이는 메타프로그래밍, 템플릿 프로그래밍, SFINAE 같은 고급 기술에서 매우 유용합니다.
주요 타입 특성
- Type Relationships:
- std::is_same<T, U>: 두 타입이 동일한지 확인.
- std::is_base_of<Base, Derived>: Derived 타입이 Base의 파생 클래스인지 확인.
- Type Properties:
- std::is_void<T>: 타입이 void인지 확인.
- std::is_integral<T>: 타입이 정수형 (예: int, char 등)인지 확인.
- std::is_floating_point<T>: 타입이 실수형 (예: float, double, long double)인지 확인.
- std::is_pointer<T>: 타입이 포인터인지 확인.
- std::is_reference<T>: 타입이 참조형인지 확인
- ... 그 외 다양한 특성들.
- Type Modifiers:
- std::remove_reference<T>: 참조를 제거한 타입을 반환.
- std::add_const<T>: 상수 타입을 반환.
사용 예제
#include <iostream>
#include <type_traits>
int main() {
if (std::is_integral<int>::value) {
std::cout << "int is an integral type.\n";
}
if (std::is_same<std::remove_reference<int&>::type, int>::value) {
std::cout << "Removing reference from int& gives int.\n";
}
return 0;
}
주요 이점
- 컴파일 시간 최적화: 타입 특성을 사용하여 컴파일 시간에 적절한 코드 경로를 선택하거나 불필요한 코드를 제거할 수 있습니다.
- 타입 안정성: 코드가 예상된 타입에만 동작하도록 보장합니다. 이를 통해 런타임 에러의 위험을 줄일 수 있습니다.
- 유연한 템플릿 코드 작성: 타입 특성을 사용하여 다양한 타입에 대응하는 유연한 템플릿 코드를 작성할 수 있습니다.
주의 사항
- 타입 특성은 컴파일 시간의 메타프로그래밍 도구로서, 런타임의 오버헤드가 없습니다. 그러나 복잡한 템플릿 코드에서 너무 많이 사용하면 컴파일 시간이 길어질 수 있습니다.
Uniform Initialization
C++11에서 도입된 유니폼 초기화 (Uniform Initialization)는 초기화 프로세스를 단순화하고 일관성을 높이기 위한 방법입니다. 중괄호 {}를 사용하여 대부분의 타입의 객체를 초기화할 수 있습니다.
기본적인 이점
- 일관성: 여러 초기화 스타일이 필요하지 않으므로 초기화 과정이 더 간결하고 예측 가능해집니다.
- 보다 안전: 가장 좁은 타입으로의 자동 변환을 방지하여 초기화 중 오류를 줄입니다.
- 집합 초기화의 확장: 일반 객체뿐만 아니라 컨테이너와 같은 복잡한 데이터 구조도 초기화할 수 있습니다.
사용 예제
기본 타입의 초기화
int i{3};
double d{2.5};
char c{'a'};
클래스 및 구조체
class MyClass {
public:
int x;
double y;
};
MyClass obj{5, 3.5};
컨테이너와 배열
std::vector<int> v{1, 2, 3, 4, 5};
int arr[]{1, 2, 3, 4};
동적 메모리 할당
auto ptr = new int[]{1, 2, 3};
주의 사항
초기화에 대한 모호성
몇몇 초기화 시나리오에서, 유니폼 초기화와 전통적인 초기화 방법이 충돌할 수 있습니다.
std::vector<int> v(10, 2); // 2로 초기화된 10개의 원소를 가진 벡터
std::vector<int> w{10, 2}; // 10과 2 두 개의 원소를 가진 벡터
직접 초기화와 복사 초기화
유니폼 초기화는 복사 초기화에서 일부 제약 사항을 피하려고 직접 초기화를 사용합니다.
class MyClass {
public:
MyClass(int) {}
};
MyClass obj1{42}; // OK
MyClass obj2 = {42}; // OK in C++11 with uniform initialization
댓글