2010-03-30 11 views
8

मैं रनटाइम पर तारों को प्रतिस्थापित करने के लिए सरल सी ++ स्ट्रिंग आधारित टेम्पलेट लाइब्रेरी चाहता हूं।सी ++ स्ट्रिंग टेम्पलेट लाइब्रेरी

उदाहरण के लिए, मैं का उपयोग करेगा

string template = "My name is {{name}}"; 

क्रम में, मैं नाम वास्तविक आधार पर बदला जा करना चाहते हैं।

मैं एक उदाहरण पाया, www.stringtemplate.org लेकिन मैं थोड़ा डर लगता है जब antlr आदि के बारे में अपनी वार्ता

+4

'टेम्पलेट्स' टैग यहां उचित नहीं है। एक टेम्पलेट स्ट्रिंग के भीतर तारों को प्रतिस्थापित करना सी ++ संदर्भ में टेम्पलेट के सामान्य अर्थ के समान नहीं है। –

+0

'वास्तविक एक' से, आपका मतलब स्ट्रिंग टेम्पलेट के दायरे में परिभाषित 'नाम' नामक एक चर है? –

+0

सवाल क्या है? –

उत्तर

14

अद्यतन: परियोजना Github में ले जाया गया और CTemplate में नाम दिया गया है: https://github.com/OlafvdSpek/ctemplate

नई परियोजना पृष्ठ से:

मूल रूप से गूगल टेम्पलेट्स बुलाया गया था, टेम्पलेट प्रणाली के रूप में अपने मूल की वजह से Google खोज परिणाम पृष्ठों के लिए उपयोग किया जाता है। अब इसका एक सामान्य नाम है जो इसकी सामुदायिक स्वामित्व वाली प्रकृति से मेल खाता है।


आप Google के CTemplate पुस्तकालय की कोशिश की है? http://code.google.com/p/google-ctemplate/

आपका उदाहरण इस तरह लागू किया जाएगा:

उदाहरण में यह होना करने के लिए आप के लिए वास्तव में क्या देख रहे हैं लगता है।TPL:

मेरा नाम {{नाम}}

example.cc में:

#include <stdlib.h> 
#include <string> 
#include <iostream> 
#include <google/template.h> 

int main(int argc, char** argv) 
{ 
    google::TemplateDictionary dict("example"); 
    dict.SetValue("name", "John Smith"); 
    google::Template* tpl = google::Template::GetTemplate("example.tpl", 
                 google::DO_NOT_STRIP); 
    std::string output; 
    tpl->Expand(&output, &dict); 
    std::cout << output; 
    return 0; 
} 

तब:

$ gcc example.cc -lctemplate -pthread 

$ ./a.out 

मेरा नाम जॉन स्मिथ है

ध्यान दें कि टेम्पलेट्स को कॉन्स्ट स्ट्रिंग के रूप में लिखने का एक तरीका भी है यदि आप अलग-अलग फ़ाइलों में अपने टेम्पलेट्स को लिखना परेशान नहीं करना चाहते हैं।

+1

https://github.com/OlafvdSpek/ctemplate यह प्रोजेक्ट है? उदाहरण पृष्ठ में एक समान उदाहरण है https://htmlpreview.github.io/?https://github.com/OlafvdSpek/ctemplate/blob/master/doc/index.html – TankorSmash

5

आप sprintf का उपयोग कर सकते हैं?

यदि आप बूस्ट शामिल करना चाहते हैं तो boost::format भी है।

+3

मुझे आश्चर्य है कि आपको 'sprintf' का उल्लेख करने के लिए मौत की धमकी नहीं मिल रही है। लेकिन मैं यही उपयोग करता हूं, इसलिए बफर ओवररन्स से बचने के लिए +1 :) –

+1

'snprintf'। Http://libslack.org/manpages/snprintf.3.html – Atmocreations

+1

\ * मौत की धमकी \ * @ जॉन: वहां, अब यह उत्तर पूरा हो गया है। – GManNickG

4

आप एक समारोह है कि एक और तार के साथ एक स्ट्रिंग की सभी घटनाओं की जगह है, तो:

std::string replace_all(std::string str, const std::string &remove, const std::string &insert) 
{ 
    std::string::size_type pos = 0; 
    while ((pos = str.find(remove, pos)) != std::string::npos) 
    { 
     str.replace(pos, remove.size(), insert); 
     pos++; 
    } 

    return str; 
} 

तो फिर तुम यह कर सकते हैं:

std::string pattern = "My name is {{first_name}} {{last_name}} and I live in {{location}}"; 

std::string str = replace_all(replace_all(replace_all(pattern, 
         "{{first_name}}", "Homer"), 
         "{{last_name}}", "Simpson"), 
         "{{location}}", "Springfield"); 
+0

सिर्फ पिक्य होने के लिए (अभ्यास में होने की संभावना बहुत कम है): यदि 'होमर' के बजाय आपने '{{last_name}}' के मूल्य के रूप में '{{last_name}}' रखा है, तो आपको वांछित परिणाम नहीं मिलेगा ... –

+2

@Andre Holzner - वांछित परिणाम क्या निर्भर करता है! –

0
string skeleton = "My name is {{name}}"; 
string placeholder = "{{name}}"; 
string::size_type pos = skeleton.find(placeholder); 
while(pos != string::npos) { 
    skeleton.replace(pos, placeholder.length(), "Gopalakrishnan"); 
    pos = skeleton.find(placeholder, ++pos); 
} 
+0

यदि आपके पास अन्य टैग हैं तो आप एक कंटेनर में स्टोर कर सकते हैं और उसके बाद लूप को अन्य लूप के साथ लपेट सकते हैं जो कंटेनर को घुमाता है, इस प्रकार इनपुट स्ट्रिंग पर प्रत्येक टैग के साथ प्रतिस्थापन लूप को लागू करता है। अगर आपके पास अन्य टैग हैं तो मुझे बताएं और मैं नमूना कोड अपडेट करूंगा। – wilhelmtell

0

यह overkill हो सकता है, लेकिन आप boost::spirit पर भी एक नज़र डालें, और अधिक विशेष रूप से, 'कर्म' भाग जो पाठ जनरेटर है।

0

यदि आपके पास कई जगह धारक हैं, उदाहरण के लिए यदि आपके पास एक पत्र के लिए मैक्रो टेम्पलेट है जिसे आप स्वचालित रूप से विस्तारित करना चाहते हैं, तो कुछ मूल टोकननाइज़ेशन को बनाए रखने, कार्यान्वित करने और बाद में विस्तार करना आसान होगा। उदा

//pseudocode 
foreach word in line 
{ 
    if word=={{name}} print getFromDB(name,entry) 
    else if word=={{address}} print getFromDB(address,entry) 
    .. 
    .. 
    else print word 

/* 
* to get rid of if-else-if tree, you can just check if starts with {{ and ends with }} and directly query the string against a db/map/hash 
*/ 

} 

हालांकि, अगर समस्या पर्याप्त एक सरल है, और टेम्पलेट काफी छोटा है, बस जवाब ऊपर उल्लेख किया है में से एक के लिए जाना।

1

क्या आपने इनलाइन फ़ंक्शंस का एक सेट माना है जो "स्ट्रिंग टेम्पलेट्स" के बजाय ostringstram का उपयोग करते हैं?

inline std::string name_template(const std::string& name) 
{ 
    std::ostringstream os; 
    os << "My name is " << name; 
    return os.str(); 
} 

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

3

यदि आप सी ++ के लिए नए हैं, तो अपनी स्थापना में नए पुस्तकालय (टेम्पलेट या अन्यथा) जोड़ना सीखने की वक्र को बढ़ाएगा। यह कुछ ऐसा है जो आप अंतर्निहित सुविधाओं के साथ आसानी से, सुंदर और कुशलता से कर सकते हैं।

समान उत्तरों के विपरीत, इस कोड इनपुट से अधिक केवल एक पास बनाता है और बड़े शब्दकोशों के साथ अच्छी तरह से अनुरूप:

// header 
#include <map> 
#include <sstream> 

typedef std::map< std::string, std::string > subst_map; 

// implementation 
using namespace std; 

string do_substitutions(string const &in, subst_map const &subst) { 
    ostringstream out; 
    size_t pos = 0; 
    for (;;) { 
     size_t subst_pos = in.find("{{", pos); 
     size_t end_pos = in.find("}}", subst_pos); 
     if (end_pos == string::npos) break; 

     out.write(&* in.begin() + pos, subst_pos - pos); 

     subst_pos += strlen("{{"); 
     subst_map::const_iterator subst_it 
      = subst.find(in.substr(subst_pos, end_pos - subst_pos)); 
     if (subst_it == subst.end()) throw runtime_error("undefined substitution"); 

     out << subst_it->second; 
     pos = end_pos + strlen("}}"); 
    } 
    out << in.substr(pos, string::npos); 
    return out.str(); 
} 

// usage 
pair< string, string > substitutions_init[] = { 
    make_pair("firstname", "homer"), 
    make_pair("lastname", "simpson") 
}; 
subst_map substitutions 
    (substitutions_init, substitutions_init + sizeof(substitutions_init)/sizeof(*substitutions_init)); 

int main() { 
    cerr << do_substitutions("Mr. {{lastname}}, {{firstname}} esquire", substitutions) << endl; 
} 
0

आप Inja पर एक नज़र हो सकता है। यह एक साधारण, हेडर-केवल टेम्पलेट इंजन है और जो आप पूछ रहे हैं वह करता है। वहां आप बस

data["name"] = "world"; 
inja::render("Hello {{ name }}!", data); // Returns "Hello world!" 
संबंधित मुद्दे