์ฝ˜ํ…์ธ  ๋Œ€ํ‘œ ์ด๋ฏธ์ง€ - ๐ŸŽฏ C++ ์ •๊ทœํ‘œํ˜„์‹๊ณผ std::regex๋ฅผ ํ™œ์šฉํ•œ ํ…์ŠคํŠธ ์ฒ˜๋ฆฌ

๐ŸŽฏ C++ ์ •๊ทœํ‘œํ˜„์‹๊ณผ std::regex๋ฅผ ํ™œ์šฉํ•œ ํ…์ŠคํŠธ ์ฒ˜๋ฆฌ

์นœ๊ตฌ์ฒ˜๋Ÿผ ์‰ฝ๊ฒŒ ๋ฐฐ์šฐ๋Š” ํ…์ŠคํŠธ ๋งˆ๋ฒ•์‚ฌ ๋˜๊ธฐ ํ”„๋กœ์ ํŠธ! โœจ

๐Ÿš€ ์ •๊ทœํ‘œํ˜„์‹, ๋„ˆ ๋ˆ„๊ตฌ๋‹ˆ?

์•ผ, ํ˜น์‹œ ํ…์ŠคํŠธ ํŒŒ์ผ์—์„œ ์ด๋ฉ”์ผ ์ฃผ์†Œ๋งŒ ์™์™ ๋ฝ‘์•„๋‚ด๊ฑฐ๋‚˜, ์ „ํ™”๋ฒˆํ˜ธ ํ˜•์‹์ด ๋งž๋Š”์ง€ ๊ฒ€์‚ฌํ•˜๊ฑฐ๋‚˜, ํŠน์ • ํŒจํ„ด์˜ ๋ฌธ์ž์—ด์„ ํ•œ ๋ฒˆ์— ๋ฐ”๊ฟ”์•ผ ํ•  ๋•Œ ๋ง‰๋ง‰ํ–ˆ๋˜ ์  ์žˆ์ง€? ๐Ÿ˜… ๊ทธ๋Ÿด ๋•Œ ํ•„์š”ํ•œ ๊ฒŒ ๋ฐ”๋กœ ์ •๊ทœํ‘œํ˜„์‹(Regular Expression)์ด์•ผ!


์ •๊ทœํ‘œํ˜„์‹์€ ์‰ฝ๊ฒŒ ๋งํ•ด์„œ ๋ฌธ์ž์—ด ํŒจํ„ด์„ ํ‘œํ˜„ํ•˜๋Š” ํŠน๋ณ„ํ•œ ์–ธ์–ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋ผ. ๋งˆ์น˜ "010์œผ๋กœ ์‹œ์ž‘ํ•˜๊ณ  ์ˆซ์ž 8๊ฐœ๊ฐ€ ๋” ์žˆ๋Š” ๊ฑฐ ์ฐพ์•„์ค˜!"๋ผ๊ณ  ์ปดํ“จํ„ฐ์—๊ฒŒ ๋ช…๋ นํ•˜๋Š” ๊ฑฐ์ง€. ์ด๊ฑธ C++์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๊ฒŒ ๋ฐ”๋กœ std::regex ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์•ผ! ๐ŸŽ‰


C++11๋ถ€ํ„ฐ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ํฌํ•จ๋˜์–ด์„œ, ๋ณ„๋„์˜ ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์—†์ด๋„ ๊ฐ•๋ ฅํ•œ ํ…์ŠคํŠธ ์ฒ˜๋ฆฌ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋์–ด. ์ด์ œ๋ถ€ํ„ฐ ์นœ๊ตฌ์ฒ˜๋Ÿผ ํŽธํ•˜๊ฒŒ ํ•˜๋‚˜์”ฉ ์•Œ์•„๋ณด์ž!

ํ…์ŠคํŠธ ์ž…๋ ฅ abc123@test.com std::regex ํŒจํ„ด ๋งค์นญ [a-z]+@[a-z]+\\.com ๊ฒฐ๊ณผ ์ถœ๋ ฅ ๋งค์นญ ์„ฑ๊ณต! ๐Ÿ“ โš™๏ธ โœ…

๐Ÿ“š std::regex ๊ธฐ๋ณธ ๊ตฌ์กฐ ํŒŒํ—ค์น˜๊ธฐ

์ž, ์ด์ œ ๋ณธ๊ฒฉ์ ์œผ๋กœ C++์˜ std::regex๋ฅผ ์‚ฌ์šฉํ•ด๋ณด์ž! ๋จผ์ € ํ•„์š”ํ•œ ํ—ค๋” ํŒŒ์ผ์„ ํฌํ•จ์‹œ์ผœ์•ผ ํ•ด:

#include <iostream>
#include <regex>
#include <string>

int main() {
    std::string text = "๋‚ด ์ด๋ฉ”์ผ์€ hello@example.com ์ด์•ผ!";
    std::regex pattern("[a-zA-Z0-9]+@[a-zA-Z0-9]+\\.[a-zA-Z]+");
    
    if (std::regex_search(text, pattern)) {
        std::cout << "์ด๋ฉ”์ผ์„ ์ฐพ์•˜์–ด! ๐ŸŽ‰" << std::endl;
    }
    
    return 0;
}

์œ„ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด ์„ธ ๊ฐ€์ง€ ํ•ต์‹ฌ ์š”์†Œ๊ฐ€ ์žˆ์–ด:


1๏ธโƒฃ std::string - ๊ฒ€์ƒ‰ํ•  ํ…์ŠคํŠธ๋ฅผ ๋‹ด๋Š” ๋ฌธ์ž์—ด

2๏ธโƒฃ std::regex - ์ฐพ๊ณ  ์‹ถ์€ ํŒจํ„ด์„ ์ •์˜ํ•˜๋Š” ์ •๊ทœํ‘œํ˜„์‹ ๊ฐ์ฒด

3๏ธโƒฃ std::regex_search - ์‹ค์ œ๋กœ ํŒจํ„ด์„ ์ฐพ์•„์ฃผ๋Š” ํ•จ์ˆ˜

๐Ÿ” ์ฃผ์š” ํ•จ์ˆ˜๋“ค ์ด์ •๋ฆฌ

std::regex ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์œ ์šฉํ•œ ํ•จ์ˆ˜๋“ค์„ ์ œ๊ณตํ•ด. ๊ฐ๊ฐ์˜ ํŠน์ง•์„ ์•Œ์•„๋ณด์ž!

ํ•จ์ˆ˜๋ช… ๊ธฐ๋Šฅ ์‚ฌ์šฉ ์‹œ๋‚˜๋ฆฌ์˜ค
regex_match ์ „์ฒด ๋ฌธ์ž์—ด์ด ํŒจํ„ด๊ณผ ์ผ์น˜ํ•˜๋Š”์ง€ ํ™•์ธ ์ž…๋ ฅ๊ฐ’ ์ „์ฒด ๊ฒ€์ฆ (์˜ˆ: ๋น„๋ฐ€๋ฒˆํ˜ธ ํ˜•์‹)
regex_search ๋ฌธ์ž์—ด ๋‚ด์—์„œ ํŒจํ„ด์„ ์ฐพ์Œ ํ…์ŠคํŠธ์—์„œ ํŠน์ • ํŒจํ„ด ์ฐพ๊ธฐ
regex_replace ํŒจํ„ด๊ณผ ์ผ์น˜ํ•˜๋Š” ๋ถ€๋ถ„์„ ์น˜ํ™˜ ๋ฌธ์ž์—ด ์ผ๊ด„ ๋ณ€๊ฒฝ
regex_iterator ๋ชจ๋“  ๋งค์นญ ๊ฒฐ๊ณผ๋ฅผ ์ˆœํšŒ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋งค์นญ ๊ฒฐ๊ณผ ์ฒ˜๋ฆฌ

๐ŸŽจ ์ •๊ทœํ‘œํ˜„์‹ ํŒจํ„ด ๋ฌธ๋ฒ• ๋งˆ์Šคํ„ฐํ•˜๊ธฐ

์ •๊ทœํ‘œํ˜„์‹์˜ ์ง„์งœ ํž˜์€ ํŒจํ„ด ๋ฌธ๋ฒ•์— ์žˆ์–ด! ์ฒ˜์Œ์—” ์ข€ ๋ณต์žกํ•ด ๋ณด์ด์ง€๋งŒ, ํ•˜๋‚˜์”ฉ ์ตํžˆ๋ฉด ์ •๋ง ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ๊ฐ€ ๋ผ. ๐Ÿ˜Ž

๐Ÿ”ค ๊ธฐ๋ณธ ๋ฌธ์ž ํด๋ž˜์Šค

. (์ ) - ์ค„๋ฐ”๊ฟˆ์„ ์ œ์™ธํ•œ ๋ชจ๋“  ๋ฌธ์ž ํ•˜๋‚˜์™€ ๋งค์นญ

\d - ์ˆซ์ž ํ•˜๋‚˜ [0-9]์™€ ๋™์ผ

\D - ์ˆซ์ž๊ฐ€ ์•„๋‹Œ ๋ฌธ์ž

\w - ๋‹จ์–ด ๋ฌธ์ž [a-zA-Z0-9_]

\W - ๋‹จ์–ด ๋ฌธ์ž๊ฐ€ ์•„๋‹Œ ๊ฒƒ

\s - ๊ณต๋ฐฑ ๋ฌธ์ž (์ŠคํŽ˜์ด์Šค, ํƒญ, ์ค„๋ฐ”๊ฟˆ)

\S - ๊ณต๋ฐฑ์ด ์•„๋‹Œ ๋ฌธ์ž

// ์ˆซ์ž 3๊ฐœ ์ฐพ๊ธฐ
std::regex pattern1("\\d{3}");  // 123, 456 ๋“ฑ

// ๋‹จ์–ด ์ฐพ๊ธฐ
std::regex pattern2("\\w+");    // hello, world123 ๋“ฑ

// ๊ณต๋ฐฑ์œผ๋กœ ๊ตฌ๋ถ„๋œ ๋‹จ์–ด๋“ค
std::regex pattern3("\\w+\\s+\\w+");  // "hello world" ๋“ฑ

๐Ÿ’ก ๊ฟ€ํŒ! C++์—์„œ๋Š” ๋ฐฑ์Šฌ๋ž˜์‹œ๋ฅผ ์ด์Šค์ผ€์ดํ”„ํ•ด์•ผ ํ•ด์„œ \\d์ฒ˜๋Ÿผ ๋‘ ๋ฒˆ ์จ์•ผ ํ•ด. ์ด๊ฒŒ ์ข€ ๊ท€์ฐฎ์œผ๋ฉด raw string literal์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด: R"(\d{3})" ์ด๋ ‡๊ฒŒ!

๐Ÿ”ข ์ˆ˜๋Ÿ‰์ž (Quantifiers)

์ˆ˜๋Ÿ‰์ž๋Š” ํŒจํ„ด์ด ๋ช‡ ๋ฒˆ ๋ฐ˜๋ณต๋˜๋Š”์ง€๋ฅผ ์ง€์ •ํ•ด์ค˜. ์ด๊ฒŒ ์ •๋ง ์œ ์šฉํ•ด!

* - 0๋ฒˆ ์ด์ƒ ๋ฐ˜๋ณต (์—†์–ด๋„ ๋˜๊ณ , ์—ฌ๋Ÿฌ ๋ฒˆ ์žˆ์–ด๋„ ๋จ)

+ - 1๋ฒˆ ์ด์ƒ ๋ฐ˜๋ณต (์ตœ์†Œ 1๋ฒˆ์€ ์žˆ์–ด์•ผ ํ•จ)

? - 0๋ฒˆ ๋˜๋Š” 1๋ฒˆ (์žˆ๊ฑฐ๋‚˜ ์—†๊ฑฐ๋‚˜)

{n} - ์ •ํ™•ํžˆ n๋ฒˆ

{n,} - n๋ฒˆ ์ด์ƒ

{n,m} - n๋ฒˆ ์ด์ƒ m๋ฒˆ ์ดํ•˜

#include <iostream>
#include <regex>
#include <string>

int main() {
    std::string text = "์ „ํ™”๋ฒˆํ˜ธ: 010-1234-5678, 02-123-4567";
    
    // ํœด๋Œ€ํฐ ๋ฒˆํ˜ธ ํŒจํ„ด (010-xxxx-xxxx)
    std::regex mobile(R"(010-\d{4}-\d{4})");
    
    // ์ผ๋ฐ˜ ์ „ํ™”๋ฒˆํ˜ธ ํŒจํ„ด (0x-xxx-xxxx ๋˜๋Š” 0xx-xxxx-xxxx)
    std::regex phone(R"(0\d{1,2}-\d{3,4}-\d{4})");
    
    std::smatch match;
    
    if (std::regex_search(text, match, mobile)) {
        std::cout << "ํœด๋Œ€ํฐ: " << match.str() << std::endl;
    }
    
    return 0;
}

๐ŸŽฏ ์•ต์ปค์™€ ๊ฒฝ๊ณ„

๋ฌธ์ž์—ด์˜ ์‹œ์ž‘์ด๋‚˜ ๋, ๋‹จ์–ด์˜ ๊ฒฝ๊ณ„๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์–ด:

^ - ๋ฌธ์ž์—ด์˜ ์‹œ์ž‘

$ - ๋ฌธ์ž์—ด์˜ ๋

\b - ๋‹จ์–ด ๊ฒฝ๊ณ„ (๋‹จ์–ด์˜ ์‹œ์ž‘์ด๋‚˜ ๋)

\B - ๋‹จ์–ด ๊ฒฝ๊ณ„๊ฐ€ ์•„๋‹Œ ๊ณณ

// ๋ฌธ์ž์—ด์ด ์ˆซ์ž๋กœ๋งŒ ์ด๋ฃจ์–ด์ ธ ์žˆ๋Š”์ง€ ํ™•์ธ
std::regex only_digits(R"(^\d+$)");

// "cat"์ด๋ผ๋Š” ๋‹จ์–ด๋งŒ ์ฐพ๊ธฐ ("catch"์˜ cat์€ ์ œ์™ธ)
std::regex word_cat(R"(\bcat\b)");

std::string test1 = "12345";
std::string test2 = "abc123";
std::string test3 = "I have a cat";
std::string test4 = "I catch fish";

std::cout << std::regex_match(test1, only_digits) << std::endl;  // 1 (true)
std::cout << std::regex_match(test2, only_digits) << std::endl;  // 0 (false)
std::cout << std::regex_search(test3, word_cat) << std::endl;    // 1 (true)
std::cout << std::regex_search(test4, word_cat) << std::endl;    // 0 (false)

๐Ÿ› ๏ธ ์‹ค์ „ ์˜ˆ์ œ๋กœ ๋ฐฐ์šฐ๋Š” std::regex

์ด๋ก ์€ ์ด์ œ ์ถฉ๋ถ„ํ•ด! ์‹ค์ œ๋กœ ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ํŒจํ„ด๋“ค์„ ์ฝ”๋“œ๋กœ ๊ตฌํ˜„ํ•ด๋ณด์ž. ๐Ÿš€

๐Ÿ“ง ์ด๋ฉ”์ผ ์ฃผ์†Œ ๊ฒ€์ฆํ•˜๊ธฐ

์ด๋ฉ”์ผ ์ฃผ์†Œ๋Š” ์›น ๊ฐœ๋ฐœ์—์„œ ๊ฐ€์žฅ ๋งŽ์ด ๊ฒ€์ฆํ•˜๋Š” ํŒจํ„ด ์ค‘ ํ•˜๋‚˜์•ผ. ์™„๋ฒฝํ•œ ์ด๋ฉ”์ผ ๊ฒ€์ฆ์€ ๋ณต์žกํ•˜์ง€๋งŒ, ์‹ค์šฉ์ ์ธ ์ˆ˜์ค€์˜ ๊ฒ€์ฆ ์ฝ”๋“œ๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž:

#include <iostream>
#include <regex>
#include <string>
#include <vector>

bool validateEmail(const std::string& email) {
    // ์ด๋ฉ”์ผ ํŒจํ„ด: ์˜๋ฌธ์ž/์ˆซ์ž/ํŠน์ˆ˜๋ฌธ์ž + @ + ๋„๋ฉ”์ธ + . + ์ตœ์ƒ์œ„๋„๋ฉ”์ธ
    std::regex pattern(
        R"(^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$)"
    );
    
    return std::regex_match(email, pattern);
}

int main() {
    std::vector<std::string> emails = {
        "user@example.com",      // โœ… ์œ ํšจ
        "test.user@domain.co.kr", // โœ… ์œ ํšจ
        "invalid@",              // โŒ ๋ฌดํšจ
        "@invalid.com",          // โŒ ๋ฌดํšจ
        "no-at-sign.com"         // โŒ ๋ฌดํšจ
    };
    
    for (const auto& email : emails) {
        std::cout << email << " : " 
                  << (validateEmail(email) ? "โœ… ์œ ํšจ" : "โŒ ๋ฌดํšจ") 
                  << std::endl;
    }
    
    return 0;
}

๐Ÿ“Œ ์ฐธ๊ณ : ์œ„ ํŒจํ„ด์€ ์ผ๋ฐ˜์ ์ธ ์ด๋ฉ”์ผ ํ˜•์‹์„ ๊ฒ€์ฆํ•ด. RFC 5322 ํ‘œ์ค€์„ ์™„๋ฒฝํ•˜๊ฒŒ ๋”ฐ๋ฅด๋ ค๋ฉด ํ›จ์”ฌ ๋ณต์žกํ•œ ํŒจํ„ด์ด ํ•„์š”ํ•˜์ง€๋งŒ, ์‹ค๋ฌด์—์„œ๋Š” ์œ„ ์ •๋„๋ฉด ์ถฉ๋ถ„ํ•ด!

๐Ÿ“ฑ ์ „ํ™”๋ฒˆํ˜ธ ์ถ”์ถœ ๋ฐ ํฌ๋งทํŒ…

ํ…์ŠคํŠธ์—์„œ ์ „ํ™”๋ฒˆํ˜ธ๋ฅผ ์ฐพ์•„์„œ ํ†ต์ผ๋œ ํ˜•์‹์œผ๋กœ ๋ฐ”๊ฟ”๋ณด์ž:

#include <iostream>
#include <regex>
#include <string>

std::string formatPhoneNumber(const std::string& text) {
    // ๋‹ค์–‘ํ•œ ์ „ํ™”๋ฒˆํ˜ธ ํ˜•์‹์„ ์ฐพ๋Š” ํŒจํ„ด
    // 010-1234-5678, 01012345678, 010.1234.5678 ๋“ฑ
    std::regex pattern(R"(010[-.\s]?(\d{4})[-.\s]?(\d{4}))");
    
    // $1, $2๋Š” ์บก์ฒ˜ ๊ทธ๋ฃน์„ ์˜๋ฏธ (๊ด„ํ˜ธ๋กœ ๋ฌถ์ธ ๋ถ€๋ถ„)
    std::string formatted = std::regex_replace(
        text, 
        pattern, 
        "010-$1-$2"
    );
    
    return formatted;
}

int main() {
    std::string text = "์—ฐ๋ฝ์ฒ˜: 01012345678, 010.9876.5432, 010-1111-2222";
    
    std::cout << "์›๋ณธ: " << text << std::endl;
    std::cout << "๋ณ€ํ™˜: " << formatPhoneNumber(text) << std::endl;
    
    // ์ถœ๋ ฅ:
    // ์›๋ณธ: ์—ฐ๋ฝ์ฒ˜: 01012345678, 010.9876.5432, 010-1111-2222
    // ๋ณ€ํ™˜: ์—ฐ๋ฝ์ฒ˜: 010-1234-5678, 010-9876-5432, 010-1111-2222
    
    return 0;
}

๐Ÿ’ก ์บก์ฒ˜ ๊ทธ๋ฃน ํ™œ์šฉ๋ฒ•! ๊ด„ํ˜ธ ()๋กœ ๋ฌถ์ธ ๋ถ€๋ถ„์€ ์บก์ฒ˜ ๊ทธ๋ฃน์ด ๋ผ. $1, $2๋กœ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์–ด์„œ ํŒจํ„ด์˜ ์ผ๋ถ€๋งŒ ์ถ”์ถœํ•˜๊ฑฐ๋‚˜ ์žฌ๋ฐฐ์น˜ํ•  ๋•Œ ์—„์ฒญ ์œ ์šฉํ•ด!

๐Ÿ” ๋น„๋ฐ€๋ฒˆํ˜ธ ๊ฐ•๋„ ๊ฒ€์ฆ

๋ณด์•ˆ์ด ์ค‘์š”ํ•œ ์‹œ๋Œ€! ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์ถฉ๋ถ„ํžˆ ๊ฐ•๋ ฅํ•œ์ง€ ๊ฒ€์ฆํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž:

#include <iostream>
#include <regex>
#include <string>

struct PasswordStrength {
    bool hasMinLength;
    bool hasUpperCase;
    bool hasLowerCase;
    bool hasDigit;
    bool hasSpecialChar;
    
    bool isStrong() const {
        return hasMinLength && hasUpperCase && 
               hasLowerCase && hasDigit && hasSpecialChar;
    }
};

PasswordStrength checkPassword(const std::string& password) {
    PasswordStrength strength;
    
    // ์ตœ์†Œ 8์ž ์ด์ƒ
    strength.hasMinLength = password.length() >= 8;
    
    // ๋Œ€๋ฌธ์ž ํฌํ•จ
    strength.hasUpperCase = std::regex_search(password, std::regex("[A-Z]"));
    
    // ์†Œ๋ฌธ์ž ํฌํ•จ
    strength.hasLowerCase = std::regex_search(password, std::regex("[a-z]"));
    
    // ์ˆซ์ž ํฌํ•จ
    strength.hasDigit = std::regex_search(password, std::regex(R"(\d)"));
    
    // ํŠน์ˆ˜๋ฌธ์ž ํฌํ•จ
    strength.hasSpecialChar = std::regex_search(
        password, 
        std::regex(R"([!@#$%^&*()_+\-=\[\]{};':"\\|,.<>/?])")
    );
    
    return strength;
}

void printPasswordAnalysis(const std::string& password) {
    auto strength = checkPassword(password);
    
    std::cout << "๋น„๋ฐ€๋ฒˆํ˜ธ: " << password << std::endl;
    std::cout << "๊ธธ์ด (8์ž ์ด์ƒ): " << (strength.hasMinLength ? "โœ…" : "โŒ") << std::endl;
    std::cout << "๋Œ€๋ฌธ์ž ํฌํ•จ: " << (strength.hasUpperCase ? "โœ…" : "โŒ") << std::endl;
    std::cout << "์†Œ๋ฌธ์ž ํฌํ•จ: " << (strength.hasLowerCase ? "โœ…" : "โŒ") << std::endl;
    std::cout << "์ˆซ์ž ํฌํ•จ: " << (strength.hasDigit ? "โœ…" : "โŒ") << std::endl;
    std::cout << "ํŠน์ˆ˜๋ฌธ์ž ํฌํ•จ: " << (strength.hasSpecialChar ? "โœ…" : "โŒ") << std::endl;
    std::cout << "๊ฐ•๋„: " << (strength.isStrong() ? "๐Ÿ”’ ๊ฐ•ํ•จ" : "โš ๏ธ ์•ฝํ•จ") << std::endl;
    std::cout << "---" << std::endl;
}

int main() {
    printPasswordAnalysis("password");           // ์•ฝํ•จ
    printPasswordAnalysis("Password123");        // ์•ฝํ•จ (ํŠน์ˆ˜๋ฌธ์ž ์—†์Œ)
    printPasswordAnalysis("Pass123!");           // ์•ฝํ•จ (8์ž ๋ฏธ๋งŒ)
    printPasswordAnalysis("Password123!");       // ๊ฐ•ํ•จ!
    
    return 0;
}
์ •๊ทœํ‘œํ˜„์‹ ๋งค์นญ ํ”„๋กœ์„ธ์Šค 1. ํŒจํ„ด ์ •์˜ std::regex pattern 2. ํ…์ŠคํŠธ ์ž…๋ ฅ std::string text 3. ๋งค์นญ ์‹คํ–‰ regex_search ๊ฒฐ๊ณผ true/false regex_match ์ „์ฒด ๋ฌธ์ž์—ด ์ผ์น˜ ์ž…๋ ฅ: "12345" ํŒจํ„ด: "^\d+$" โ†’ ๋งค์นญ! regex_search ๋ถ€๋ถ„ ๋ฌธ์ž์—ด ๊ฒ€์ƒ‰ ์ž…๋ ฅ: "abc123def" ํŒจํ„ด: "\d+" โ†’ "123" ๋ฐœ๊ฒฌ! regex_replace ํŒจํ„ด ์น˜ํ™˜ ์ž…๋ ฅ: "010-1234-5678" โ†’ "***-****-5678"

๐ŸŽฏ ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ: regex_iterator์™€ smatch

ํ•œ ๋ฌธ์ž์—ด์—์„œ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋งค์นญ ๊ฒฐ๊ณผ๋ฅผ ์ฐพ์•„์•ผ ํ•  ๋•Œ๊ฐ€ ์žˆ์ง€? ๊ทธ๋Ÿด ๋•Œ๋Š” regex_iterator๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ผ! ๐Ÿ˜Š

๐Ÿ”„ ๋ชจ๋“  ๋งค์นญ ๊ฒฐ๊ณผ ์ˆœํšŒํ•˜๊ธฐ

#include <iostream>
#include <regex>
#include <string>

int main() {
    std::string text = "์ด๋ฉ”์ผ ๋ชฉ๋ก: user1@test.com, admin@example.com, info@company.co.kr";
    std::regex pattern(R"([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})");
    
    // regex_iterator ์ƒ์„ฑ
    auto words_begin = std::sregex_iterator(text.begin(), text.end(), pattern);
    auto words_end = std::sregex_iterator();
    
    int count = 0;
    std::cout << "๋ฐœ๊ฒฌ๋œ ์ด๋ฉ”์ผ ์ฃผ์†Œ๋“ค:" << std::endl;
    
    for (std::sregex_iterator i = words_begin; i != words_end; ++i) {
        std::smatch match = *i;
        std::cout << ++count << ". " << match.str() << std::endl;
    }
    
    std::cout << "์ด " << count << "๊ฐœ์˜ ์ด๋ฉ”์ผ์„ ์ฐพ์•˜์–ด์š”! ๐Ÿ“ง" << std::endl;
    
    return 0;
}

// ์ถœ๋ ฅ:
// ๋ฐœ๊ฒฌ๋œ ์ด๋ฉ”์ผ ์ฃผ์†Œ๋“ค:
// 1. user1@test.com
// 2. admin@example.com
// 3. info@company.co.kr
// ์ด 3๊ฐœ์˜ ์ด๋ฉ”์ผ์„ ์ฐพ์•˜์–ด์š”! ๐Ÿ“ง

๐Ÿ“ฆ smatch๋กœ ์ƒ์„ธ ์ •๋ณด ์ถ”์ถœํ•˜๊ธฐ

smatch๋Š” ๋งค์นญ ๊ฒฐ๊ณผ์— ๋Œ€ํ•œ ์ƒ์„ธํ•œ ์ •๋ณด๋ฅผ ๋‹ด๊ณ  ์žˆ์–ด. ์บก์ฒ˜ ๊ทธ๋ฃน๋ณ„๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์–ด์„œ ์ •๋ง ์œ ์šฉํ•ด!

#include <iostream>
#include <regex>
#include <string>

int main() {
    std::string text = "์ƒ๋…„์›”์ผ: 1990-05-15";
    
    // ์บก์ฒ˜ ๊ทธ๋ฃน์œผ๋กœ ๋…„, ์›”, ์ผ์„ ๋ถ„๋ฆฌ
    std::regex pattern(R"((\d{4})-(\d{2})-(\d{2}))");
    std::smatch match;
    
    if (std::regex_search(text, match, pattern)) {
        std::cout << "์ „์ฒด ๋งค์นญ: " << match.str(0) << std::endl;
        std::cout << "๋…„๋„: " << match.str(1) << std::endl;
        std::cout << "์›”: " << match.str(2) << std::endl;
        std::cout << "์ผ: " << match.str(3) << std::endl;
        
        // ์ถ”๊ฐ€ ์ •๋ณด
        std::cout << "\n๋งค์นญ ์œ„์น˜: " << match.position() << std::endl;
        std::cout << "๋งค์นญ ๊ธธ์ด: " << match.length() << std::endl;
        std::cout << "๋งค์นญ ์ „ ๋ฌธ์ž์—ด: " << match.prefix() << std::endl;
        std::cout << "๋งค์นญ ํ›„ ๋ฌธ์ž์—ด: " << match.suffix() << std::endl;
    }
    
    return 0;
}

// ์ถœ๋ ฅ:
// ์ „์ฒด ๋งค์นญ: 1990-05-15
// ๋…„๋„: 1990
// ์›”: 05
// ์ผ: 15
// 
// ๋งค์นญ ์œ„์น˜: 7
// ๋งค์นญ ๊ธธ์ด: 10
// ๋งค์นญ ์ „ ๋ฌธ์ž์—ด: ์ƒ๋…„์›”์ผ: 
// ๋งค์นญ ํ›„ ๋ฌธ์ž์—ด: 

๐ŸŽ“ smatch ์ฃผ์š” ๋ฉ”์„œ๋“œ:

โ€ข str(n) - n๋ฒˆ์งธ ์บก์ฒ˜ ๊ทธ๋ฃน์˜ ๋ฌธ์ž์—ด (0์€ ์ „์ฒด ๋งค์นญ)

โ€ข position(n) - n๋ฒˆ์งธ ์บก์ฒ˜ ๊ทธ๋ฃน์˜ ์‹œ์ž‘ ์œ„์น˜

โ€ข length(n) - n๋ฒˆ์งธ ์บก์ฒ˜ ๊ทธ๋ฃน์˜ ๊ธธ์ด

โ€ข prefix() - ๋งค์นญ ์ด์ „์˜ ๋ฌธ์ž์—ด

โ€ข suffix() - ๋งค์นญ ์ดํ›„์˜ ๋ฌธ์ž์—ด

โ€ข size() - ์บก์ฒ˜ ๊ทธ๋ฃน์˜ ๊ฐœ์ˆ˜ (์ „์ฒด ๋งค์นญ ํฌํ•จ)

โšก ์„ฑ๋Šฅ ์ตœ์ ํ™” ํŒ

์ •๊ทœํ‘œํ˜„์‹์€ ๊ฐ•๋ ฅํ•˜์ง€๋งŒ, ์ž˜๋ชป ์‚ฌ์šฉํ•˜๋ฉด ์„ฑ๋Šฅ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธธ ์ˆ˜ ์žˆ์–ด. ์‹ค์ „์—์„œ ์œ ์šฉํ•œ ์ตœ์ ํ™” ํŒ๋“ค์„ ์•Œ๋ ค์ค„๊ฒŒ! ๐Ÿš€

1๏ธโƒฃ ์ •๊ทœํ‘œํ˜„์‹ ๊ฐ์ฒด ์žฌ์‚ฌ์šฉํ•˜๊ธฐ

โš ๏ธ ๋น„ํšจ์œจ์ ์ธ ์ฝ”๋“œ:

// ๋‚˜์œ ์˜ˆ: ๋งค๋ฒˆ regex ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ
for (const auto& text : texts) {
    std::regex pattern(R"(\d+)");  // ๋ฐ˜๋ณต๋ฌธ๋งˆ๋‹ค ์ปดํŒŒ์ผ! ๐Ÿ˜ฑ
    if (std::regex_search(text, pattern)) {
        // ...
    }
}

โœ… ํšจ์œจ์ ์ธ ์ฝ”๋“œ:

// ์ข‹์€ ์˜ˆ: regex ๊ฐ์ฒด๋ฅผ ํ•œ ๋ฒˆ๋งŒ ์ƒ์„ฑ
std::regex pattern(R"(\d+)");  // ํ•œ ๋ฒˆ๋งŒ ์ปดํŒŒ์ผ! ๐Ÿ˜Š

for (const auto& text : texts) {
    if (std::regex_search(text, pattern)) {
        // ...
    }
}

์ •๊ทœํ‘œํ˜„์‹ ํŒจํ„ด์„ ์ปดํŒŒ์ผํ•˜๋Š” ๊ฑด ๋น„์šฉ์ด ํฐ ์ž‘์—…์ด์•ผ. ๊ฐ™์€ ํŒจํ„ด์„ ์—ฌ๋Ÿฌ ๋ฒˆ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ๋ฐ˜๋“œ์‹œ ๊ฐ์ฒด๋ฅผ ์žฌ์‚ฌ์šฉํ•ด์•ผ ํ•ด!

2๏ธโƒฃ ์ ์ ˆํ•œ ํ•จ์ˆ˜ ์„ ํƒํ•˜๊ธฐ

regex_match - ์ „์ฒด ๋ฌธ์ž์—ด์ด ํŒจํ„ด๊ณผ ์ผ์น˜ํ•˜๋Š”์ง€๋งŒ ํ™•์ธํ•  ๋•Œ (๊ฐ€์žฅ ๋น ๋ฆ„)

regex_search - ๋ฌธ์ž์—ด ๋‚ด์—์„œ ํŒจํ„ด์„ ์ฐพ์„ ๋•Œ

regex_iterator - ๋ชจ๋“  ๋งค์นญ์„ ์ฐพ์•„์•ผ ํ•  ๋•Œ

std::string input = "12345";

// ์ „์ฒด๊ฐ€ ์ˆซ์ž์ธ์ง€๋งŒ ํ™•์ธํ•˜๋ฉด ๋˜๋Š” ๊ฒฝ์šฐ
if (std::regex_match(input, std::regex(R"(^\d+$)"))) {
    // regex_match๊ฐ€ regex_search๋ณด๋‹ค ๋น ๋ฆ„!
}

// ์ˆซ์ž๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๊ฒฝ์šฐ
if (std::regex_search(input, std::regex(R"(\d+)"))) {
    // ์ด ๊ฒฝ์šฐ๋Š” regex_search ์‚ฌ์šฉ
}

3๏ธโƒฃ ํƒ์š•์  vs ๊ฒŒ์œผ๋ฅธ ์ˆ˜๋Ÿ‰์ž

์ˆ˜๋Ÿ‰์ž์˜ ํƒ์š•์„ฑ(greedy)์„ ์ดํ•ดํ•˜๋ฉด ์„ฑ๋Šฅ๊ณผ ์ •ํ™•์„ฑ์„ ๋ชจ๋‘ ์žก์„ ์ˆ˜ ์žˆ์–ด!

ํƒ์š•์  ์ˆ˜๋Ÿ‰์ž (Greedy): ๊ฐ€๋Šฅํ•œ ํ•œ ๋งŽ์ด ๋งค์นญ

โ€ข *, +, {n,}


๊ฒŒ์œผ๋ฅธ ์ˆ˜๋Ÿ‰์ž (Lazy): ๊ฐ€๋Šฅํ•œ ํ•œ ์ ๊ฒŒ ๋งค์นญ

โ€ข *?, +?, {n,}?

#include <iostream>
#include <regex>
#include <string>

int main() {
    std::string html = "<div>์ฒซ๋ฒˆ์งธ</div><div>๋‘๋ฒˆ์งธ</div>";
    
    // ํƒ์š•์ : ๊ฐ€๋Šฅํ•œ ํ•œ ๋งŽ์ด ๋งค์นญ
    std::regex greedy(R"(<div>.*</div>)");
    std::smatch match1;
    if (std::regex_search(html, match1, greedy)) {
        std::cout << "ํƒ์š•์ : " << match1.str() << std::endl;
        // ์ถœ๋ ฅ: <div>์ฒซ๋ฒˆ์งธ</div><div>๋‘๋ฒˆ์งธ</div> (์ „์ฒด๋ฅผ ๋งค์นญ!)
    }
    
    // ๊ฒŒ์œผ๋ฅธ: ๊ฐ€๋Šฅํ•œ ํ•œ ์ ๊ฒŒ ๋งค์นญ
    std::regex lazy(R"(<div>.*?</div>)");
    std::smatch match2;
    if (std::regex_search(html, match2, lazy)) {
        std::cout << "๊ฒŒ์œผ๋ฅธ: " << match2.str() << std::endl;
        // ์ถœ๋ ฅ: <div>์ฒซ๋ฒˆ์งธ</div> (์ฒซ ๋ฒˆ์งธ๋งŒ ๋งค์นญ!)
    }
    
    return 0;
}

๐Ÿ’ก HTML/XML ํŒŒ์‹ฑํ•  ๋•Œ๋Š” ๊ฒŒ์œผ๋ฅธ ์ˆ˜๋Ÿ‰์ž๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ ์ผ๋ฐ˜์ ์ด์•ผ. ํ•˜์ง€๋งŒ ๋ณต์žกํ•œ HTML์€ ์ •๊ทœํ‘œํ˜„์‹๋ณด๋‹ค ์ „์šฉ ํŒŒ์„œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ ์ข‹์•„!

4๏ธโƒฃ ์ปดํŒŒ์ผ ์˜ต์…˜ ํ™œ์šฉํ•˜๊ธฐ

std::regex๋Š” ๋‹ค์–‘ํ•œ ์ปดํŒŒ์ผ ์˜ต์…˜์„ ์ œ๊ณตํ•ด. ์ƒํ™ฉ์— ๋งž๊ฒŒ ์‚ฌ์šฉํ•˜๋ฉด ์„ฑ๋Šฅ๊ณผ ๊ธฐ๋Šฅ์„ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์–ด!

#include <iostream>
#include <regex>
#include <string>

int main() {
    std::string text = "Hello WORLD";
    
    // ๊ธฐ๋ณธ: ๋Œ€์†Œ๋ฌธ์ž ๊ตฌ๋ถ„
    std::regex pattern1("hello");
    std::cout << std::regex_search(text, pattern1) << std::endl;  // 0 (false)
    
    // icase: ๋Œ€์†Œ๋ฌธ์ž ๋ฌด์‹œ
    std::regex pattern2("hello", std::regex::icase);
    std::cout << std::regex_search(text, pattern2) << std::endl;  // 1 (true)
    
    // optimize: ์„ฑ๋Šฅ ์ตœ์ ํ™” (์ปดํŒŒ์ผ ์‹œ๊ฐ„์€ ๋Š˜์–ด๋‚˜์ง€๋งŒ ์‹คํ–‰ ์†๋„ ํ–ฅ์ƒ)
    std::regex pattern3(R"(\d+)", std::regex::optimize);
    
    // ECMAScript (๊ธฐ๋ณธ), extended, awk, grep, egrep ๋“ฑ ๋ฌธ๋ฒ• ์„ ํƒ ๊ฐ€๋Šฅ
    std::regex pattern4(R"(\d+)", std::regex::extended);
    
    return 0;
}
์˜ต์…˜ ์„ค๋ช… ์‚ฌ์šฉ ์‹œ๋‚˜๋ฆฌ์˜ค
icase ๋Œ€์†Œ๋ฌธ์ž ๋ฌด์‹œ ์‚ฌ์šฉ์ž ์ž…๋ ฅ ๊ฒ€์ฆ
optimize ์‹คํ–‰ ์†๋„ ์ตœ์ ํ™” ๊ฐ™์€ ํŒจํ„ด์„ ๋งŽ์ด ์‚ฌ์šฉํ•  ๋•Œ
nosubs ์บก์ฒ˜ ๊ทธ๋ฃน ๋ฌด์‹œ ๋งค์นญ ์—ฌ๋ถ€๋งŒ ํ™•์ธํ•  ๋•Œ
multiline ^์™€ $๊ฐ€ ๊ฐ ์ค„์— ์ ์šฉ ์—ฌ๋Ÿฌ ์ค„ ํ…์ŠคํŠธ ์ฒ˜๋ฆฌ

๐ŸŽจ ์‹ค์ „ ํ”„๋กœ์ ํŠธ: ๋กœ๊ทธ ํŒŒ์ผ ๋ถ„์„๊ธฐ

์ด์ œ ๋ฐฐ์šด ๋‚ด์šฉ์„ ์ข…ํ•ฉํ•ด์„œ ์‹ค์šฉ์ ์ธ ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž! ์„œ๋ฒ„ ๋กœ๊ทธ ํŒŒ์ผ์„ ๋ถ„์„ํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์ด์•ผ. ๐Ÿ”

#include <iostream>
#include <regex>
#include <string>
#include <vector>
#include <map>
#include <fstream>

struct LogEntry {
    std::string timestamp;
    std::string level;
    std::string ip;
    std::string message;
};

class LogAnalyzer {
private:
    // ๋กœ๊ทธ ํŒจํ„ด: [2024-01-15 10:30:45] ERROR 192.168.1.1 - Connection failed
    std::regex logPattern{
        R"(\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\] (\w+) ([\d.]+) - (.+))"
    };
    
    std::vector<LogEntry> logs;
    std::map<std::string, int> levelCount;
    std::map<std::string, int> ipCount;

public:
    void parseLine(const std::string& line) {
        std::smatch match;
        if (std::regex_search(line, match, logPattern)) {
            LogEntry entry;
            entry.timestamp = match.str(1);
            entry.level = match.str(2);
            entry.ip = match.str(3);
            entry.message = match.str(4);
            
            logs.push_back(entry);
            levelCount[entry.level]++;
            ipCount[entry.ip]++;
        }
    }
    
    void parseFile(const std::string& filename) {
        std::ifstream file(filename);
        std::string line;
        
        while (std::getline(file, line)) {
            parseLine(line);
        }
    }
    
    void printStatistics() {
        std::cout << "๐Ÿ“Š ๋กœ๊ทธ ๋ถ„์„ ๊ฒฐ๊ณผ\n" << std::endl;
        std::cout << "์ด ๋กœ๊ทธ ์ˆ˜: " << logs.size() << std::endl;
        
        std::cout << "\n๋กœ๊ทธ ๋ ˆ๋ฒจ๋ณ„ ํ†ต๊ณ„:" << std::endl;
        for (const auto& [level, count] : levelCount) {
            std::cout << "  " << level << ": " << count << "๊ฑด" << std::endl;
        }
        
        std::cout << "\nIP๋ณ„ ์ ‘์† ํ†ต๊ณ„ (์ƒ์œ„ 5๊ฐœ):" << std::endl;
        std::vector<std::pair<std::string, int>> sortedIPs(ipCount.begin(), ipCount.end());
        std::sort(sortedIPs.begin(), sortedIPs.end(),
                  [](const auto& a, const auto& b) { return a.second > b.second; });
        
        int count = 0;
        for (const auto& [ip, cnt] : sortedIPs) {
            if (++count > 5) break;
            std::cout << "  " << ip << ": " << cnt << "ํšŒ" << std::endl;
        }
    }
    
    std::vector<LogEntry> findErrorsFromIP(const std::string& ip) {
        std::vector<LogEntry> errors;
        for (const auto& log : logs) {
            if (log.ip == ip && log.level == "ERROR") {
                errors.push_back(log);
            }
        }
        return errors;
    }
    
    std::vector<LogEntry> findByTimeRange(
        const std::string& startTime, 
        const std::string& endTime
    ) {
        std::vector<LogEntry> results;
        for (const auto& log : logs) {
            if (log.timestamp >= startTime && log.timestamp <= endTime) {
                results.push_back(log);
            }
        }
        return results;
    }
};

int main() {
    LogAnalyzer analyzer;
    
    // ์ƒ˜ํ”Œ ๋กœ๊ทธ ๋ฐ์ดํ„ฐ
    std::vector<std::string> sampleLogs = {
        "[2024-01-15 10:30:45] INFO 192.168.1.100 - User login successful",
        "[2024-01-15 10:31:20] ERROR 192.168.1.100 - Database connection failed",
        "[2024-01-15 10:32:15] INFO 192.168.1.101 - Page loaded",
        "[2024-01-15 10:33:00] WARNING 192.168.1.102 - High memory usage",
        "[2024-01-15 10:34:30] ERROR 192.168.1.100 - Timeout occurred",
        "[2024-01-15 10:35:45] INFO 192.168.1.103 - File uploaded",
        "[2024-01-15 10:36:20] ERROR 192.168.1.101 - Invalid request"
    };
    
    // ๋กœ๊ทธ ํŒŒ์‹ฑ
    for (const auto& log : sampleLogs) {
        analyzer.parseLine(log);
    }
    
    // ํ†ต๊ณ„ ์ถœ๋ ฅ
    analyzer.printStatistics();
    
    // ํŠน์ • IP์˜ ์—๋Ÿฌ ์ฐพ๊ธฐ
    std::cout << "\n๐Ÿ” 192.168.1.100์˜ ์—๋Ÿฌ ๋กœ๊ทธ:" << std::endl;
    auto errors = analyzer.findErrorsFromIP("192.168.1.100");
    for (const auto& error : errors) {
        std::cout << "  [" << error.timestamp << "] " 
                  << error.message << std::endl;
    }
    
    return 0;
}

์ด ๋กœ๊ทธ ๋ถ„์„๊ธฐ๋Š” ์‹ค์ œ ์„œ๋ฒ„ ๊ด€๋ฆฌ์—์„œ ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด! ์ •๊ทœํ‘œํ˜„์‹์œผ๋กœ ๋กœ๊ทธ ํ˜•์‹์„ ํŒŒ์‹ฑํ•˜๊ณ , ํ†ต๊ณ„๋ฅผ ๋‚ด๊ณ , ํŠน์ • ์กฐ๊ฑด์˜ ๋กœ๊ทธ๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์ง€. ๐Ÿ˜Š

๐ŸŒ ์‹ค์ „ ํ™œ์šฉ: URL ํŒŒ์‹ฑ๊ณผ ๊ฒ€์ฆ

์›น ๊ฐœ๋ฐœ์—์„œ ๋น ์งˆ ์ˆ˜ ์—†๋Š” ๊ฒŒ URL ์ฒ˜๋ฆฌ์ง€! URL์„ ํŒŒ์‹ฑํ•˜๊ณ  ๊ฒ€์ฆํ•˜๋Š” ์‹ค์šฉ์ ์ธ ์˜ˆ์ œ๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž. ๐ŸŒ

#include <iostream>
#include <regex>
#include <string>
#include <optional>

struct URL {
    std::string protocol;
    std::string domain;
    std::string port;
    std::string path;
    std::string query;
    std::string fragment;
    
    void print() const {
        std::cout << "๐Ÿ”— URL ๋ถ„์„ ๊ฒฐ๊ณผ:" << std::endl;
        std::cout << "  ํ”„๋กœํ† ์ฝœ: " << protocol << std::endl;
        std::cout << "  ๋„๋ฉ”์ธ: " << domain << std::endl;
        if (!port.empty()) 
            std::cout << "  ํฌํŠธ: " << port << std::endl;
        if (!path.empty()) 
            std::cout << "  ๊ฒฝ๋กœ: " << path << std::endl;
        if (!query.empty()) 
            std::cout << "  ์ฟผ๋ฆฌ: " << query << std::endl;
        if (!fragment.empty()) 
            std::cout << "  ํ”„๋ž˜๊ทธ๋จผํŠธ: " << fragment << std::endl;
    }
};

class URLParser {
private:
    // URL ํŒŒ์‹ฑ ์ •๊ทœํ‘œํ˜„์‹
    std::regex urlPattern{
        R"(^(https?):\/\/"                    // ํ”„๋กœํ† ์ฝœ
        R"(([a-zA-Z0-9.-]+)"                  // ๋„๋ฉ”์ธ
        R"((?::(\d+))?"                       // ํฌํŠธ (์„ ํƒ)
        R"(([\/\w.-]*)"                       // ๊ฒฝ๋กœ (์„ ํƒ)
        R"((?:\?([^#]*))?"                    // ์ฟผ๋ฆฌ (์„ ํƒ)
        R"((?:#(.*))?$)"                      // ํ”„๋ž˜๊ทธ๋จผํŠธ (์„ ํƒ)
    };

public:
    std::optional<URL> parse(const std::string& urlString) {
        std::smatch match;
        
        if (!std::regex_match(urlString, match, urlPattern)) {
            return std::nullopt;
        }
        
        URL url;
        url.protocol = match.str(1);
        url.domain = match.str(2);
        url.port = match.str(3);
        url.path = match.str(4);
        url.query = match.str(5);
        url.fragment = match.str(6);
        
        return url;
    }
    
    bool isValidURL(const std::string& urlString) {
        return std::regex_match(urlString, urlPattern);
    }
    
    std::string extractDomain(const std::string& urlString) {
        std::regex domainPattern(R"(https?:\/\/([a-zA-Z0-9.-]+))");
        std::smatch match;
        
        if (std::regex_search(urlString, match, domainPattern)) {
            return match.str(1);
        }
        return "";
    }
    
    std::map<std::string, std::string> parseQueryString(const std::string& query) {
        std::map<std::string, std::string> params;
        std::regex paramPattern(R"(([^&=]+)=([^&]*))");
        
        auto begin = std::sregex_iterator(query.begin(), query.end(), paramPattern);
        auto end = std::sregex_iterator();
        
        for (auto it = begin; it != end; ++it) {
            std::smatch match = *it;
            params[match.str(1)] = match.str(2);
        }
        
        return params;
    }
};

int main() {
    URLParser parser;
    
    std::vector<std::string> testURLs = {
        "https://www.jaenung.net/knowledge/article?id=123&category=cpp#section2",
        "http://example.com:8080/api/users",
        "https://github.com/user/repo",
        "invalid-url",
        "ftp://files.example.com/download"
    };
    
    for (const auto& urlString : testURLs) {
        std::cout << "\n๋ถ„์„ ๋Œ€์ƒ: " << urlString << std::endl;
        
        if (auto url = parser.parse(urlString)) {
            url->print();
            
            // ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ ํŒŒ์‹ฑ
            if (!url->query.empty()) {
                std::cout << "\n  ๐Ÿ“‹ ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ:" << std::endl;
                auto params = parser.parseQueryString(url->query);
                for (const auto& [key, value] : params) {
                    std::cout << "    " << key << " = " << value << std::endl;
                }
            }
        } else {
            std::cout << "  โŒ ์œ ํšจํ•˜์ง€ ์•Š์€ URL์ž…๋‹ˆ๋‹ค." << std::endl;
        }
        std::cout << std::string(50, '-') << std::endl;
    }
    
    return 0;
}

์ด URL ํŒŒ์„œ๋Š” ์›น ํฌ๋กค๋Ÿฌ๋‚˜ API ํด๋ผ์ด์–ธํŠธ๋ฅผ ๋งŒ๋“ค ๋•Œ ์ •๋ง ์œ ์šฉํ•ด! ์žฌ๋Šฅ๋„ท ๊ฐ™์€ ํ”Œ๋žซํผ์—์„œ๋„ URL ๊ฒ€์ฆ๊ณผ ํŒŒ์‹ฑ์€ ํ•„์ˆ˜์ ์ธ ๊ธฐ๋Šฅ์ด์ง€. ๐ŸŽฏ

๐ŸŽญ ์ •๊ทœํ‘œํ˜„์‹ ๋””๋ฒ„๊น…๊ณผ ํ…Œ์ŠคํŠธ

์ •๊ทœํ‘œํ˜„์‹์€ ๊ฐ•๋ ฅํ•˜์ง€๋งŒ ๋ณต์žกํ•ด์งˆ์ˆ˜๋ก ๋””๋ฒ„๊น…์ด ์–ด๋ ค์›Œ์ ธ. ํšจ๊ณผ์ ์œผ๋กœ ํ…Œ์ŠคํŠธํ•˜๊ณ  ๋””๋ฒ„๊น…ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด์ž! ๐Ÿ”ง

๐Ÿงช ํ…Œ์ŠคํŠธ ํ”„๋ ˆ์ž„์›Œํฌ ๋งŒ๋“ค๊ธฐ

#include <iostream>
#include <regex>
#include <string>
#include <vector>

class RegexTester {
private:
    struct TestCase {
        std::string input;
        bool shouldMatch;
        std::string description;
    };
    
    std::string pattern;
    std::regex regex;
    std::vector<TestCase> testCases;
    
public:
    RegexTester(const std::string& pattern) 
        : pattern(pattern), regex(pattern) {}
    
    void addTest(const std::string& input, bool shouldMatch, 
                 const std::string& description = "") {
        testCases.push_back({input, shouldMatch, description});
    }
    
    void runTests() {
        std::cout << "๐Ÿงช ์ •๊ทœํ‘œํ˜„์‹ ํ…Œ์ŠคํŠธ ์‹œ์ž‘" << std::endl;
        std::cout << "ํŒจํ„ด: " << pattern << "\n" << std::endl;
        
        int passed = 0;
        int failed = 0;
        
        for (size_t i = 0; i < testCases.size(); ++i) {
            const auto& test = testCases[i];
            bool result = std::regex_match(test.input, regex);
            bool success = (result == test.shouldMatch);
            
            if (success) {
                std::cout << "โœ… ํ…Œ์ŠคํŠธ " << (i + 1) << " ํ†ต๊ณผ";
                passed++;
            } else {
                std::cout << "โŒ ํ…Œ์ŠคํŠธ " << (i + 1) << " ์‹คํŒจ";
                failed++;
            }
            
            std::cout << " - " << test.input;
            if (!test.description.empty()) {
                std::cout << " (" << test.description << ")";
            }
            std::cout << std::endl;
            
            if (!success) {
                std::cout << "  ์˜ˆ์ƒ: " << (test.shouldMatch ? "๋งค์นญ" : "๋ถˆ์ผ์น˜")
                          << ", ์‹ค์ œ: " << (result ? "๋งค์นญ" : "๋ถˆ์ผ์น˜") << std::endl;
            }
        }
        
        std::cout << "\n๐Ÿ“Š ๊ฒฐ๊ณผ: " << passed << "๊ฐœ ํ†ต๊ณผ, " 
                  << failed << "๊ฐœ ์‹คํŒจ" << std::endl;
    }
    
    void explainPattern() {
        std::cout << "\n๐Ÿ“– ํŒจํ„ด ์„ค๋ช…:" << std::endl;
        std::cout << pattern << std::endl;
        // ์—ฌ๊ธฐ์— ํŒจํ„ด ๋ถ„์„ ๋กœ์ง์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์–ด
    }
};

int main() {
    // ์ด๋ฉ”์ผ ๊ฒ€์ฆ ํ…Œ์ŠคํŠธ
    RegexTester emailTester(R"(^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$)");
    
    emailTester.addTest("user@example.com", true, "๊ธฐ๋ณธ ์ด๋ฉ”์ผ");
    emailTester.addTest("test.user@domain.co.kr", true, "์ ๊ณผ ์„œ๋ธŒ๋„๋ฉ”์ธ");
    emailTester.addTest("user+tag@example.com", true, "ํ”Œ๋Ÿฌ์Šค ๊ธฐํ˜ธ");
    emailTester.addTest("invalid@", false, "๋„๋ฉ”์ธ ์—†์Œ");
    emailTester.addTest("@invalid.com", false, "์‚ฌ์šฉ์ž๋ช… ์—†์Œ");
    emailTester.addTest("no-at-sign.com", false, "@๊ธฐํ˜ธ ์—†์Œ");
    emailTester.addTest("user@domain", false, "์ตœ์ƒ์œ„ ๋„๋ฉ”์ธ ์—†์Œ");
    
    emailTester.runTests();
    
    std::cout << "\n" << std::string(60, '=') << "\n" << std::endl;
    
    // ์ „ํ™”๋ฒˆํ˜ธ ๊ฒ€์ฆ ํ…Œ์ŠคํŠธ
    RegexTester phoneTester(R"(^01[0-9]-\d{4}-\d{4}$)");
    
    phoneTester.addTest("010-1234-5678", true, "์ผ๋ฐ˜ ํœด๋Œ€ํฐ");
    phoneTester.addTest("011-9876-5432", true, "011 ๋ฒˆํ˜ธ");
    phoneTester.addTest("010-123-5678", false, "์ค‘๊ฐ„ ์ž๋ฆฌ ๋ถ€์กฑ");
    phoneTester.addTest("02-1234-5678", false, "์ง€์—ญ๋ฒˆํ˜ธ");
    phoneTester.addTest("01012345678", false, "ํ•˜์ดํ”ˆ ์—†์Œ");
    
    phoneTester.runTests();
    
    return 0;
}

๐Ÿ’ก ์‹ค์ „ ํŒ: ์ •๊ทœํ‘œํ˜„์‹์„ ์ž‘์„ฑํ•  ๋•Œ๋Š” ํ•ญ์ƒ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค๋ฅผ ํ•จ๊ป˜ ๋งŒ๋“ค์–ด. ํŠนํžˆ ๊ฒฝ๊ณ„ ์กฐ๊ฑด(boundary conditions)์„ ๊ผญ ํ…Œ์ŠคํŠธํ•ด์•ผ ํ•ด!

๐Ÿ” ์ผ๋ฐ˜์ ์ธ ์‹ค์ˆ˜์™€ ํ•ด๊ฒฐ๋ฒ•

์‹ค์ˆ˜ 1: ๋ฐฑ์Šฌ๋ž˜์‹œ ์ด์Šค์ผ€์ดํ”„ ์žŠ๊ธฐ

// โŒ ์ž˜๋ชป๋œ ์ฝ”๋“œ
std::regex pattern("\d+");  // ์ปดํŒŒ์ผ ์—๋Ÿฌ ๋˜๋Š” ์˜ˆ์ƒ๊ณผ ๋‹ค๋ฅธ ๋™์ž‘

// โœ… ์˜ฌ๋ฐ”๋ฅธ ์ฝ”๋“œ
std::regex pattern("\\d+");  // ๋ฐฑ์Šฌ๋ž˜์‹œ ๋‘ ๋ฒˆ
// ๋˜๋Š”
std::regex pattern(R"(\d+)");  // raw string literal ์‚ฌ์šฉ

์‹ค์ˆ˜ 2: ํŠน์ˆ˜ ๋ฌธ์ž ์ด์Šค์ผ€์ดํ”„ ์•ˆ ํ•˜๊ธฐ

// โŒ ์ž˜๋ชป๋œ ์ฝ”๋“œ - ์ (.)์€ ๋ชจ๋“  ๋ฌธ์ž๋ฅผ ์˜๋ฏธ
std::regex pattern("192.168.1.1");  // "192A168B1C1"๋„ ๋งค์นญ๋จ!

// โœ… ์˜ฌ๋ฐ”๋ฅธ ์ฝ”๋“œ
std::regex pattern(R"(192\.168\.1\.1)");  // ์ ์„ ๋ฆฌํ„ฐ๋Ÿด๋กœ ์ฒ˜๋ฆฌ

์‹ค์ˆ˜ 3: regex_match์™€ regex_search ํ˜ผ๋™

std::string text = "๋‚ด ๋ฒˆํ˜ธ๋Š” 010-1234-5678์ด์•ผ";
std::regex pattern(R"(010-\d{4}-\d{4})");

// regex_match: ์ „์ฒด ๋ฌธ์ž์—ด์ด ํŒจํ„ด๊ณผ ์ผ์น˜ํ•ด์•ผ ํ•จ
std::cout << std::regex_match(text, pattern) << std::endl;  // 0 (false)

// regex_search: ๋ฌธ์ž์—ด ๋‚ด์—์„œ ํŒจํ„ด์„ ์ฐพ์Œ
std::cout << std::regex_search(text, pattern) << std::endl;  // 1 (true)
์ •๊ทœํ‘œํ˜„์‹ ํ™œ์šฉ ์‹œ๋‚˜๋ฆฌ์˜ค ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ โœ… ์ด๋ฉ”์ผ, ์ „ํ™”๋ฒˆํ˜ธ ๋น„๋ฐ€๋ฒˆํ˜ธ, URL ์‹ ์šฉ์นด๋“œ ๋ฒˆํ˜ธ ๋“ฑ ํ…์ŠคํŠธ ์ถ”์ถœ ๐Ÿ” ๋กœ๊ทธ ํŒŒ์ผ ๋ถ„์„ ์›น ์Šคํฌ๋ž˜ํ•‘ ๋ฐ์ดํ„ฐ ๋งˆ์ด๋‹ ๋ฌธ์ž์—ด ๋ณ€ํ™˜ ๐Ÿ”„ ํฌ๋งท ํ†ต์ผ ๋ฏผ๊ฐ์ •๋ณด ๋งˆ์Šคํ‚น ํ…์ŠคํŠธ ์ •์ œ ๊ตฌ๋ฌธ ๋ถ„์„ ๐Ÿ“ ์„ค์ • ํŒŒ์ผ ํŒŒ์‹ฑ ๊ฐ„๋‹จํ•œ DSL ํ…œํ”Œ๋ฆฟ ์ฒ˜๋ฆฌ ์„ฑ๋Šฅ ๊ณ ๋ ค์‚ฌํ•ญ ์ •๊ทœํ‘œํ˜„์‹ ๊ฐ์ฒด ์žฌ์‚ฌ์šฉ ์ ์ ˆํ•œ ํ•จ์ˆ˜ ์„ ํƒ optimize ํ”Œ๋ž˜๊ทธ ํ™œ์šฉ ๋ณต์žก๋„ ์ตœ์†Œํ™” ๋””๋ฒ„๊น… ํŒ ๋‹จ๊ณ„๋ณ„๋กœ ํŒจํ„ด ๊ตฌ์ถ• ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค ์ž‘์„ฑ ์˜จ๋ผ์ธ ๋„๊ตฌ ํ™œ์šฉ ์ฃผ์„์œผ๋กœ ์„ค๋ช… ์ถ”๊ฐ€ ๋ณด์•ˆ ์ฃผ์˜์‚ฌํ•ญ ReDoS ๊ณต๊ฒฉ ๋ฐฉ์ง€ ์ž…๋ ฅ ๊ธธ์ด ์ œํ•œ ํƒ€์ž„์•„์›ƒ ์„ค์ • ์•ˆ์ „ํ•œ ํŒจํ„ด ์‚ฌ์šฉ

๐Ÿ›ก๏ธ ๋ณด์•ˆ๊ณผ ์„ฑ๋Šฅ: ReDoS ๊ณต๊ฒฉ ๋ฐฉ์–ดํ•˜๊ธฐ

์ •๊ทœํ‘œํ˜„์‹์€ ๊ฐ•๋ ฅํ•˜์ง€๋งŒ, ์ž˜๋ชป ์ž‘์„ฑํ•˜๋ฉด ReDoS(Regular Expression Denial of Service) ๊ณต๊ฒฉ์— ์ทจ์•ฝํ•ด์งˆ ์ˆ˜ ์žˆ์–ด. ์ด๊ฑด ์ •๋ง ์ค‘์š”ํ•œ ๋ณด์•ˆ ์ด์Šˆ์•ผ! ๐Ÿšจ

โš ๏ธ ์œ„ํ—˜ํ•œ ํŒจํ„ด์˜ ์˜ˆ

์œ„ํ—˜ํ•œ ํŒจํ„ด: ์ค‘์ฒฉ๋œ ์ˆ˜๋Ÿ‰์ž

// โŒ ์œ„ํ—˜ํ•œ ํŒจํ„ด - ๋ฐฑํŠธ๋ž˜ํ‚น์ด ๊ธฐํ•˜๊ธ‰์ˆ˜์ ์œผ๋กœ ์ฆ๊ฐ€
std::regex dangerous(R"((a+)+b)");

// ์ด ์ž…๋ ฅ์€ ์—„์ฒญ๋‚œ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆผ (ReDoS ๊ณต๊ฒฉ!)
std::string malicious = "aaaaaaaaaaaaaaaaaaaaaaaaaaaa!";
// 'b'๊ฐ€ ์—†์–ด์„œ ๋ชจ๋“  ์กฐํ•ฉ์„ ์‹œ๋„ํ•˜๊ฒŒ ๋จ

โœ… ์•ˆ์ „ํ•œ ํŒจํ„ด์œผ๋กœ ๊ฐœ์„ 

// โœ… ์•ˆ์ „ํ•œ ํŒจํ„ด - ์ค‘์ฒฉ ์ œ๊ฑฐ
std::regex safe(R"(a+b)");

// ๋˜๋Š” ์†Œ์œ  ์ˆ˜๋Ÿ‰์ž ์‚ฌ์šฉ (C++์—์„œ๋Š” ์ œํ•œ์ )
std::regex safer(R"(a++b)");  // ๋ฐฑํŠธ๋ž˜ํ‚น ์—†์Œ

๐Ÿ”’ ์•ˆ์ „ํ•œ ์ •๊ทœํ‘œํ˜„์‹ ์ž‘์„ฑ ๊ฐ€์ด๋“œ

1. ์ค‘์ฒฉ๋œ ์ˆ˜๋Ÿ‰์ž ํ”ผํ•˜๊ธฐ

โ€ข (a+)+, (a*)* ๊ฐ™์€ ํŒจํ„ด์€ ์œ„ํ—˜

โ€ข ๊ฐ€๋Šฅํ•˜๋ฉด ๋‹จ์ผ ์ˆ˜๋Ÿ‰์ž๋กœ ํ‘œํ˜„: a+


2. ๊ต๋Œ€(alternation) ์ตœ์ ํ™”

โ€ข (a|a)* ๊ฐ™์€ ์ค‘๋ณต ํ”ผํ•˜๊ธฐ

โ€ข ๊ณตํ†ต ๋ถ€๋ถ„์„ ์•ž์œผ๋กœ: (abc|abd) โ†’ ab(c|d)


3. ์ž…๋ ฅ ๊ธธ์ด ์ œํ•œ

โ€ข ์‚ฌ์šฉ์ž ์ž…๋ ฅ์€ ํ•ญ์ƒ ๊ธธ์ด ๊ฒ€์ฆ

โ€ข ํ•ฉ๋ฆฌ์ ์ธ ์ตœ๋Œ€ ๊ธธ์ด ์„ค์ •


4. ํƒ€์ž„์•„์›ƒ ์„ค์ • ๊ณ ๋ ค

โ€ข ์žฅ์‹œ๊ฐ„ ์‹คํ–‰๋˜๋Š” ์ •๊ทœํ‘œํ˜„์‹ ๊ฐ์ง€

โ€ข ๋ณ„๋„ ์Šค๋ ˆ๋“œ์—์„œ ์‹คํ–‰ํ•˜๊ณ  ํƒ€์ž„์•„์›ƒ ์ ์šฉ

#include <iostream>
#include <regex>
#include <string>
#include <chrono>
#include <future>

class SafeRegex {
private:
    std::regex pattern;
    std::chrono::milliseconds timeout;
    size_t maxInputLength;

public:
    SafeRegex(const std::string& pattern, 
              std::chrono::milliseconds timeout = std::chrono::milliseconds(1000),
              size_t maxInputLength = 10000)
        : pattern(pattern), timeout(timeout), maxInputLength(maxInputLength) {}
    
    bool safeMatch(const std::string& input) {
        // ์ž…๋ ฅ ๊ธธ์ด ๊ฒ€์ฆ
        if (input.length() > maxInputLength) {
            std::cerr << "โš ๏ธ ์ž…๋ ฅ์ด ๋„ˆ๋ฌด ๊น๋‹ˆ๋‹ค!" << std::endl;
            return false;
        }
        
        // ํƒ€์ž„์•„์›ƒ์„ ์ ์šฉํ•œ ๋งค์นญ
        auto future = std::async(std::launch::async, [this, &input]() {
            return std::regex_match(input, this->pattern);
        });
        
        if (future.wait_for(timeout) == std::future_status::timeout) {
            std::cerr << "โฑ๏ธ ์ •๊ทœํ‘œํ˜„์‹ ์‹คํ–‰ ์‹œ๊ฐ„ ์ดˆ๊ณผ!" << std::endl;
            return false;
        }
        
        return future.get();
    }
    
    // ํŒจํ„ด์˜ ์œ„ํ—˜๋„ ๊ฐ„๋‹จํžˆ ์ฒดํฌ
    static bool isDangerousPattern(const std::string& pattern) {
        // ์ค‘์ฒฉ๋œ ์ˆ˜๋Ÿ‰์ž ํŒจํ„ด ๊ฐ์ง€
        std::regex nested(R"(\([^)]*[+*]\)[+*])");
        if (std::regex_search(pattern, nested)) {
            std::cout << "โš ๏ธ ๊ฒฝ๊ณ : ์ค‘์ฒฉ๋œ ์ˆ˜๋Ÿ‰์ž๊ฐ€ ๊ฐ์ง€๋˜์—ˆ์Šต๋‹ˆ๋‹ค!" << std::endl;
            return true;
        }
        return false;
    }
};

int main() {
    // ์œ„ํ—˜ํ•œ ํŒจํ„ด ์ฒดํฌ
    std::string dangerousPattern = R"((a+)+b)";
    SafeRegex::isDangerousPattern(dangerousPattern);
    
    // ์•ˆ์ „ํ•œ ์ •๊ทœํ‘œํ˜„์‹ ์‚ฌ์šฉ
    SafeRegex safeRegex(R"(^[a-zA-Z0-9]+$)", std::chrono::milliseconds(100));
    
    std::cout << "ํ…Œ์ŠคํŠธ 1: " << safeRegex.safeMatch("abc123") << std::endl;
    std::cout << "ํ…Œ์ŠคํŠธ 2: " << safeRegex.safeMatch("abc-123") << std::endl;
    
    // ๋„ˆ๋ฌด ๊ธด ์ž…๋ ฅ ํ…Œ์ŠคํŠธ
    std::string longInput(20000, 'a');
    std::cout << "ํ…Œ์ŠคํŠธ 3: " << safeRegex.safeMatch(longInput) << std::endl;
    
    return 0;
}

๐ŸŽจ ์‹ค์ „ ํ”„๋กœ์ ํŠธ: ๋งˆํฌ๋‹ค์šด ํŒŒ์„œ ๋งŒ๋“ค๊ธฐ

์ด์ œ ์ •๋ง ์‹ค์šฉ์ ์ธ ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž! ๊ฐ„๋‹จํ•œ ๋งˆํฌ๋‹ค์šด ํŒŒ์„œ๋ฅผ ์ •๊ทœํ‘œํ˜„์‹์œผ๋กœ ๊ตฌํ˜„ํ•ด๋ณผ๊ฒŒ. ๐Ÿ“

#include <iostream>
#include <regex>
#include <string>
#include <sstream>

class MarkdownParser {
private:
    // ๋‹ค์–‘ํ•œ ๋งˆํฌ๋‹ค์šด ํŒจํ„ด๋“ค
    std::regex headerPattern{R"(^(#{1,6})\s+(.+)$)"};
    std::regex boldPattern{R"(\*\*(.+?)\*\*)"};
    std::regex italicPattern{R"(\*(.+?)\*)"};
    std::regex codePattern{R"(`(.+?)`)"};
    std::regex linkPattern{R"(\[([^\]]+)\]\(([^)]+)\))"};
    std::regex imagePattern{R"(!\[([^\]]*)\]\(([^)]+)\))"};
    std::regex listPattern{R"(^[\*\-]\s+(.+)$)"};
    std::regex blockquotePattern{R"(^>\s+(.+)$)"};

public:
    std::string parseHeader(const std::string& line) {
        std::smatch match;
        if (std::regex_match(line, match, headerPattern)) {
            int level = match.str(1).length();
            std::string content = match.str(2);
            return "<h" + std::to_string(level) + ">" + 
                   content + "</h" + std::to_string(level) + ">";
        }
        return line;
    }
    
    std::string parseInline(const std::string& text) {
        std::string result = text;
        
        // ๋ณผ๋“œ ์ฒ˜๋ฆฌ
        result = std::regex_replace(result, boldPattern, "<strong>$1</strong>");
        
        // ์ดํƒค๋ฆญ ์ฒ˜๋ฆฌ
        result = std::regex_replace(result, italicPattern, "<em>$1</em>");
        
        // ์ฝ”๋“œ ์ฒ˜๋ฆฌ
        result = std::regex_replace(result, codePattern, "<code>$1</code>");
        
        // ๋งํฌ ์ฒ˜๋ฆฌ
        result = std::regex_replace(result, linkPattern, 
                                   "<a href=\"$2\">$1</a>");
        
        // ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ
        result = std::regex_replace(result, imagePattern, 
                                   "<img src=\"$2\" alt=\"$1\" />");
        
        return result;
    }
    
    std::string parseList(const std::string& line) {
        std::smatch match;
        if (std::regex_match(line, match, listPattern)) {
            return "<li>" + parseInline(match.str(1)) + "</li>";
        }
        return line;
    }
    
    std::string parseBlockquote(const std::string& line) {
        std::smatch match;
        if (std::regex_match(line, match, blockquotePattern)) {
            return "<blockquote>" + parseInline(match.str(1)) + "</blockquote>";
        }
        return line;
    }
    
    std::string parse(const std::string& markdown) {
        std::istringstream stream(markdown);
        std::string line;
        std::string html;
        bool inList = false;
        
        while (std::getline(stream, line)) {
            if (line.empty()) {
                if (inList) {
                    html += "</ul>\n";
                    inList = false;
                }
                html += "<br>\n";
                continue;
            }
            
            // ํ—ค๋” ์ฒดํฌ
            std::string parsed = parseHeader(line);
            if (parsed != line) {
                if (inList) {
                    html += "</ul>\n";
                    inList = false;
                }
                html += parsed + "\n";
                continue;
            }
            
            // ๋ฆฌ์ŠคํŠธ ์ฒดํฌ
            parsed = parseList(line);
            if (parsed != line) {
                if (!inList) {
                    html += "<ul>\n";
                    inList = true;
                }
                html += parsed + "\n";
                continue;
            }
            
            // ์ธ์šฉ๊ตฌ ์ฒดํฌ
            parsed = parseBlockquote(line);
            if (parsed != line) {
                if (inList) {
                    html += "</ul>\n";
                    inList = false;
                }
                html += parsed + "\n";
                continue;
            }
            
            // ์ผ๋ฐ˜ ํ…์ŠคํŠธ
            if (inList) {
                html += "</ul>\n";
                inList = false;
            }
            html += "<p>" + parseInline(line) + "</p>\n";
        }
        
        if (inList) {
            html += "</ul>\n";
        }
        
        return html;
    }
};

int main() {
    MarkdownParser parser;
    
    std::string markdown = R"(# ์žฌ๋Šฅ๋„ท์—์„œ ๋ฐฐ์šฐ๋Š” C++ ์ •๊ทœํ‘œํ˜„์‹

## ์†Œ๊ฐœ

**์ •๊ทœํ‘œํ˜„์‹**์€ *ํ…์ŠคํŠธ ์ฒ˜๋ฆฌ*์˜ ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค.

### ์ฃผ์š” ๊ธฐ๋Šฅ

- ํŒจํ„ด ๋งค์นญ
- ํ…์ŠคํŠธ ์ถ”์ถœ
- ๋ฌธ์ž์—ด ์น˜ํ™˜

> ์ •๊ทœํ‘œํ˜„์‹์„ ๋งˆ์Šคํ„ฐํ•˜๋ฉด ํ…์ŠคํŠธ ์ฒ˜๋ฆฌ๊ฐ€ ์ •๋ง ์‰ฌ์›Œ์ ธ์š”!

์ž์„ธํ•œ ๋‚ด์šฉ์€ [์žฌ๋Šฅ๋„ท](https://www.jaenung.net)์—์„œ ํ™•์ธํ•˜์„ธ์š”.

์ฝ”๋“œ ์˜ˆ์ œ: `std::regex pattern(R"(\d+)")`
)";

    std::cout << "=== ๋งˆํฌ๋‹ค์šด ์›๋ณธ ===" << std::endl;
    std::cout << markdown << std::endl;
    std::cout << "\n=== HTML ๋ณ€ํ™˜ ๊ฒฐ๊ณผ ===" << std::endl;
    std::cout << parser.parse(markdown) << std::endl;
    
    return 0;
}

์ด ๋งˆํฌ๋‹ค์šด ํŒŒ์„œ๋Š” ์‹ค์ œ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ˆ˜์ค€์ด์•ผ! ๋ฌผ๋ก  ์™„์ „ํ•œ ๋งˆํฌ๋‹ค์šด ํŒŒ์„œ๋ฅผ ๋งŒ๋“ค๋ ค๋ฉด ๋” ๋งŽ์€ ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•˜์ง€๋งŒ, ์ •๊ทœํ‘œํ˜„์‹์˜ ํ™œ์šฉ๋ฒ•์„ ๋ฐฐ์šฐ๊ธฐ์—” ์™„๋ฒฝํ•œ ์˜ˆ์ œ์ง€. ๐Ÿ˜Š

๐ŸŒŸ ์‹ค์ „ ํ™œ์šฉ: ๋ฏผ๊ฐ์ •๋ณด ๋งˆ์Šคํ‚น

๊ฐœ์ธ์ •๋ณด ๋ณดํ˜ธ๊ฐ€ ์ค‘์š”ํ•œ ์‹œ๋Œ€! ๋กœ๊ทธ๋‚˜ ์ถœ๋ ฅ์—์„œ ๋ฏผ๊ฐํ•œ ์ •๋ณด๋ฅผ ์ž๋™์œผ๋กœ ๋งˆ์Šคํ‚นํ•˜๋Š” ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž. ๐Ÿ”

#include <iostream>
#include <regex>
#include <string>
#include <map>

class SensitiveDataMasker {
private:
    struct MaskRule {
        std::regex pattern;
        std::function<std::string(const std::smatch&)> replacer;
    };
    
    std::vector<MaskRule> rules;

public:
    SensitiveDataMasker() {
        // ์ด๋ฉ”์ผ ๋งˆ์Šคํ‚น: user@example.com โ†’ u***@example.com
        rules.push_back({
            std::regex(R"(([a-zA-Z0-9])[a-zA-Z0-9._%+-]*@([a-zA-Z0-9.-]+\.[a-zA-Z]{2,}))"),
            [](const std::smatch& m) {
                return m.str(1) + "***@" + m.str(2);
            }
        });
        
        // ์ „ํ™”๋ฒˆํ˜ธ ๋งˆ์Šคํ‚น: 010-1234-5678 โ†’ 010-****-5678
        rules.push_back({
            std::regex(R"((01[0-9])-(\d{4})-(\d{4}))"),
            [](const std::smatch& m) {
                return m.str(1) + "-****-" + m.str(3);
            }
        });
        
        // ์ฃผ๋ฏผ๋“ฑ๋ก๋ฒˆํ˜ธ ๋งˆ์Šคํ‚น: 123456-1234567 โ†’ 123456-*******
        rules.push_back({
            std::regex(R"((\d{6})-(\d{7}))"),
            [](const std::smatch& m) {
                return m.str(1) + "-*******";
            }
        });
        
        // ์‹ ์šฉ์นด๋“œ ๋ฒˆํ˜ธ ๋งˆ์Šคํ‚น: 1234-5678-9012-3456 โ†’ ****-****-****-3456
        rules.push_back({
            std::regex(R"((\d{4})-(\d{4})-(\d{4})-(\d{4}))"),
            [](const std::smatch& m) {
                return "****-****-****-" + m.str(4);
            }
        });
        
        // IP ์ฃผ์†Œ ๋งˆ์Šคํ‚น: 192.168.1.100 โ†’ 192.168.*.*
        rules.push_back({
            std::regex(R"((\d{1,3}\.\d{1,3})\.\d{1,3}\.\d{1,3})"),
            [](const std::smatch& m) {
                return m.str(1) + ".*.*";
            }
        });
    }
    
    std::string mask(const std::string& text) {
        std::string result = text;
        
        for (const auto& rule : rules) {
            std::string temp;
            auto begin = std::sregex_iterator(result.begin(), result.end(), rule.pattern);
            auto end = std::sregex_iterator();
            
            size_t lastPos = 0;
            for (auto it = begin; it != end; ++it) {
                const std::smatch& match = *it;
                temp += result.substr(lastPos, match.position() - lastPos);
                temp += rule.replacer(match);
                lastPos = match.position() + match.length();
            }
            temp += result.substr(lastPos);
            result = temp;
        }
        
        return result;
    }
    
    void addCustomRule(const std::string& pattern, 
                       std::function<std::string(const std::smatch&)> replacer) {
        rules.push_back({std::regex(pattern), replacer});
    }
};

int main() {
    SensitiveDataMasker masker;
    
    std::vector<std::string> testData = {
        "์‚ฌ์šฉ์ž ์ด๋ฉ”์ผ: john.doe@example.com",
        "์—ฐ๋ฝ์ฒ˜: 010-1234-5678",
        "์ฃผ๋ฏผ๋ฒˆํ˜ธ: 901234-1234567",
        "์นด๋“œ๋ฒˆํ˜ธ: 1234-5678-9012-3456",
        "์ ‘์† IP: 192.168.1.100",
        "๋ณตํ•ฉ ์ •๋ณด: user@test.com, 010-9876-5432, 192.168.0.50"
    };
    
    std::cout << "๐Ÿ”’ ๋ฏผ๊ฐ์ •๋ณด ๋งˆ์Šคํ‚น ๊ฒฐ๊ณผ\n" << std::endl;
    
    for (const auto& data : testData) {
        std::cout << "์›๋ณธ: " << data << std::endl;
        std::cout << "๋งˆ์Šคํ‚น: " << masker.mask(data) << std::endl;
        std::cout << std::string(60, '-') << std::endl;
    }
    
    // ์ปค์Šคํ…€ ๊ทœ์น™ ์ถ”๊ฐ€ ์˜ˆ์ œ
    masker.addCustomRule(
        R"(๋น„๋ฐ€๋ฒˆํ˜ธ:\s*(\S+))",
        [](const std::smatch& m) {
            return "๋น„๋ฐ€๋ฒˆํ˜ธ: ********";
        }
    );
    
    std::string passwordLog = "๋กœ๊ทธ์ธ ์‹œ๋„ - ๋น„๋ฐ€๋ฒˆํ˜ธ: MySecret123!";
    std::cout << "\n์ปค์Šคํ…€ ๊ทœ์น™ ํ…Œ์ŠคํŠธ:" << std::endl;
    std::cout << "์›๋ณธ: " << passwordLog << std::endl;
    std::cout << "๋งˆ์Šคํ‚น: " << masker.mask(passwordLog) << std::endl;
    
    return 0;
}

๐Ÿ’ก ์‹ค์ „ ํ™œ์šฉ: ์ด๋Ÿฐ ๋งˆ์Šคํ‚น ์œ ํ‹ธ๋ฆฌํ‹ฐ๋Š” ๋กœ๊น… ์‹œ์Šคํ…œ, ๋””๋ฒ„๊ทธ ์ถœ๋ ฅ, ์—๋Ÿฌ ๋ฆฌํฌํŠธ ๋“ฑ์—์„œ ํ•„์ˆ˜์ ์ด์•ผ. GDPR ๊ฐ™์€ ๊ฐœ์ธ์ •๋ณด ๋ณดํ˜ธ ๊ทœ์ •์„ ์ค€์ˆ˜ํ•˜๋Š” ๋ฐ๋„ ์ค‘์š”ํ•˜์ง€!

๐Ÿ“š ์ •๊ทœํ‘œํ˜„์‹ ์น˜ํŠธ์‹œํŠธ

์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ํŒจํ„ด๋“ค์„ ์ •๋ฆฌํ•ด๋ดค์–ด. ๋ถ๋งˆํฌํ•ด๋‘๊ณ  ํ•„์š”ํ•  ๋•Œ๋งˆ๋‹ค ์ฐธ๊ณ ํ•ด! ๐Ÿ“–

๐Ÿ”ค ๊ธฐ๋ณธ ๋ฌธ์ž ํด๋ž˜์Šค

ํŒจํ„ด ์˜๋ฏธ ์˜ˆ์ œ
. ์ค„๋ฐ”๊ฟˆ ์ œ์™ธ ๋ชจ๋“  ๋ฌธ์ž a.c โ†’ "abc", "a1c"
\d ์ˆซ์ž [0-9] \d{3} โ†’ "123"
\D ์ˆซ์ž๊ฐ€ ์•„๋‹Œ ๋ฌธ์ž \D+ โ†’ "abc"
\w ๋‹จ์–ด ๋ฌธ์ž [a-zA-Z0-9_] \w+ โ†’ "hello_123"
\W ๋‹จ์–ด ๋ฌธ์ž๊ฐ€ ์•„๋‹Œ ๊ฒƒ \W โ†’ "@", "!"
\s ๊ณต๋ฐฑ ๋ฌธ์ž \s+ โ†’ " ", "\t"
\S ๊ณต๋ฐฑ์ด ์•„๋‹Œ ๋ฌธ์ž \S+ โ†’ "hello"

๐Ÿ”ข ์ˆ˜๋Ÿ‰์ž

ํŒจํ„ด ์˜๋ฏธ ์˜ˆ์ œ
* 0๋ฒˆ ์ด์ƒ ab*c โ†’ "ac", "abc", "abbc"
+ 1๋ฒˆ ์ด์ƒ ab+c โ†’ "abc", "abbc"
? 0๋ฒˆ ๋˜๋Š” 1๋ฒˆ ab?c โ†’ "ac", "abc"
{n} ์ •ํ™•ํžˆ n๋ฒˆ \d{3} โ†’ "123"
{n,} n๋ฒˆ ์ด์ƒ \d{2,} โ†’ "12", "123"
{n,m} n๋ฒˆ ์ด์ƒ m๋ฒˆ ์ดํ•˜ \d{2,4} โ†’ "12", "123", "1234"

๐ŸŽฏ ์•ต์ปค์™€ ๊ฒฝ๊ณ„

ํŒจํ„ด ์˜๋ฏธ ์˜ˆ์ œ
^ ๋ฌธ์ž์—ด ์‹œ์ž‘ ^hello โ†’ "hello world"
$ ๋ฌธ์ž์—ด ๋ world$ โ†’ "hello world"
\b ๋‹จ์–ด ๊ฒฝ๊ณ„ \bcat\b โ†’ "the cat"
\B ๋‹จ์–ด ๊ฒฝ๊ณ„ ์•„๋‹˜ \Bcat\B โ†’ "concatenate"

๐Ÿ“ฆ ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ํŒจํ„ด ๋ชจ์Œ

์ด๋ฉ”์ผ: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$


URL: ^https?:\/\/[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(\/.*)?$


์ „ํ™”๋ฒˆํ˜ธ (ํ•œ๊ตญ): ^01[0-9]-\d{3,4}-\d{4}$


๋‚ ์งœ (YYYY-MM-DD): ^\d{4}-\d{2}-\d{2}$


์‹œ๊ฐ„ (HH:MM:SS): ^([01]\d|2[0-3]):[0-5]\d:[0-5]\d$


IPv4 ์ฃผ์†Œ: ^(\d{1,3}\.){3}\d{1,3}$


16์ง„์ˆ˜ ์ƒ‰์ƒ ์ฝ”๋“œ: ^#[0-9A-Fa-f]{6}$


๋น„๋ฐ€๋ฒˆํ˜ธ (8์ž ์ด์ƒ, ๋Œ€์†Œ๋ฌธ์ž+์ˆซ์ž): ^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$

๐ŸŽ“ ํ•™์Šต ๋ฆฌ์†Œ์Šค์™€ ๋‹ค์Œ ๋‹จ๊ณ„

์—ฌ๊ธฐ๊นŒ์ง€ ์ •๋ง ๋งŽ์€ ๋‚ด์šฉ์„ ๋ฐฐ์› ์–ด! ์ด์ œ ์ •๊ทœํ‘œํ˜„์‹๊ณผ std::regex๋ฅผ ์ž์œ ์ž์žฌ๋กœ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ์„ ๊ฑฐ์•ผ. ํ•˜์ง€๋งŒ ํ•™์Šต์€ ์—ฌ๊ธฐ์„œ ๋์ด ์•„๋‹ˆ์ง€! ๐Ÿ˜Š

๐Ÿ“– ์ถ”์ฒœ ํ•™์Šต ์ž๋ฃŒ

1. ์˜จ๋ผ์ธ ์ •๊ทœํ‘œํ˜„์‹ ํ…Œ์Šคํ„ฐ

โ€ข regex101.com - ์‹ค์‹œ๊ฐ„ ํ…Œ์ŠคํŠธ์™€ ์„ค๋ช… ์ œ๊ณต

โ€ข regexr.com - ์‹œ๊ฐ์ ์ธ ์ธํ„ฐํŽ˜์ด์Šค

โ€ข debuggex.com - ์ •๊ทœํ‘œํ˜„์‹ ์‹œ๊ฐํ™”


2. C++ ๊ณต์‹ ๋ฌธ์„œ

โ€ข cppreference.com/w/cpp/regex - ์™„๋ฒฝํ•œ ๋ ˆํผ๋Ÿฐ์Šค

โ€ข C++ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ฌธ์„œ


3. ์‹ค์ „ ์—ฐ์Šต

โ€ข LeetCode, HackerRank์˜ ์ •๊ทœํ‘œํ˜„์‹ ๋ฌธ์ œ

โ€ข ์‹ค์ œ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•ด๋ณด๊ธฐ

โ€ข ์žฌ๋Šฅ๋„ท์—์„œ ๋‹ค๋ฅธ ๊ฐœ๋ฐœ์ž๋“ค๊ณผ ์ง€์‹ ๊ณต์œ ํ•˜๊ธฐ

๐Ÿš€ ๋‹ค์Œ ๋‹จ๊ณ„๋กœ

์ดˆ๊ธ‰ โ†’ ์ค‘๊ธ‰์œผ๋กœ

โœ… ๊ธฐ๋ณธ ํŒจํ„ด ์ž‘์„ฑ ์™„๋ฃŒ

โœ… std::regex ํ•จ์ˆ˜๋“ค ์ดํ•ด

๐ŸŽฏ ๋‹ค์Œ ๋ชฉํ‘œ: ๋ณต์žกํ•œ ํŒจํ„ด ์ตœ์ ํ™”, ์„ฑ๋Šฅ ํŠœ๋‹


์ค‘๊ธ‰ โ†’ ๊ณ ๊ธ‰์œผ๋กœ

โœ… ๋ณต์žกํ•œ ํŒจํ„ด ์ž‘์„ฑ ๊ฐ€๋Šฅ

โœ… ์„ฑ๋Šฅ ์ตœ์ ํ™” ์ดํ•ด

๐ŸŽฏ ๋‹ค์Œ ๋ชฉํ‘œ: ์ปค์Šคํ…€ ํŒŒ์„œ ๊ตฌํ˜„, ๋ณด์•ˆ ๊ณ ๋ ค์‚ฌํ•ญ ๋งˆ์Šคํ„ฐ

๐Ÿ’ผ ์‹ค๋ฌด ์ ์šฉ ์•„์ด๋””์–ด

1. ๋กœ๊ทธ ๋ถ„์„ ์‹œ์Šคํ…œ

์„œ๋ฒ„ ๋กœ๊ทธ๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ถ„์„ํ•˜๊ณ  ์ด์ƒ ํŒจํ„ด์„ ๊ฐ์ง€ํ•˜๋Š” ์‹œ์Šคํ…œ


2. ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

๋‹ค์–‘ํ•œ ํ˜•์‹์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒ€์ฆํ•˜๋Š” ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ


3. ํ…์ŠคํŠธ ์ฒ˜๋ฆฌ ๋„๊ตฌ

๋งˆํฌ๋‹ค์šด ํŒŒ์„œ, ์ฝ”๋“œ ํ•˜์ด๋ผ์ดํ„ฐ, ํ…œํ”Œ๋ฆฟ ์—”์ง„ ๋“ฑ


4. ๋ณด์•ˆ ๋„๊ตฌ

๋ฏผ๊ฐ์ •๋ณด ํƒ์ง€ ๋ฐ ๋งˆ์Šคํ‚น, SQL ์ธ์ ์…˜ ๋ฐฉ์–ด ๋“ฑ


5. ์›น ์Šคํฌ๋ž˜ํ•‘

์›น ํŽ˜์ด์ง€์—์„œ ํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ์ถ”์ถœํ•˜๋Š” ํฌ๋กค๋Ÿฌ

๐ŸŽ‰ ๋งˆ๋ฌด๋ฆฌํ•˜๋ฉฐ

์™€! ์—ฌ๊ธฐ๊นŒ์ง€ ์ •๋ง ๊ธด ์—ฌ์ •์ด์—ˆ์–ด. C++์˜ ์ •๊ทœํ‘œํ˜„์‹๊ณผ std::regex์— ๋Œ€ํ•ด ๊ธฐ์ดˆ๋ถ€ํ„ฐ ๊ณ ๊ธ‰ ํ™œ์šฉ๊นŒ์ง€ ๋ชจ๋‘ ๋‹ค๋ค„๋ดค์ง€. ๐ŸŽŠ


์ •๊ทœํ‘œํ˜„์‹์€ ์ฒ˜์Œ์—” ์–ด๋ ต๊ฒŒ ๋А๊ปด์งˆ ์ˆ˜ ์žˆ์ง€๋งŒ, ํ•œ ๋ฒˆ ์ต์ˆ™ํ•ด์ง€๋ฉด ์ •๋ง ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ๊ฐ€ ๋ผ. ํ…์ŠคํŠธ ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•œ ๊ฑฐ์˜ ๋ชจ๋“  ๊ณณ์—์„œ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๊ฑฐ๋“ ! ๐Ÿ’ช


๐ŸŒŸ ํ•ต์‹ฌ ์š”์•ฝ


1๏ธโƒฃ std::regex๋Š” C++11๋ถ€ํ„ฐ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ํฌํ•จ๋œ ๊ฐ•๋ ฅํ•œ ์ •๊ทœํ‘œํ˜„์‹ ์—”์ง„


2๏ธโƒฃ regex_match, regex_search, regex_replace ๋“ฑ ๋‹ค์–‘ํ•œ ํ•จ์ˆ˜ ์ œ๊ณต


3๏ธโƒฃ ํŒจํ„ด ๋ฌธ๋ฒ•์„ ์ดํ•ดํ•˜๋ฉด ๋ณต์žกํ•œ ํ…์ŠคํŠธ ์ฒ˜๋ฆฌ๋„ ๊ฐ„๋‹จํ•˜๊ฒŒ ํ•ด๊ฒฐ


4๏ธโƒฃ ์„ฑ๋Šฅ๊ณผ ๋ณด์•ˆ์„ ํ•ญ์ƒ ๊ณ ๋ คํ•ด์•ผ ํ•จ (ReDoS ๊ณต๊ฒฉ ์ฃผ์˜!)


5๏ธโƒฃ ์‹ค์ „ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•˜๋ฉด์„œ ์‹ค๋ ฅ์„ ํ‚ค์šฐ๋Š” ๊ฒŒ ์ตœ๊ณ ์˜ ํ•™์Šต๋ฒ•

์ด์ œ ์—ฌ๋Ÿฌ๋ถ„๋„ ํ…์ŠคํŠธ ์ฒ˜๋ฆฌ์˜ ๋งˆ๋ฒ•์‚ฌ๊ฐ€ ๋  ์ค€๋น„๊ฐ€ ๋์–ด! ๐Ÿง™โ€โ™‚๏ธ ์žฌ๋Šฅ๋„ท์—์„œ ๋ฐฐ์šด ๋‚ด์šฉ์„ ์‹ค์ œ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•ด๋ณด๊ณ , ๋‹ค๋ฅธ ๊ฐœ๋ฐœ์ž๋“ค๊ณผ๋„ ์ง€์‹์„ ๋‚˜๋ˆ ๋ณด์ž. ํ•จ๊ป˜ ์„ฑ์žฅํ•˜๋Š” ๊ฒŒ ๊ฐ€์žฅ ๋น ๋ฅธ ๊ธธ์ด๋‹ˆ๊นŒ! ๐Ÿ˜Š


๊ถ๊ธˆํ•œ ์ ์ด ์žˆ๊ฑฐ๋‚˜ ๋” ๋ฐฐ์šฐ๊ณ  ์‹ถ์€ ๋‚ด์šฉ์ด ์žˆ๋‹ค๋ฉด, ์žฌ๋Šฅ๋„ท์˜ ์ง€์‹์ธ์˜ ์ˆฒ์—์„œ ๋‹ค๋ฅธ ๊ธ€๋“ค๋„ ์ฐพ์•„๋ณด๊ณ , ์ง์ ‘ ์งˆ๋ฌธ๋„ ํ•ด๋ด. ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ํ˜ผ์ž๊ฐ€ ์•„๋‹ˆ๋ผ ํ•จ๊ป˜ ๋ฐฐ์›Œ๊ฐ€๋Š” ๊ฑฐ๋‹ˆ๊นŒ! ๐ŸŒณ


๊ทธ๋Ÿผ ์—ฌ๋Ÿฌ๋ถ„์˜ ์ฝ”๋”ฉ ์—ฌ์ •์— ํ–‰์šด์„ ๋นŒ์–ด! Happy Coding! ๐Ÿš€โœจ

๐ŸŽฏ

์ •๊ทœํ‘œํ˜„์‹ ๋งˆ์Šคํ„ฐ ์™„๋ฃŒ!

์ด์ œ ์—ฌ๋Ÿฌ๋ถ„์€ ํ…์ŠคํŠธ ์ฒ˜๋ฆฌ์˜ ์ „๋ฌธ๊ฐ€์ž…๋‹ˆ๋‹ค

์žฌ๋Šฅ๋„ท์—์„œ ๋” ๋งŽ์€ ์ง€์‹์„ ํƒํ—˜ํ•ด๋ณด์„ธ์š”! ๐ŸŒŸ

๋Œ“๊ธ€ ์ž‘์„ฑ

์ด ๊ธ€์— ๋Œ€ํ•œ ์—ฌ๋Ÿฌ๋ถ„์˜ ์ƒ๊ฐ์„ ๋“ค๋ ค์ฃผ์„ธ์š”

๋Œ“๊ธ€ 0
๋Œ“๊ธ€์„ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘์ž…๋‹ˆ๋‹ค.

์•„์ง ๋Œ“๊ธ€์ด ์—†์Šต๋‹ˆ๋‹ค.