I am just learning c++ and am attempting to understand arrays.. So forgive my ignorance on what's wrong here.
#include <iostream>
#include <string>
#include <array>
using namespace std;
void readArray(int *readfile, int ArraySize){
int Interator;
for(Interator = 1; Interator < ArraySize; Interator++){
cout << " " << readfile[Interator];
}
}
int main(){
std::array<int, 5> array2={{1, 2, 3, 4, 5}};
readArray(array2, array2.end());
}
Error: Can't Convert 'std::array' to 'int*' for arg '1'to void 'readArray'
How would I fix this?
You cannot convert std::array to int* as compiler says. For such conversion you can use plain old array:
void readArray(int *readfile, int ArraySize)
{
int Interator;
for(Interator = 0; Interator < ArraySize; Interator++)
{
cout << " " << readfile[Interator];
}
}
int main()
{
//std::array<int, 5> array2={{1, 2, 3, 4, 5}};
int array2[] = {1, 2, 3, 4, 5};
readArray(array2, 5);
}
Also, Interator is changed to start from zero. If you need std::array then use std::array::begin() and std::array::begin():
void readArray2(const std::array<int, 5>& a)
{
for (auto elem : a)
cout << " " << elem;
}
int main()
{
std::array<int, 5> array2={{1, 2, 3, 4, 5}};
//int array2[] = {1, 2, 3, 4, 5};
readArray2(array2);
}
Just browse some reference to discover that std::array has a T* data() and a constexpr size_type size() which can and should be used for that purpose.
But this is a poor solution. The best solution would be to use iterators directly, eg:
template <typename T> void readArray(const T& data) {
for (const auto& element : data)
cout << element;
}
std::array<int, 5> data1 = { 1, 2, 3, 4, 5};
readArray(data1);
std::vector<int> data2 = {1, 2, 3, 4, 5};
readArray(data2);
std::list<int> data3 = {1, 2, 3, 4, 5};
readArray(data3);
Which would expect T to be a type that has proper begin and end() overloads.
It makes no sense to tag questions with C++11 if you try to use C solutions,
Related
This is my attempt at passing a N-D vector of arbitrary element types, inner and outer lengths to a class and printing its contents.
I know there are a few issues but I have not been able to resolve.
How would I assign the arbitrary inner vector length to a variable or set of variables?
I have attempted to pass iterators to the constructor and assign them to member variables (with and without passing the vector) but that has not been successful.
I understand there are libraries for handling matrix objects and other questions which address problems similar to the one posed herein, however, there are unique/fringe scenarios which comprise the motivation for this question.
#include <iostream>
#include <iterator>
#include <vector>
template <typename V, typename I>
class myVec{
private:
I rows;
I cols;
std::vector< std::vector<V> > vec( rows , vector<int> (cols));
public:
myVec(std::vector< std::vector<V> > const &myArr){
vec = myArr;
rows = myArr.size();
cols = myArr[].size();
}
void printVec(){
for(int i = 0; i < vec.size(); i++){
std::cout << "{";
for(int j = 0; j < vec[i].size(); j++){
std::cout << vec[i][j];
}
if (i < vec.size()){
std::cout << "}";
if (i < vec.size()-1){
std::cout << ",";
std::cout << " ";
}
}
}
std::cout << std::endl;
}
};
int main () {
std::vector< std::vector<int> > mainVec = {{1, 2, 4}, {5, 6, 7, 8}, {4, 3, 2, 1, 7}, {8, 7, 6, 5, 9, 3}};
myVec<int, int> vec1 = myVec<int, int>(mainVec);
vec1.printVec();
return 0;
Basic solution that utilizes iterators as previously suggested for the print method. The vector is passed by const ref, how much of an advantage is there to using move assign instead? Index operator overloads and access methods are not included at this time, plan to include exception handling for out of bounds and other cases.
#include <iostream>
#include <vector>
template <typename V>
class myVec{
private:
std::vector< std::vector<V> > vec;
public:
myVec();
explicit myVec(const std::vector< std::vector<V> > &myArr):vec(myArr) {};
explicit myVec(std::vector< std::vector<V> > &&myArr):vec(std::move(myArr)) {};
}
void printVec(){
std::cout << '{';
for(auto& row:vec){
if(&row != &vec.front()) std::cout << ", ";
std::cout << '{';
if(auto cln = row.begin(); cln != row.end()) {
std::cout << *cln;
for(++cln; cln != row.end(); ++cln) std::cout << ", " << *cln;
}
std::cout << '}';
}
std::cout << '}' << std::endl;
}
};
int main () {
std::vector< std::vector<int> > mainVec = {{1, 2, 4}, {5, 6, 7, 8}, {4, 3, 2, 1, 7}, {8, 7, 6, 5, 9, 3}};
myVec<int, int> vec1 = myVec<int, int>(mainVec);
vec1.printVec();
return 0;
I want to write a function in C++ that take a matrix of any size and print it.
my code is as follows and it works. But my questions:
1) Is it the best practice?
2) Why casting using (int *) works but static_cast<int *> does not?
Thanks
#include <iostream>
using namespace std;
void print_matrix(int *, int, int);
int main()
{
int mat[3][3] = {{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
int mat2[5][5] = {{1, 2, 3, 40, 50},
{4, 5, 6, 70, 80},
{7, 8, 9, 10, 20},
{17, 18, 19, 10, 20},
{71, 81, 91, 110, 120}
};
print_matrix((int *)mat2, 5, 5);
cout << endl;
print_matrix((int *)(mat), 3, 3);
cout << endl;
// static cast does not work:
// error: invalid static_cast from type 'int [3][3]' to type 'int*'|
// print_matrix(static_cast<int *>(mat), 3, 3);
return 0;
}
void print_matrix(int *matPtr, int row, int col)
{
for(int i = 0; i < row; i++) {
for(int j = 0; j < col; j++)
cout << *(matPtr + col * i + j) << '\t';
cout << endl;
}
}
Is it the best practice?
No, it is not.
It will be better to use a function template.
template <size_t NR, size_t NC>
void print_matrix(int (&matrix)[NR][NC])
{
...
}
and call it as:
print_matrix(mat2); // NR and NC are deduced by the compiler
Why casting using (int *) works but static_cast<int *> does not?
Given
int mat[3][3] = { ... };
the following pointers have the same numerical value even though the pointers are of different types.
int (*p1)[3][3] = &mat;
int (*p2)[3] = &mat[0];
int *p3 = &mat[0][0];
Because of this coincidence, use of (int*) works.
Using static_cast<int*> does not work because when a 2D array decays to a pointer, it does not decay to int* -- mat decays to int (*)[3] (pointer to an "array of 3 ints") and mat2 decays to int (*)[5] (pointer to an "array of 5 ints"). They cannot be cast to int* in general.
I am trying to replace the elements in a 2D vector (vector<vector<int>>). I want to change the elements not only by one value, but by a list, which means, for example, change 1,3,4,5,8,9 to 1,2,3,4,5,6 one-to-one correspondence. I have made a very slow code with double loops. Is there any way to speed up the process, with new function or sort the element? Because my 2D vector is very big, 3*300000 actually. My example code is below:
int myints[] = { 1,3,4,5,8,9 };
int myints2[] = { 1,2,3,4,5,6 };
std::vector<int> vals (myints, myints+6);
std::vector<int> vals2 (myints2, myints2+6);
vector<vector<int>> V0(3);
V0[0]={1,4,5};
V0[1]={3,1,8};
V0[2]={1,9,4};
for (size_t j = 0; j < V0.size(); j++)
{
for (int i = 0; i < vals.size(); i++)
replace(V0[j].begin(), V0[j].end(), vals[i], vals2[i]);
};
The ideal output V0 should be
1 3 4
2 1 5
1 6 3
You can use an unordered_map to replace each value directly, instead of searching through the whole vector for each replacement:
#include <vector>
#include <unordered_map>
#include <algorithm>
#include <iostream>
using namespace std;
int main()
{
unordered_map<int, int> replacements{{1, 1}, {3, 2}, {4, 3}, {5, 4}, {8, 5}, {9, 6}};
vector<vector<int>> v0(3);
v0[0] = {1, 4, 5};
v0[1] = {3, 1, 8};
v0[2] = {1, 9, 4};
for_each(v0.begin(), v0.end(), [&](vector<int>& v)
{
transform(v.begin(), v.end(), v.begin(), [&](int val)
{
auto it = replacements.find(val);
return it != replacements.end() ? replacements[val] : val;
});
});
// Print
for (auto& v : v0)
{
cout << "[ ";
for (auto val : v)
{
cout << val << ", ";
}
cout << "]" << endl;
}
return 0;
}
Output:
[ 1, 3, 4, ]
[ 2, 1, 5, ]
[ 1, 6, 3, ]
In C++17, you may also choose a parallel execution policy in for_each and/or transform, since all the changes can be done in parallel.
I have vectors and I would like to retrieve one vector that contains all entries which aren't duplicated anywhere in all input vectors.
#include <vector>
int main() {
std::vector<int> a = {2, 1, 3};
std::vector<int> b = {99, 1, 3, 5, 4};
std::vector<int> c = {5, 6, 7, 1};
// magic to retrieve {2, 99, 4, 6, 7} (order doesn't matter)
}
Is there a library function that can help performing this task efficiently?
I'm not tied to using vectors. The solution could include lists, sets, or whatever are most appropriate for the task.
Using unordered_map, O(N) space complexity and O(N) time complexity:
#include <vector>
#include <unordered_map>
#include <iostream>
std::vector<int>
get_unique_values(std::initializer_list<std::vector<int>> vectors)
{
std::unordered_map<int, size_t> tmp;
auto insert_value_in_tmp = [&tmp](int v) {
auto i = tmp.find(v);
if (i == tmp.end())
tmp[v] = 1;
else if (i->second != 2)
i->second = 2;
};
for ( auto& vec : vectors) {
for ( auto vec_value : vec ) {
insert_value_in_tmp(vec_value);
}
}
std::vector<int> result;
for (auto v : tmp) {
if (v.second == 1)
result.push_back(v.first);
}
return result;
};
int main() {
std::vector<int> a = {2, 1, 3};
std::vector<int> b = {99, 3, 5, 4};
std::vector<int> c = {5, 6, 7};
std::vector<int> result = get_unique_values({a,b,c});
for (auto v : result) {
std::cout << v << " ";
}
std::cout << '\n';
return 0;
}
In c++11 you can do this wonderful syntax:
vector<int> numbers = {1, 2, 3};
Is there a way to concatenate a further initializer list onto an existing vector?
numbers.??? ({4, 5, 6});
or
std::??? (numbers, {4, 5, 6});
You can use std::vector::insert for that:
#include <vector>
vector<int> numbers = {1, 2, 3};
numbers.insert( numbers.end(), {4, 5, 6} );
Use std::vector::insert:
numbers.insert(numbers.end(), {4, 5, 6});
You can use std::vector::insert. Link to example code
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> a = {1,2,3};
a.insert(a.end(), {4,5,6});
for(int &i : a) {
cout << i << " ";
}
cout << endl;
return 0;
}