Skip to content

Instantly share code, notes, and snippets.

@beyondwdq
Created March 25, 2014 05:06
Show Gist options
  • Save beyondwdq/9755557 to your computer and use it in GitHub Desktop.
Save beyondwdq/9755557 to your computer and use it in GitHub Desktop.
// Compile: g++ -std=c++11 -Wall replace_var.cc -o replace_var
// Tested with g++-4.7.2
#include <string>
#include <map>
#include <cctype>
#include <iostream>
typedef std::map<std::string, std::string> TVarMap;
using namespace std;
constexpr char kVarBegin[] = "$(";
constexpr char kVarEnd = ')';
constexpr size_t kVarBeginLen = sizeof(kVarBegin) - 1;
/******************************************
* A helper function to extract the variable
* name. Invoked by replaceVars()
* ****************************************/
std::string extractVar(const std::string &buf, size_t bpos, size_t epos)
{
bpos += kVarBeginLen;
--epos;
while (std::isspace(buf[bpos])) ++bpos;
while (std::isspace(buf[epos])) --epos;
if (bpos > epos) return std::string();
return buf.substr(bpos, epos - bpos + 1);
}
/*************************************************
* Replace the variables with their values defined
* in varmap. A variable is identified by $(var).
* Example:
* let varmap = {"x"="1", "y"="2", z="3"}
* buf = "$(x) + $(y) = $(z)"
* The content in buf at the end of this functions is:
* buf = "1 + 2 = 3"
* Nested variable is allowed. See the example in main().
*
* Return number of replacements happened on success,
* -1 on failure.
* ************************************************/
int replaceVars(std::string &buf, const TVarMap &varmap)
{
int pos = 0;
int cnt = 0;
for(auto epos = buf.find(kVarEnd, 0);
epos != std::string::npos && pos < (int)buf.size();
epos = buf.find(kVarEnd, pos)) {
pos = epos + 1;
if (epos > kVarBeginLen) {
auto bpos = buf.rfind(kVarBegin, epos - 1);
if (bpos == std::string::npos) continue;
auto var = extractVar(buf, bpos, epos);
auto it = varmap.find(var);
if (it == varmap.end()) {
cerr << "variable '" << var << "' not defined" << endl;
return -1;
}
int len = epos - bpos + 1;
buf.replace(bpos, len, it->second);
pos += (int)it->second.size() - len;
++cnt;
}
}
return cnt;
}
int main(int argc, const char *argv[])
{
string buf("$( x ) + $( y) = $($(z))");
TVarMap varmap{{"x", "1"}, {"y", "2"}, {"xy", "3"}, {"z", "xy"}};
int cnt = replaceVars(buf, varmap);
cout << cnt << endl;
cout << buf << endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment