Sometimes you may encounter the following problems when writing code:
Assume that a text file contains content similar to the C language, with a line of statements in the following format:
Layout (local_size_x = A, local_size_y = B, local_size_z = C) in; |
Layout, local_size_x, local_size_y, local_size_y, local_size_z, in are the keywords, And the Italic part (A, B, C) is the number whose data type is unsigned Int, compile a function to extract the values of A, B, and C from the file. The file name is the input parameter, and the return value of this function is the extracted a, B, c.
For example, for the next text file, the Program expects the output to be (16, 16, 1)
# Version 430 Core Layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in; Void main (void) { Imagestore (utexture, ivec2 (gl_globalinvocationid.xy), vec4 (0, 0, 0, 0 )); } |
Note the following points when analyzing text:
A. Assume that there is only one layout statement in the text to define local_size_x, local_size_y and local_size_z, And the syntax of this statement is correct;
B. You can use // or /*... */Method to comment out some code;
C. You can use # define for macro definition;
D. the default values of local_size_x, expires, and dimensions are 1. local_size_x and local_size_y can be omitted, or local_size_z can be omitted if local_size_x is defined.
For example, the return value of the following text should be (32, 16, 1 ).
# Version 430 Core # Define local_x32 // Layout (local_size_x = 16, local_size_y = 13, local_size_z = 2) in; Layout (local_size_x = local_x, local_size_y = 16) in; Void main (void) { Imagestore (utexture, ivec2 (gl_globalinvocationid.xy), vec4 (0, 0, 0, 0 )); } |
Use boost: string to write a code,
#include <iostream>#include <fstream>#include <map>#include <vector>#include <boost/tuple/tuple.hpp>#include <boost/lexical_cast.hpp>#include <boost/algorithm/string.hpp>#include <boost/utility/string_ref.hpp>class CTest{public:CTest(int vX = 1, int vY = 1, int vZ = 1) : m_X(vX), m_Y(vY), m_Z(vZ) {}~CTest() {}//*********************************************************************************//FUNCTION:void parseText(const char* vFileName){std::vector<std::string> StrVec;preprocess(vFileName, StrVec);/*for (int i=0; i<StrVec.size(); ++i){std::cout << StrVec[i] << std::endl;}*/processLayout(StrVec);}//*********************************************************************************//FUNCTION:void printMember() const{std::cout << m_X << " " << m_Y << " " << m_Z << std::endl;}//*********************************************************************************//FUNCTION:boost::tuples::tuple<int, int, int> getValue() const{return boost::make_tuple(m_X, m_Y, m_Z);}private://*********************************************************************************//FUNCTION:void preprocess(const char* vFileName, std::vector<std::string>& voStrVec){std::ifstream Ifs(vFileName);if (!Ifs) {std::cout << "Can not open the file " << vFileName << std::endl;exit(-1);}std::string LineStr;while (getline(Ifs, LineStr)){if (LineStr.find("//") != std::string::npos){std::string::iterator End = LineStr.begin()+LineStr.find("//");if (LineStr.begin() != End) voStrVec.push_back(std::string(LineStr.begin(), End));}else if (LineStr.find("/*") != std::string::npos){while (getline(Ifs, LineStr)){if (LineStr.find("*/") != std::string::npos) break;}}else if (LineStr.size() > 0) voStrVec.push_back(LineStr);}Ifs.close();}//*********************************************************************************//FUNCTION:void processLayout(const std::vector<std::string>& vStrVec){std::map<std::string, int> DataMap;for (unsigned int i=0; i<vStrVec.size(); ++i){if (vStrVec[i].find("#define") != std::string::npos) processDefine(vStrVec[i], DataMap);else if (vStrVec[i].find("layout") != std::string::npos) processLayout(vStrVec[i], DataMap);}}//*********************************************************************************//FUNCTION:void processDefine(const std::string& vSorceString, std::map<std::string, int>& voDataMap){typedef boost::split_iterator<std::string::const_iterator> Split_String_Itearor;Split_String_Itearor Bgn, End;std::vector<std::string> StrVec;for (Bgn = boost::algorithm::make_split_iterator(vSorceString, boost::algorithm::token_finder(boost::is_any_of(" "))); Bgn != End; ++Bgn){ if ((*Bgn).size()>0) StrVec.push_back(std::string((*Bgn).begin(), (*Bgn).end()));}//for (int i=0; i<StrVec.size(); ++i)//{//std::cout << StrVec[i] << std::endl;//}voDataMap[StrVec[1]] = boost::lexical_cast<int>(StrVec[2]);}void processLayout(const std::string& vSorceString, std::map<std::string, int>& vDataMap){typedef boost::split_iterator<std::string::const_iterator> Split_String_Itearor;Split_String_Itearor Bgn, End;std::vector<std::string> StrVec;for (Bgn = boost::algorithm::make_split_iterator(vSorceString, boost::algorithm::token_finder(boost::is_any_of(" (,);="))); Bgn != End; ++Bgn){ if ((*Bgn).size()>0) StrVec.push_back(std::string((*Bgn).begin(), (*Bgn).end()));}/*for (int i=0; i<StrVec.size(); ++i){std::cout << "[" << StrVec[i] << "]";}std::cout << std::endl;*/if (StrVec.size() >= 4){if (StrVec[2][0] >= '0' && StrVec[2][1] <= '9'){m_X = boost::lexical_cast<int>(StrVec[2]);}else{if (vDataMap.find(StrVec[2]) == vDataMap.end()){std::cout << "somethind if wrong \n";exit(1);}m_X = vDataMap[StrVec[2]];}}if (StrVec.size() >= 6){if (StrVec[4][0] >= '0' && StrVec[4][0] <= '9'){m_Y = boost::lexical_cast<int>(StrVec[4]);}else{if (vDataMap.find(StrVec[4]) == vDataMap.end()){std::cout << "somethind if wrong \n";exit(1);}m_Y = vDataMap[StrVec[4]];}}if (StrVec.size() >= 8){if (StrVec[6][0] >= '0' && StrVec[6][1] <= '9'){m_Z = boost::lexical_cast<int>(StrVec[6]);}else{if (vDataMap.find(StrVec[6]) == vDataMap.end()){std::cout << "somethind if wrong \n";exit(1);}m_Z = vDataMap[StrVec[6]];}}}private:int m_X;int m_Y;int m_Z;};int main(){CTest Test;Test.parseText("test.txt");Test. printMember();getchar();return 0;}
However, you can use boost: RegEx to write this question.
#include <string>#include <fstream>#include <iostream>#include <boost\regex.hpp>#include <boost\algorithm\string\split.hpp>#include <boost\algorithm\string\regex.hpp>#include <boost\algorithm\string\classification.hpp>//****************************************************************************************************************//FUNCTION:unsigned int convertString2Ui(const std::string& vString){unsigned int Value = 0;for (unsigned int i=0; i<vString.length(); i++){Value = Value*10 + vString.at(i)-'0';}return Value;}//****************************************************************************************************************//FUNCTION:void readContentFromFile(const char* vFileName, std::string& voContent){std::ifstream InFile(vFileName);char* pContent = NULL;if (InFile){InFile.seekg(0, InFile.end); unsigned int NumCharacter = unsigned int (InFile.tellg()); pContent = new char[NumCharacter+1];InFile.seekg(0, std::ios::beg);int i=0;while (!InFile.eof()){if(InFile.read(&pContent[i], sizeof(char))) i++;}pContent[i] = '\0';voContent = std::string(pContent);}delete[] pContent;}//****************************************************************************************************************//FUNCTION:void deleteComments(std::string& vioString){boost::regex CommentRegEx("(//.*?\\n)|(/\\*.*?(\\*)+/)");vioString = boost::regex_replace(vioString, CommentRegEx, "", boost::regex_constants::match_not_dot_newline);}//****************************************************************************************************************//FUNCTION:void replaceMacro(std::string& vioString){boost::smatch MacroString;boost::regex MacroRegex("^#define(\\s)+([a-zA-z_0-9\\(\\)]+)(\\s)+([a-zA-z_0-9\\(\\)]+)");std::string::const_iterator Start = vioString.begin();std::string::const_iterator End = vioString.end();std::vector<std::string> MacroSet, ValueSet;while (boost::regex_search(Start, End, MacroString, MacroRegex, boost::regex_constants::match_not_null|boost::regex_constants::match_not_dot_newline)){Start = MacroString[0].second;MacroSet.push_back(MacroString[2].str());ValueSet.push_back(MacroString[4].str());}_ASSERT(MacroSet.size() == ValueSet.size());for (unsigned int i=0; i<MacroSet.size(); i++){vioString = boost::regex_replace(vioString, boost::regex(MacroSet.at(i)), ValueSet.at(i));}}//****************************************************************************************************************//FUNCTION:void dumpNums(const std::string& vContent, unsigned int& voA, unsigned int& voB, unsigned int& voC){voA = voB = voC = 1;boost::regex MatchRegex("layout \\(local_size_x = ([0-9]+)(, local_size_y = ([0-9]+)(, local_size_z = ([0-9]+))?)?\\) in;");boost::smatch MatchString;boost::regex_search(vContent, MatchString, MatchRegex);voA = convertString2Ui(MatchString[1].str());if (!MatchString[3].str().empty()) {voB = convertString2Ui(MatchString[3].str());if (!MatchString[5].str().empty()) voC = convertString2Ui(MatchString[5].str());}}//****************************************************************************************************************//FUNCTION:void parseFile(const std::string& vFileName, unsigned int& voA, unsigned int& voB, unsigned int& voC){std::string Content;readContentFromFile(vFileName.c_str(), Content);deleteComments(Content);replaceMacro(Content);dumpNums(Content, voA, voB ,voC);}void installMemoryLeakDetector(){#if defined(DEBUG) | defined(_DEBUG)_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);//_crtBreakAlloc = 955;#endif}int main(int argc, char** argv){installMemoryLeakDetector();_ASSERT(argc >= 2);const std::string FileName(argv[1]);unsigned int A = 0, B = 0, C = 0; parseFile(FileName, A, B, C);std::cout << A << " " << B << " " << C << std::endl;return 0;}