How not to create temporary QRegularExpression objects - qt

I am getting a warning (in the QtCreator IDE) regarding the code snippet below. The warning is that I should not create temporary QRegularExpression objects; instead use a static QRegularExpression object.
QRegularExpression re("SEARCHING...",QRegularExpression::CaseInsensitiveOption);
QRegularExpressionMatch match = re.match(frame);
if (match.hasMatch()) {
It's not obvious to me...how should I use the QRegular expression instead?

That's a clazy warning message which you can find a description of here. It's just suggesting that you don't want to keep recreating the QRegularExpression every time you enter that function because the expression is always the same. So doing something like this should work:
static QRegularExpression re("SEARCHING...", QRegularExpression::CaseInsensitiveOption);
QRegularExpressionMatch match = re.match(frame);
if (match.hasMatch()) {

Related

Partial key matching QHash

I have a QHash defined as follows
QHash<QString, QString> hashLookup;
I have inserted a few values to this hash as follows:
hashLookup.insert("OMG", "Oh my God!");
hashLookup.insert("LOL", "Laugh out loud");
hashLookup.insert("RIP", "Rest in peace");
// and so on
I have a few QStrings as follows:
QString a = "OMG_1";
QString b = "LOL_A";
QStirng c = "OMG_YOU";
QString d = "RIP_two";
I am supposed to find if these values exist in hashLookup, i.e, since OMG_1 contains OMG, I should be able to retrieve Oh my God!.
I have tried to do this using
if(hashLookup.contains(a)
//do something
which ofcourse tries to look for a key OMG which is not present in the lookup table and does not return anything. Is partial matching of key values possible in Qt? If yes, how should I go about implementing this.
There is no opportunity in QHash class to extract values by partial matching of key, because QHash use hash function (Qt documentation: qHash) which:
The qHash() function computes a numeric value based on a key. It can
use any algorithm imaginable, as long as it always returns the same
value if given the same argument. In other words, if e1 == e2, then
qHash(e1) == qHash(e2) must hold as well. However, to obtain good
performance, the qHash() function should attempt to return different
hash values for different keys to the largest extent possible.
Different keys give almost always different hash.
In your task you can run on QHash keys and make comparison with QString functionality. Something like this:
QString getHashValue(const QString& strKey, const QHash<QString, QString>& hashLookup)
{
QList<QString> uniqueKeys = hashLookup.uniqueKeys();
foreach(const QString& key, uniqueKeys)
{
if(strKey.contains(key))
return hashLookup.value(key);
}
}
...
getHashValue("OMG_1", hashLookup);
First, in your example the QHash.contains(QString key) method tries to find OMG_1, which in fact it will not find.
You may implement a method which will take a expanded key and tries to locate any subkey of the given value in the hash. Here you have to define some rules I think or it may not return the intendend value.
Think of following example: the hash contains the keys OMG and OM. To match the provided expanded key you implement something like this
bool hashContainsExpanded(const QString &key) const {
if (!hash.contains(key) && key.length() > 1)
return hasContainsExpanded(key.substring(0, key.length() - 1));
return hash.contains(key);
}
This method will let you find the key OMG but not OM which is contained in this key. You may also implement a method which will take the first character of the provided expanded key and test it for containment. If not found, it will take the second and test again and so on. This will match OM in favour of OMG.
Also keep in mind, that you may work later with the matched key and thus you should return it instead of only returning true.

Accessing elements of a map when using a variable key in Groovy

I'm trying to replace some characters in a String From a map
Case 1
​map= ['O':'0', 'L':'1', 'Z':'2', 'E':'3']
"Hey".toUpperCase().toCharArray().each{
print map.get(it,it)
}
The result is
HEY
Case 2 : I dont use toCharArray()
"Hey".toUpperCase().each{
print map.get(it,it)
}
The result is like expected
H3Y
So I tried several alternatives when using toCharArray(), and the only way to access the value is to use map."$it"
Why i can only use map."$it" to access my map when using toCharArray() ?
Because you are trying to get a value from a map using a char whilst every key there are String, and they are not equals:
assert !'E'.equals('E' as char)
$it works because it is converted to String:
e = 'E' as char
assert "$e".toString().equals('E')
(Note the toString() is needed, otherwise the comparison will happen between String and GStringImpl which are not equals)

Adding values to a JsonCpp object/nested JsonCpp Json:Value objects

I have a JSON object say:
Json::Value temp;
temp["example1"] = "first";
which will be represented as
{
"example1" : "first"
}
Now if I want to add another object into the above object without using the index method, how can I do it? For example:
{
"example1" : "first",
"example2" : "second"
}
but avoiding using syntax
temp["example2"] = "second";
Are there any equivalents to push_back() (like in C++ vector/list) in JsonCpp?
The equivalent to push_back in JsonCpp is append, but you can use it only on Json::nullValue or Json::arrayValue.
That makes sense because only one parameter is needed to add an element to an array.
What are you asking is unclear/not possible, because you are trying to create an object, which is like a std::map in C++, and two parameters are needed to insert an element here.

C++ Static vector loses data after exiting function

I have a static function:
void TextManager::printDialogue(vector<Button*>* options, int optionsCount, vector<string> outputDisplayText)
{
active = true;
buttons = *options;
buttonsCount = optionsCount;
outputText = outputDisplayText;
}
The "buttons" variable is static:
static vector<Button*> buttons;
I make a call to printDialogue in an execute function:
void WorldDoor::execute()
{
vector<Button*> buttons;
buttons.push_back(new CancelButton());
buttons.push_back(new ChangeRoomButton(room));
TextManager::printDialogue(&buttons, 2, messages); //<----
std::vector<Button*>::iterator i = buttons.begin();
for ( i = buttons.begin() ; i < buttons.end(); i++ )
{
delete * i;
}
}
For whatever reason, when I debug and have a break point inside of the printDialogue function, the values in "buttons" are perfectly fine. However, after I leave printDialogue, the strings contained in my buttons go from being readable to giving me an error message saying:
I tried passing a pointer to an array instead of using
vector<Button*>
but it was only reading the first variable. Now it is not reading anything. Could anyone please help?
There is a static member variable called buttons, and also a local variable inside execute() called buttons. You should rename to avoid confusion, otherwise, the local variable will be used instead of the static member variable inside execute().
Edit: Completely misunderstood the question.
When you do this:
vector<int*> vector1;
vector<int*> vector2;
vector1.push_back(new int(5));
vector2 = vector1;
It copies the pointers, not the value of the pointers.
So when you later iterate over the first vector and delete the dynamic memory, both vectors have pointers pointing to the same memory that you deleted, so your second vector is pointing to invalid memory.
If you are using C++11, you can use a vector of unique pointers, and std::move() one vector into another.
Otherwise, you can just call 'clear()' on the vector, without deleting the memory.
Here's how the function could be written:
void TextManager::printDialogue(vector<Button*>* options, int optionsCount, vector<string> outputDisplayText)
{
active = true;
buttons = *options;
options->clear(); //<--- Instead of crawling over it and delete-ing it.
buttonsCount = optionsCount;
outputText = outputDisplayText;
}
Everything below this was my misunderstanding the question: (contains other information that might be important)
When you do:
vector<Button*> buttons;
Inside the function, you are creating a new vector called 'buttons', which gets destroyed at the end of the function call.
If you want to access the global one, don't create a new one inside the function, or name them something different.
Example:
int myVar = 100; //Declares a variable called 'myVar' at global scope.
void func()
{
int myVar = 200; //Declares a *different* variable called 'myVar' at function scope.
std::cout << myVar << std::endl; //Prints the one inside the function, not the one outside it.
}
By the way, the variable 'static' shouldn't be used at global scope, unless the variable belongs to a class.
To make a variable global, you just put it outside of any function. To make a class member shared between all instances of that class, you declare it static so that class knows to have all instances share the one variable. It's a different thing. =)
If you have your code split into multiple files, to make a global really-truly global, you have to declare it 'extern' in your header, and not extern in one source file, and have other source files #include the header that externs it. Slightly clunky, but that's how it's done. They are working on a better system for it, but it'll be several years before it becomes standardized.

Recovering multiple errors in Javacc

Is there a way in javacc to parse an input file further even after detecting an error. I got to know that there are several ways such as panic mode recovery, phrase level recovery and so on. But I can't figure how to implement it in javacc jjt file.
For an example assume my input file is
Line 1: int i
Line 2: int x;
Line 3: int k
So what I want is after detecting the error of missing semicolon at line 1, proceed parsing and find the error at line 3 too.
I found the answer in the way of panic mode error recovery,but it too have some bugs. What I did was I edit my grammar so that once I encounter a missing character in a line of the input file(in the above case a semicolon) parser proceed until it finds a similar character. Those similar characters are called synchronizing tokens.
See the example below.
First I replaced all the SEMICOLON tokens in my grammar with this.
Semicolon()
Then add this new production rule.
void Semicolon() :
{}
{
try
{
<SEMICOLON>
} catch (ParseException e) {
Token t;
System.out.println(e.toString());
do {
t = getNextToken();
} while (t.kind != SEMICOLON && t!=null && t.kind != EOF );
}
}
Once I encounter a missing character parser search for a similar character.When it finds such character it returns to the rule which called it.
Example:-
Assume a semicolon missing in a variable declaration.
int a=10 <--- no semicolon
So parser search for a semicolon.At some point it finds a semicolon.
___(some code)__; method(param1);
So after finding the first semicolon in the above example it returns to the variable declaration rule(because it is the one which called the semicolon() method.) But what we find after the newly find semicolon is a function call,not a variable declaration.
Can anyone please suggest a way to solve this problem.

Resources