online compiler and debugger for c/c++

code. compile. run. debug. share.
Source Code   
Language
//C++17 #include <iostream> #include <string> #include <algorithm> #include <optional> #include <cassert> #include <iomanip> //? Π›ΡŽΠ±ΠΎΠΉ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ символ //* Ноль ΠΈΠ»ΠΈ Π±ΠΎΠ»Π΅Π΅ символов //# Π›ΡŽΠ±Π°Ρ однозначная Ρ†ΠΈΡ„Ρ€Π° (0-9) //[charlist] Π›ΡŽΠ±ΠΎΠΉ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ символ Π² charlist //[!charlist] Π›ΡŽΠ±ΠΎΠΉ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ символ, ΠΎΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ Π² charlist //Symbol Meaning //LIKE '5[*]' 5* //LIKE '[?]n' ?n //LIKE '[a-cdf]' a, b, c, d, or f //LIKE '[-acdf]' -, a, c, d, or f //LIKE '[ [ ]' [ //LIKE ']' ] //LIKE 'abc[_]d*' abc_d and abc_de //LIKE 'abc[def]' abcd, abce, and abcf constexpr bool MatchWildcardAndText_showDebugOutput=!true; constexpr std::wstring_view MatchWildcardAndText_DebugPrefix=L" dbg: "; bool MatchWildcardAndText(const std::wstring_view text, const std::wstring_view wc) { auto wc_cur=wc.cbegin(); auto wc_end=wc.cend(); auto text_cur=text.cbegin(); auto text_end=text.cend(); //информация ΠΎ пропарсСнных ΠΊΠ²Π°Π΄Ρ€Π°Ρ‚Π½Ρ‹Ρ… скобках struct s_SquareBracketsInfo { private: //#todo - для ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΠΏΡ€ΠΎΠ±ΠΎΠ²Π°Ρ‚ΡŒ Π·Π°ΠΌΠ΅Π½ΠΈΡ‚ΡŒ строку массивом, Ρ‚ΠΎΠ³Π΄Π° убСрётся Ρ€Π°Π±ΠΎΡ‚Π° с ΠΊΡƒΡ‡Π΅ΠΉ std::wstring m_CharsList;//список символов, раскрытый ΠΈΠ· ΠΊΠ²Π°Π΄Ρ€Π°Ρ‚Π½Ρ‹Ρ… скобой size_t m_ClosingBracketPos{};//позиция Π·Π°ΠΊΡ€Ρ‹Π²Π°ΡŽΡ‰Π΅ΠΉ скобки bool m_Inverted{};//Ρ„Π»Π°Π³ инвСрсии ΠΈΠ· Π½Π°Ρ‡Π°Π»Π° скобок private: //для ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ: ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΠΉ распарсСнный тСкст. //Если ΠΎΠ½ Ρ‚Π°ΠΊΠΎΠΉ ΠΆΠ΅, Ρ‚ΠΎ Π·Π°Π½ΠΎΠ²ΠΎ ΠΏΠ°Ρ€ΡΠΈΡ‚ΡŒ Π½Π΅ Π½ΡƒΠΆΠ½ΠΎ, всё ΡƒΠΆΠ΅ Π³ΠΎΡ‚ΠΎΠ²ΠΎ std::optional<std::wstring_view> m_lastParsedText; public: bool TestChar(const char c)const noexcept { const bool contains=(m_CharsList.find(c)!=m_CharsList.npos); if(m_Inverted) { return !contains; } else { return contains; } } bool Parse(const std::wstring_view text) { if(m_lastParsedText) { if(m_lastParsedText->size()==text.size()) { if(m_lastParsedText->data()==text.data()) { if constexpr(MatchWildcardAndText_showDebugOutput)std::wcout<<MatchWildcardAndText_DebugPrefix<<L"m_lastParsedText reused\n"; return true; } } } auto res=Parse__(text); if(res) { //Π·Π°ΠΏΠΎΠΌΠΈΠ½Π°Π΅ΠΌ послСдний парсённый тСкст m_lastParsedText=text; //if constexpr(MatchWildcardAndText_showDebugOutput)std::wcout<<MatchWildcardAndText_DebugPrefix<<L"m_lastParsedText saved\n"; assert(m_lastParsedText); assert(!m_lastParsedText->empty()); assert(m_lastParsedText->size()>m_ClosingBracketPos); assert((*m_lastParsedText)[m_ClosingBracketPos]==L']'); } else { //ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ состояниС ΠΌΠΎΠ³Π»ΠΎ ΠΌΠ΅Π½ΡΡ‚ΡŒΡΡ, Π·Π°Π±Ρ‹Π²Π°Π΅ΠΌ послСдний тСкст m_lastParsedText.reset(); if constexpr(MatchWildcardAndText_showDebugOutput)std::wcout<<MatchWildcardAndText_DebugPrefix<<L"m_lastParsedText reset\n"; } return res; } size_t PosOfClosingBracket()const noexcept { return m_ClosingBracketPos; } private: //Π·Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ списка символов ΠΈΠ· ΠΊΠ²Π°Π΄Ρ€Π°Ρ‚Π½Ρ‹Ρ… скобок //text - начинаСтся с ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ символа послС ΠΎΡ‚ΠΊΡ€Ρ‹Π²Π°ΡŽΡ‰Π΅ΠΉ L'[' bool Parse__(std::wstring_view text) { //Ρ‚ΡƒΡ‚ Π½Π΅ производится оптимизация ΠΏΠΎ ΡƒΠ΄Π°Π»Π΅Π½ΠΈΡŽ ΠΏΠΎΠ²Ρ‚ΠΎΡ€ΠΎΠ² [ababa]. //ΠŸΡ€Π΅Π΄ΠΏΠΎΠ»Π°Π³Π°Π΅Ρ‚ΡΡ, Ρ‡Ρ‚ΠΎ ΡŽΠ·Π΅Ρ€ сам сСбС Π½Π΅ Π²Ρ€Π°Π³, Π° Ссли Π΄ΠΎΠ±Π°Π²Π»ΡΡ‚ΡŒ Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌ //удалСния ΠΏΠΎΠ²Ρ‚ΠΎΡ€ΠΎΠ² - это Π±ΡƒΠ΄Π΅Ρ‚ постоянная Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Π°Ρ Π½Π°Π³Ρ€ΡƒΠ·ΠΊΠ° m_CharsList.clear(); m_ClosingBracketPos={}; m_Inverted={}; m_CharsList.reserve(256); if(text.empty())return false; //справа ограничиваСмся ΠΏΠΎ Π·Π°ΠΊΡ€Ρ‹Π²Π°ΡŽΡ‰Π΅ΠΉ скобкС { const auto pos=text.find_first_of(L']'); if(pos==text.npos)return false; text=text.substr(0, pos); m_ClosingBracketPos=pos; } //Ρ„Π»Π°Π³ инвСрсии if(!text.empty() && text.front()==L'!') { m_Inverted=true; text.remove_prefix(1); } //сСйчас text Ρ‚Π°ΠΊΠΎΠΉ: //begin,front - ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ символ послС L'[' ΠΈΠ»ΠΈ L"[!" //back - символ ΠΏΠ΅Ρ€Π΅Π΄ L']' //end - L']' auto text_cur=text.cbegin(); auto text_end=text.cend(); while(text_cur!=text_end) { //text_cur - Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ символ //Ссли ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ символ это минус, if(auto hyphen=text_cur+1; hyphen!=text_end && *hyphen==L'-') { //Ρ‚ΠΎ послС минуса Ρ‚ΠΎΠΆΠ΅ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Ρ‚ΡŒ ΠΊΠ°ΠΊΠΎΠΉ-Ρ‚ΠΎ символ if(auto second=hyphen+1; second!=text_end) { //ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° X-Z, сСйчас находимся Π½Π° X char c1=*text_cur; char c2=*second; if(c1>c2)std::swap(c1, c2); for(char c=c1; c<=c2; ++c)m_CharsList.push_back(c); //ΠΈΠ΄Ρ‘ΠΌ дальшС text_cur=second+1; continue; } } //ΠΎΠ΄ΠΈΠ½ символ ΠΊΠ»Π°Π΄Ρ‘ΠΌ Π² список m_CharsList.push_back(*text_cur); text_cur++; } return true; } }; s_SquareBracketsInfo SBInfo; while(wc_cur!=wc_end) { if(text_cur==text_end) { //Π·Π°Π²Π΅Ρ€ΡˆΠ°ΡŽΡ‰ΠΈΠ΅ Π·Π²Ρ‘Π·Π΄ΠΎΡ‡ΠΊΠΈ ΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΡƒΠ΅ΠΌ if(*wc_cur==L'*') { ++wc_cur; continue; } return false; } switch(*wc_cur) { default: { //любой Π΄Ρ€ΡƒΠ³ΠΎΠΉ символ - Π΄ΠΎΠ»ΠΆΠ΅Π½ ΡΠΎΠ²ΠΏΠ°ΡΡ‚ΡŒ с тСкстовым if(*wc_cur == *text_cur) { ++wc_cur; ++text_cur; } else { return false; } }break; case L'?': { ++wc_cur; ++text_cur; }break; case L'#': { if(L'0' <= *text_cur && *text_cur<=L'9') { ++wc_cur; ++text_cur; } else { return false; } }break; case L'*': { auto wc_next=wc_cur+1; bool done{}; do { if(wc_next!=wc_end) { switch(*wc_next) { default: { //любой Π΄Ρ€ΡƒΠ³ΠΎΠΉ символ - Π΄ΠΎΠ»ΠΆΠ΅Π½ ΡΠΎΠ²ΠΏΠ°ΡΡ‚ΡŒ с тСкстовым if(*wc_next == *text_cur) { //совпал, поэтому Π·Π²Ρ‘Π·Π΄ΠΎΡ‡ΠΊΡƒ считаСм Π·Π°Π²Π΅Ρ€ΡˆΡ‘Π½Π½ΠΎΠΉ ++wc_cur; done=true; } else { //Π·Π²Ρ‘Π·Π΄ΠΎΡ‡ΠΊΠ° Π·Π°Π±ΠΈΡ€Π°Π΅Ρ‚ ΠΎΠ΄ΠΈΠ½ символ ΠΈΠ· тСкста ++text_cur; } }break; case L'?': { //Π·Π²Π΅Π·Π΄Π° ΡΠΌΠ°Ρ‚Ρ‡ΠΈΠ»Π°ΡΡŒ с пустотой ++wc_cur; done=true; }break; case L'#': { if(L'0' <= *text_cur && *text_cur<=L'9') { //Π·Π²Π΅Π·Π΄Π° ΡΠΌΠ°Ρ‚Ρ‡ΠΈΠ»Π°ΡΡŒ с пустотой ++wc_cur; done=true; } }break; case L'*': { //Π·Π²Π΅Π·Π΄Π° ΡΠΌΠ°Ρ‚Ρ‡ΠΈΠ»Π°ΡΡŒ с пустотой ++wc_cur; //Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΠ΅ Π½Π΅ Π΄Π΅Π»Π°Π΅ΠΌ, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ ΠΈΠ΄Ρ‘ΠΌ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒ Π·Π²Π΅Π·Π΄Ρƒ //done=true; }break; case L'[': { auto wc_past_next=wc_next+1; if(wc_past_next!=wc_end && SBInfo.Parse({&*wc_past_next, size_t(wc_end-wc_past_next)})) { //дальшС Π»Π΅ΠΆΠ°Ρ‚ ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½Ρ‹Π΅ ΠΊΠ²Π°Π΄Ρ€Π°Ρ‚Π½Ρ‹Π΅ скобки //символ строки Π»Π΅ΠΆΠΈΡ‚ Π² спискС? if(SBInfo.TestChar(*text_cur)) { //Π½Π°Π΄ΠΎ Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅ΠΉΡ‚ΠΈ ΠΊ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ΅ скобок ++wc_cur; done=true; } else { //Ρ‚ΠΎ Π·Π²Ρ‘Π·Π΄ΠΎΡ‡ΠΊΠ° Π·Π°Π±ΠΈΡ€Π°Π΅Ρ‚ ΠΎΠ΄ΠΈΠ½ символ ΠΈΠ· тСкста ++text_cur; } } else { //считаСм ΠΎΠ±Ρ‹Ρ‡Π½Ρ‹ΠΌ символом //любой Π΄Ρ€ΡƒΠ³ΠΎΠΉ символ - Π΄ΠΎΠ»ΠΆΠ΅Π½ ΡΠΎΠ²ΠΏΠ°ΡΡ‚ΡŒ с тСкстовым if(*wc_next == *text_cur) { ++wc_cur; done=true; } } }break; } } else { //ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π³ΠΎ символа Π² маскС Π½Π΅Ρ‚, поэтому всё ΠΎΡΡ‚Π°Π»ΡŒΠ½ΠΎΠ΅ - матчится return true; } } while(!done && wc_cur!=wc_end && text_cur!=text_end); }break; case L'[': { auto wc_next=wc_cur+1; if(wc_next!=wc_end && SBInfo.Parse({&*wc_next, size_t(wc_end-wc_next)})) { //символ строки Π΄ΠΎΠ»ΠΆΠ΅Π½ Π»Π΅ΠΆΠ°Ρ‚ΡŒ Π² спискС if(SBInfo.TestChar(*text_cur)) { wc_cur=wc_next+SBInfo.PosOfClosingBracket()+1; ++text_cur; } else { return false; } } else { //считаСм ΠΎΠ±Ρ‹Ρ‡Π½Ρ‹ΠΌ символом //любой Π΄Ρ€ΡƒΠ³ΠΎΠΉ символ - Π΄ΠΎΠ»ΠΆΠ΅Π½ ΡΠΎΠ²ΠΏΠ°ΡΡ‚ΡŒ с тСкстовым if(*wc_cur == *text_cur) { ++wc_cur; ++text_cur; } else { return false; } } }break; } } //#todo - эти Ρ‚Ρ€ΠΈ строки ΠΌΠΎΠΆΠ½ΠΎ Π·Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ с ΠΎΠ΄Π½ΠΈΠΌ return if(wc_cur!=wc_end) return false; if(text_cur!=text_end) return false; return true; } int main() { struct s_test { const std::wstring_view string; const std::wstring_view mask; bool result{}; }; const std::vector<s_test> tests { {L"" , L"*" , 1}, {L"5*" , L"5[*]" , 1}, {L"?n" , L"[?]n" , 1}, {L"a" , L"[a-cdf]" , 1}, {L"b" , L"[a-cdf]" , 1}, {L"c" , L"[a-cdf]" , 1}, {L"d" , L"[a-cdf]" , 1}, {L"f" , L"[a-cdf]" , 1}, {L"-" , L"[-acdf]" , 1}, {L"a" , L"[-acdf]" , 1}, {L"c" , L"[-acdf]" , 1}, {L"d" , L"[-acdf]" , 1}, {L"f" , L"[-acdf]" , 1}, {L"[" , L"[ [ ]" , 1}, {L"]" , L"]" , 1}, {L"abc_d" , L"abc[_]d*" , 1}, {L"abc_de", L"abc[_]d*" , 1}, {L"abcd" , L"abc[def]" , 1}, {L"abce" , L"abc[def]" , 1}, {L"abcf" , L"abc[def]" , 1}, {L"abcdef", L"abc*[de]ef", 1}, {L"abcyef", L"abc[xz]ef" , 0}, {L"abcxef", L"abc[xz]ef" , 1}, {L"abcyef", L"abc[!xz]ef", 1}, {L"abcxef", L"abc[!xz]ef", 0}, {L"aBBBa" , L"a*a" , 1}, {L"ac5c5b", L"a*[1-56-9][!c-e]", 0} }; for(auto& test:tests) { if(test.result==MatchWildcardAndText(test.string, test.mask)) { std::wcout<<L"ok :"; } else { std::wcout<<L"error:"; } std::wcout<<L"must be"; if(test.result) { std::wcout<<L" true >>"; } else { std::wcout<<L" false >>"; } std::wcout<<L" string "<<std::left<<std::setw(10)<<(L"'"+std::wstring(test.string)+L"'"); std::wcout<<L" mask " <<std::left <<std::setw(16)<<(L"'"+std::wstring(test.mask )+L"'"); std::wcout<<'\n'; if constexpr(MatchWildcardAndText_showDebugOutput)std::wcout<<L"\n"; } return 0; }

Compiling Program...

Command line arguments:
Standard Input: Interactive Console Text

                

                

Program is not being debugged. Click "Debug" button to start program in debug mode.

#FunctionFile:Line
VariableValue
RegisterValue
ExpressionValue