2015-07-01 9 views
12

बिना डिलीमीटर सहित कई डिलीमीटरों के साथ स्ट्रिंग टोकेनाइज़र मुझे सी ++ में स्ट्रिंग पार्सर बनाने की आवश्यकता है। मैंबूस्ट

vector<string> Tokenize(const string& strInput, const string& strDelims) 
{ 
vector<string> vS; 

string strOne = strInput; 
string delimiters = strDelims; 

int startpos = 0; 
int pos = strOne.find_first_of(delimiters, startpos); 

while (string::npos != pos || string::npos != startpos) 
{ 
    if(strOne.substr(startpos, pos - startpos) != "") 
    vS.push_back(strOne.substr(startpos, pos - startpos)); 

    // if delimiter is a new line (\n) then add new line 
    if(strOne.substr(pos, 1) == "\n") 
    vS.push_back("\\n"); 
    // else if the delimiter is not a space 
    else if (strOne.substr(pos, 1) != " ") 
    vS.push_back(strOne.substr(pos, 1)); 

    if(string::npos == strOne.find_first_not_of(delimiters, pos)) 
    startpos = strOne.find_first_not_of(delimiters, pos); 
    else 
    startpos = pos + 1; 

     pos = strOne.find_first_of(delimiters, startpos); 

} 

return vS; 
} 

यह 2X + 7cos (3Y)

(tokenizer("2X+7cos(3Y)","+-/^() \t");)

लिए काम करता है लेकिन 2X

मैं गैर बूस्ट समाधान की जरूरत के लिए एक रनटाइम त्रुटि देता है उपयोग करने की कोशिश।

मैं C++ String Toolkit (StrTk) Tokenizer

std::vector<std::string> results; 
strtk::split(delimiter, source, 
      strtk::range_to_type_back_inserter(results), 
      strtk::tokenize_options::include_all_delimiters); 

return results; 

उपयोग करने की कोशिश लेकिन यह एक अलग स्ट्रिंग के रूप में टोकन नहीं देता है।

उदाहरण के लिए: अगर मैं 2x + 3y

उत्पादन वेक्टर के रूप में इनपुट देना होता है

2X +

3Y

+0

मुमकिन है आप इस मामले में जहां '' lastPos' npos' है से 'स्थिति = str.find_first_of (सीमांकक, lastPos)' की रक्षा के लिए की जरूरत है। – ooga

+0

यदि आप गैर-मानक लाइब्रेरी का उपयोग करके कोड दिखाने जा रहे हैं (जाहिर है [यह] (http://www.codeproject.com/Articles/23198/C-String-Toolkit-StrTk-Tokenizer), आपको इसका नाम देना चाहिए प्रश्न में, एक लिंक प्रदान करें, और अपने प्रश्न में एक संबंधित टैग जोड़ने पर विचार करें। –

+3

मैं उस स्ट्रैट को जोड़ता हूं क्योंकि यह कहने के लिए कि समाधान मेरी समस्या को ठीक करने में सक्षम नहीं था। अब लिंक जोड़ें – user2473015

उत्तर

1

लूप से बाहर निकलें हालत टूट गया है:

while (string::npos != pos || string::npos != startpos) 

साथ प्रवेश की अनुमति देता है, का कहना है कि स्थिति = एनपीओ और startpos = 1.

तो

strOne.substr(startpos, pos - startpos) 
strOne.substr(1, npos - 1) 

अंत है नहीं एनपीओ, तो substr नहीं करता है इसे रोकना चाहिए और बूम!

तो स्थिति = एनपीओ और startpos = 0,

strOne.substr(startpos, pos - startpos) 

जीवन है, लेकिन

strOne.substr(pos, 1) == "\n" 
strOne.substr(npos, 1) == "\n" 

मरता।तो

strOne.substr(pos, 1) != " " 

दुर्भाग्य से मैं समय से बाहर हूँ और अब यह सही समाधान नहीं कर सकते है, लेकिन QuestionC के सही विचार आया। बेहतर फ़िल्टरिंग। की तर्ज पर कुछ:

if (string::npos != pos) 
    { 
     if (strOne.substr(pos, 1) == "\n") // can possibly simplify this with strOne[pos] == '\n' 
      vS.push_back("\\n"); 
     // else if the delimiter is not a space 
     else if (strOne[pos] != ' ') 
      vS.push_back(strOne.substr(pos, 1)); 
    } 
2

इस जब npos पारित कर दिया क्रैश हो रहा है क्या शायद हो रहा है है:

lastPos = str.find_first_not_of(delimiters, pos); 

बस यो में ब्रेक जोड़ें इसके दौरान तोड़ने के लिए थोड़ी देर के खंड पर भरोसा करने के बजाय यूआर लूप।

if (pos == string::npos) 
    break; 
lastPos = str.find_first_not_of(delimiters, pos); 

if (lastPos == string::npos) 
    break; 
pos = str.find_first_of(delimiters, lastPos); 
0

मैं एक छोटे से समारोह है कि सबस्ट्रिंग (जो एक वेक्टर में जमा हो जाती है) में एक स्ट्रिंग विभाजन बनाया है और इसे आप जो वर्ण आप सफेद स्थान के रूप में इलाज के लिए चाहते हैं स्थापित करने के लिए अनुमति देता है। सामान्य सफेद जगह अभी भी व्हाइटस्पेस के रूप में माना जाएगा, इसलिए आपको इसे परिभाषित करने की आवश्यकता नहीं है। दरअसल, यह सब उस चरित्र को बदल देता है जिसे आपने व्हाइट्स स्पेस के रूप में परिभाषित किया है जो वास्तविक सफेद जगह (स्पेस चार ') में है। फिर यह एक धारा (स्ट्रिंगस्ट्रीम) में सबस्ट्रिंग को अलग करने और उन्हें वेक्टर में स्टोर करने के लिए चलाता है। यह आपको इस विशेष समस्या के लिए आवश्यक नहीं हो सकता है, लेकिन शायद यह आपको कुछ विचार दे सकता है।

// split a string into its whitespace-separated substrings and store 
// each substring in a vector<string>. Whitespace can be defined in argument 
// w as a string (e.g. ".;,?-'") 
vector<string> split(const string& s, const string& w) 
{ 
    string temp{ s }; 
    // go through each char in temp (or s) 
    for (char& ch : temp) {  
     // check if any characters in temp (s) are whitespace defined in w 
     for (char white : w) { 
      if (ch == white) 
       ch = ' ';  // if so, replace them with a space char (' ') 
     } 
    } 

    vector<string> substrings; 
    stringstream ss{ temp }; 

    for (string buffer; ss >> buffer;) { 
     substrings.push_back(buffer); 
    } 
    return substrings; 
} 
+1

दिलचस्प, लेकिन बहुत भारी ब्रूट फोर्स। क्या आपने डब्ल्यू में 'स्ट्रिंग' के स्थान पर 'सेट' का उपयोग करने पर विचार किया है? आप 'char (char white: w) 'loop को' if (w.find (ch)! = w.end ()) 'भयानक नहीं, लेकिन एन-स्क्वायर नहीं। – user4581301

+0

हम्म ... मैंने इसके बारे में सोचा नहीं है। ईमानदार होने के लिए, मैं सामान्य रूप से सी ++ और प्रोग्रामिंग के लिए काफी नया हूं, इसलिए मुझे बहुत कुछ पता नहीं है। मुझे यह कोशिश करना होगा और दोनों तरीकों के प्रदर्शन का परीक्षण करना होगा। मैं इस बात से सहमत हूं कि जिस तरह से मैं इसे कर रहा हूं वह अब भारी तरफ है। अरे, यह काम करता है। मैं हमेशा नीचे रहता हूं एक अलग, अधिक कुशल तरीके से प्रयास करने के लिए। टिप्पणी के लिए धन्यवाद। –

0

यदि आप अपने पर्यावरण पर कुछ जानकारी साझा कर सकते हैं तो बहुत अच्छा होगा। आपका प्रोग्राम g ++ का उपयोग करके मेरे फेडोरा 20 पर 2 एक्स के इनपुट मान के साथ ठीक चला गया।

+1

यह उत्तर एक टिप्पणी के रूप में अधिक उपयुक्त है और वास्तव में प्रश्न का उत्तर नहीं है – SteveFerg

+0

मैं WinG में हूँ MingW C++ कंपाइलर के साथ – user2473015