How to use the QVector with multiple object - c++

I'm trying to use the QVector class from Qt to work (for me :P). What I want to do is to put multiple instances of the object Question in a QVector.
I went on multiple forums, but they're all too complicated for me as I am a beginner.
This one post was perfect but I did not find a way to resolve my problem.
So I'm turning to you to help me!
Here's the function that I want to work :
The part that create the bundle/ the vector
/**
* #brief MenuQuestionnary::assembleQuiz
* Assemble the bundle of question that will be used in Quiz class
*/
void MenuQuestionnary::assembleQuiz(){
QVector<Question> vectorQuiz;
vectorQuiz.reserve(spinBoxNumberOfQuestion->value());
for(int i = 0; i <= spinBoxNumberOfQuestion->value(); i++){
vectorQuiz.append(Question((qrand()% maximumNumberOfQuestionAvailable)));
}
}
Here's my Question constructor :
Question::Question(int id)
{
this->questionId = id;
//TODO: Actually get it from DB
this->questionText = "2+2?";
this->explanation = "Addition mechanics";
this->creatorId = 1;
}
What i expect to do here is to put the selected number of the Question object in a vector. After that i can pass it to another class. From there i should be able to extract the text from them(questionText and questionExplanation).

You are trying to push objects of class type Question into a QVector<int>, which obviously is expecting an int instead. You should change it to QVector<Question> to begin with.
What I highly suggest, though, is that you read a good book on C++ before going any further, or your experience with it will just get more and more complicated.
Copy pasting code from forums on the internet is not programming and will get you in troubles soon.

I think what you want is this: QVector vectorQuiz; vectorQuiz.reserve(spinBoxNumberOfQuestion->value()); // reserve correct amount of space in vector for performance (not required). I don't know exactly how you are going to use vectorQuiz, but maybe you should use pointers to the questions i.e. QVector and insert questions using new Question()
/**
* #brief MenuQuestionnary::assembleQuiz
* Assemble the bundle of question that will be used in Quiz class
*/
void MenuQuestionnary::assembleQuiz(){
int iVectorSize = spinBoxNumberOfQuestion->value();
QVector<Question> vectorQuiz;
vectorQuiz.reserve(iVectorSize );
for(int i = 0; i <= iVectorSize ; ++i){
vectorQuiz.append(Question(i));
}
}

Your object (vectorQuiz) declared as vector of integers. If you want to add some integer value to it you should write something:
vectorQuiz.append( someIntegerValue );
or
vectorQuiz.push_back( someIntegerValue );
For vector of another type (i.e. Question), write code like this:
QVector<Question> vectorQuiz;
// ...
for(int i = 0; i <= spinBoxNumberOfQuestion->value(); ++i){
vectorQuiz.append(Question(i)); // without [i] after vector object
}
And possible your should use strict inequality < instead of <= in for-cycle (but I'm not sure).

I solved it by trying few things
Here's the explanation of what i did
I've split my function in two. The first one put the element in a QList and the second one shuffles it.
/**
* #brief MenuQuestionnary::assembleQuiz
* #param list
* Asseble a quiz in the Qlist and then ask shuffle to shuffle it...
*/
void MenuQuestionnary::assembleQuiz(QList<Question> &list){
for(int i = 0; i < spinBoxNumberOfQuestion->value(); ++i){
int rand = qrand() * maximumNumberOfQuestionAvailable;
Question newQuestion(rand);
list.append(newQuestion);
}
shuffleQuiz(list);
}
/**
* Method Shuffle
* equivalent to shuffling a deck of cards: we take a random one, move it to be the last one,
* then do it again enough times to have statistically touched every card.
*/
void MenuQuestionnary::shuffleQuiz(QList<Question> &list){
int iters = list.size() * list.size();
for (int i = 0; i < iters; ++i){
int rand = qrand() * list.size();
list.append(list[rand]);
list.removeAt(rand);
}
}
Thanks for the help though.

Related

Modularizing spaghetti code

I'm still a newbie to C++ and I've been trying to modularize some spaghetti code that was given to me. So far (apart from learning how to use git and installing the rarray library to replace the automatic arrays with them) I've been sort of stumped as to how to modularize things and then compile it via make.
I understand that I must create prototypes in a header, create my object files from my functions, and then compile it all with a 'driver' code. Running/writing a make file is not my concern, but it's how to begin modularizing code like this; I'm not sure how to make functions that modify arrays!
Any pointers in the right direction would be amazing. I can clarify more if necessary.
#include <cmath>
#include <iostream>
#include <rarray> // Including the rarray library.
#include <rarrayio> // rarray input/output, if necessary. Probably not.
int main()
{
// ants walk on a table
rarray<float,2> number_of_ants(356,356);
rarray<float,2> new_number_of_ants(356,356);
rarray<float,2> velocity_of_ants(356,356);
const int total_ants = 1010; // initial number of ants
// initialize
for (int i=0;i<356;i++) {
for (int j=0;j<356;j++) {
velocity_of_ants[i][j] = M_PI*(sin((2*M_PI*(i+j))/3560)+1);
}
}
int n = 0;
float z = 0;
for (int i=0;i<356;i++) {
for (int j=0;j<356;j++) {
number_of_ants[i][j] = 0.0;
}
}
while (n < total_ants) {
for (int i=0;i<356;i++) {
for (int j=0;j<356;j++) {
z += sin(0.3*(i+j));
if (z>1 and n!=total_ants) {
number_of_ants[i][j] += 1;
n += 1;
}
}
}
}
// run simulation
for (int t = 0; t < 40; t++) {
float totants = 0.0;
for (int i=0;i<356;i++) {
for (int j=0;j<356;j++) {
totants += number_of_ants[i][j];
}
}
std::cout << t<< " " << totants << std::endl;
for (int i=0;i<356;i++) {
for (int j=0;j<356;j++) {
new_number_of_ants[i][j] = 0.0;
}
}
for (int i=0;i<356;i++) {
for (int j=0;j<356;j++) {
int di = 1.9*sin(velocity_of_ants[i][j]);
int dj = 1.9*cos(velocity_of_ants[i][j]);
int i2 = i + di;
int j2 = j + dj;
// some ants do not walk
new_number_of_ants[i][j]+=0.8*number_of_ants[i][j];
// the rest of the ants walk, but some fall of the table
if (i2>0 and i2>=356 and j2<0 and j2>=356) {
new_number_of_ants[i2][j2]+=0.2*number_of_ants[i][j];
}
}
}
for (int i=0;i<356;i++) {
for (int j=0;j<356;j++) {
number_of_ants[i][j] = new_number_of_ants[i][j];
totants += number_of_ants[i][j];
}
}
}
return 0;
}
I've been sort of stumped as to how to modularize things and then compile it via make.
That might be in part due to the code you are trying to modularize. Modularization is an idiom that is often used to help separate problem domains so that if one area of code has an issue, it won't necessarily* affect another area, and is especially useful when building larger applications; modularization is also one of the key points to classes in object oriented design.
*necessarily with regards to "spaghettification", that is, if the code really is "spaghetti code", often modifying or fixing one area of code most certainly affects other areas of code with unintended or unforeseen consequences, in other words, not modular.
The code you've posted is 63 lines (the main function), and doesn't really require any modularization. Though if you wanted to, you'd want to look at what could be modularized and what should be, but again, there isn't really much in the way to separate out, aside from making separate functions (which would just add to the code bulk). And since you asked specifically
I'm not sure how to make functions that modify arrays!
That can be done with the following:
// to pass a variable by reference (so as to avoid making copies), just give the type with the & symbol
void run_simulation(rarray<float,2>& noa, rarray<float,2>& new_noa, rarray<float,2>& voa)
{
// do something with the arrays
}
int main()
{
// ants walk on a table
rarray<float,2> number_of_ants(356,356);
rarray<float,2> new_number_of_ants(356,356);
rarray<float,2> velocity_of_ants(356,356);
...
run_simulation(number_of_ants, new_number_of_ants, velocity_of_ants);
...
}
Also, it should be noted there's a potential bug in your code; under the run simulation loop, you declare float totants = 0.0; then act on that variable until the end of the loop, at which point you still modify it with totants += number_of_ants[i][j];. If this variable is to be used to keep a 'running' total without being reset, you'd need to move the totants declaration outside of the for loop, otherwise, strictly speaking, that last totants += statement is not necessary.
Hope that can help add some clarity.
Except for replacing the magic numbers with constants in the beginning, there is not much that can be done to improve scientific code as barely anything is reusable.
The only part that is repeated is:
for (int i=0;i<356;i++) {
for (int j=0;j<356;j++) {
new_number_of_ants[i][j] = 0.0;
}
}
Which you can extract as a function (I have not replaced the magic numbers, you should do that first and give them as parameters):
void zeroRarray(rarray<float, 2> number_of_ants) {
for (int i = 0; i < 356; i++) {
for (int j = 0; j < 356; j++) {
number_of_ants[i][j] = 0.0;
}
}
}
And call like:
zeroRarray(number_of_ants); // Btw the name of this rarray is misleading!
Also, replace the mathematical expressions with function calls:
velocity_of_ants[i][j] = M_PI* (sin((2 * M_PI * (i + j)) / 3560) + 1);
with:
velocity_of_ants[i][j] = calculateSomething(i, j);
where the function looks something like:
double calculateSomethingHere(int i, int j) {
return M_PI * (sin((2 * M_PI * (i + j)) / 3560) + 1);
}
so you can give these long and insightful names and focus on what each part of your code does and not what it looks like.
Most IDE's have a refactoring functionality built-in where you highlight part of code that you want to extract and right-click and select Extract function from Refactor (or something similar).
If your code is short (e.g under 200 lines) there is not much you can do except extracting parts of your code that are very abstract. The next step is to write a class for ants and what ever these ants are doing, but there is little benefit for this unless you have more code.
This is not spaghetti code at all. The control structure is actually quite straight-forward (a series of loops, sometimes nested). From the manner csome constructs are being used, it has been translated from some other programming language to C++ without much effort to turn it from the original language to "effective C++" (i.e. it is C++ written with techniques from another language). But my guess is that the original language was somewhat different from C++ - or that the original code did not make a lot of use of that language's features.
If you want to modularise it, consider breaking some things into separately, appropriately named, functions.
Get rid of the magic values (like 356, 3560, 0.3, 40, 1.9, etc). Turn them into named constants (if they are to be fixed at compile time) or named variables (if there is a reasonable chance you may wish them to be inputs to the code at some time in the future). Bear in mind that M_PI is not actually standard in C or C++ (it is common to a number of C and C++ implementations, but is not standard so is not guaranteed to work with all compilers).
Work out what rarray is, and work out how to replace it with a standard C++ container. My guess, from the usage, is that rarray<float, 2> number_if_ants(356,356) represents a two-dimensional array of floats, with both dimensions equal to 356. As such, it might be appropriate to use a std::vector<std::vector<float> > (any version of C++) or (in C++11) std::array<std::array<float, dimension>, dimension> (where dimension is my arbitrary name to replace your magic value of 356). That may look a bit more complicated, but can be made much simpler with the help of a couple of tyepdefs. In the long run, C++ developers will understand the code better than they will if you insist on using rarray.
Look carefully at operations that work on the C++ standard containers. For example, construction and resizing of a std::vector - by default - initialises elements to zero in many circumstances. You might be able replace some of sets of nested loops with a single statement.
Also, dig into the standard algorithms (in header algorithm). They can act on a range of elements in any std::vector - via iterators - and possibly do other things directly that this code needs nested loops for.

Faster way to sort an array of structs c++

I have a struct called count declared called count with two things in it, an int called frequency and a string called word. To simplify, my program takes in a book as a text file and I count how many times each word appears. I have an array of structs and I have my program to where it will count each time a word appears and now I want a faster way to sort the array by top frequency than the way I have below. I used the bubble sorting algorithm below but it is taking my code way too long to run using this method. Any other suggestions or help would be welcome!! I have looked up sort from the algorithm library but don't understand how I would use it here. I am new to c++ so lots of explanation on how to use sort would help a lot.
void sortArray(struct count array[],int size)
{
int cur_pos = 0;
string the_word;
bool flag= true;
for(int i=0; i<(size); i++)
{
flag = false;
for(int j=0; j< (size); j++)
{
if((array[j+1].frequency)>(array[j].frequency))
{
cur_pos = array[j].frequency;
the_word = array[j].word;
array[j].frequency = array[j+1].frequency;
array[j].word = array[j+1].word;
array[j+1].frequency = cur_pos;
array[j+1].word = the_word;
flag = true;
}
}
}
};
You just need to define operator less for your structures,
and use std::sort, see example:
http://en.wikipedia.org/wiki/Sort_%28C%2B%2B%29
After you created a pair of for the data set, you can use std::map as container and insert the pairs into it. If you want to sort according to frequency define std:map as follows
std::map myMap;
myMap.insert(std::make_pair(frequency,word));
std::map is internally using a binary tree so you will get a sorted data when you retrieve it.

How to generate a hashmap for huge chunk of data?

I want to make a map such that a set of pointers point to arrays of dynamic size.
I did use hashing with chaining. But since data I am using it for is huge, the program give std::bad_alloc after few iterations. The reason of which may be new used to generate the linked list.
Someone please suggest which data structure shall I use?
Or anything else that can improve memory usage with my hash table?
Program is in C++.
This is what my code looks like:
Initialization of hashtable:
class Link
{
public:
double iData;
Link* pNext;
Link(double it) : iData(it)
{ }
void displayLink()
{ cout << iData << " "; }
};
class List
{
private:
Link* pFirst;
public:
List()
{ pFirst = NULL; }
void insert(double key)
{
if(pFirst==NULL)
pFirst = new Link(key);
else
{
Link* pLink = new Link(key);
pLink->pNext = pFirst;
pFirst = pLink;
}
}
};
class HashTable
{
public:
int arraySize;
vector<List*> hashArray;
HashTable(int size)
{
hashArray.resize(size);
for(int j=0; j<size; j++)
hashArray[j] = new List;
}
};
main snippet:
int t_sample = 1000;
for(int i=0; i < k; i++) // initialize random position
{
x[i] = (cal_rand() * dom_sizex); //dom_sizex = 20e-10 cal_rand() generates rand no between 0 and 1
y[i] = (cal_rand() * dom_sizey); //dom_sizey = 10e-10
}
for(int t=0; t < t_sample; t++)
{
int size;
size = cell_nox * cell_noy; //size of hash table cell_nox = 212, cell_noy = 424
HashTable theHashTable(size); //make table
int hashValue = 0;
for(int n=0; n<k; n++) // k = 10*212*424
{
int m = x[n] /cell_width; //cell_width = 4.7e-8
int l = y[n] / cell_width;
hashValue = (kx*l)+m;
theHashTable.hashArray[hashValue]->insert(n);
}
-------
-------
}
First things first, use a Standard Container. In your specific case, you might want:
either std::unordered_multimap<int, double>
or std::unordered_map<int, std::vector<double>>
(Note: if you do not have C++11, those are available in Boost)
Your main loop becomes (using the second option):
typedef std::unordered_map<int, std::vector<double>> HashTable;
for(int t = 0; t < t_sample; ++t)
{
size_t const size = cell_nox * cell_noy;
// size of hash table cell_nox = 212, cell_noy = 424
HashTable theHashTable;
theHashTable.reserve(size);
for (int n = 0; n < k; ++n) // k = 10*212*424
{
int m = x[n] / cell_width; //cell_width = 4.7e-8
int l = y[n] / cell_width;
int const cellId = (kx*l)+m;
theHashTable[cellId].push_back(n);
}
}
This will not leak memory (reliably), although of course you might have other leaks, and thus will give you a reliable baseline. It is also probably faster than your approach, with a more convenient interface, etc...
In general you should not re-invent the wheel, unless you have a specific need that is not addressed by the available wheels or you are actually trying to learn how to create a wheel or to create a better wheel.
The OS has to solve the same issues with the memory pages, maybe it's worth looking at how that is done? First of all, let's assume all pages are on the disk. A page is a fixed size memory chunk. For your use case, let's say it's an array of your records. Because RAM is limited, the OS maintains a mapping between the page number and it's location in RAM.
So, let's say your pages have 1000 records, and you want to access record 2024, you would ask the OS for page 2, and read record 24 from that page. That way, your map is only 1/1000 in size.
Now, if your page has no mapping to a memory location, then it is either on disk or has never been accessed before (is empty). Then you need to swap out another page, and load that page from disk (and update the location mapping).
This is a very simplified description of what happens and i wouldn't be surprised if someone jumps me in the neck for describing it like this.
The point is:
What does this mean for you?
First of all, your data exceeds your RAM - you won't get around writing to disk, if you don't want to try compression first.
Second, your chains can work as pages if you want, but i wonder whether just paging your hashcode would work better. What i mean is, use the upper bits as page number, and the lower bits as offset in the page. Avoiding collisions is still key, as you want to load the least pages possible. You can still chain your pages, and end up with a much smaller map.
Second - a crucial part is deciding which pages to swap out to make room for the new pages. LRU should do ok. If you can better predict which pages you will (not) need, so much better for you.
Third - you need placeholders for your pages to tell you whether they are in-memory or on disk.
Hope this helps.

Trying to fill a 2d array of structures in C++

As above, I'm trying to create and then fill an array of structures with some starting data to then write to/read from.
I'm still writing the cache simulator as per my previous question:
Any way to get rid of the null character at the end of an istream get?
Here's how I'm making the array:
struct cacheline
{
string data;
string tag;
bool valid;
bool dirty;
};
cacheline **AllocateDynamicArray( int nRows, int nCols)
{
cacheline **dynamicArray;
dynamicArray = new cacheline*[nRows];
for( int i = 0 ; i < nRows ; i++ )
dynamicArray[i] = new cacheline [nCols];
return dynamicArray;
}
I'm calling this from main:
cacheline **cache = AllocateDynamicArray(nooflines,noofways);
It seems to create the array ok, but when I try to fill it I get memory errors, here's how I'm trying to do it:
int fillcache(cacheline **cache, int cachesize, int cachelinelength, int ways)
{
for (int j = 0; j < ways; j++)
{
for (int i = 0; i < cachesize/(cachelinelength*4); i++)
{
cache[i][ways].data = "EMPTY";
cache[i][ways].tag = "";
cache[i][ways].valid = 0;
cache[i][ways].dirty = 0;
}
}
return(1);
}
Calling it with:
fillcache(cache, cachesize, cachelinelength, noofways);
Now, this is the first time I've really tried to use dynamic arrays, so it's entirely possible I'm doing that completely wrong, let alone when trying to make it 2d, any ideas would be greatly appreciated :)
Also, is there an easier way to do write to/read from the array? At the moment (I think) I'm having to pass lots of variables to and from functions, including the array (or a pointer to the array?) each time which doesn't seem efficient?
Something else I'm unsure of, when I pass the array (pointer?) and edit the array, when I go back out of the function, will the array still be edited?
Thanks
Edit:
Just noticed a monumentally stupid error, it should ofcourse be:
cache[i][j].data = "EMPTY";
You should find your happiness. You just need the time to check it out (:
The way to happiness

Radix Sort using C++

Suppose I have bunch of numbers. I have to first put the least significant digit into the corresponding bucket. Ex: 530 , I have to first put into the bucket 0. For number 61, I have to put into bucket 1.
I planned to use a multidimensional array to do this. So I create a 2-dimenional array, which nrows is 10 ( for 0~ 9) and ncolumns is 999999 ( because I don't know how large will the list be):
int nrows = 10;
int ncolumns = 999999;
int **array_for_bucket = (int **)malloc(nrows * sizeof(int *));
for(i = 0; i < nrows; i++)
array_for_bucket[i] = (int *)malloc(ncolumns * sizeof(int));
left = (a->value)%10;
array_for_bucket[left][?? ] = a->value;
Then I created one node call a. In this node a, there is a value 50. To find out which bucket I want to put it in, I calculate "left" and I got 0. So I want to put this a-> value into bucket 0. But now I am stuck. How do I put this value into the bucket? I have to use a pointer array to do this.
I thought for a long time but still couldn't find a good way to do it. So please share some ideas with me. thank you!
There is a much easier way of doing this, and instead of radix*nkeys space you only need an nkeys-sized buffer.
Allocate a second buffer that can fit nkeys keys. Now do a first pass through your data and simply count how many keys end up in each bucket. You now can create a radix-sized array of pointers where each pointer is to the start of that bucket in the output buffer. Finally, the second pass though the data moves the keys. Every time you move a key, increment that bucket pointer.
Here's some C code to make into C++:
void radix_sort(int *keys, int nkeys)
{
int *shadow = malloc(nkeys * sizeof(*keys));
int bucket_count[10];
int *bucket_ptrs[10];
int i;
for (i = 0; i < 10; i++)
bucket_count[i] = 0;
for (i = 0; i < nkeys; i++)
bucket_count[keys[i] % 10]++;
bucket_ptrs[0] = shadow;
for (i = 1; i < 10; i++)
bucket_ptrs[i] = bucket_ptrs[i-1] + bucket_count[i-1];
for (i = 0; i < nkeys; i++)
*(bucket_ptrs[keys[i] % 10]++) = keys[i];
//shadow now has the sorted keys
free(shadow);
}
But I may have misunderstood the question. If you are doing something a little different than radix sort, pleas add some details.
Look the Boost Pointer containers library if you want to store pointers.
C++ isn't my forte but this code from wikipedia-Raidx Sort is very comprehensive and probably is more C++-ish than what you've implemented so far. Hope it helps
This is C++, we don't use malloc anymore. We use containers. A two-dimensional array is a vector of vectors.
vector<vector<int> > bucket(10);
left = (a->value)%10;
bucket[left].push_back(a->value);