I'm going to parse a string of mathematical functions in Qt 5.12, for example
"fabs( sin( pow( cos(30) , pow(1,2) ) ) )"
How do I parse out each function name and its arguments correctly, continue parsing when the function argument is another function, and call a library function with the same name for a numeric value? Finally, the result is returned to the function above.
I tried to write code like this, with ", "as the separator to get each parameter. But when the argument is a function that requires more than one argument, a BUG occurs. But I can't think of a solution
double Cal::calculate(const QString & funcstr)
{
int lb = funcstr.indexOf("(");
int rb = funcstr.lastIndexOf(")");
double result = 0;
if(funcstr.startsWith("pow", Qt::CaseInsensitive))
{
QStringList paramList_str = funcstr.mid(lb + 1, rb - lb - 1).split(",");
QList<double> paramList;
for(int i = 0; i < paramList_str.size(); ++i)
{
if(parse(paramList_str[i]))
{
paramList.push_back(paramList_str[i].toDouble());
}else{
paramList.push_back(calculate(paramList_str[i]));
}
}
result = pow(paramList[0], paramList[1]);
}
else if(funcstr.startsWith("sin", Qt::CaseInsensitive))
{
QString param = funcstr.mid(lb + 1, rb - lb - 1);
if(parse(param))
result = sin(param.toDouble());
else
result = sin(calculate(param));
}else if(funcstr.startsWith("cos", Qt::CaseInsensitive))
{
QString param = funcstr.mid(lb + 1, rb - lb - 1);
if(parse(param))
result = cos(param.toDouble());
else
result = cos(calculate(param));
}else if(funcstr.startsWith("tan", Qt::CaseInsensitive))
{
QString param = funcstr.mid(lb + 1, rb - lb - 1);
if(parse(param))
result = tan(param.toDouble());
else
result = tan(calculate(param));
}
retur result;
}
bool parse(const QString &funcName)
{
QChar c = funcName[0];
bool res = true;
if(c.isLetter())
res = false;
return res;
}
Can Someone explain what is wrong in this code ?
It is failing on testcase s = "aa" and p = "*".
I have followed recursion and dynamic programming code here
Leetcode 44 Wildcard Matching
class Solution {
public boolean isMatch(String s, String p) {
int n = s.length();
int m = p.length();
int[][] dp = new int[n][m];
for(int[] it : dp)
Arrays.fill(it, -1);
return solve(n-1 , m-1, s ,p , dp);
}
public boolean solve(int i, int j, String s, String p, int[][] dp){
if(i < 0 && j < 0) return true;
if(i < 0 && j >=0){
while(j>=0){
if(p.charAt(j) + "" == "*") j--;
else return false;
}
return true;
}
if(j < 0 && i >=0) return false;
if(dp[i][j] != -1){
if(dp[i][j]==1) return true;
return false;
}
if(s.charAt(i) == p.charAt(j) || p.charAt(j) + "" == "?"){
boolean temp = solve(i-1,j-1,s,p,dp);
if(temp == false) dp[i][j] = 0;
else
dp[i][j] = 1;
return temp;
}
if(p.charAt(j) + "" == "*"){
boolean temp = solve(i-1,j,s,p,dp) || solve(i,j-1,s,p,dp);
if(temp == false)
dp[i][j] = 0;
else
dp[i][j] = 1;
return temp;
}
dp[i][j] = 0;
return false;
}
}
Unable to figure out what is causing the buffer overflow in below code. I reckon it has to do with the vector but I am guarding against out of bounds access. Is there anything else that could be causing the overflow?
class Solution {
public:
bool canPartition(vector<int>& nums) {
int sum = 0;
bool canPartition = true;
vector<vector<int>> dp(nums.size(), vector<int>(sum / 2 + 1, -1));
sum = accumulate(nums.begin(),nums.end(),0);
if (sum % 2 != 0)
{
canPartition = false;
}
if (true == canPartition)
{
canPartition = canPartitionRecursive(nums, 0, sum/2, dp);
}
return canPartition;
}
bool canPartitionRecursive(vector<int>& nums, int index, int sum,
vector<vector<int>>& dp)
{
if (sum == 0)
{
return true;
}
if (index >= nums.size() || sum < 0)
{
return false;
}
if (dp[index][sum] != -1)
{
if (true == canPartitionRecursive(nums, index+1, sum - nums[index],dp))
{
dp[index][sum] = 1;
return true;
}
dp[index][sum] = canPartitionRecursive(nums, index + 1, sum, dp);
}
return dp[index][sum] = 1? true:false;
}
};
This looks like a transpositional error (all subvector will have size 1):
int sum = 0;
vector<vector<int>> dp(nums.size(), vector<int>(sum / 2 + 1, -1));
sum = accumulate(nums.begin(),nums.end(),0);
Perhaps calculation of sum should be moved before dp initialization?
msg.append(QString("\"settime\": %1000,") .arg(eventList[i].failureBegin)); // set time
I would like to know if it`s ok to have %1 right next to 000. Since there is only 1 argument then there is obviously no confusion possible for QString but what if I had 10 .arg() Then it would confuse it with %10 right? Is there an escape sequence for this or do I have to break it down into concatenations?
It is not ok. You can explore the source code of QString::arg or let me show you.
QString QString::arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const
{
ArgEscapeData d = findArgEscapes(*this);
if (d.occurrences == 0) {
qWarning() << ""QString::arg: Argument missing:"" << *this << ',' << a;
return *this;
}
//.... something not important.
}
This is how findArgEscapes is implemented. I think source code of Qt is much more readable than most STL implementations.
static ArgEscapeData findArgEscapes(const QString &s)
{
const QChar *uc_begin = s.unicode();
const QChar *uc_end = uc_begin + s.length();
ArgEscapeData d;
d.min_escape = INT_MAX;
d.occurrences = 0;
d.escape_len = 0;
d.locale_occurrences = 0;
const QChar *c = uc_begin;
while (c != uc_end) {
while (c != uc_end && c->unicode() != '%')
++c;
if (c == uc_end)
break;
const QChar *escape_start = c;
if (++c == uc_end)
break;
bool locale_arg = false;
if (c->unicode() == 'L') {
locale_arg = true;
if (++c == uc_end)
break;
}
int escape = c->digitValue();
if (escape == -1)
continue;
++c;
if (c != uc_end) {
int next_escape = c->digitValue();
if (next_escape != -1) {
escape = (10 * escape) + next_escape; //*************
++c;
}
}
if (escape > d.min_escape)
continue;
if (escape < d.min_escape) {
d.min_escape = escape;
d.occurrences = 0;
d.escape_len = 0;
d.locale_occurrences = 0;
}
++d.occurrences;
if (locale_arg)
++d.locale_occurrences;
d.escape_len += c - escape_start;
}
return d;
}
Is it possible to do something like this:
var s:String = format("%20d %-10s %s", time, type, message);
In languages like C, C++, C#, Python, and Perl there is something similar to my example, but I can't seem to find it for Flex.
I don't want to create special class Formatter for every string that I want to format.
You probably are looking for mx.utils.StringUtil.substitute(). Works similar to .NET String.Format().
For Example:
StringUtil.substitute("Hello {0}", ["World"]);
Adobe Livedocs for StringUtil class
Found this script that implements sprintf - and that's exactly what I was looking for. Thanks to Manish Jethani!
/* sprintf(3) implementation in ActionScript 3.0.
*
* Author: Manish Jethani (manish.jethani#gmail.com)
* Date: April 3, 2006
* Version: 0.1
*
* Copyright (c) 2006 Manish Jethani
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package
{
/* sprintf(3) implementation in ActionScript 3.0.
*
* http://www.die.net/doc/linux/man/man3/sprintf.3.html
*
* The following flags are supported: '#', '0', '-', '+'
*
* Field widths are fully supported. '*' is not supported.
*
* Precision is supported except one difference from the standard: for an
* explicit precision of 0 and a result string of "0", the output is "0"
* instead of an empty string.
*
* Length modifiers are not supported.
*
* The following conversion specifiers are supported: 'd', 'i', 'o', 'u', 'x',
* 'X', 'f', 'F', 'c', 's', '%'
*
* Report bugs to manish.jethani#gmail.com
*/
public function sprintf(format:String, ... args):String
{
var result:String = "";
var length:int = format.length;
for (var i:int = 0; i < length; i++)
{
var c:String = format.charAt(i);
if (c == "%")
{
var pastFieldWidth:Boolean = false;
var pastFlags:Boolean = false;
var flagAlternateForm:Boolean = false;
var flagZeroPad:Boolean = false;
var flagLeftJustify:Boolean = false;
var flagSpace:Boolean = false;
var flagSign:Boolean = false;
var fieldWidth:String = "";
var precision:String = "";
c = format.charAt(++i);
while (c != "d"
&& c != "i"
&& c != "o"
&& c != "u"
&& c != "x"
&& c != "X"
&& c != "f"
&& c != "F"
&& c != "c"
&& c != "s"
&& c != "%")
{
if (!pastFlags)
{
if (!flagAlternateForm && c == "#")
flagAlternateForm = true;
else if (!flagZeroPad && c == "0")
flagZeroPad = true;
else if (!flagLeftJustify && c == "-")
flagLeftJustify = true;
else if (!flagSpace && c == " ")
flagSpace = true;
else if (!flagSign && c == "+")
flagSign = true;
else
pastFlags = true;
}
if (!pastFieldWidth && c == ".")
{
pastFlags = true;
pastFieldWidth = true;
c = format.charAt(++i);
continue;
}
if (pastFlags)
{
if (!pastFieldWidth)
fieldWidth += c;
else
precision += c;
}
c = format.charAt(++i);
}
switch (c)
{
case "d":
case "i":
var next:* = args.shift();
var str:String = String(Math.abs(int(next)));
if (precision != "")
str = leftPad(str, int(precision), "0");
if (int(next) < 0)
str = "-" + str;
else if (flagSign && int(next) >= 0)
str = "+" + str;
if (fieldWidth != "")
{
if (flagLeftJustify)
str = rightPad(str, int(fieldWidth));
else if (flagZeroPad && precision == "")
str = leftPad(str, int(fieldWidth), "0");
else
str = leftPad(str, int(fieldWidth));
}
result += str;
break;
case "o":
var next:* = args.shift();
var str:String = uint(next).toString(8);
if (flagAlternateForm && str != "0")
str = "0" + str;
if (precision != "")
str = leftPad(str, int(precision), "0");
if (fieldWidth != "")
{
if (flagLeftJustify)
str = rightPad(str, int(fieldWidth));
else if (flagZeroPad && precision == "")
str = leftPad(str, int(fieldWidth), "0");
else
str = leftPad(str, int(fieldWidth));
}
result += str;
break;
case "u":
var next:* = args.shift();
var str:String = uint(next).toString(10);
if (precision != "")
str = leftPad(str, int(precision), "0");
if (fieldWidth != "")
{
if (flagLeftJustify)
str = rightPad(str, int(fieldWidth));
else if (flagZeroPad && precision == "")
str = leftPad(str, int(fieldWidth), "0");
else
str = leftPad(str, int(fieldWidth));
}
result += str;
break;
case "X":
var capitalise:Boolean = true;
case "x":
var next:* = args.shift();
var str:String = uint(next).toString(16);
if (precision != "")
str = leftPad(str, int(precision), "0");
var prepend:Boolean = flagAlternateForm && uint(next) != 0;
if (fieldWidth != "" && !flagLeftJustify
&& flagZeroPad && precision == "")
str = leftPad(str, prepend
? int(fieldWidth) - 2 : int(fieldWidth), "0");
if (prepend)
str = "0x" + str;
if (fieldWidth != "")
{
if (flagLeftJustify)
str = rightPad(str, int(fieldWidth));
else
str = leftPad(str, int(fieldWidth));
}
if (capitalise)
str = str.toUpperCase();
result += str;
break;
case "f":
case "F":
var next:* = args.shift();
var str:String = Math.abs(Number(next)).toFixed(
precision != "" ? int(precision) : 6);
if (int(next) < 0)
str = "-" + str;
else if (flagSign && int(next) >= 0)
str = "+" + str;
if (flagAlternateForm && str.indexOf(".") == -1)
str += ".";
if (fieldWidth != "")
{
if (flagLeftJustify)
str = rightPad(str, int(fieldWidth));
else if (flagZeroPad && precision == "")
str = leftPad(str, int(fieldWidth), "0");
else
str = leftPad(str, int(fieldWidth));
}
result += str;
break;
case "c":
var next:* = args.shift();
var str:String = String.fromCharCode(int(next));
if (fieldWidth != "")
{
if (flagLeftJustify)
str = rightPad(str, int(fieldWidth));
else
str = leftPad(str, int(fieldWidth));
}
result += str;
break;
case "s":
var next:* = args.shift();
var str:String = String(next);
if (precision != "")
str = str.substring(0, int(precision));
if (fieldWidth != "")
{
if (flagLeftJustify)
str = rightPad(str, int(fieldWidth));
else
str = leftPad(str, int(fieldWidth));
}
result += str;
break;
case "%":
result += "%";
}
}
else
{
result += c;
}
}
return result;
}
}
// Private functions
function leftPad(source:String, targetLength:int, padChar:String = " "):String
{
if (source.length < targetLength)
{
var padding:String = "";
while (padding.length + source.length < targetLength)
padding += padChar;
return padding + source;
}
return source;
}
function rightPad(source:String, targetLength:int, padChar:String = " "):String
{
while (source.length < targetLength)
source += padChar;
return source;
}
The printf-as3 project sounds like it should fit your needs