Cartesian Product in c++ - c++

I have been searching for weeks on how to come up with piece of code which I could applied the cartesian product. Let's say I have two arrays :
int M[2]= {1,2};
int J[3] = {0,1,2};
So the code will takes those two arrays in apply the rule M X J
therefore we will have the pairs (1,0)(1,1)(1,2)(2,0)(2,1)(2,2) and I want the new result to be saved into a new array where each index in the array contains a pair , for example c[0] = (1,0).
Help please :(

Here is an implementation where the sequences of values is a parameter (rather than pre-known as in all the other implementations):
void CartesianRecurse(vector<vector<int>> &accum, vector<int> stack,
vector<vector<int>> sequences, int index)
{
vector<int> sequence = sequences[index];
for (int i : sequence)
{
stack.push_back(i);
if (index == 0)
accum.push_back(stack);
else
CartesianRecurse(accum, stack, sequences, index - 1);
stack.pop_back();
}
}
vector<vector<int>> CartesianProduct(vector<vector<int>> sequences)
{
vector<vector<int>> accum;
vector<int> stack;
if (sequences.size() > 0)
CartesianRecurse(accum, stack, sequences, sequences.size() - 1);
return accum;
}
main() {
vector<vector<int>> sequences = { {1,2,7},{3,4},{5,6} };
vector<vector<int>> res = CartesianProduct(sequences);
// now do something with the result in 'res'.
}

#include <iostream>
#include <iterator>
#include <vector>
#include <utility>
#include <tuple>
template<typename Range1, typename Range2, typename OutputIterator>
void cartesian_product(Range1 const &r1, Range2 const &r2, OutputIterator out) {
using std::begin; using std::end;
for (auto i = begin(r1);i != end(r1); ++i) {
for (auto j = begin(r2); j != end(r2); ++j) {
*out++ = std::make_tuple(*i, *j);
}
}
}
int main() {
std::vector<int> a{1,2,3};
std::vector<char> b{'a','b','c','d','e','f'};
std::vector<std::tuple<int, char>> c;
cartesian_product(a, b, back_inserter(c));
for (auto &&v : c) {
std::cout << "(" << std::get<int>(v) << "," << std::get<char>(v) << ")";
}
}
Prints:
(1,a)(1,b)(1,c)(1,d)(1,e)(1,f)(2,a)(2,b)(2,c)(2,d)(2,e)(2,f)(3,a)(3,b)(3,c)(3,d)(3,e)(3,f)
And you can also apply the function to your case:
template<typename T, int N> constexpr int size(T (&)[N]) { return N; }
int main() {
int M[2] = {1,2};
int J[3] = {0,1,2};
std::tuple<int, int> product[size(M) * size(J)];
cartesian_product(M, J, product);
for (auto &&v : product) {
std::cout << "(" << std::get<0>(v) << "," << std::get<1>(v) << ")";
}
}
The output is:
(1,0)(1,1)(1,2)(2,0)(2,1)(2,2)
http://coliru.stacked-crooked.com/a/3ce388e10c61a3a4

Here is an simple example of implementing Cartesian product using vector. Vectors are much better choice as we do not need to worry about its size as it dynamically changes it.
#include <iostream>
#include <vector>
#include <utility>
using namespace std;
int main() {
int M[2]= {1,2};
int J[3] = {0,1,2};
vector<pair<int,int>> C;
for (int i = 0; i < sizeof(M)/sizeof(M[0]); i++)
{
for (int j = 0; j < sizeof(J)/sizeof(J[1]); j++)
{
C.push_back(make_pair(M[i],J[j]));
}
}
/*
for (vector<int>::iterator it = C.begin(); it != C.end(); it++)
{
cout << *it << endl;
}
*/
for (int i = 0; i < C.size(); i++)
{
cout << C[i].first << "," << C[i].second << endl;
}
}
Here is the link where I implemented the above code. Although I wouldn't post solution directly relating to your question, links posted in the comments already contains answer which is why I posted.

I think using of c++ two-dimensional arrays is a very bad idea, but if you want, you probably could use this code
#include <iostream>
int** cartesian_prod( int* s1, int* s2, int s1size, int s2size )
{
int ressize = s1size*s2size;
int** res = new int*[ressize];
for ( int i = 0; i < s1size; i++ )
for ( int j = 0; j < s2size; j++ )
{
res[i*s2size+j] = new int[2];
res[i*s2size+j][0] = s1[i];
res[i*s2size+j][1] = s2[j];
}
return res;
}
int main() {
int M[2]= {1,2};
int J[3] = {0,1,2};
int** res;
int Msize = sizeof(M)/sizeof(M[0]);
int Jsize = sizeof(J)/sizeof(J[1]);
res = cartesian_prod(M, J, Msize, Jsize);
for ( int i = 0; i < Msize*Jsize; i++ )
std::cout << res[i][0] << " " << res[i][1] << std::endl;
for (int i = 0; i < Msize*Jsize; i++)
delete[] res[i];
delete[] res;
return 0;
}
But it is much better to deal with std::vector - it much faster (in terms of development time) and will save you from many errors.

Solution without for loops.
#include<array>
#include<iostream>
#include<tuple>
#include<utility>
template
<typename T, typename Tuple, std::size_t... I>
auto cartesian_product_base(
const T& a,
const Tuple& t,
std::index_sequence<I...>) {
return std::make_tuple(std::make_pair(a, std::get<I>(t))...);
}
template
<typename T, typename... Ts, std::size_t... I>
std::array<T, sizeof...(Ts) + 1> to_array(std::tuple<T, Ts...> t, std::index_sequence<I...>) {
return {std::get<I>(t)...};
}
template
<typename Tuple1, typename Tuple2, std::size_t... I>
auto cartesian_product_impl(
const Tuple1& t1,
const Tuple2& t2,
std::index_sequence<I...>) {
return std::tuple_cat(cartesian_product_base(
std::get<I>(t1),
t2,
std::make_index_sequence<std::tuple_size<Tuple2>::value>{})...);
}
template
<typename T1, std::size_t N1, typename T2, std::size_t N2>
auto cartesian_product(
const std::array<T1, N1>& a1,
const std::array<T2, N2>& a2) {
return to_array(
cartesian_product_impl(a1, a2, std::make_index_sequence<N1>{}),
std::make_index_sequence<N1 * N2>{});
}
using namespace std;
int main() {
array<int, 2> M = {1, 2};
array<int, 3> J = {0, 1, 2};
auto C = cartesian_product(M, J);
cout << C.size() << endl;
cout << "{";
for (size_t i = 0; i != C.size(); ++i) {
if (i != 0) {
cout << ", ";
}
cout << "(" << C[i].first << ", " << C[i].second << ")";
}
cout << "}" << endl;
}

Related

How to Print whole array inside square brackets rather then printing every single value?

In the following code I want to print the whole array instead of printing each single value. Can we do that? I'm familiar with python where we append values but I can't find that in C++. So how to get desired result. What if I have to print it using printf?
#include <iostream>
using namespace std;
int *name(){
static int n[5];
for(int i=0;i<5;i++){
n[i]=i;}
return n;}
int main(){
int *p;
p=name();
for(int i=0;i<5;i++){
cout<<*(p+i)<<endl;}
return 0;
desired output should be -
[0,1,2,3,4]
#include <iostream>
using namespace std;
int *name() {
static int n[5];
for (int i = 0; i < 5; ++i)
n[i] = i;
return n;
}
int main()
{
int *p;
p = name();
cout << '[';
for (int i = 0; i < 5; ++i)
cout << *(p+i) << (i != 4 ? ',' : ']');
}
Or, if you want to encapsulate the array-printing into a general function:
#include <iostream>
#include <string>
using namespace std;
std::string PrintArray(int* array, size_t size) {
std::string answer = "[";
for (size_t i = 0; i < size; ++i) {
answer += std::to_string(array[i]);
answer += (i < size-1) ? "," : "]";
}
return answer;
}
int* name() {
static int n[5];
for (int i = 0; i < 5; i++) {
n[i] = i;
}
return n;
}
int main() {
int* p;
p = name();
cout << PrintArray(p, 5) << endl;
return 0;
}
I usually end up overloading operator<< for the desired type, but your mileage may vary.
#include <iostream>
#include <vector>
template <class InputIt>
std::ostream& print_impl(std::ostream& os, InputIt first, InputIt last)
{
os << '[';
if (first != last)
{
os << *first;
while ( ++first != last )
os << ", " << *first;
}
return os << ']';
}
template <class T>
std::ostream& operator<<(std::ostream& os, std::vector<T> const& v)
{
return print_impl(os, v.cbegin(), v.cend());
}
template <class T, size_t N>
std::ostream& operator<<(std::ostream& os, T const (&a)[N])
{
return print_impl(os, std::cbegin(a), std::cend(a));
}
int main()
{
std::vector<int> a{1, 2, 3, 4, 5};
std::cout << a << '\n';
float b[] = {3.14f, -0.1f, 2.0f};
std::cout << b << '\n';
}

code crashes when using auto loop

I am sorting a vector using a swap function.
When I use the loop:
for (int i = 0; i < vec.size(); i++)
code runs fine but when I use:
for (auto const &i:vec)
it crashes!
Error in ./run': free(): invalid next size (fast): 0x0000000001df0c20
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <ctime>
#include <vector>
#include <array>
template <class T>
void myswap(T &a,
T &b)
{
T temp = a;
a = b;
b = temp;
}
int main() {
const int N = 5;
std::vector<int> vec = {112,32,11,4,7};
std::cout << "\nInit\n";
for (const auto &i:vec)
{
std::cout << i << "\t";
}
int j;
for (auto const &i:vec)
//for (int i = 0; i < vec.size(); i++)
{
j = i;
while (j > 0 && vec[j] < vec[j-1])
{
myswap(vec[j], vec[j-1]);
j--;
}
}
std::cout << "\n\nFinal\n";
for (const auto &i:vec)
{
std::cout << i << "\t";
}
std::cout << "\n";
return 0;
}
Answer already in the comments to the question (range based loop iterates over the values, not the indices), but for illustration, try this:
std::vector<std::vector<int>> v;
int j;
for(auto const& i : v)
{
j = v;
}
You will quickly discover that this piece of code does not compile – a good compiler will show you an error like this one (from GCC):
error: cannot convert 'std::vector<std::vector<int> >' to 'int' in assignment
What you now could do would be the following:
std::vector<std::vector<int>> v;
for(auto const& i : v)
{
std::vector<int> const& vv = v; // assign a reference
std::vector<int> vvv = v; // make a COPY(!)
}
Pretty self-explaining, isn't it?
it may be due to auto const try like this const auto and also you are using j in while loop instead of i you change it to j in while or change for(const auto &j:vec)
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <ctime>
#include <vector>
#include <array>
template <class T>
void myswap(T &a,
T &b)
{
T temp = a;
a = b;
b = temp;
}
int main() {
const int N = 5;
std::vector<int> vec = {112,32,11,4,7};
std::cout << "\nInit\n";
for (const auto &i:vec)
{
std::cout << i << "\t";
}
int j;
for (const auto &j:vec)
//for (int j = 0; j < vec.size(); j++)
{
while (j > 0 && vec[j] < vec[j-1])
{
myswap(vec[j], vec[j-1]);
j--;
}
}
std::cout << "\n\nFinal\n";
for (const auto &i:vec)
{
std::cout << i << "\t";
}
std::cout << "\n";
return 0;
}
From the way you use swap, it is intended for j to represent a valid index of vec. Now i is not an index, but it is a value instead. When you assign j=i, then j contains 112 which is clearly out of bounds.
The way ranged loop works is that i takes the value vec[0], vec[1], vec[2] ... at each iteration.
Read here to learn about ranged loop.

Heapsort order of magnitude slower than Bubblesort (C++)

I have implemented a heap data structure, and use it to sort. My understanding is that it is O(nlogn) complexity. However, when compared to bubble sort, it is order of magnitude slower -- and yeah, I tried running it for larger arrays. I checked some answers at SO (in particular this and this), but still lost. Could anyone point out what am I doing wrong here, please?
The results are:
HEAP SORT: 12415690ns
QUICK SORT: 71ns
BUBBLE SORT: 541659ns
Here are the codes:
main.cpp:
#include <chrono>
#include <iostream>
#include <stdexcept>
#include <vector>
// #include "heap.cpp"
// #include "pqueue.cpp"
#include "sort.cpp"
using namespace std;
using namespace std::chrono;
template <class T>
void printVector (vector<T> A) {
for (std::vector<int>::iterator it = A.begin(); it != A.end(); ++it) {
std::cout << *it << ' ';
}
cout << endl;
}
template <class T>
vector<T> constructVector(int A[], std::size_t len, std::size_t num) {
vector<T> res (A, A+len);
for (std::size_t idx = 0; idx < num-1; ++idx) {
res.push_back(A[idx%len]);
}
return res;
}
int main() {
high_resolution_clock::time_point t1;
high_resolution_clock::time_point t2;
int a[] = {4, 1, 3, 2, 16, 9, 10, 14, 8, 7};
std::size_t len = sizeof(a) / sizeof(int);
vector<int> HEAP = constructVector<int>(a, len, 32000); // (a, a + sizeof(a) / sizeof(int));
vector<int> QUICK = constructVector<int>(a, len, 32000); // (a, a + sizeof(a) / sizeof(int));
vector<int> BUBBLE = constructVector<int>(a, len, 32000);
// cout << "Original Array: "; printVector(HEAP);
cout << "HEAP SORT: ";
t1 = high_resolution_clock::now();
heapsort(HEAP);
t2 = high_resolution_clock::now();
cout << duration_cast<nanoseconds>( t2 - t1 ).count() << "ns\n";
// cout << "New Array: "; printVector(HEAP);
// cout << "Original Array: "; printVector(QUICK);
cout << "QUICK SORT: ";
t1 = high_resolution_clock::now();
quicksort(QUICK, 0, QUICK.size());
t2 = high_resolution_clock::now();
cout << duration_cast<nanoseconds>( t2 - t1 ).count() << "ns\n";
// cout << "New Array: "; printVector(HEAP);
// cout << "Original Array: "; printVector(QUICK);
cout << "BUBBLE SORT: ";
t1 = high_resolution_clock::now();
bublesort(BUBBLE);
t2 = high_resolution_clock::now();
cout << duration_cast<nanoseconds>( t2 - t1 ).count() << "ns\n";
// cout << "New Array: "; printVector(HEAP);
}
sort.cpp:
#ifndef __SORT_CPP_INCLUDED_
#define __SORT_CPP_INCLUDED_
#include <vector>
#include "heap.cpp"
template <class T>
void heapsort(std::vector<T> &A, bool increasing = true) {
Heap<T> H(A, increasing);
H.sort();
A = H.get();
}
template <class T>
std::size_t partition(std::vector<T> &A, std::size_t p, std::size_t r) {
T x = A[r-1];
std::size_t i = p - 1;
for (std::size_t j = p; j < r; ++j) {
if (A[j] <= x) {
++i;
A[i] ^= A[j];
A[j] ^= A[i];
A[i] ^= A[j];
}
}
A[i+1] ^= A[r-1];
A[r-1] ^= A[i+1];
A[i+1] ^= A[r-1];
return i + 1;
}
template <class T>
void quicksort(std::vector<T> &A, std::size_t p, std::size_t r) {
if (p-1 < r) {
std::size_t q = partition(A, p, r);
quicksort(A, p, q);
quicksort(A, q+1, r);
}
}
template <class T>
void bublesort(std::vector<T> &A) {
bool swapped = false;
do {
swapped = false;
for (std::size_t idx = 1; idx < A.size(); ++idx) {
if (A[idx-1] > A[idx]) {
// swap them
A[idx] = A[idx-1];
A[idx-1] = A[idx];
A[idx] = A[idx-1];
swapped = true;
}
}
} while (swapped);
}
#endif
heap.cpp:
#ifndef __HEAP_CPP_INCLUDED__
#define __HEAP_CPP_INCLUDED__
#include <vector>
template <class T>
class Heap {
public:
Heap(bool maxHeap = true) : heap_size(0), max_heap(maxHeap) {}
Heap(const std::vector<T> &a, bool maxHeap = true) : A(a), max_heap(maxHeap) {
if (maxHeap) this->build_max_heap(); else this->build_min_heap(); }
~Heap() {}
protected:
std::vector<T> A;
std::size_t heap_size;
bool max_heap;
public:
std::size_t parent(std::size_t idx) { return (idx - 1) >> 1; }
std::size_t left(std::size_t idx) { return (idx << 1) + 1; }
std::size_t right (std::size_t idx) { return (idx + 1) << 1; }
public:
std::vector<T> get() { return A; }
std::size_t size() { return heap_size; }
void sort();
void build_max_heap();
void build_min_heap();
void max_heapify(std::size_t idx);
void min_heapify(std::size_t idx);
};
template <class T>
void Heap<T>::sort() {
if (this->heap_size <= 0) return; // Already sorted or empty
if (this->heap_size != this->A.size()){ // Not sorted and not heapified
max_heap ? build_max_heap() : build_min_heap();
}
for (std::size_t idx = this->A.size()-1; idx > 0; --idx) {
A[0] ^= A[idx];
A[idx] ^= A[0];
A[0] ^= A[idx];
--this->heap_size;
max_heap ? max_heapify(0) : min_heapify(0);
}
}
template<class T>
void Heap<T>::build_max_heap() {
this->heap_size = this->A.size();
for (std::size_t idx = (this->A.size() - 1) >> 1; idx > 0; --idx)
this->max_heapify(idx);
this->max_heapify(0);
}
template<class T>
void Heap<T>::build_min_heap() {
this->heap_size = this->A.size();
for (std::size_t idx = (this->A.size()-1) >> 1; idx > 0; --idx)
this->min_heapify(idx);
this->min_heapify(0);
}
template <class T>
void Heap<T>::max_heapify(std::size_t idx) {
std::size_t l = this->left(idx);
std::size_t r = this->right(idx);
std::size_t largest;
if (l < this->heap_size && A[l] > A[idx]) largest = l;
else largest = idx;
if (r < this->heap_size && A[r] > A[largest]) largest = r;
if (largest != idx) {
this->A[idx] ^= this->A[largest];
this->A[largest] ^= this->A[idx];
this->A[idx] ^= this->A[largest];
this->max_heapify(largest);
}
}
template <class T>
void Heap<T>::min_heapify(std::size_t idx) {
std::size_t l = this->left(idx);
std::size_t r = this->right(idx);
std::size_t smallest;
// std::cout << "DEBUG: " << idx << std::endl;
if (l < this->heap_size && A[l] < A[idx]) smallest = l;
else smallest = idx;
if (r < this->heap_size && A[r] < A[smallest]) smallest = r;
if (smallest != idx) {
this->A[idx] ^= this->A[smallest];
this->A[smallest] ^= this->A[idx];
this->A[idx] ^= this->A[smallest];
this->min_heapify(smallest);
}
}
#endif
Your bubble sort doesn't swap, but only copy. This would make it somewhat faster. Not sure this alone explains being so fast, though.
Your Heap<T> makes a copy of the array. This can explain the slowness. I guess you forgot a &.
You should have noticed 71ns to sort 32k array is not real. Your quicksort never sorts anything. You can use std::sort for a reliable quicksort.
Too much is known at compile time and the numbers are far from random. Switch to arrays with random numbers in this kind of testing.

C++ non recursive function with variable number of args

I have a Matrix template class and I need a function to set it's elements with variable number of args.
I should be able to call it like this:
aghMatrix<string> matrix;
matrix.setItems(2, 3, "torzmiae", "jestdnaci", "tablickore", "wyrazobed", "oelmntai", "rozmiaecy");
Where first integer is rows number, second is columns and rest (R * C) arguments are elements that I should put into matrix.
It should work with any data types, not only primitive ones.
For now, my function looks like this:
template<typename T>
template<typename... ARGS>
void aghMatrix<T>::setItems(const int rows, const int cols, ARGS... args) {
array<T, sizeof...(args)>unpacked_args {args...};
int row = 0;
int col = 0;
for (T arg : unpacked_args)
{
this->matrixPtr[row][col] = arg;
col++;
if (col == this->cols) {
row++;
col = 0;
}
}
return;
}
I assumed my matrix object is able to hold all elements. It does compile with many warnings about casting everything to unsigned int, but the program doesn't work anyway (it freezes on start).
Class declaration:
template<typename T>
class aghMatrix {
public:
[...]
template<typename... ARGS> void setItems(const int rows, const int cols, ARGS... args);
[...]
private:
T **matrixPtr;
int rows;
int cols;
void createMatrix(const int row, const int col);
bool checkRowCol(const int row, const int col) const;
};
Github project
EDIT: Oops! I just noticed you said "non recursive," so I presume the following pattern doesn't work for you. I'll still leave it hanging here for now, but I have provided also a non recursive solution below (which is based on va_list and hence only works with POD types)
If I understand correctly what you want to do, then you probably want the recursive variadic argument unpacking pattern; something like this seems to do the trick...
#include <iostream>
using namespace std;
// Helper for build_matrix, taking zero variadic arguments.
// This serves as the termination in the recursive unpacking of the args.
template<typename T>
void build_matrix_helper(T**, size_t, size_t, size_t, size_t) { return; }
// Helper for build_matrix, taking at least one variadic argument.
template <typename T, typename ...ARGS>
void build_matrix_helper(T** matrix, size_t curr_row, size_t curr_col,
size_t row, size_t col, const T& first, ARGS...rest) {
if (curr_col < col) {
matrix[curr_row][curr_col] = first;
++curr_col;
return build_matrix_helper<T>(matrix, curr_row, curr_col, row, col, rest...);
}
else {
++curr_row;
curr_col = 0;
return build_matrix_helper<T>(matrix, curr_row, curr_col, row, col, first, rest...);
}
return;
}
// Bare bones implementation.
template<typename T, typename ...ARGS>
T **build_matrix(size_t row, size_t col, ARGS...elements) {
T **new_mat = new T*[row];
for (size_t j = 0; j < row; ++j)
new_mat[j] = new T[col];
build_matrix_helper<T>(new_mat, 0, 0, row, col, elements...);
return new_mat;
}
int main() {
int **nm = build_matrix<int>(2, 3, 1, 2, 3, 4, 5, 6);
for (size_t i = 0; i < 2; ++i) {
cout << "[" << i + 1 << "]: ";
for (size_t j = 0; j < 3; ++j)
cout << nm[i][j] << " ";
cout << endl;
}
delete[] nm;
return 0;
}
In general, you want to avoid any direct manipulation of memory as much as possible. Also avoid as much as possible any casting voodoo unless you absolutely need it (which also ties in with direct memory manipulation).
Anyway, can use a non recursive solution below, using std::va_list.
NOTE Since this uses va_list, it does not work with non POD types.
#include <iostream>
#include <cstdarg>
using namespace std;
template <typename T>
T **build_matrix(size_t row, size_t col, ...) {
va_list args;
T **matrix = new T*[row];
va_start(args, col);
for (size_t i = 0; i < row; ++i) {
matrix[i] = new T[col];
for (size_t j = 0; j < col; ++j)
matrix[i][j] = va_arg(args, T);
}
va_end(args);
return matrix;
}
int main() {
int **nm = build_matrix<int>(2, 3, 1, 2, 3, 4, 5, 6);
for (size_t i = 0; i < 2; ++i) {
cout << "[" << i + 1 << "]: ";
for (size_t j = 0; j < 3; ++j)
cout << nm[i][j] << " ";
cout << endl;
}
delete[] nm;
return 0;
}
EDIT Initializer lists
As has been suggested in the comments to your OP, it is better to use initializer lists. I know this isn't what you asked for originally, but maybe it's worth considering:
#include <iostream>
#include <stdexcept>
using namespace std;
template <typename T>
T **build_matrix(size_t row, size_t col, initializer_list<T> il) {
if (il.size() != row*col)
throw out_of_range("Number of elements does not match matrix dimensions!");
size_t curr_row = 0;
size_t curr_col = 0;
T **nm = new T*[row];
nm[0] = new T[col];
for (T elm : il) {
if (curr_col == col) {
++curr_row;
nm[curr_row] = new T[col];
curr_col = 0;
}
nm[curr_row][curr_col] = elm;
++curr_col;
}
return nm;
}
int main() {
int **nm = build_matrix<int>(2, 3, {1, 2, 3, 4, 5, 6});
for (size_t i = 0; i < 2; ++i) {
cout << "[" << i + 1 << "]: ";
for (size_t j = 0; j < 3; ++j)
cout << nm[i][j] << " ";
cout << endl;
}
delete[] nm;
return 0;
}

How do you save a whole array to a disk in c++

I've been looking, but i've never been able to save anything other than one coordinate in a 2 dimensional array
This is called serialization. Have a look at this question for more info on using Boost to do just that.
Based on StackedCrooked's idea, here's a solution that allows you to user either a C-style array of std::vector or any other sequence whose elements have << defined for them.
#include <cstddef>
#include <fstream>
#include <iostream>
// Beware, brain-compiled code ahead!
template<class InpIt>
void save_seq(const std::ostream& os, InpIt begin, InpIt end)
{
if(begin != end)
os << *begin++;
while(begin != end)
os << ' ' << *begin++;
}
template<class OutpIt>
bool load_seq(const std::istream& is, OutpIt begin, std::size_t n)
{
for( std::size_t i=0; is && i<n; ++i)
is >> *begin++
return is.good() || is.eof();
}
template<class OutpIt>
bool load_seq(const std::istream& is, OutpIt begin)
{
while(is.good())
is >> *begin++
return is.eof();
}
template<class T, std::size_t N>
void save_array(const std::ostream& os, const T (&data)[N])
{
save_seq(os, data, data+N);
}
template<class T, std::size_t N>
bool load_array(const std::istream& is, T (&data)[N])
{
return load_seq(is, data, N);
}
int main()
{
const std::size_t size = 5;
int numbers[size];
numbers[0] = 10;
numbers[1] = 11;
numbers[2] = 12;
numbers[3] = 13;
numbers[4] = 14;
{
std::oftsream ofs("array.txt");
if(!ofs.good())
return 1;
save_array(ofs, numbers);
}
{
std::iftsream ifs("array.txt");
if(!ifs.good())
return 2;
int test[size];
load_array(ifs, test);
for (std::size_t idx = 0; idx < size; ++idx)
std::cout << "test[" << idx << "]: " << test[idx] << std::endl;
}
std::vector<int> numbers2;
numbers2.push_back(20);
numbers2.push_back(21);
numbers2.push_back(22);
numbers2.push_back(23);
{
std::oftsream ofs("array.txt");
if(!ofs.good())
return 1;
save_Seq(ofs, numbers2.begin(), numbers2.end());
}
{
std::iftsream ifs("array.txt");
if(!ifs.good())
return 2;
std::vector<int> test;
load_seq(ifs, std::back_inserter(test));
for (std::size_t idx = 0; idx < numbers2.size(); ++idx)
std::cout << "test[" << idx << "]: " << test[idx] << std::endl;
}
return 0;
}
You could use a std::fstream or boost::serialization. Your question is a bit vague, so I'm not entirely sure what it is you want, need?
If the array contains flat data (i.e., data that does not include pointers to other data), you can write an entire array in a single write to a file.
Without any idea what your data looks like, it would not be possible to say much more about it.
After some tinkering I came up with this:
#include <cstddef>
#include <fstream>
#include <iostream>
template<class T>
void SaveArray(const std::string & file, T * data, std::size_t length)
{
std::ofstream out(file.c_str());
for (std::size_t idx = 0; idx < length; ++idx)
{
if (idx != 0)
{
out << " ";
}
out << *data++;
}
}
template<class T>
std::size_t LoadArray(const std::string & file, T * data, std::size_t length)
{
std::ifstream in(file.c_str());
std::size_t count = 0;
while (count++ < length && in >> *data++);
return count - 1; // return number of items
}
int main()
{
int numbers[5];
numbers[0] = 10;
numbers[1] = 11;
numbers[2] = 12;
numbers[3] = 13;
numbers[4] = 14;
SaveArray("array.txt", &numbers[0], 5);
int test[5];
LoadArray("array.txt", &test[0], 5);
for (std::size_t idx = 0; idx < 5; ++idx)
{
std::cout << "test[" << idx << "]: " << test[idx] << std::endl;
}
return 0;
}
Suggestions for improvement are welcome.