Use a regular expression (regex) to match polynomials (polynomial), regexpolynomial
Because of the requirements of the job, I need to identify the polynomials input by the user from the command line and extract the coefficients and exponent for subsequent computation.
I used to think about using an array to store all user input, and then write the logical judgment. But when I think about the complicated logic, my head will be numb. At this time, a friend asked me to write a simple little crawler. After writing it, I had a chance, isn't the regular expression used by crawlers the best way to handle it ?? (Thanks for the fog)
Let's get down to the truth.
First, let's briefly talk about the knowledge of regular expressions. Here we only focus on what I will use later.
[] Square brackets are called atomic tables. They can match any element in brackets.
[abcd] // match any letter in abcd
[! @ #] // Match any symbol in @ #
[0-9] // match any number from 0,1,2,3,4,5,6,7,8,9
Three Common special symbols: * +?
* An asterisk can be used to match the preceding element 0 times, 1 time, or any number of times.
+ The plus sign can match the preceding element once or multiple times.
? The question mark can match the previous element 0 times or 1 time.
ab * // match a, ab, abb, abbb ...
ab + // match ab, abb, abbb, abbabb ...
ab? // match a, ab
() Parentheses are called the Pattern Unit operators here. They can combine some elements into a large, indissoluble new element, similar to the functions of parentheses in normal operations.
(ab *)? // match empty string or a, ab, abb, abbb ...
(ab +)? // match empty string or ab, abb, abbb, abbbb .......
(ab?)? // match empty string or a, ab
Match any character:. (except for line breaks)
A. c // match aac, abc, acc, adc .......
Escape Character: If you want to match symbols with special meanings, you can use the Escape Character \
\. // Match a decimal point
Boundary character: ^ $
- ^ Match the start of a string
- $ End of matching string
^ a. * // Match a string starting with a
. * a $ // match a string ending in a
Now, let's look back at the problem we want to solve.
We want to deal with a string similar to this. The user may enter some spaces, so the most secure way is to store the input information in the next line using a string, then, delete all spaces and tabs.
x^2+x-3x^-1
How to match such a complex expression ?? First, you have to split the file and start with it.
We can split a complete polynomial into several items.
x^2
+x
-3x^-1
Let's take a look at how to match one of them.
Obviously, the first occurrence is a positive or negative symbol, but it can also not appear.
[+-]? // Match the plus sign, minus sign, or no symbol
Then we should consider matching a floating point number. Of course, if the coefficient is 1, this floating point number can also not appear, so we can use one at the end? It indicates the meaning that does not appear.
[0-9] * \.? [0-9] + // match a floating point number
([0-9] * \.? [0-9] +)? // This floating point number can also not appear
Then consider matching the index bit. Of course, when the index is 1, it can also not appear. When the index is 0, x does not need to appear.
\\ ^ [+-]? [0-9] + // match ^ 1, ^ 2, ^ 3 ......
x (\\ ^ [+-]? [0-9] +)? // match x ^ 1, x ^ 2, x ^ 3 ...... or x (in case of index 1)
(x (\\ ^ [+-]? [0-9] +)?)? // Allow matching empty strings, used when the index is 0
Now, let's talk about the combination of the above three parts.
[-+]? ([0-9] * \.? [0-9] + )? (X (\ ^ [+-]? [0-9] + )?)? // Match x ^ 2,-3x ^ 5, 5,-x ^-1 ......
The last bit is complete !! The following is how to make this entire part appear multiple times to match the whole polynomial and match the start of the string through ^.
^ ([-+]? ([0-9] * \.? [0-9] + )? (X (\ ^ [+-]? [0-9] + )?)?) + // Match the whole Polynomial
Emmmmm, good! Success! (In fact, there are still some flaws, but I am very satisfied with it)
Next, set the code implementation method. Oh, yes. If you want to use a regular expression, remember to # include <regex>
std::string poly = "x^2-x+3+x^-5";
std::regex polyPattern("^([-+]?([0-9]*\.?[0-9]+)?(x(\\^[+-]?[0-9]+)?)?)+");
if(!std::regex_match(poly,polyPattern)){
std::cout<<"invalid polynomial!"<<std::endl;
}
What I need to do below is to identify the coefficients and indexes in each item and convert them into double and int variables for easy calculation.
Std: regex cofPattern ("^ [-+]? ([0-9] * \.? [0-9] +) "); // matching coefficient
Because x and-x cannot be matched, you can make a proper judgment when writing code.
std :: smatch cofResult;
double cof;
std :: string term = "3x ^ 5";
if (std :: regex_search (term, cofResult, cofPattern)) {
const char * tempCof = cofResult.str (). data (); // The parameter of atof function is of type const char *, we need to convert it
cof = std :: atof (tempCof); // Convert string to double type number
} else if (term [0] == '-')
cof = -1;
else
cof = 1;
The following is the last step! Extraction Index
Std: regex expPattern1 ("x \ ^ [+-]? [0-9] + $ "); // matching index
However, as this does not match the exponential value of 1, I wrote a separate regular expression.
Std: regex expPattern2 ("x $"); // match x at the end
std::smatch expResult;
std::smatch expResult;
int exp;
if( std::regex_search(term,expResult,expPattern1) ){
const char* tempExp = expResult.str().substr(2).data();
exp = std::atoi(tempExp);
}else if(std::regex_search(term,expResult,expPattern2))
exp = 1;
else
exp = 0;
2017-10-20 19:48:49