What is the optimal way of printing a 2d array vector - c++

I have a function which receive a 2D vector of char from another class and print it
void dat_Output::print_All(Board *board)
{
int x;
int y;
x = 0;
y = 0;
while(x < 26)
{
while(y < 59)
{
std::cout << board->get_Board()[x][y];
y++;
}
std::cout << std::endl;
y = 0;
x++;
}
}
here is the get_Board() function
std::vector<std::vector<char> > Board::get_Board()
{
return(board);
}
My question is for resource efficiency which is the better should I make a copy of the vector at the start of my printing function to avoid calling get_Board() 26*59 time? and whats the difference on resource consuming?

If get_Board() must return a copy, make a single copy before the loops (instead of 26 * 59 copies), and work directly on it. It will also avoid you the board-> indirection.
If possible, return a const reference instead of a copy from get_Board()
Assuming you want to print the entire board, don't use nested while loops, you can use nested for-range loops and avoid explicit indexing.
Minimal example :
#include <iostream>
#include <vector>
class X
{
public :
X() : v({ { 'a', 'b'} , { 'a', 'b' } , { 'c', 'd' } }) {}
const std::vector<std::vector<char>> & GetVector() const { return v; }
private:
std::vector<std::vector<char> > v;
};
int main() {
X x;
const std::vector<std::vector<char> >& v = x.GetVector();
for(auto& v2 : v)
for(auto& c : v2)
std::cout << c << ' ';
}

void dat_Output::print_All(Board *board)
{
std::vector<std::vector<char> > myboard = board->get_Board()[x][y];
int x;
int y;
x = 0;
y = 0;
while(x < 26)
{
while(y < 59)
{
std::cout << myboard[x][y];
y++;
}
std::cout << std::endl;
y = 0;
x++;
}
}
I would create a copy initially. I think every time you call get_Board() you would return a array of vector of vectors and this would be hit on the performance, while calling it once would be cheaper.

Related

C++: confusion about accessing class data members while multithreading

I have the following minimal working example in which I create a number of markov_chain objects in a vector chains and an equal number of thread objects in a vector workers, each of which executes a markov_chain class member function sample on each of the corresponding markov_chain objects. This function takes some integer (99 in the below example) and assigns it to the acceptance public data member of the markov_chain object. I then print the value of acceptance for each object in the vector.
#include <iostream>
#include <thread>
#include <algorithm>
#include <vector>
class markov_chain
{
public:
unsigned int length{0}, acceptance{0};
markov_chain(unsigned int l) {length=l;}
~markov_chain() {}
void sample(int acc);
};
void markov_chain::sample(int acc)
{
acceptance = acc;
std::cout << length << ' ' << acceptance << std::endl;
}
int main()
{
int number_of_threads{3};
int number_of_samples{1000};
std::vector<markov_chain> chains;
std::vector<std::thread> workers;
for (int i = 0; i <= number_of_threads; i++) {
chains.push_back(markov_chain(number_of_samples));
workers.push_back(std::thread(&markov_chain::sample, chains[i], 99));
}
std::for_each(workers.begin(), workers.end(), [](std::thread &t)
{
t.join();
});
for (int i = 0; i <= number_of_threads; i++) {
std::cout << chains[i].length << ' ' << chains[i].acceptance << std::endl;
}
return 0;
}
Upon executing, the program outputs
1000 99
1000 99
1000 99
1000 99
1000 0
1000 0
1000 0
1000 0
So the program failed to change the value of acceptance for the objects in the vector chains. I don't know why this happens; the function sample successfully assigns the desired value when I use it without creating threads.
There are 2 problems with your code:
when creating each std::thread, you are passing a copy of each object as the this parameter of sample().
Pushing multiple objects into the chains vector the way you are doing may cause the vector to re-allocate its internal array, thus invaliding any object pointers you have already passed to existing threads, since those original objects are now gone after the re-allocation.
You need to fully initialize the chains vector before creating any of the threads. And you need to pass a pointer to each object to each thread.
You can reserve() the array up front to avoid re-allocation while pushing into it, eg:
int main()
{
int number_of_threads{3};
int number_of_samples{1000};
std::vector<markov_chain> chains;
std::vector<std::thread> workers;
chains.reserve(number_of_threads);
for (int i = 0; i < number_of_threads; ++i) {
chains.push_back(markov_chain(number_of_samples));
workers.push_back(std::thread(&markov_chain::sample, &chains[i], 99));
}
for(auto &t : workers) {
t.join();
}
for (auto &c : chains) {
std::cout << c.length << ' ' << c.acceptance << std::endl;
}
return 0;
}
Demo
However, since all of the objects are being initialized with the same starting value, an easier way is to simply get rid of chains.push_back() altogether and use chains.resize() instead, eg:
int main()
{
int number_of_threads{3};
int number_of_samples{1000};
std::vector<markov_chain> chains;
std::vector<std::thread> workers;
chains.resize(number_of_threads, markov_chain(number_of_samples));
for (int i = 0; i < number_of_threads; ++i) {
workers.push_back(std::thread(&markov_chain::sample, &chains[i], 99));
}
for(auto &t : workers) {
t.join();
}
for (auto &c : chains) {
std::cout << c.length << ' ' << c.acceptance << std::endl;
}
return 0;
}
Demo
Or, even use the vector constructor itself:
int main()
{
int number_of_threads{3};
int number_of_samples{1000};
std::vector<markov_chain> chains(number_of_threads, markov_chain(number_of_samples));
std::vector<std::thread> workers;
for (int i = 0; i < number_of_threads; ++i) {
workers.push_back(std::thread(&markov_chain::sample, &chains[i], 99));
}
for(auto &t : workers) {
t.join();
}
for (auto &c : chains) {
std::cout << c.length << ' ' << c.acceptance << std::endl;
}
return 0;
}
Demo

C++ : Error could not convert from std::vector<int>* to std::vector<std::vector<int> >

I want to use vector<int> adj[] as my parameter and vector<vector<int>> as my return function type but doing that will cause an error : This happens when returning the vector adj.
could not convert adj from std::vector<int>* to std::vector<std::vector<int> >
return adj;
How can I solve this issue ?
This is my program :
vector<vector<int>>printGraph(int V, vector<int> adj[])
{
for ( int i = 0 ; i < V ; i ++)
{
for (auto x : adj[i])
cout << x;
cout<<"\n";
}
return adj;
}
I realized you are unnecessarily returning adj, if you just want to print you can do yourself a favor and use a void function instead check this code out:
#include <iostream>
#include <vector>
using namespace std;
void printGraph(int V, vector<int> adj[])
{
for (int i = 0; i < V; i++) {
for (auto x : adj[i]) {
cout << x << endl;
}
}
}
int main()
{
vector<int> cat{ 1, 2, 3, 4 };
vector<int> arr[4] = { cat, cat, cat, cat };
printGraph(4, arr);
}
As I got your are trying to convert the array of vectors to a vector of vectors.
Try to return an interval of elements of the original array.
return { adj, adj + V };

How to sort an array of structures according to the value of an included pointer

my aim is to sort an array of structures. The structure contains the index of a customer {1,..., number} and a pointer to a value of an other sturcture,
e.g,
for (int i = 1; i < no_orders+1; i++){
sorting_array[i].index_order = i;
sorting_array[i].some_vaule = &order_data[i].some_value;
}
Here, order_data is an array of structures contains all customer data which allows for directly accessing variable data a customer the index. The array sorting_array is the one to sort according to a value in order_data; therefore the pointer in DATA_TO_SORT in order to avoid copying effort since this function is called millions of times (same indices, changed values).
The actual problem appears with the sorting function. If I do not use the pointer but the real value (int some_value, including copying effort however), sorting works as it should.
Defining some_value as pointer, std::sort terminates after some seconds without any feedback the whole program. The actual question is why and what may I change.
struct DATA_TO_SORT {
int index_order;
int *some_value;
};
bool compare_by_val( DATA_TO_SORT &a, DATA_TO_SORT &b) {
return *a.some_value > *b.some_value;
}
void sort_acc_release() {
std::sort(sorting_array.begin() + 1, sorting_array.end(), compare_by_val);
}
Also tried the following from a related topic, however, the depicted error statement occurs - besides several similar error statements.
std::sort(sorting_array.begin() + 1, sorting_array.end(), [&](size_t a, size_t b) {return *sorting_array[a].some_value > *sorting_array[b].some_value; });
<lambda_0a6c4bdbc69eba5706031ee8a4b875c6>::operator ()(::size_t,::size_t) const" : Konvertierung von Argument 1 von "DATA_TO_SORT" in "::size_t" nicht möglich Algorithm ...\microsoft visual studio\2017\community\vc\tools\msvc\14.12.25827\include\xutility 1017
Minimum Example which WORKS.
#include <iostream>
#include <cstdlib> //rand
#include <algorithm> //swap etc
#include <array> //array
struct OTHER_DATA {
int other_data;
};
struct DATA_TO_SORT {
int index_order;
int *some_value;
};
bool compare_by_val(DATA_TO_SORT &a, DATA_TO_SORT &b) {
return *a.some_value > *b.some_value;
}
int main() {
const int max_no = 10;
std::array<OTHER_DATA, max_no> some_other_values;
std::array<DATA_TO_SORT, 10> sorting_array;
for (int i = 0; i < some_other_values.size(); i++)
{
some_other_values[i].other_data = i * 5;
sorting_array[i].index_order = i;
sorting_array[i].some_value = &some_other_values[i].other_data;
}
for (int i = 0; i < sorting_array.size(); i++)
{
std::cout << "\n" << sorting_array[i].index_order << "\t" << *sorting_array[i].some_value;
}
std::sort(sorting_array.begin(), sorting_array.end(), compare_by_val);
for (int i = 0; i < sorting_array.size(); i++)
{
std::cout << "\n" << sorting_array[i].index_order << "\t" << *sorting_array[i].some_value;
}
system("pause");
return 0;
}
Thank you in advance for your problem-related and well-intentioned answers!

Take item position in vector with structure

Let see code:
struct tmp {
int a;
std::vector <second_struct> b;
}
struct second_struct {
int x;
int y;
}
//main.cpp
int main {
std::vector<tmp> test;
(...); //push data to test
}
So when i push data to test, in second function i want to get vector "b" from this vector 'test'. And find vector b by a;
(i.e I have int a and std::vector<tmp> test; , dont have std::vector <second_struct> b;(from vector test) and want to get it. (vector test is a big array, so i need to do it fastest and using little power )
How to do that? (i suppose std::map will be better? But if you tell me yes, tell me too how to do that in std::Vector)
Loop through test vector checking if tmp::a member is equal to your int a. If so, you have your vector<second_struct> b
for (int i=0;i<test.size();i++) {
if (test[i].a == a) {
// do whatever you need to do with test[i].b
break;
}
}
P.S. map would be easier, just
std::map<int, std::vector<second_struct>> map;
//insert data
std::vector<second_struct> b = map[a]; //assuming it's a that you're looking for
The most straightforward approach is to use map (or unordered_map in C++11). Hope this full example helps:
#include <map>
#include <vector>
#include <iostream>
struct str {
str(int _x, int _y) : x(_x), y(_y) {}
int x, y;
};
std::map<int, std::vector<str> > test;
int main() {
std::vector<str> vec;
for (int i = 0; i < 100; ++i) {
vec.clear();
vec.push_back(str(i, 2 * i));
vec.push_back(str(i + 1, i + 2));
test[i] = vec;
}
std::vector<str> result;
// get some element
result = test[10];
std::cout << "Found at position 10:\n";
for (int i = 0; i < result.size(); ++i)
std::cout << result[i].x << ' ' << result[i].y << '\n';
return 0;
}

Operator Overloading

I'm new to C++, this is my first week since the upgrade from fortran. Sorry if this is a simple question, but could someone help me with operator overloading. I have written a program which has two classes. One object contains a vector and two scalars, the other class simply contains the first object. In a test implementation of this code I suspect the operator overloading to be at fault. The program tries to accomplish the following goals:
1) Initialize first structure.
2) Initialize a second structure containing the initialized first structure. After this is imported, the value val0 = 10 is added to every element of the vector in the enclosing structure, structure2.structure1 .
3) Output structure1 and structure2 variables to compare.
For this simple program my output is:
100
100
0
0
0 0 10
1 1 11
2 2 12
3 3 13
...
I was expecting:
100
100
0
10
0 0 10
1 1 11
2 2 12
3 3 13
...
Clearly my overloaded = operator is copying my vector properly, but one of the scalars? Could someone help?
#include <iostream>
using namespace std;
typedef double* doublevec;
// This first class contains a vector, a scalar N representing the size of the vector, and another scalar used for intializing the vector.
typedef class Structure1
{
int N, vec0;
doublevec vec;
public:
// Constructor and copy constructor.
Structure1(int Nin, int vecin) : N(Nin), vec0(vecin) { vec = new double [N]; for(int i = 0; i < N; i++) { vec[i] = i + vec0; } }
Structure1(const Structure1& structurein);
// Accessor functions:
int get_vec0() { return vec0; }
int get_N() { return N; }
doublevec get_vec() { return vec; }
// Overide equivalence operator:
Structure1& operator=(const Structure1& right)
{
//Handle Self-Assignment
if (this == &right) return *this;
N = right.N;
vec0 = right.vec0;
for (int i = 0; i < N; i++)
{
vec[i] = right.vec[i];
}
return *this;
}
// Destructor:
~Structure1() { delete []vec; }
} Structure1;
Structure1::Structure1(const Structure1& structurein)
{
N = structurein.N;
vec = new double[N];
for(int i = 0; i < N; i++)
{
vec[i] = structurein.vec[i];
}
}
// This class just contains the first structure.
typedef class Structure2
{
Structure1 structure;
// Mutator Function:
void mutate_structure();
public:
// Constructor:
Structure2(const Structure1& structurein) : structure(structurein) { mutate_structure(); }
// Accessor Function:
Structure1 get_structure() { return structure; }
// Destructor:
~Structure2() {}
} Structure2;
void Structure2::mutate_structure()
{
int N = structure.get_N();
Structure1 tempstruct(N,10);
structure = tempstruct;
}
int main (int argc, char * const argv[])
{
const int N = 100;
Structure1 structure1(N,0);
Structure2 structure2(structure1);
cout << structure1.get_N() << endl;
cout << structure2.get_structure().get_N() << endl;
cout << structure1.get_vec0() << endl;
cout << structure2.get_structure().get_vec0() << endl;
for(int i = 0; i < N; i++)
{
cout << i << " " << structure1.get_vec()[i] << " " << structure2.get_structure().get_vec()[i] << endl;
}
return 0;
}
it looks like vec0 isn't initialized by your copy constructor...
Try modifying your copy constructor to:
Structure1::Structure1(const Structure1& structurein)
{
N = structurein.N;
vec = new double[N];
for (int i = 0; i < N; i++)
{
vec[i] = structurein.vec[i];
}
// ADD THIS LINE
vec0 = structurein.vec0;
}
Your copy-constructor Structure1::Structure1(const Structure1 &) doesn't copy vec0. It's not getting initialised at all, so gets whatever is in memory.
Also, you might want to check Structure1's operator=. If you assign a large vector to a small vector, then you'll potentially overflow the array in the destination. You might need to reallocate memory in operator=.