This code parses a text file, replacing special tokens marked as $(token) with some replaced text. The $ symbol can be escaped by entering a double $$. In the example a user enters a text file containing tokens to replace and a separate mapping file with, for instance, colour:red to denote how to replace a token.
Some remarks I have is that is is not using any OO really. Does it need to be?
#include <fstream>
#include <iostream>
#include <vector>
#include <map>
#include <string>
static void readToken(std::istream& strm, std::vector<char>& token)
{
while(strm) {
int c (strm.get());
token.push_back(c);
if(')' == c) break;
}
}
static void lookup_replacement(const std::map<std::string,std::string>& token_map,
const std::vector<char>& key, std::vector<char>& value) {
if(key.size() > 3) { //3 chars min are '$', '(' and ')'
std::map<std::string,std::string>::const_iterator it = token_map.find(std::string(key.begin()+2, key.end()-1));
if(it != token_map.end())
value.insert(value.end(), it->second.begin(), it->second.end());
}
}
static bool readTo(std::istream& strm, std::vector<char>& buf, const char term[])
{
bool ret(false);
while(strm) {
int c (strm.peek());
if(strchr(term, c)) {
strm.get();
int c2(strm.peek());
if(c != c2) {
strm.unget();
ret = true;
break;
}
}
strm.get();
buf.push_back(c);
}
return ret;
}
static void create_mapping(std::ifstream& strm, std::map<std::string,std::string>& tokens) {
if(strm.good()) {
std::string line;
while(std::getline(strm, line)) {
std::string::size_type pos = line.find_first_of(':');
if(pos != std::string::npos)
tokens.insert(std::make_pair<std::string, std::string>(line.substr(0, pos), line.substr(pos+1)));
}
}
}
int main() {
std::map<std::string,std::string> token_map;
typedef std::map<std::string,std::string>::iterator map_iter;
std::cout << "Enter path to text file to replace\nTokens to be replaced should be of form: $(token)\n";
std::string file;
std::cin >> file;
std::cout << "Enter path to file with target token <-> replacement token in format:\n"
"<toreplace1>:<replacement1>\n<toreplace2>:<replacement2>\netc\n";
std::string mapfile;
std::cin >> mapfile;
std::ifstream strmmap(mapfile.c_str());
create_mapping(strmmap, token_map);
// replaced text
std::vector<char> replaced;
std::ifstream strm(file.c_str());
if(!strm.bad()) {
while(!strm.eof()) {
if(readTo(strm, replaced, "$")) {
std::vector<char> token;
readToken(strm, token);
std::vector<char> replace_tok;
lookup_replacement(token_map, token, replace_tok);
if(!replace_tok.empty())
replaced.insert(replaced.end(), replace_tok.begin(), replace_tok.end());
}
}
}
//print out replaced text
std::cout << "your replaced text file\n";
std::vector<char>::iterator pit = replaced.begin();
while(pit != replaced.end())
std::cout << *pit++;
return 0;
}
The example input file I was using:
Once upon a $(place1) there was a $(adjective1) $(colour) $(animal).
Do you have a $$
You have enemies? Good. That means you've stood up for something, sometime in your life. by $(author) on $(date)
A fanatic is one who can't change his mind and won't change the subject. By $(author)
And the mapping file:
place1:time adjective1:cunning colour:brown animal:fox author:Winston Churchill date:06/06/2013
$X
? You replacement thing is$(<X>)
. So the questions are: 1) What is$()
2) what is$<Y>
(Y => any character not '('). 3) What happens when the replacement is not terminated$(<Z>\n
\$\endgroup\$