C++ Replace Value in Config File - c++

I am trying to replace a value in a configuration file. It can be edited in a text editor.
[MODEL]
...
Latitude = 1.034
Longitude = 110.58334
...
How can I search for the keyword "Latitude" and replace "1.034" with another value? (e.g. 1.04)
Edit: Thanks for the down votes. I have attached my code below:
QFile fileReadModels(CP1);
fileReadModels.open(QIODevice::ReadOnly | QIODevice::Text);
QTextStream inModels(&fileReadModels);
while(!inModels.atEnd())
{
QString lineModels = inModels.readLine();
if(lineModels.isNull())
{
break;
}
else
{
strListInModels.append(lineModels);
}
}
fileReadModels.close();
int startFlag = 0;
int stopFlag = 0;
for(int i = 1; i <= strListInModels.count(); i++)
{
if(strListInModels[i].contains("Latitude", Qt::CaseInsensitive) == 1)
{
//! get start position
startFlag = i - 1;
//! get stop position
stopFlag = i + 2;
break;
}
}
//! get data from start till start position
for(int x = 0; x <= startFlag; x++)
{
strListOutModels << strListInModels[x];
}
//! insert in Ownship1 lat/lon
QString os1LatStr = " Latitude = " + os1Lat;
QString os1LonStr = " Longitude = " + os1Lon;
strListOutModels << os1LatStr;
strListOutModels << os1LonStr;
//! get data from stop postion till end
for(int y = stopFlag; y < strListInModels.count(); y++)
{
strListOutModels << strListInModels[y];
}
//! write to file
QFile fileWriteModels(CP1);
fileWriteModels.open(QIODevice::ReadWrite | QIODevice::Truncate);
QTextStream outModels(&fileWriteModels);
QString qStrModels = strListOutModels.join("\r");
outModels << qStrModels;
fileWriteModels.close();

You can use QSettings feature
location.ini
[MODEL]
Latitude = 1.034
Longitude = 110.58334
You can use QSetting to modify your data
//Access your datafile
QSettings settings("location.ini", QSettings::IniFormat);
//Read Data
QString sLatitude = settings.value("MODEL/Latitude").toString();
//Write Data
settings.setValue("MODEL/Latitude", "18.55");

Related

QTableWidget to multiple files

I’ve got QTableWidget with data like this:
table.png
The table can contains only names from the QList:
QList<QString> shapes { "Triangle", "Circle", "Trapeze", "Square", "Rectangle", "Diamond" };
with random int values in the neighboring cell.
Table can contain all "shapes" or only a part of it (like in the example).
I try to create separate file for each shape form the table and write down corresponding int values to them.
To achieve this I wrote something like that:
QList<QTableWidgetItem *> ItemList
/.../
for(int i = 0; i < rows; ++i)
{
for(int i = 0; i<columns; ++i)
{
foreach(QString itm, shapes )
{
ItemList = ui->tableWidget->findItems(itm, Qt::MatchExactly);
QFile mFile(itm + ".txt");
if(mFile.open(QFile::ReadWrite))
{
for(int i = 0; i < ItemList.count(); ++i)
{
int rowNR = ItemList.at(i)->row();
int columnNR = ItemList.at(i)->column();
out << "Values = " << ui->tableWidget->item(rowNR, columnNR+1)->text() << endl;
}
}
}
mFile.flush();
mFile.close();
}
}
Files are created for every item from the QList – if the shape from the QList is not in the table, an empty file is created.
How to create files only on the basis of available names in the table?
You can write like this.
QList<QTableWidgetItem *> ItemList
/.../
for(QString str : Shapes){
ItemList = ui->tableWidget->findItems(itm, Qt::MatchExactly); // Get the matching list
if(ItemList.isEmpty(){
continue; // If shape does not exist in table skip the iteration
}
QFile mFile(str + ".txt");
if(!mFile.open(QFile::ReadWrite){
return; // This should not happen ; this is error
}
for(QTableWidgetItem *item : ItemList){
int row = item->row();
int col = item->column()+1; // since it is neighboring cell
QString Value = ui->tableWidget->item(row,col)->text();
mFile.write(Value.toUtf8()); // You can change the way in which values are written
}
mFile.flush();
mFile.close();
}

c++ String returning with an extra char

I have tested my program and am certain right before being returned the string in my function equals "card001". But the returned value equals "card0011". I have no idea how this even happens. Help me before I lose my mind. ;)
std::string function_cardTexture(int card) {
//removes the last 1
card = card - 10000;
int ctr = 0;
card = floor(card / 10);
std::cout << card << std::endl;
//turn int card into a string
std::string a = static_cast<std::ostringstream*>(&(std::ostringstream() << card))->str();
//combines card and string a into one string
std::string nametext = "card00" + a;
std::cout << nametext << std::endl;
return (nametext);
}
void function_Battle(tempPlayer &Player, tempCard &card001) {
if (Player.Start == true) {
//Draw hand
for (int i = 0; i < Player.numDrawn; i++) {
int x = rand() % Player.deckSize + 0; ;
Player.Hand[i] = Player.Deck[x];
Player.Discarded[x] = 1;
}
Player.Start = false;
}
std::map<std::string, tempCard> Vars;
//draw hand
for (int i = 0; i < Player.handMax;i++) {
if (Player.Hand[i] != 0) {
sf::RectangleShape Card(sf::Vector2f(80.0f, 128.0f));
std::string nametext = function_cardTexture(Player.Hand[i]);
std::cout << nametext;
sf::Texture texture = Vars[nametext].Art;
Card.setTexture(&texture);
window.draw(Card);
}
}
}
Your problem is how you're printing things out without a newline in the function_Battle() function, so you're likely "smashing together" your new value with an old one. If you replace your main function with just a loop with clearer printing of values, you can see you don't have a problem:
http://coliru.stacked-crooked.com/a/8d1e4f51643b84b9
That link will go to an online compiler where I just replaced the calling function with a loop that makes numbers. It even supplies a negative one.

c++ process does not stop

There is something wrong in the code but I do not understand why.
I think one of the reason could be the threads that I used in the code.
The code looks like this.
in main.cpp
vector<thread> t;
vector<future<myClass>> futures;
vector<myClass> chV;
for(int i = 0; i < NumberOfThreads; i++) // NumberOfThreads are 2 here
{
promise<myClass> promises;
futures.push_back(promises.get_future());
t.push_back(thread(MyFunction ,i, PointsNumberInThreads , pointList, std::move(promises)));
}
for_each(t.begin(), t.end(), std::mem_fn(&std::thread::join));
for(int i = 0; i < futures.size(); i++ )
{
// futures.at(i).get().fOut(i); // <-- if I comment out then it gives error. but why?
chV.push_back(futures.at(i).get());
}
myClass c1 = chV.at(0);
myClass c2 = chV.at(1);
cout << "merge start" << endl; // <-- it prints out
c1.Merge(c2);
cout << "merge end" << endl; // <-- does not print out this message. so I have to kill the process
the Merge function in the myClass.cpp I have these sentences at the bottom of the function.
int aSt,aMid,aEnd;
int bSt,bMid,bEnd;
aSt = 0, aEnd = upperV.size(), aMid = (aEnd + aSt)/2;
bSt = 0, bEnd = b.upperV.size(), bMid = (bEnd + bSt)/2;
Point aPoint, bPoint, aPrev, aNext, bPrev, bNext;
aPoint = upperV.at(aMid);
aPrev = upperV.at(aMid-1);
aNext = upperV.at(aMid+1);
bPoint = b.upperV.at(bMid);
bPrev = b.upperV.at(bMid-1);
bNext = b.upperV.at(bMid+1);
bool done = true;
while(done)
{
done = false;
if(orientation(aPoint,bPoint,bPrev) > 0)
{
bEnd = bMid;
bMid = (bEnd + bSt)/2;
bPoint = b.upperV.at(bMid);
done = true;
}
if(orientation(aPoint,bPoint,bNext) > 0)
{
bSt = bMid;
bMid = (bEnd + bSt)/2;
bPoint = b.upperV.at(bMid);
done = true;
}
if(orientation(bPoint,aPoint,aPrev) < 0)
{
aEnd = aMid;
aMid = (aEnd + aSt)/2;
aPoint = upperV.at(aMid);
done = true;
}
if(orientation(bPoint,aPoint,aNext) < 0)
{
aSt = aMid;
aMid = (aEnd + aSt)/2;
aPoint = upperV.at(aMid);
done = true;
}
}
cout << "aPoint = (" << aPoint.x << " , " << aPoint.y << ")" << endl;
cout << "bPoint = (" << bPoint.x << " , " << bPoint.y << ")" << endl;
and they are printed but as I mentioned the process seems to keep running in somewhere.
This is the section of code that I think you should be concerned with. This may
not be why your code is continuing execution as you have stated in your problem, but from the code that you did provide to us; I still think this is an issue that should be addressed.
bool done = true;
while(done)
{
done = false;
if(orientation(aPoint,bPoint,bPrev) > 0)
{
bEnd = bMid;
bMid = (bEnd + bSt)/2;
bPoint = b.upperV.at(bMid);
done = true;
}
if(orientation(aPoint,bPoint,bNext) > 0)
{
bSt = bMid;
bMid = (bEnd + bSt)/2;
bPoint = b.upperV.at(bMid);
done = true;
}
if(orientation(bPoint,aPoint,aPrev) < 0)
{
aEnd = aMid;
aMid = (aEnd + aSt)/2;
aPoint = upperV.at(aMid);
done = true;
}
if(orientation(bPoint,aPoint,aNext) < 0)
{
aSt = aMid;
aMid = (aEnd + aSt)/2;
aPoint = upperV.at(aMid);
done = true;
}
}
You are initially setting this to be true. You are then going into your while loop and are setting it to false. All of your if statements set it back to true. So if any of these conditions are met depending on what orientation() returns then you are not going to break out of this while loop. It may seem to be illogical at first, but I learned over time that a good way to do while loops is in this structure.
bool done = false;
while ( !done ) {
// terminating case - I usually almost always check for this first!
if ( done ) {
break;
}
// Do work here and one or more cases could trip done to be equal to true
// within a if... else if ... else statement or within a series of if satements
// or none of them can, but if they don't then it must be set at the end of the while loop.
// Any one of these or all of them could set done = true and if they don't
// then you should set done = true at the end of the while loop since
// if none of these conditions are met, it will execute the assignment
// before it begins to loop.
if ( some condidition ) {
// Do this
} else if ( some other condidition ) {
// Do this instead
} else {
// Then do this
}
// Or this: Any of these could trip done = true or none of them
// and once again if none of them do, it should be the last thing done
// before the ending brace to your while loop.
if ( this ) {
// Do Work;
}
if ( this ) {
// Do Work;
}
// etc.
// Set this last if none of the if statements trip done to be true;
// otherwise if one or more does trip done, then you can omit this line.
// Note: If none of the if statements trip this flag and you trip it here
// in this section, this loop will occur only one time.
done = true;
}

How to prepare statements and bind parameters in Postgresql for C++

I'm quite new to C++ and know a little bit about pqxx library. What I want to implement is to prepare statements and bind parameters. In PHP I'm used to doing this in such a nice and concise manner:
$s = $db->prepare("SELECT id FROM mytable WHERE id = :id");
$s->bindParam(':id', $id);
$s->execute();
or using tokens:
$data = array();
$data[] = 1;
$data[] = 2;
$s = $db->prepare("SELECT id FROM mytable WHERE id = ? or id = ?");
$s->execute($data);
I tried to fugure out from pqxx documentation how to implement this, but to me documentation looks like a mess and lacks short and simple examples (like I provided above). I hope someone can also provide such simple examples (or of comparable simplicity - without having to write some behemoth code) when dealing with Postgresql in C++.
A simple example. This just prints the number of entries with id value 0.
#include<pqxx/pqxx>
#include<iostream>
int main()
{
std::string name = "name";
int id = 0;
try {
//established connection to data base
pqxx::connection c("dbname=mydb user=keutoi");
pqxx::work w(c);
//statement template
c.prepare("example", "SELECT id FROM mytable WHERE id = $1");
//invocation as in varible binding
pqxx::result r = w.prepared("example")(id).exec();
w.commit();
//result handling for accessing arrays and conversions look at docs
std::cout << r.size() << std::endl;
}
catch(const std::exception &e)
{
std::cerr << e.what() << std::endl;
return 1;
}
return 0;
}
The function w.prepared() is a bit convoluted. It's similar to a curried(curry) function in haskell, as in it takes a parameter and returns another function which in turn takes another parameter. That kind of thing.
Documentation says:
How do you pass those parameters? C++ has no good way to let you pass an unlimited, variable number of arguments to a function call, and the compiler does not know how many you are going to pass. There's a trick for that: you can treat the value you get back from prepared as a function, which you call to pass a parameter. What you get back from that call is the same again, so you can call it again to pass another parameter and so on.
Once you've passed all parameters in this way, you invoke the statement with the parameters by calling exec on the invocation
If there are more parameters use $1 $2 and so on in the prepare function.
c.prepare("SELECT id name FROM mytable WHERE id = $1 AND name = $2")
and give the varibles as
w.prepared("example")(dollar1_var)(dollar2_var).exec()
An Example for dynamic preparation
#include<pqxx/pqxx>
#include<iostream>
#include<vector>
//Just give a vector of data you can change the template<int> to any data type
pqxx::prepare::invocation& prep_dynamic(std::vector<int> data, pqxx::prepare::invocation& inv)
{
for(auto data_val : data)
inv(data_val);
return inv;
}
int main()
{
std::string name = "name";
//a data array to be used.
std::vector<int> ids;
ids.push_back(0);
ids.push_back(1);
try {
pqxx::connection c("dbname=mydb user=keutoi");
pqxx::work w(c);
c.prepare("example", "SELECT id FROM mytable WHERE id = $1 or id = $2");
pqxx::prepare::invocation w_invocation = w.prepared("example");
//dynamic array preparation
prep_dynamic(ids, w_invocation);
//executing prepared invocation.
pqxx::result r = w_invocation.exec();
w.commit();
std::cout << r.size() << std::endl;
}
catch(const std::exception &e)
{
std::cerr << e.what() << std::endl;
return 1;
}
return 0;
}
if you want to handle other data types use this function definition
template<class T> pqxx::prepare::invocation& prep_dynamic(std::vector<T> data, pqxx::prepare::invocation& inv)
{
for(auto data_val : data)
inv(data_val);
return inv;
}
Use pqxx::prepare::invocation where you can, and bind more values before execution, because it's more stable and error preventative, but there is a faster way as I describe it below.
I.
With invocation:
pqxx::nontransaction W(C);
std::string m_insertCommand = "INSERT INTO tableforperftest(column1, column2) VALUES";
unsigned int m_nCurrentRow = 32767;
for (size_t i = 0; i < m_nCurrentRow; i++)
{
unsigned int countOf$ = i * 2;
for (unsigned int i = 0; i < 2; ++i)
{
if (i == 0)
{
m_insertCommand += "(";
}
else
{
m_insertCommand += ", ";
}
m_insertCommand += "$";
std::stringstream ss;
ss << countOf$ + i + 1;
m_insertCommand += ss.str();
}
if(i < m_nCurrentRow - 1)
m_insertCommand += ") ,";
}
m_insertCommand += ")";
C.prepare("insert_into_db", m_insertCommand);
pqxx::prepare::invocation inv = W.prepared("insert_into_db");
for (size_t i = 0; i < m_nCurrentRow; i++)
{
inv(i)(i);
}
inv.exec();
II.
With stored procedure which gets more values for parameters:
CREATE OR REPLACE FUNCTION insertintoboosted(valuesforinsert TEXT) RETURNS VOID AS
$$
BEGIN
EXECUTE 'INSERT INTO tableforperftestproof(column1, column2) VALUES (' || valuesforinsert || ')';
END;
$$
LANGUAGE plpgsql;
Code:
for (size_t i = 0; i < m_nCurrentRow; i++)
{
if (i == 0)
ss << i << "," << i;
else
ss << "(" << i << "," << i;
if (i < m_nCurrentRow - 1)
ss << "),";
}
C.prepare("prep2", "select insertintoboosted($1::text)");
W.prepared("prep2")(ss).exec();
III.
With parameter bindings and execution for each time:
std::string m_insertCommand3 = "INSERT INTO tableforperftest(column1, column2) VALUES ($1, $2)";
C.prepare("insert_into_db3", m_insertCommand3);
for (size_t i = 0; i < m_nCurrentRow; i++)
{
W.prepared("insert_into_db3")(i)(i).exec();
}
To compare the solutions with 32767 inserts:
Invocation: --> Elapsed: 0.250292s
Stored Proc: --> Elapsed: 0.154507s
Parameter binding + execution each time: --> Elapsed: 29.5566s

how can I verify if multiple checkboxes are checked

std::string output;
if ((checkbox1->isChecked() && checkbox2->isChecked()) &&
(!checkbox3->isChecked() || !checkbox4->isChecked() || !checkbox5->isChecked() || !checkbox6->isChecked()))
{
output = " Using Checkbox: 1, 2 ";
}
if ((checkbox1->isChecked() && checkbox2->isChecked() && checkbox3->isChecked()) &&
(!checkbox4->isChecked() || !checkbox5->isChecked() || !checkbox6->isChecked()))
{
output = " Using Checkbox: 1, 2, 3 ";
}
....
using QT creator how can I verify how many checkboxes have been checked and change the output string accordingly?
with multiple if statements it's not working due to me getting confused with all those NOT AND OR.
and it takes a long time to code all possibilities.
All your checkBoxes should be in groupBox
Try this:
QList<QCheckBox *> allButtons = ui->groupBox->findChildren<QCheckBox *>();
qDebug() <<allButtons.size();
for(int i = 0; i < allButtons.size(); ++i)
{
if(allButtons.at(i)->isChecked())
qDebug() << "Use" << allButtons.at(i)->text()<< i;//or what you need
}
Use an array of checkboxes like this
// h-file
#include <vector>
class MyForm {
...
std::vector< QCheckBox* > m_checkBoxes;
};
// cpp-file
MyForm::MyForm() {
...
m_checkBoxes.push_back( checkbox1 );
m_checkBoxes.push_back( checkbox2 );
...
m_checkBoxes.push_back( checkbox5 );
}
...
output = " Using Checkbox:";
for ( int i = 0, size = m_checkBoxes.size(); i < size; ++i ) {
if ( m_checkBoxes[ i ]->isChecked() ) {
output += std::to_string( i + 1 ) + ", ";
}
}
TLDR: Place them in a container and build your string by iterating over them.
Code:
// line taken from #Chernobyl
QList<QCheckBox *> allButtons = ui->groupBox->findChildren<QCheckBox *>();
auto index = 1;
std::ostringstream outputBuffer;
outputBuffer << "Using Checkbox: ";
for(const auto checkBox: allButtons)
{
if(checkBox->isChecked())
outputBuffer << index << ", ";
++index;
}
auto output = outputBuffer.str();
Use QString instead of std::string and then:
QCheckBox* checkboxes[6];
checkbox[0] = checkbox1;
checkbox[1] = checkbox2;
checkbox[2] = checkbox3;
checkbox[3] = checkbox4;
checkbox[4] = checkbox5;
checkbox[5] = checkbox6;
QStringList usedCheckboxes;
for (int i = 0; i < 6; i++)
{
if (checkbox[i]->isChecked())
usedCheckboxes << QString::number(i+1);
}
QString output = " Using Checkbox: " + usedCheckboxes.join(", ") + " ";
This is just an example, but there's numerous ways to implement this. You could keep your checkboxes in the QList which is a class field, so you don't have to "build" the checkboxes array every time. You could also use QString::arg() instead of + operator for string when you build the output, etc, etc.
What I've proposed is just a quick example.