I am unable to get how this will work...
how object.function1.function2 works
following is the code
l_floatValue = l_objMeter.getWATTHrs().getChannelA();
function 1 retrun you object and you call method of it
Please consider following example
int len = QString(" TEST ").simplified().length();
Suppose
QString test = QString(" TEST "); // will create string object of lengh 6
QString simTest = test.simplified(); // Will create string of len 4 remove white spaces
int len = simTest.length(); // len 4
This is how program will work
Related
I have a class with an initialiser list in the constructor where one of the fields I'm initialising is a std::filesystem::path but it doesn't seem to be initialising to the expected value.
MyClass::MyClass(
unsigned int deviceSerial,
const std::string& processName
) :
deviceSerial(deviceSerial),
processName(processName),
configFilePath(GetBasePath() / std::to_string(deviceSerial) / ("#" + processName + ".json"))
{
/* Parameter checks */
}
Using the debugger I can see that GetBasePath() is returning exactly what I expect (returns std::filesystem::path with correct path) but the / operator doesn't seem to be having an effect. Once inside the body of the constructor I can see that configFilePath is setup to the result of GetBasePath() without the extra info appended.
I'm using MSVS-2019, I have the C++ language standard set to C++17 and in debug mode I have all optimisations disabled.
I have also tested the following in the body of the class and I still see path as simply the result of GetBasePath() and the extra items are not being appended.
{
auto path = GetBasePath(); // path = "C:/Users/Me/Desktop/Devices"
path /= std::to_string(deviceSerial); // path = "C:/Users/Me/Desktop/Devices"
path /= ("#" + processName + ".json"); // path = "C:/Users/Me/Desktop/Devices"
}
On a slight side note I also tried the above test with += instead of /= and I still see the same results.
Edit
As requested, below is a minimal complete and verifiable example.
#include <Windows.h>
#include <cstdio>
#include <filesystem>
#include <memory>
#include <string>
std::string ExpandPath(const std::string &str) {
auto reqBufferLen = ExpandEnvironmentStrings(str.c_str(), nullptr, 0);
if (reqBufferLen == 0) {
throw std::system_error((int)GetLastError(), std::system_category(),
"ExpandEnvironmentStrings() failed.");
}
auto buffer = std::make_unique<char[]>(reqBufferLen);
auto setBufferLen =
ExpandEnvironmentStrings(str.c_str(), buffer.get(), reqBufferLen);
if (setBufferLen != reqBufferLen - 1) {
throw std::system_error((int)GetLastError(), std::system_category(),
"ExpandEnvironmentStrings() failed.");
}
return std::string{buffer.get(), setBufferLen};
}
int main() {
unsigned int serial = 12345;
std::string procName = "Bake";
std::filesystem::path p(ExpandPath("%USERPROFILE%\\Desktop\\Devices"));
std::printf("Path = %s\n", p.string().c_str());
// p = C:\Users\Me\Desktop\Devices
p /= std::to_string(serial);
std::printf("Path = %s\n", p.string().c_str());
// p = C:\Users\Me\Desktop\Devices
p /= "#" + procName + ".json";
std::printf("Path = %s\n", p.string().c_str());
// p = C:\Users\Me\Desktop\Devices
std::getchar();
}
I've also used this example and tested with `p.append()` and got the same result.
I'd like to give thanks to #rustyx and #Frank for their suggestions, following this advice has led me to discover a bug in the way I create the initial string that gets passed to the path constructor (Also #M.M who found the exact bug while I was typing this answer)
I created a function (that is in use in my class) std::string ExpandPath(const std::string& path) which uses the Windows API to expand any environment variables in a path and return a string. This string is generated from a char* and a count, that count includes the null byte so when creating an string using the constructor variant std::string(char* cstr, size_t len) this includes the null byte in the string itself.
Because I was using the debugger to interrogate the variables it reads C-style strings and stops at the null byte. In my original example I also use printf() as I just happen to prefer this function for output, but again this stops printing at the null byte. If I change the output to use std::cout I can see that the output has the expected path but with an extra space their (the null byte being printed as a space). Using std::cout I see that my paths result as the following with each append:
Path = C:\Users\Me\Desktop\Devices
Path = C:\Users\Me\Desktop\Devices \12345
Path = C:\Users\Me\Desktop\Devices \12345\#Bake.json
Summary:
Bug in my ExpandPath() where
return std::string{buffer.get(), setBufferLen};
Should be
return std::string{buffer.get(), setBufferLen - 1};
Im working on an online game and I have a problem with getting the ms-sql results into a other cpp file.
cpp file1 to start the query:
databaseManager.Query( hDB, new CQuery_AuthServer(req->awchUserId, req->awchPasswd);
req->awchUserId and req->awchPasswd are data from socket (username and password)
now on cpp file2 I execute the query inside a class
class CQuery_AuthServer : public CNtlQuery
{
public:
CQuery_AuthServer(const WCHAR * lpszUserID, const WCHAR * lpszUserPW)
{
ZeroMemory( m_szUserID, MAX_SIZE_USER_ID + 1 );
ZeroMemory( m_szUserPW, MAX_SIZE_USER_PW + 1 );
memcpy(m_szUserID, lpszUserID, MAX_SIZE_USER_ID);
memcpy(m_szUserPW, lpszUserPW, MAX_SIZE_USER_PW);
}
int ExecuteQuery(CNtlDatabaseConnection * pConnection)
{
FIND_SQLUNIT( SP_AuthLogin, pConnection, pSqlUnit2 );
if( NULL == pSqlUnit2 )
{
return NTL_FAIL;
}
strncpy_s( pSqlUnit2->m_szUserID, m_szUserID, MAX_SIZE_USER_ID );
strncpy_s( pSqlUnit2->m_szUserPW, m_szUserPW, MAX_SIZE_USER_ID );
pSqlUnit2->Exec();
printf("ExecuteQuery Done: result: %i ACC ID: %i \n", pSqlUnit2->m_nResultCode, pSqlUnit2->m_dwAccountID );
return NTL_SUCCESS;
}
public:
char m_szUserID[MAX_SIZE_USER_ID + 1];
char m_szUserPW[MAX_SIZE_USER_PW + 1];
};
This is needed for the query
BEGIN_DECLARE_SQLUNIT( SP_AuthLogin, "{ ? = call AuthLogin(?,?,?) }" )
BEGIN_VARIABLE()
char m_szUserID[MAX_SIZE_USER_ID + 1];
char m_szUserPW[MAX_SIZE_USER_PW + 1];
int m_dwAccountID;
int m_nResultCode;
END_VARIABLE()
BEGIN_PARAM(3)
PARAM_ENTRY(SQL_PARAM_OUTPUT, m_nResultCode)
PARAM_ENTRY_STR(SQL_PARAM_INPUT, m_szUserID)
PARAM_ENTRY_STR(SQL_PARAM_INPUT, m_szUserPW)
PARAM_ENTRY(SQL_PARAM_OUTPUT, m_dwAccountID)
END_PARAM()
END_DECLARE_SQLUNIT()
Now I can get the result but the result only works inside int ExecuteQuery
The query results are:
pSqlUnit2->m_nResultCode
pSqlUnit2->m_dwAccountID
how can I get those 2 results in the first cpp file where I made the query?
edit: the first cpp file:
void CClientSession::SendCharLogInReq(CNtlPacket * pPacket)
{
sUA_LOGIN_REQ * req = (sUA_LOGIN_REQ *)pPacket->GetPacketData();
HDATABASE hDB = INVALID_HDATABASE;
CNtlDatabaseManager databaseManager;
databaseManager.Query( hDB, new CQuery_AuthServer(req->awchUserId, req->awchPasswd) );
//WANT RESULT HERE
}
I dont really know what to do.. Im really newbie
here is the complete source https://www.sendspace.com/file/oc5v34
at PacketAuthServer.cpp I run the query
at AuthQueryServer.h I execute the query
Disregard the previous answer. The problem with the previous answer is that it was expecting databaseManager.Query to be syncrhonous, and to execute CQuery_AuthServer::ExecuteQuery before it returns to the caller. In fact it doesn't - it just adds the query to the queue, and your database management framework doesn't give you the ability to wait for completion of that query.
You should read the NtlDatabase manual to know how to make synchronous database calls
I am creating a little application in which I create a SHA1 hash with php and use the chunk_split function in php to insert a "|" every x characters.
Is there something similar? Or how would one split the string and insert a character there?
PHP Code:
substr(strtoupper(chunk_split(sha1("this is my super secure test application"), 5, "-")), 0, 29);
How can I do this with Qt?
You could write something like this:
main.cpp
#include <QString>
#include <QDebug>
int main()
{
const int step = 3;
const char mychar = 'x';
QString myString = "FooBarBaz";
for (int i = step; i <= myString.size(); i+=step+1)
myString.insert(i, mychar);
qDebug() << myString;
return 0;
}
main.pro
TEMPLATE = app
TARGET = main
QT = core
SOURCES += main.cpp
Build and Run
qmake && make && ./main
Output
"FooxBarxBazx"
See the documentation of the insert method in here.
I have these following codes set up-
class ID3{
const char* fileName;
TagLib::FileRef *file;
public:
ID3(const char *);
QImage* artwork();
}
ID3::ID3(const char* fileNameStr){
this->fileName = fileNameStr;
this->file = new TagLib::FileRef(fileNameStr);
qDebug()<<fileNameStr; //OUTPUT 2
}
QImage* ID3::artwork(){
QString str = QString::fromLocal8Bit(this->fileName);
qDebug()<<str; //OUTPUT 3
//MORE CODES-------
}
const char * QstrTocChar(QString str){
QByteArray ba = str.toLocal8Bit();
qDebug()<<ba.constData(); //OUTPUT 1
return ba.constData();
}
int main(int argc, char *argv[]){
.
.
.
QString fileName = "C:/Qt/Qt5.0.2/Projects/taglib_test/music files/Muse_-_Madness.mp3";
file = new ID3(QstrTocChar(fileName));
QImage *image = file->artwork();
}
Now when I run the program, I get these strange outputs
OUTPUT 1
C:/Qt/Qt5.0.2/Projects/taglib_test/music files/Muse_-_Madness.mp3
OUTPUT 2
????p???e'2/
OUTPUT 3
"°í³àpµ˜Æe'2/"
Not sure about OUTPUT 2 but I expect OUTPUT 3 to be same as OUTPUT 1. I am a Qt newbie. Would really appreciate advice/help in understanding, these strange character encoding issues and how to get OUTPUT 3 fixed.
Thanks!
ba.constantData() is returning a pointer to data which will be invalid when QstrToChar finishes executing (the 8-bit converted QByteArray), when QstrToChar completes, all you have left is free'd junk.
What if you just did:
file = new ID3(fileName.toLocal8Bit().constData());
in your main routine?
Actually, you still probably need to keep your own copy of this data in your private ID3 char *, since it can go away with the destruction of these temporaries.
Your code should be this, instead:
class ID3{
std::string fileName;
std::smart_ptr<TagLib::FileRef> file;
public:
ID3(std::string);
QImage* artwork();
}
ID3::ID3(std::string fileNameStr) {
this->fileName = fileNameStr;
this->file.reset(new TagLib::FileRef(fileNameStr));
qDebug()<<fileNameStr; //OUTPUT 2
}
QImage* ID3::artwork(){
QString str = QString::fromLocal8Bit(this->fileName);
qDebug()<<str; //OUTPUT 3
//MORE CODES-------
}
std::string QstrToCppString(QString str){
QByteArray ba = str.toLocal8Bit();
qDebug()<<ba.constData(); //OUTPUT 1
return std::string(ba.constData());
}
int main(int argc, char *argv[]){
.
.
.
QString fileName = "C:/Qt/Qt5.0.2/Projects/taglib_test/music files/Muse_-_Madness.mp3";
file = new ID3(QstrToCppString(fileName));
QImage *image = file->artwork();
}
Notice that I've wrapped your TagLib::FileRef in a smart_ptr as well, since you are new-ing it, you'll need to manage the memory. An alternative would be to write a proper destructor for your ID3 class. You're definitely leaking these currently (unless you just didn't share your destructor code).
I have in a log file some lines like this:
11-test.domain1.com Logged ...
37-user1.users.domain2.org Logged ...
48-me.server.domain3.net Logged ...
How can I extract each domain without the subdomains? Something between "-" and "Logged".
I have the following code in c++ (linux) but it doesn't extract well. Some function which is returning the extracted string would be great if you have some example of course.
regex_t preg;
regmatch_t mtch[1];
size_t rm, nmatch;
char tempstr[1024] = "";
int start;
rm=regcomp(&preg, "-[^<]+Logged", REG_EXTENDED);
nmatch = 1;
while(regexec(&preg, buffer+start, nmatch, mtch, 0)==0) /* Found a match */
{
strncpy(host, buffer+start+mtch[0].rm_so+3, mtch[0].rm_eo-mtch[0].rm_so-7);
printf("%s\n", tempstr);
start +=mtch[0].rm_eo;
memset(host, '\0', strlen(host));
}
regfree(&preg);
Thank you!
P.S. no, I cannot use perl for this because this part is inside of a larger c program which was made by someone else.
EDIT:
I replace the code with this one:
const char *p1 = strstr(buffer, "-")+1;
const char *p2 = strstr(p1, " Logged");
size_t len = p2-p1;
char *res = (char*)malloc(sizeof(char)*(len+1));
strncpy(res, p1, len);
res[len] = '\0';
which is extracting very good the whole domain including subdomains.
How can I extract just the domain.com or domain.net from abc.def.domain.com ?
is strtok a good option and how can I calculate which is the last dot ?
#include <vector>
#include <string>
#include <boost/regex.hpp>
int main()
{
boost::regex re(".+-(?<domain>.+)\\s*Logged");
std::string examples[] =
{
"11-test.domain1.com Logged ...",
"37-user1.users.domain2.org Logged ..."
};
std::vector<std::string> vec(examples, examples + sizeof(examples) / sizeof(*examples));
std::for_each(vec.begin(), vec.end(), [&re](const std::string& s)
{
boost::smatch match;
if (boost::regex_search(s, match, re))
{
std::cout << match["domain"] << std::endl;
}
});
}
http://liveworkspace.org/code/1983494e6e9e884b7e539690ebf98eb5
something like this with boost::regex. Don't know about pcre.
Is the in a standard format?
it appears so, is there a split function?
Edit:
Here is some logic.
Iterate through each domain to be parsed
Find a function to locate the index of the first string "-"
Next find the index of the second string minus the first string "Logged"
Now you have the full domain.
Once you have the full domain "Split" the domain into your object of choice (I used an array)
now that you have the array broken apart locate the index of the value you wish to reassemble (concatenate) to capture only the domain.
NOTE Written in C#
Main method which defines the first value and the second value
`static void Main(string[] args)
{
string firstValue ="-";
string secondValue = "Logged";
List domains = new List { "11-test.domain1.com Logged", "37-user1.users.domain2.org Logged","48-me.server.domain3.net Logged"};
foreach (string dns in domains)
{
Debug.WriteLine(Utility.GetStringBetweenFirstAndSecond(dns, firstValue, secondValue));
}
}
`
Method to parse the string:
`public string GetStringBetweenFirstAndSecond(string str, string firstStringToFind, string secondStringToFind)
{
string domain = string.Empty;
if(string.IsNullOrEmpty(str))
{
//throw an exception, return gracefully, whatever you determine
}
else
{
//This can all be done in one line, but I broke it apart so it can be better understood.
//returns the first occurrance.
//int start = str.IndexOf(firstStringToFind) + 1;
//int end = str.IndexOf(secondStringToFind);
//domain = str.Substring(start, end - start);
//i.e. Definitely not quite as legible, but doesn't create object unnecessarily
domain = str.Substring((str.IndexOf(firstStringToFind) + 1), str.IndexOf(secondStringToFind) - (str.IndexOf(firstStringToFind) + 1));
string[] dArray = domain.Split('.');
if (dArray.Length > 0)
{
if (dArray.Length > 2)
{
domain = string.Format("{0}.{1}", dArray[dArray.Length - 2], dArray[dArray.Length - 1]);
}
}
}
return domain;
}
`