How to make a readable return of data - c++

I read this article http://www.slideshare.net/redigon/refactoring-1658371
on page 53 it states that "You have a method that returns a value but also changes the state of the object. create two methods,one for the query and one for the modification.
But what if on the query I need the values of more than 1 field.
For example:
QSqlQuery query(QSqlDatabase::database("MAIN"));
QString command = "SELECT FIELD1, FIELD2, FIELD3, FIELD4, FIELD5 FROM TABLE";
query.exec( command );
This is the method I know but I really feel that this is not that readable
QString values;
columnDelimiter = "[!##]";
rowDelimiter = "[$%^]";
while( query.next )
{
values += query.value(0).toString() + columnDelimiter;
values += query.value(1).toString() + columnDelimiter;
values += query.value(2).toString() + columnDelimiter;
values += query.value(3).toString() + columnDelimiter;
values += rowDelimiter;
}
And I will retrive it like this.
QStringList rowValues, columnValues;
rowValues = values.split(rowDelimiter);
int rowCtr =0;
while( rowCtr < rowValues.count() )
{
columnValues.clear();
// Here i got the fields I need
columnValues = rowValues.at( rowCtr ).split( columnDelimiter );
// I will put the modification on variables here
rowCtr++;
}
EDIT: Is there a more readable way of doing this?

"Is there a more readable way of doing this?" is a subjective question. I'm not sure whether your question will last long on SO, as SO prefers factual problems and solutions.
What I personally think will make your code more readable, would be:
Use a custom made data structure for your data set. Strings are not the right data structures for tabulated data. Lists of custom made structs are better.
Example:
// data structure for a single row
struct MyRow {
QString a, b, c;
}
...
QList<MyRow> myDataSet;
while( query.next )
{
MyRow currentRow;
// fill with data
currentRow.a = query.value(0).toString();
currentRow.b = query.value(1).toString();
...
myDataSet.append(currentRow);
}
I doubt all your data is text. Some is probably numbers. Never store numbers as strings. That's inefficient.
You first read all data into a data structure, and then read the data structure to process it. Why don't you combine the two? I.e. process while reading the data, in the same while(...)
In your comment, you're confused by the difference between an enum and struct. I suggest, stop doing complex database and QT stuff. Grab a basic C++ book and try to understand C++ first.

Related

How can I get my price vector to = values inside my json array

Hello I am pretty new to json parsing and parsing in general so I am wondering what is the best way I can assaign the correct values for the price of the underlying stock I am looking at. Below is an example of the code I am working with and comments next to them showing kinda what Im confused about
Json::Value chartData = IEX::stocks::chart(symbolSearched);
int n = 390;
QVector<double> time(n), price(n);
//Time and Date Setup
QDateTime start = QDateTime(QDate::currentDate());
QDateTime local = QDateTime::currentDateTime();
QDateTime UTC(local);
start.setTimeSpec(Qt::UTC);
double startTime = start.toTime_t();
double binSize = 3600*24;
time[0] = startTime;
price[0] = //First market price of the stock at market open (930AM)
for(int i = 0; i < n; i++)
{
time[i] = startTime + 3600*i;
price[i] = //Stores prices of specific company stock price all the way until 4:30PM(Market close)
}
the charData is the json output with all the data,
.
I am wondering how I can get the various values inside the json and store them, and also since its intraday data how can I get it where it doesnt store p[i] if there is no data yet due to it being early in the day, and what is the best way to update this every minute so it continously reads in real time data?
Hope I understood correctly (correct me if not) and you just want to save some subset of json data to your QVector. Just iterate through all json elements:
for (int idx = 0; index < chartData.size(); ++idx) {
time[idx] = convert2Timestamp(chartData[idx]["minute"]);
price[idx] = convert2Price(chartData[idx]["high"], chartData[idx]["low"],
chartData[idx]["open"], chartData[idx]["close"], chartData[idx]["average"]);
}
Then you should define what is the logic of convert2Timestamp (how would you like to store the time information) and the logic of convert2Price - how would you like to store the price info, only highest/lowest, only the closing value, maybe all of these numbers grouped together in a structure/class.
Then if you want to execute similar logic every minute to update your locally recorded data, maybe instead of price[idx] = /* something */ you should push additional items that are new to your vector.
If there is a possibility that some of the json keys might not exist, in JsonCPP you could provide a default value e.g. elem.get(KEY, DEFAULT_VAL).

Manage multiple variable in one, big if-else

I have to solve problem with some Word's like editor and it's codes, witch return some logic.
Now I have over 4000 variables:
string code1 = "onePlusOne";
string code2 = "onePlusTwo";
...
string code4000 = "onePlusFourThousands"
and the same number of logic if-else statements:
if(code == code1)
return 2;
else if(code == code2)
return 3;
...
else if(code = code4000)
return 4001;
Client can paste code into editor to get value, for example:
"Some test, #onePlusTwenty# some test."
..and the result will be:
"Some test, 21 some test."
My problems are:
over 4000 variables in code,
over 4000 lines of if-else (with returns it's over 10 000 lines).
contradiction with SOLID :)
I was thinking about store those codes in database (but this solve almost nothing), also I can sort those codes into groups (but this only will help me to split if-else into many others if-else).
I will be grateful for any idea how to mange this.
You can use a key-value structure for storing your data and instead of writing +10,000 LOC, use a for loop to replace your values. For exampleL
struct key_value {
string key;
int value;
};
And for loop will be like
for(int i = 0; i < MAPSIZE; i ++) {
if(YOUR_COMPARE_MODULE) {
// replace here
}
}

Fast search through QTableWidget rows

I need to search rows through a QTableWidget. Each of the rows in the table contains a field with date and I need to show only rows that are within a specified date interval based on user input. Here is my function:
void nvr::sort()
{
QTableWidget* tabela = this->findChild<QTableWidget*>("NCtable");
QDateEdit* c1 = this->findChild<QDateEdit*>("c1");
QDateEdit* c2 = this->findChild<QDateEdit*>("c2");
// user specified ranges for date
QDate date1 = c1->date();
QDate date2 = c2->date();
//row numbers in table
int rowsNum = tabela->rowCount();
// hide all rows
for(int z = 0; z < rowsNum; z++) {
tabela->hideRow(z);
}
// show only rows that are within range
for(int z = 0; z < rowsNum; z++) {
QDateTime dateTime = QDateTime::fromString(tabela->item(z,2)->text(),"dd.MM.yyyy hh:mm");
QDate date = dateTime.date();
//date compares
if ( (date1.operator <=(date)) && (date2.operator >=(date) ) ) {
tabela->showRow(z);
}
}
}
This works fine if i have 200 rows. But when i have 30 000 rows and i surely will, the gui freezes because i suppose the function executes very slow. Any suggestions for faster execution?
It is hard to reproduce your problem, but here is the approach I would take:
Create a custom class to store the data of one row, let's call it
DataRow.
Store those in a QVector<DataRow>, that you can sort by Date1 for example.
Loop through this QVector<DataRow> and find the elements that correspond to the criteria.
Add those DataRow to a class derived from QAbstractItemModel.
Show this model derived from QAbstractItemModel with a QTableView.
QTableWidget is heavyweight and was not really built for speed. It's really convenient to build something quickly with few elements though.
QTableView is the one you want, with a custom model inherited from QAbstractItemModel.
Then, when the user requests a new input, you could just wipe the model and restart the process. This is not optimal, but the user should not see the difference. Feel free to add more logic here to keep the good elements and only remove the bad ones.
About the GUI freezing, one way to always avoid that is to have the GUI thread separated from other worker threads. The QThread documentation is exhaustive and can help you set up something like this.

Optimizating my code simulating a database

I have been working on a program, simulating a small database where I could make queries, and after writing the code, I have executed it, but the performance is quite bad. It works really slow. I have tried to improve it, but I started with C++ on my own a few months ago, so my knowledge is still very low. So I would like to find a solution to improve the performance.
Let me explain how my code works. Here I have atached a summarized example of how my code works.
First of all I have a .txt file simulating a database table with random strings separated with "|". Here you have an example of table (with 5 rows and 5 columns).
Table.txt
0|42sKuG^uM|24465\lHXP|2996fQo\kN|293cvByiV
1|14772cjZ`SN|28704HxDYjzC|6869xXj\nIe|27530EymcTU
2|9041ByZM]I|24371fZKbNk|24085cLKeIW|16945TuuU\Nc
3|16542M[Uz\|13978qMdbyF|6271ait^h|13291_rBZS
4|4032aFqa|13967r^\\`T|27754k]dOTdh|24947]v_uzg
This information in a .txt file is read by my program and stored in the computer memory. Then, when making queries, I will access to this information stored in the computer memory. Loading the data in the computer memory can be a slow process, but accessing to the data later will be faster, what really matters me.
Here you have the part of the code that read this information from a file and store in the computer.
Code that reads data from the Table.txt file and store it in the computer memory
string ruta_base("C:\\a\\Table.txt"); // Folder where my "Table.txt" is found
string temp; // Variable where every row from the Table.txt file will be firstly stored
vector<string> buffer; // Variable where every different row will be stored after separating the different elements by tokens.
vector<ElementSet> RowsCols; // Variable with a class that I have created, that simulated a vector and every vector element is a row of my table
ifstream ifs(ruta_base.c_str());
while(getline( ifs, temp )) // We will read and store line per line until the end of the ".txt" file.
{
size_t tokenPosition = temp.find("|"); // When we find the simbol "|" we will identify different element. So we separate the string temp into tokens that will be stored in vector<string> buffer
while (tokenPosition != string::npos)
{
string element;
tokenPosition = temp.find("|");
element = temp.substr(0, tokenPosition);
buffer.push_back(element);
temp.erase(0, tokenPosition+1);
}
ElementSet ss(0,buffer);
buffer.clear();
RowsCols.push_back(ss); // We store all the elements of every row (stores as vector<string> buffer) in a different position in "RowsCols"
}
vector<Table> TablesDescriptor;
Table TablesStorage(RowsCols);
TablesDescriptor.push_back(TablesStorage);
DataBase database(1, TablesDescriptor);
After this, comes the IMPORTANT PART. Let's suppose that I want to make a query, and I ask for input. Let's say that my query is row "n", and also the consecutive tuples "numTuples", and the columns "y". (We must say that the number of columns is defined by a decimal number "y", that will be transformed into binary and will show us the columns to be queried, for example, if I ask for columns 54 (00110110 in binary) I will ask for columns 2, 3, 5 and 6). Then I access to the computer memory to the required information and store it in a vector shownVector. Here I show you the part of this code.
Code that access to the required information upon my input
int n, numTuples;
unsigned long long int y;
clock_t t1, t2;
cout<< "Write the ID of the row you want to get more information: " ;
cin>>n; // We get the row to be represented -> "n"
cout<< "Write the number of followed tuples to be queried: " ;
cin>>numTuples; // We get the number of followed tuples to be queried-> "numTuples"
cout<<"Write the ID of the 'columns' you want to get more information: ";
cin>>y; // We get the "columns" to be represented ' "y"
unsigned int r; // Auxiliar variable for the columns path
int t=0; // Auxiliar variable for the tuples path
int idTable;
vector<int> columnsToBeQueried; // Here we will store the columns to be queried get from the bitset<500> binarynumber, after comparing with a mask
vector<string> shownVector; // Vector to store the final information from the query
bitset<500> mask;
mask=0x1;
t1=clock(); // Start of the query time
bitset<500> binaryNumber = Utilities().getDecToBin(y); // We get the columns -> change number from decimal to binary. Max number of columns: 5000
// We see which columns will be queried
for(r=0;r<binaryNumber.size();r++) //
{
if(binaryNumber.test(r) & mask.test(r)) // if both of them are bit "1"
{
columnsToBeQueried.push_back(r);
}
mask=mask<<1;
}
do
{
for(int z=0;z<columnsToBeQueried.size();z++)
{
int i;
i=columnsToBeQueried.at(z);
vector<int> colTab;
colTab.push_back(1); // Don't really worry about this
//idTable = colTab.at(i); // We identify in which table (with the id) is column_i
// In this simple example we only have one table, so don't worry about this
const Table& selectedTable = database.getPointer().at(0); // It simmulates a vector with pointers to different tables that compose the database, but our example database only have one table, so don't worry ElementSet selectedElementSet;
ElementSet selectedElementSet;
selectedElementSet=selectedTable.getRowsCols().at(n);
shownVector.push_back(selectedElementSet.getElements().at(i)); // We save in the vector shownVector the element "i" of the row "n"
}
n=n+1;
t++;
}while(t<numTuples);
t2=clock(); // End of the query time
float diff ((float)t2-(float)t1);
float microseconds = diff / CLOCKS_PER_SEC*1000000;
cout<<"The query time is: "<<microseconds<<" microseconds."<<endl;
Class definitions
Here I attached some of the class definitions so that you can compile the code, and understand better how it works:
class ElementSet
{
private:
int id;
vector<string> elements;
public:
ElementSet();
ElementSet(int, vector<string>);
const int& getId();
void setId(int);
const vector<string>& getElements();
void setElements(vector<string>);
};
class Table
{
private:
vector<ElementSet> RowsCols;
public:
Table();
Table(vector<ElementSet>);
const vector<ElementSet>& getRowsCols();
void setRowsCols(vector<ElementSet>);
};
class DataBase
{
private:
int id;
vector<Table> pointer;
public:
DataBase();
DataBase(int, vector<Table>);
const int& getId();
void setId(int);
const vector<Table>& getPointer();
void setPointer(vector<Table>);
};
class Utilities
{
public:
Utilities();
static bitset<500> getDecToBin(unsigned long long int);
};
So the problem that I get is that my query time is very different depending on the table size (it has nothing to do a table with 100 rows and 100 columns, and a table with 10000 rows and 1000 columns). This makes that my code performance is very low for big tables, what really matters me... Do you have any idea how could I optimizate my code????
Thank you very much for all your help!!! :)
Whenever you have performance problems, the first thing you want to do is to profile your code. Here is a list of free tools that can do that on windows, and here for linux. Profile your code, identify the bottlenecks, and then come back and ask a specific question.
Also, like I said in my comment, can't you just use SQLite? It supports in-memory databases, making it suitable for testing, and it is lightweight and fast.
One obvious issue is that your get-functions return vectors by value. Do you need to have a fresh copy each time? Probably not.
If you try to return a const reference instead, you can avoid a lot of copies:
const vector<Table>& getPointer();
and similar for the nested get's.
I have not done the job, but you may analyse the complexity of your algorithm.
The reference says that access an item is in constant time, but when you create loops, the complexity of your program increases:
for (i=0;i<1000; ++i) // O(i)
for (j=0;j<1000; ++j) // O(j)
myAction(); // Constant in your case
The program complexity is O(i*j), so how big may be i an j?
What if myAction is not constant in time?
No need to reinvent the wheel again, use FirebirdSQL embedded database instead. That combined with IBPP C++ interface gives you a great foundation for any future needs.
http://www.firebirdsql.org/
http://www.ibpp.org/
Though I advise you to please use a profiler to find out which parts of your code are worth optimizing, here is how I would write your program:
Read the entire text file into one string (or better, memory-map the file.) Scan the string once to find all | and \n (newline) characters. The result of this scan is an array of byte offsets into the string.
When the user then queries item M of row N, retrieve it with code something like this:
char* begin = text+offset[N*items+M]+1;
char* end = text+offset[N*items+M+1];
If you know the number of records and fields before the data is read, the array of byte offsets can be a std::vector. If you don't know and must infer from the data, it should be a std::deque. This is to minimize costly memory allocation and deallocation, which I imagine is the bottleneck in such a program.

Iterate through Enums in C++

C++ enum question.
So I have a list of files, and their IDs that I need to iterate over, and do stuff to. Most of the stuff is the same, but there are a few file-specific things that need to be done. I tried putting the file IDs in an enum, and iterating over that. Howver, the fileIDs are non contiguous, and jump around.
Currently, I have something akin to this
for(int i = 0; i < FILE_ENUM_MAX; i++)
{
currentFile = myEnum(i);
// do stuff
}
enum myEnum {
file1 = 0x1111,
file2 = 0x8000,
file3 = 0x75,
file4 = 0x120,
FILE_ENUM_MAX = 4
}
This doesn't work; I just go through files 0, 1, 2, and 3. I get the idea that I can't just get the Nth item in an enumeration by asking for item N. So what would be the best way to iterate over this enum? Or should I just get rid of it? I probably could put the items in numerical order, but I'd prefer a solution to where order didn't matter.
Unfortunately, C++ does not provide a way to iterate through enums like you want.
I guess the low-tech answer might be to skip the enum, and just create a static array:
#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
int FILE_ENUM[] = { 0x1111, 0x8000, 0x75, 0x120 };
for(int i = 0; i < ARRAYSIZE(FILE_ENUM); i++) {
currentFile = myEnum[i];
// do stuff
}
TJ
I have two suggestions:
Use a std::vector to contain the enums.
Use a std::map to contain the
enums.
Solution 2 offers a benefit where the key is the file ID and the value can be the name of the file (or an object containing attributes of the file, such as a file handle or pointer).
i <= FILE_ENUM_MAX and it will iterate with 4th file. Sorry if this is an old thread but maybe someone will still need an answer trying to find it here.