I have a text file which looks like this:
VariableA = 10 VariableB = 20 VariableC = "Hello World"
The code works fine, but my trouble is getting the text strings between " ".
QStringList Data;
Data << "VariableA = " << "VariableB = " << "VariableC = ";
QStringList Values;
int VariableA;
int VariableB;
QString VariableC;
foreach(const QString &DataToFind, Data) {
QRegExp DataExpression(DataToFind);
int DataStart = DataExpression.indexIn(TextToFind);
if(DataStart >= 0) {
int DataLength = DataExpression.matchedLength();
int ValueSize = 1;
while(TextToFind.at(DataStart + DataLength + ValueSize) != QChar(' ')) {
ValueSize++;
}
QStringRef DataValue(&TextToFind, DataStart + DataLength, ValueSize);
Values += DataValue.toString();
DataStart = DataExpression.indexIn(description, DataStart + DataLength);
} else {
continue;
}
}
VariableA = Values[0].toInt();
VariableB = Values[1].toInt();
VariableC = Values[2];
The issue is that the text on VariableC can have spaces and/or " (double quotes) inside it. So the method I've posted above to retrieve the variables from the file is useless. Since it uses " " to reach end of variable in the file.
How can I retrieve the full text inside the double quotes?
QStringList Data;
Data << "A = " << "B = " << "X = ";
int A;
int B;
QString X;
foreach(const QString &DataToFind, Data) {
QRegExp DataExpression(DataToFind);
int DataStart = DataExpression.indexIn(TextToFind);
if(DataStart >= 0) {
int DataLength = DataExpression.matchedLength();
int ValueSize = 1;
while(TextToFind.at(DataStart + DataLength + ValueSize) != QChar(' ')) {
ValueSize++;
}
QStringRef DataValue(&TextToFind, DataStart + DataLength, ValueSize);
DataStart = DataExpression.indexIn(description, DataStart + DataLength);
} else {
continue;
}
}
This does the work.
Related
I am trying to get Windows boot up time using WMI query and got it as CIM_DATETIME format.
I converted it into File time .The value I get form it is 132372033265000000.
I need to convert it in to Date time(Sunday, June 21, 2020 8:55:27am).
I found many solutions in C# but couldn't able to find one in C++.
Here is a solution that takes the current locale into account. I takes a SYSTEMTIME but you can easily convert that from a FILETIME:
CString DateTimeStr(const SYSTEMTIME *pST, bool bSeconds, bool bDate, bool bTime, bool bLongDate, bool bMilliSec, LCID Locale)
{
CString sDate, sTime;
DWORD dwFlags;
int iStrLen;
LPTSTR pBuf;
if (bDate)
{
dwFlags = 0;
if (bLongDate)
dwFlags |= DATE_LONGDATE;
else
dwFlags |= DATE_SHORTDATE;
iStrLen = GetDateFormat(Locale, dwFlags, pST, NULL, NULL, 0);
pBuf = sDate.GetBuffer(iStrLen + 2);
(void)GetDateFormat(Locale, dwFlags, pST, NULL, pBuf, iStrLen+2);
sDate.ReleaseBuffer();
}
if (bTime)
{
dwFlags = 0;
if (!bSeconds)
dwFlags |= TIME_NOSECONDS;
iStrLen = GetTimeFormat(Locale, dwFlags, pST, NULL, NULL, 0);
pBuf = sTime.GetBuffer(iStrLen + 2);
(void)GetTimeFormat(Locale, dwFlags, pST, NULL, pBuf, iStrLen+2);
sTime.ReleaseBuffer();
if (bMilliSec)
sTime += _T(" ") + FmtNum(pST->wMilliseconds, 3, true) + TEXT(" ms");
}
if (bDate && bTime)
return sDate + _T(" ") + sTime;
if (bDate)
return sDate;
if (bTime)
return sTime;
return (_T(""));
}
To convert a FILETIME structure into a time that is easy to
display to a user, use the FileTimeToSystemTime function.
Code Sample:
#include <Windows.h>
#include <iostream>
int main()
{
const char *day[] = {"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};
const char* month[] = {"January","February","March","April","May","June","July", "August","September","October","November","December"};
long long value = 132372033265000000;
FILETIME ft = { 0 };
ft.dwHighDateTime = (value & 0xffffffff00000000) >> 32;
ft.dwLowDateTime = value & 0xffffffff;
SYSTEMTIME sys = { 0 };
FileTimeToSystemTime(&ft, &sys);
std::cout << day[sys.wDayOfWeek] << "," << month[sys.wMonth] << " " << sys.wDay << "," << sys.wYear << " "<< sys.wHour << ":" << sys.wMinute << ":" << sys.wSecond;
return 0;
}
Output:
Sunday,July 21,2020 8:55:26
I'm getting warning msg saying:
comparison between pointer and integer
char * replaceWord(const char * str, const char * oldWord, const char * newWord)
{
char * resultString;
int i, count = 0;
int newWordLength = strlen(newWord);
int oldWordLength = strlen(oldWord);
//count the no of occurance of word in string in a file
for (i = 0; str[i] !='\0'; i++)
{
if (strstr(str[i], oldWord) == str[i])//i m getting warning here
{
count++;
i = i + oldWordLength - 1;
}
}
// Making a new string to fit in the replaced words
resultString = (char *)malloc(i + count * (newWordLength - oldWordLength) + 1);
i = 0;
while (*str!='\0')
{
// Compare the substring with result
if(strstr(str, oldWord) == str)//here i used same syantax its working but not above
{
strcpy(&resultString[i], newWord);
i += newWordLength;
str += oldWordLength;
}
else{
resultString[i] = *str;
i += 1;
str +=1;
}
}
resultString[i] = '\0';
return resultString;
}
From the man page for strstr():
#include <string.h>
char *strstr(const char *haystack, const char *needle);
So, strstr() returns the substring's char* pointer as the result, and you are comparing it against a char variable (str[i]), thus the error.
i am using arduino due. what i am trying to do is to receive a string at serial. like this one:
COMSTEP 789 665 432 END
if the string starts with comstep, then to tokenize the string and get an integer array {789, 665, 432}.
is there anyway to do that?
P.S: im a noob at programming, so any help is appreciated.
I have a function that I wrote long ago to parse strings up in an easy manner. It is in use on several of my Arduino projects.
Sample usage:
char pinStr[3];
char valueStr[7];
int pinNumber, value;
getstrfld (parms_in, 0, 0, (char *)",", pinStr);
getstrfld (parms_in, 1, 0, (char *)",", valueStr);
pinNumber = atoi (pinStr);
value = atoi (valueStr);
The functions:
// My old stand-by to break delimited strings up.
char * getstrfld (char *strbuf, int fldno, int ofset, char *sep, char *retstr)
{
char *offset, *strptr;
int curfld;
offset = strptr = (char *)NULL;
curfld = 0;
strbuf += ofset;
while (*strbuf) {
strptr = !offset ? strbuf : offset;
offset = strpbrk ((!offset ? strbuf : offset), sep);
if (offset) {
offset++;
} else if (curfld != fldno) {
*retstr = 0;
break;
}
if (curfld == fldno) {
strncpy (retstr, strptr,
(int)(!offset ? strlen (strptr)+ 1 :
(int)(offset - strptr)));
if (offset)
retstr[offset - strptr - 1] = 0;
break;
}
curfld++;
}
return retstr;
}
// Included because strpbrk is not in the arduino gcc/g++ libraries
// Or I just could not find it :)
char * strpbrk (const char *s1, const char *s2)
{
const char *c = s2;
if (!*s1) {
return (char *) NULL;
}
while (*s1) {
for (c = s2; *c; c++) {
if (*s1 == *c)
break;
}
if (*c)
break;
s1++;
}
if (*c == '\0')
s1 = NULL;
return (char *) s1;
}
A light-weight approach (no strict checks on valid parses of the integers and ignoring any list elements past a fixed maximum):
char buf[32] = "COMSTEP 789 665 432 END"; // assume this has just been read
int res[8], nres = 0;
bool inlist = false;
for (char *p = strtok(buf, " "); p; p = strtok(0, " "))
if (inlist)
{
if (!strcmp(p, "END"))
{
inlist = false;
break;
}
else if (nres < sizeof(res) / sizeof(*res))
res[nres++] = atoi(p);
}
else if (!strcmp(p, "COMSTEP"))
inlist = true;
if (!inlist)
for (size_t i = 0; i < nres; ++i)
printf("%d%s", res[i], i + 1 < nres ? " " : "\n"); // do whatever
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;
}
I am trying to index a matrix with names. The usual method gives errors:
NumericMatrix mytest(NumericVector v) {
NumericMatrix ans(v.length(), v.length());
rownames(ans) = v;
float y = ans("1",0);
NumericVector x = ans.row("1");
return (ans);
}
I looked over in Matrix.h and the matrix unit tests in rcpp and couldn't find a similar example. Also this mailing list question didn't provide a method to do it.
Can I write my own code to index the matrix, perhaps using R's internal C interface?
This is by no means a robust solution, but hopefully a jumping off point for you, where operator() is overloaded to handle different combinations of int and string passed as row & column indices:
#include <Rcpp.h>
// [[Rcpp::plugins(cpp11)]]
class MyMat : public Rcpp::NumericMatrix {
public:
MyMat(const Rcpp::NumericMatrix& data_,
const std::vector<std::string>& rnames_,
const std::vector<std::string>& cnames_)
: data(data_),
rnames(rnames_),
cnames(cnames_) {}
double operator()(const std::string& i, const std::string& j) {
typedef std::vector<std::string>::const_iterator cit;
cit it_i = std::find(rnames.begin(), rnames.end(), i);
cit it_j = std::find(cnames.begin(), cnames.end(), j);
int idx_i, idx_j;
if (it_i != rnames.end() ) {
idx_i = it_i - rnames.begin();
} else {
idx_i = rnames.size();
}
if (it_j != cnames.end() ) {
idx_j = it_j - cnames.begin();
} else {
idx_j = cnames.size();
}
return data(idx_i, idx_j);
}
double operator()(const std::string& i, const size_t j) {
typedef std::vector<std::string>::const_iterator cit;
cit it_i = std::find(rnames.begin(), rnames.end(), i);
int idx_i, idx_j;
if (it_i != rnames.end() ) {
idx_i = it_i - rnames.begin();
} else {
idx_i = rnames.size();
}
if (j <= cnames.size() ) {
idx_j = j;
} else {
idx_j = cnames.size();
}
return data(idx_i, idx_j);
}
double operator()(const size_t i, const std::string& j) {
typedef std::vector<std::string>::const_iterator cit;
cit it_j = std::find(cnames.begin(), cnames.end(), j);
int idx_i, idx_j;
if (i <= rnames.size() ) {
idx_i = i;
} else {
idx_i = rnames.size();
}
if (it_j != cnames.end() ) {
idx_j = it_j - cnames.begin();
} else {
idx_j = cnames.size();
}
return data(idx_i, idx_j);
}
double operator()(const int& i, const int& j) {
return data(i, j);
}
private:
Rcpp::NumericMatrix data;
std::vector<std::string> rnames;
std::vector<std::string> cnames;
};
// [[Rcpp::export]]
void test_MyMat(Rcpp::NumericMatrix m)
{
std::vector<std::string> rnames = { "a", "b", "c" };
std::vector<std::string> cnames = { "A", "B", "C" };
MyMat mmObj(m,rnames,cnames);
Rcpp::Rcout << "(Row 1, Column 1)" <<
std::endl;
Rcpp::Rcout << "(b,B) = " << mmObj("b","B") <<
std::endl << "(b,1) = " << mmObj("b",1) <<
std::endl << "(1,B) = " << mmObj(1,"B") <<
std::endl << "(1,1) = " << mmObj(1,1) <<
std::endl;
}
/*** R
x <- matrix(1:9,nrow=3)
test_MyMat(x)
#(Row 1, Column 1)
#(b,B) = 5
#(b,1) = 5
#(1,B) = 5
#(1,1) = 5
x[2,2]
#[1] 5
*/
We only support numeric (row) indices.
You could add a "names" attribute and look up the index in that, and/or add your own accessor methods.