2013-10-11 7 views
5

मैं एक ऐसा एप्लिकेशन लिख रहा हूं जो एक साधारण पाठ फ़ाइल से कुछ डेटा पढ़ता है। , तोपार्सिंग डेटा के लिए नियमित अभिव्यक्ति

Mem(100) = 120 
Mem(200) = 231 
Mem(43) = 12 
... 
Mem(1293) = 12.54 

के रूप में आप समझ सकते हैं, प्रत्येक पंक्ति के पैटर्न की तरह

(\s)*(\t)*Mem([0-9]*) (\s,\t)*= (\s,\t)*[0-9]*(.)*[0-9]* 

की तरह मेरे पास है कुछ है: डेटा फ़ाइलें, है कि मैं में दिलचस्पी है, निम्नलिखित रूप में पंक्तियाँ वर्ण अनुक्रम "मेम" से पहले सफेद जगहों की संख्या, एक बाएं कोष्ठक के बाद। फिर, एक संख्या और एक सही संश्लेषण है। इसके बाद, जब तक '=' (बराबर) वर्ण का सामना नहीं किया जाता है तब तक कई सफेद रिक्त स्थान होते हैं। फिर, जब तक मैं एक (संभवतः) फ्लोटिंग पॉइंट नंबर पर नहीं आ जाता तब तक सफेद रिक्त स्थान की संख्या।

मैं इसे C++ regex पैटर्न में कैसे व्यक्त कर सकता हूं? मैं सी ++ में नियमित अभिव्यक्ति अवधारणा के लिए वास्तव में नया हूं इसलिए मुझे कुछ मदद की आवश्यकता होगी।

आप

+0

मुझे इस सवाल को काफी समझ में नहीं आता है। यदि आप जानना चाहते हैं कि सी ++ में रेगेक्स का उपयोग कैसे करें, वहां बहुत से उदाहरण हैं। वैसे, आपको शायद अपने ब्रैकेट से बच जाना चाहिए - '... मेम \ ([0-9] * \) ... '। – Dukeling

+0

@ डकलिंग इसलिए मैंने यहां पूछा। मैं न तो वहां एक समान उदाहरण पा सकता था, न ही मैं यह समझ सकता था कि नियमित अभिव्यक्ति पैटर्न मिलान कैसे काम करता है। –

+1

नियमित अभिव्यक्ति इस तरह के एक साधारण पैटर्न के लिए overkill हैं। एक स्ट्रिंग में लाइन पढ़ें, '(', 'के लिए खोजें '' के लिए खोजें, अगले अंक की खोज करें। –

उत्तर

15

सबसे पहले, #include <regex> के लिए याद धन्यवाद।

सी ++ std::regex_match अन्य भाषाओं में नियमित अभिव्यक्तियों की तरह काम करता है। एक सरल उदाहरण से

आइए शुरू:

std::string str = "Mem(100)=120"; 
std::regex regex("^Mem\\([0-9]+\\)=[0-9]+$"); 
std::cout << std::regex_match(str, regex) << std::endl; 

इस मामले में, हमारे regex ^Mem\([0-9]+\)=[0-9]+$ है। की यह क्या करता है पर एक नज़र डालें:

  • ^ शुरुआत में सी बताता ++ इस जहां लाइन शुरू होता है, तो AMem(1)=2 से मेल नहीं करना चाहिए।
  • $ अंत में सी ++ बताता है कि यह लाइन कहां समाप्त होती है, इसलिए Mem(1)=2x मेल नहीं होना चाहिए।
  • \\( एक शाब्दिक ( चरित्र है। ( नियमित अभिव्यक्तियों में एक बहुत ही विशेष अर्थ है, इसलिए हम इसे \( से बचते हैं। हालांकि, \ चरित्र का सी ++ तारों में एक विशेष अर्थ है, इसलिए हम नियमित अभिव्यक्ति इंजन में \( पास करने के लिए C++ को बताने के लिए \\( का उपयोग करते हैं।
  • [0-9] एक अंक से मेल खाता है। \\d भी काम करना चाहिए, लेकिन then again maybe not
  • [0-9]+ का अर्थ है कम से कम एक अंक। यदि Mem() स्वीकार्य है, तो इसके बजाय [0-9]* का उपयोग करें।

जैसा कि आप देख सकते हैं, यह नियमित अभिव्यक्तियों की तरह है जो आपको अन्य भाषाओं (जैसे जावा या सी #) में मिलेंगे।

अब, खाली स्थान के विचार करते हैं, का उपयोग std::regex regex("^\\s*Mem\\([0-9]+\\)\\s*=\\s*[0-9]+\\s*$");

ध्यान दें कि \s, \t शामिल हैं, इसलिए दोनों को निर्दिष्ट करने की कोई जरूरत नहीं है। यदि ऐसा नहीं होता है, तो आप (\s|\t) या [\s\t] का उपयोग करेंगे, (\s,\t) नहीं।

अंत में, फ्लोट नंबरों को शामिल करने के लिए, हमें सबसे पहले यह सोचने की आवश्यकता है कि Mem(1) = 1. (यानी, इसके बाद किसी संख्या के बिना एक बिंदु) स्वीकार्य है।

यदि यह नहीं है, तो .231.23वैकल्पिक है। Regexes में, हम इसे इंगित करने के लिए ? का उपयोग करें।

std::regex regex("^[\\s]*Mem\\([0-9]+\\)\\s*=\\s*[0-9]+(\\.[0-9]+)?\\s*$"); 

ध्यान दें कि हम सिर्फ . के बजाय \. इस्तेमाल करते हैं। . नियमित अभिव्यक्तियों में एक विशेष अर्थ है - यह किसी भी चरित्र से मेल खाता है - इसलिए हमें इसे बचाना होगा।

आप एक संकलक कि कच्चे तार का समर्थन करता है है, तो (जैसे Visual Studio 2013, GCC 4.5, Clang 3.0), तो आपको regex स्ट्रिंग को आसान बनाने में कर सकते हैं:

std::regex regex(R"(^[\s]*Mem\([0-9]+\)\s*=\s*[0-9]+(\.[0-9]+)?\s*$)") 

मिलान किया स्ट्रिंग के बारे में जानकारी निकालने के लिए, आप उपयोग कर सकते std::smatch और समूह। एक छोटा सा परिवर्तन के साथ

आइए शुरू:

std::string str = " Mem(100)=120"; 
std::regex regex("^[\\s]*Mem\\(([0-9]+)\\)\\s*=\\s*([0-9]+(\\.[0-9]+)?)\\s*$"); 
std::smatch m; 

std::cout << std::regex_match(str, m, regex) << std::endl; 

नोट तीन बातें:

  1. हम smatch जोड़ा गया। यह वर्ग मैच के बारे में अतिरिक्त परिणाम जानकारी संग्रहीत करता है।
  2. हमने [0-9]* के आस-पास अतिरिक्त कोष्ठक जोड़ा। यह एक समूह को परिभाषित करता है। समूह रेगेक्स इंजन को उनके भीतर जो कुछ भी ट्रैक रखने के लिए कहते हैं।
  3. अभी भी फ़्लोटिंग पॉइंट नंबर के चारों ओर अधिक ब्रांडेसिस। यह एक दूसरे समूह को परिभाषित करता है।

बहुत महत्वपूर्ण बात कोष्ठक कि समूहों को परिभाषित भाग निकले नहीं हैं के बाद से हम उन्हें वास्तविक कोष्टक वर्णों से मेल नहीं करना चाहती। हम वास्तव में विशेष regex अर्थ चाहते हैं।

अब जब हम समूह नहीं हैं, हम उनका उपयोग कर सकते हैं:

for (auto result : m) { 
    std::cout << result << std::endl; 
} 

यह पहली पूरी स्ट्रिंग, तो संख्या Mem() में है, तो अंतिम संख्या प्रिंट होगा।

दूसरे शब्दों में, m[0] हमें पूरे मैच देता है, m[1] हमें पहले समूह देता है, m[2] हमें दूसरे समूह देता है और m[3] हमें तीसरे समूह देना होगा अगर हम एक था।

+3

आप भागने के दृश्यों से छुटकारा पाने के लिए कच्चे स्ट्रिंग अक्षर का भी उपयोग कर सकते हैं।'आर" रेगेक्स (हैलो \ वर्ल्ड) रेगेक्स "' – dyp

+1

@ डीईपी हाँ, चूंकि 'रेगेक्स' सी ++ 11 है, वैसे भी कच्चे स्ट्रिंग अक्षर * उपलब्ध होना चाहिए। दुर्भाग्यवश, कुछ सी ++ कार्यान्वयन जैसे विजुअल स्टूडियो जो रेगेक्स का समर्थन करते हैं, कच्चे स्ट्रिंग अक्षर का समर्थन नहीं करते हैं। – luiscubal

+0

@luiscubal आपके उत्तर के लिए बहुत बहुत धन्यवाद। यह वास्तव में मुझे बहुत मदद की। मेरा अनुवर्ती प्रश्न यह होगा कि दो कोष्ठक के अंदर संख्या को कैसे पकड़ें। जैसे कि मेरे पास मेम (संख्या) है, तो मैं न्यू स्ट्रिंग को अलग कैसे कर सकता हूं? –

संबंधित मुद्दे