Below is a simple code to find 2401 in the string. I do not know what that the number is 2401, it can be any number from 0-9. To find the 4 digit number i want to use "DDDD". The letter D will find a number between 0->9. How do i make it so the compiler realizes that a letter D is a a code to find a 1 digit number.
#include <string>
#include <iostream>
#include <vector>
using namespace std;
int main()
{
std::string pattern ;
std::getline(std::cin, pattern);
std::string sentence = "where 2401 is";
//std::getline(std::cin, sentence);
int a = sentence.find(pattern,0);
int b = pattern.length();
cout << sentence.substr(a,b) << endl;
//std::cout << sentence << "\n";
}
try using regular expressions. They can be kind of a pain in the ass, but pretty powerful once mastered. In your case i would recommend using regex_search(), like here:
#include <string>
#include <iostream>
#include <vector>
#include <regex>
using namespace std;
int main()
{
std::smatch m;
std::regex e ("[0-9]{4}"); // matches numbers
std::string sentence = "where 2401 is";
//int a = sentence.find(pattern,0);
//int b = pattern.length();
if (std::regex_search (sentence, m, e))
cout << m.str() << endl;
//cout << sentence.substr(a,b) << endl;
//std::cout << sentence << "\n";
}
If you want to make the exact matching user-specific you can also just ask for the number of digits in the number or the complete regular expression, etc.
Also noted:
the simple regular expression provided [0-9]{4} means: "any character between 0 and 9 excactly 4 times in a sequence". Have a look here for more information
in your question you mentioned, you wanted the compiler to do the matching. Regular expressions are not matched by the compiler, but at runtime. In that case you could also variable the input string and the regular expression.
using namespace std; makes the prefix std:: unnecessary for those variable declarations
std::getline(std::cin, pattern); could be replaced by cin >> pattern;
Related
I'm trying to replace a special character Æ with space using the boost regex replace, but I cannot do so. In order to replace the special character, can anyone please help me with what exactly my regular expression should be. Below is the code snippet which I am trying out.
#include <iostream>
#include <regex>
#include <string>
using namespace std;
int main()
{
regex escape("\\xC6");
const char* specialChar = "bananaÆ,test";
string xml = regex_replace(specialChar, escape, "");
cout << specialChar << "\n";
cout << xml << '\n';
}
Output:
bananaÆ,test
bananaÆ,test
How can I use the already-defined regex pattern in another regex pattern. For example in the following code sign and number are defined and I want to use them in defining relation:
regex sign("=<|=|>|<=|<>|>=");
regex number("^[1-9]\\d*");
regex relation(number, sign, number)
So, I need to find all matches (to the pattern like 23<=34 or 123<>2000) in the given file.
Since I haven't completed the relation, I've been testing with sign:
#include <iostream>
#include <fstream>
#include <regex>
using namespace std;
int main() {
regex sign("=<|=|>|<=|<>|>=");
regex digit("[0-9]");
regex number("^[1-9]\\d*");
//regex relation("^[1-9]\d*[=<|=|>|<=|<>|>=]^[1-9]\d*"); (this part is what I couldn't do)
string line;
ifstream fin;
fin.open("name.txt");
if (fin.good()) {
while (getline(fin, line)) {
bool match_sign = regex_search(line, sign);
if (match_sign) {
cout << line << endl; // but I need to print the match only
}
}
}
return 0;
}
When I want to print the matches in the file, it prints the whole line which contains any match. How can I make it print only the match itself but not the whole line?
Update:
#include <iostream>
#include <fstream>
#include <vector>
#include <regex>
using namespace std;
#define REGEX_SIGN "=<|=|>|<=|<>|>="
#define REGEX_DIGIT "[0-9]"
#define REGEX_NUMBER "^" REGEX_DIGIT "\\d*"
int main() {
regex sign(REGEX_SIGN);
regex digit(REGEX_DIGIT);
regex number(REGEX_NUMBER);
regex relation(REGEX_NUMBER REGEX_SIGN REGEX_NUMBER);
string line, text;
ifstream fin;
fin.open("name.txt");
if (fin.good()) {
while (getline(fin, line)) {
text += line + " ";
}
int count = 0;
string word = "";
for (int i = 0; i < text.length(); i++) {
if (text[i] == ' ') {
cout << "word = " << word << " | match: " << regex_match(word, relation) << endl;
if (regex_match(word, relation)) {
cout << word << endl;
}
word = "";
}
else {
word += text[i];
}
}
}
// cout << text << endl;
return 0;
}
Current name.txt looks like this:
But I think the regular expression is not working right:
It says no word matches. Where is the problem?
The problem of "reusing" a smaller regex inside a larger regex is not really possible.
The only workaround I can see is to define the strings of the regexes as macros, and use the compilers literal-string concatenation feature to create larger strings:
#define REGEX_SIGN "=<|=|>|<=|<>|>="
#define REGEX_DIGIT "[0-9]"
#define REGEX_NUMBER "^" REGEX_DIGIT "\\d*"
regex sign(REGEX_SIGN);
regex digit(REGEX_DIGIT);
regex number(REGEX_NUMBER);
regex relation(REGEX_NUMBER REGEX_SIGN REGEX_NUMBER);
This doesn't reuse the actual regex objects, only create longer literal strings from smaller.
The bottom line is that I need to find all the comments in some Python code and cut them out, leaving only the code itself.
But I can't do it from the opposite. That is, I find the comments themselves, but I cannot find everything except them.
I tried using "?!", Made up a regular expression like "(. *) (?! #. *)". But it does not work as I expected.
Just as in the code that I attached, there is an "else" that I tried to use too, that is, write to different variables, but for some reason it doesn't even go there
#include <iostream>
#include <fstream>
#include <string>
#include <regex>
int main()
{
std::string line;
std::string new_line;
std::string result;
std::string result_re;
std::string path;
std::smatch match;
std::regex re("(#.*)");
std::cout << "Enter the path\n";
std::cin >> path;
std::ifstream in(path);
if (in.is_open())
{
while (getline(in, line))
{
if (std::regex_search(line, match, re))
{
for (int i = 0; i < match.size(); i++)
result_re += match[i + 1];
result_re += "\n";
}
else
{
for (int i = 0; i < match.size(); i++)
result += match[i];
//result += "\n";
}
std::cout << line << std::endl;
}
}
in.close();
std::cout << result_re << std::endl;
std::cout << "End of program" << std::endl;
std::cout << result << std::endl;
system("pause");
return 0;
}
As I said above, I want to get everything except comments, and not the other way around.
I also need to do a search for multi-line comments, which are defined in """Text""".
But in this implementation, I can’t even imagine how to do it, since now it is reading line by line, and a multi-line comment in this case with the help of a regulars program is impossible for me to get
I would be grateful for your advices and help.
1. don't try parsing your input file line by line. Instead suck in the whole text and let regex to replace all the comments, this way your entire program would look like this:
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <regex>
using namespace std; // for brevity
int main() {
cout << "Enter the path: ";
string filename;
getline(cin, filename);
string pprg{ istream_iterator<char>(ifstream{filename, ifstream::in} >> noskipws),
istream_iterator<char>{} };
pprg = regex_replace(pprg, regex{"#.*"}, "");
cout << pprg << endl;
}
to handle multi-line Python literals """...""", with C++ regex is quite uneasy to do (unlike in the example above): there are few mutually exclusive requirements (imho):
regex should be extended POSIX, but
POSIX regex does not support empty regex matches, however
for crafting an RE to match a negated sequence of characters a negative look-ahead assert is required, which will be an empty match :(
thus it would mean, you'd need to think and put up some programming logic to remove multi-line Python text literals
I need to validate a string that is at least 5 characters long, contains at least one upper-case letter, at least one lower-case letter, at least one digit and no other characters except the dash and the underscore. I've tested this in other languages and it apparently works:
^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z_\-]{5,}$
However, in C++, this simple test program validates strings such as "AasdA" as correct input. I know I am missing something glaringly obvious, but after much research I cannot tell what is wrong. Maybe it's something to do with the way getline() stores strings. Here is my code:
#include <iostream>
#include <regex>
#include <string>
using namespace std;
int main() {
string test;
do {
cout << "Test: ";
getline(cin, test);
if (regex_match(test, regex("^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z_\-]{5,}$"))) {
cout << "True." << endl;
} else {
cout << "False." << endl;
}
} while (test != "");
return 0;
}
You need to double the backslashes in your string constant:
if (regex_match(test, regex("^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z_\\-]{5,}$"))) {
I have a C++ program which needs to take user input. The user input will either be two ints (for example: 1 3) or it will be a char (for example: s).
I know I can get the twos ints like this:
cin >> x >> y;
But how do I go about getting the value of the cin if a char is input instead? I know cin.fail() will be called but when I call cin.get(), it does not retrieve the character that was input.
Thanks for the help!
Use std::getline to read the input into a string, then use std::istringstream to parse the values out.
You can do this in c++11. This solution is robust, will ignore spaces.
This is compiled with clang++-libc++ in ubuntu 13.10. Note that gcc doesn't have a full regex implementation yet, but you could use Boost.Regex as an alternative.
EDIT: Added negative numbers handling.
#include <regex>
#include <iostream>
#include <string>
#include <utility>
using namespace std;
int main() {
regex pattern(R"(\s*(-?\d+)\s+(-?\d+)\s*|\s*([[:alpha:]])\s*)");
string input;
smatch match;
char a_char;
pair<int, int> two_ints;
while (getline(cin, input)) {
if (regex_match(input, match, pattern)) {
if (match[3].matched) {
cout << match[3] << endl;
a_char = match[3].str()[0];
}
else {
cout << match[1] << " " << match[2] << endl;
two_ints = {stoi(match[1]), stoi(match[2])};
}
}
}
}