I need som help outputting the content of this multidimensional array. I'm trying pass the address of the array to the function and let it grab and run thru it.
#include <iostream>
using namespace std;
void LoopDeLoop(int[][] *arr)
{
for(int k = 0; k < 3; k++)
{
for(int j = 0; j < 4; j++)
{
cout << arr[k][j];
}
}
}
int main() {
int arr[3][4] = { {1,2,3,4}, {5,6,7,8}, {10,11,12,13} };
LoopDeLoop(&arr);
return 0;
}
This pattern you are trying to use is old fashioned C.
Modern C++ way to do it should be more clear for you:
#include <array>
#include <iostream>
using MyArray = std::array<std::array<int, 4>, 3>;
void LoopDeLoop(const MyArray& arr)
{
for (auto& row : arr) {
for (auto x : row) {
std::cout << x << ' ';
}
std::cout << '\n';
}
}
int main()
{
MyArray arr { std::array { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 10, 11, 12, 13 } };
LoopDeLoop(arr);
return 0;
}
https://godbolt.org/z/Mbcjf9bx5
C++ allows to pass plain array by reference and also automatically deduce dimensions using templates:
Try it online!
#include <iostream>
using namespace std;
template <int Rows, int Cols>
void LoopDeLoop(int const (& arr)[Rows][Cols])
{
for(int k = 0; k < Rows; k++)
{
for(int j = 0; j < Cols; j++)
{
cout << arr[k][j];
}
}
}
int main() {
int arr[3][4] = { {1,2,3,4}, {5,6,7,8}, {10,11,12,13} };
LoopDeLoop(arr);
return 0;
}
Output:
1234567810111213
Related
I have a 2D vector, and i would like to sort all its columns by a sorting a specific row (the inner vectors) like this:
input:
{{5,6,9},
{1,7,5},
{3,5,7}}
sorting the elements to asc in row 2, the vector would be:
{{5,9,6},
{1,5,7},
{3,7,5}}
If stl sort is an acceptable choice, you can do like this:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
// According to your description, the input is row major
vector<vector<int>> vec_2d{
{5,6,9},
{1,7,5},
{3,5,7} };
// Convert the input vec to col major
int rows = vec_2d.size();
int cols = vec_2d.front().size();
// Allocate a new 2d vec which stores values by col major
vector<vector<int>> vec_2d_col_major(cols, vector<int>(rows));
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
vec_2d_col_major[j][i] = vec_2d[i][j];
}
}
// Sort by asc the 2nd row
sort(vec_2d_col_major.begin(), vec_2d_col_major.end(), [](const vector<int>& a, vector<int>& b) {
return a[1] < b[1];
});
// Copy data from col major to row major
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
vec_2d[i][j] = vec_2d_col_major[j][i];
}
}
// Check the sort result
for (const auto& row : vec_2d) {
for (auto num : row) {
cout << num << " ";
}
cout << endl;
}
}
Output:
5 9 6
1 5 7
3 7 5
I suppose your input vector is stored in row major by std::vector
sorted by reorder, use a vector to keep the order for each column.
#include <vector>
#include <algorithm>
#include <iostream>
template<class T>
void show(const std::vector<std::vector<T>>& values) {
for (auto& raw : values) {
for (auto& v : raw)
std::cout << v << " ";
std::cout << std::endl;
}
}
template<class T>
void swap(std::vector<std::vector<T>>& values, uint32_t i, uint32_t j) {
for (auto& row : values)
std::swap(row[i], row[j]);
}
template<class T>
void reorder(std::vector<std::vector<T>>& values, std::vector<uint32_t>& order) {
for (uint32_t i = 0; i < order.size(); ++i) {
while (order[i] != order[order[i]]) {
swap(values, order[i], order[order[i]]);
std::swap(order[i], order[order[i]]);
}
}
}
template<class T>
void sort_row(std::vector<std::vector<T>>& values, int32_t row) {
uint32_t row_count = values.size();
uint32_t col_count = values[row].size();
std::vector<uint32_t> sorted_idx(col_count);
for (uint32_t i = 0; i < col_count; ++i)
sorted_idx[i] = i;
std::sort(sorted_idx.begin(), sorted_idx.end(),
[&](uint32_t i, uint32_t j) {
return values[row][i] < values[row][j];
});
reorder(values, sorted_idx);
}
int main(int, char**) {
std::vector<std::vector<int32_t>> values = {
{-1, -3, -2, -4},
{ 0, 1, 2, 3},
{ 5, 6, 7, 8}
};
sort_row(values, 0);
show(values);
return 0;
}
I have an integer array:
int listint[10] = {1,2,2,2,4,4,5,5,7,7,};
What I want to do is to create another array in terms of the multiplicity. So I define another array by:
int multi[7]={0};
the first index of the multi array multi[0] will tell us the number of multiplicity of the array listint that has zero. We can easily see that, there is no zero in the array listint, therefore the first member would be 0. Second would be 1 spice there are only 1 member in the array. Similarly multi[2] position is the multiplicity of 2 in the listint, which would be 3, since there are three 2 in the listint.
I want to use an for loop to do this thing.
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
unsigned int count;
int j;
int listint[10] = { 1,2,2,2,4,4,5,5,7,7, };
int multi[7] = { 0 };
for (int i = 0; i < 9; i++)
{
if (i == listint[i])
count++;
j = count;
multi[j] = 1;
}
cout << "multi hit \n" << multi[1] << endl;
return 0;
}
After running this code, I thought that I would want the multiplicity of the each element of the array of listint. So i tried to work with 2D array.
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
unsigned int count;
int i, j;
int listint[10] = { 1,2,2,2,4,4,5,5,7,7, };
int multi[7][10] = { 0 };
for (int i = 0; i < 9; i++)
{
if (i == listint[i])
count++;
j = count;
for (j = 0; j < count; j++) {
multi[j][i] = 1;
}
}
cout << "multi hit \n" << multi[4][i] << endl;
return 0;
}
The first code block is something that I wanted to print out the multiplicity. But later I found that, I want in a array that multiplicity of each elements. SO isn't the 2D array would be good idea?
I was not successful running the code using 2D array.
Another question. When I assign j = count, I mean that that's the multiplicity. so if the value of count is 2; I would think that is a multiplicity of two of any element in the array listint.
A 2d array is unnecessary if you're just trying to get the count of each element in a list.
#include <iostream>
int main() {
int listint[10] = { 1,2,2,2,4,4,5,5,7,7, };
int multi[8] = { 0 };
for (int i : listint)
++multi[i];
for (int i = 0; i < 8; ++i)
std::cout << i << ": " << multi[i] << '\n';
return 0;
}
There's also a simpler and better way of doing so using the standard collection std::map. Notably, this doesn't require you to know what the largest element in the array is beforehand:
#include <map>
#include <iostream>
int main() {
int listint[10] = {1,2,2,2,4,4,5,5,7,7,};
std::map<int, int> multi;
for (int i : listint)
multi[i]++;
for (auto [k,v] : multi)
std::cout << k << ": " << v << '\n';
}
Try this incase maps won't work for you since you're a beginner, simple:
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
unsigned int count;
int j;
int listint[10] = {1,2,2,2,4,4,5,5,7,7};
int multi[8]={0};
for(int i=0; i<10; i++)
{
multi[listint[i]]++; // using listint arrays elements as index of multi to increase count.
}
for( int i=1; i<8; i++)
{
cout << "multi hit of "<<i<<" : "<< multi[i]<<endl;
}
return 0;
}
OR if numbers could get large and are unknown but sorted
#include <iostream>:
#include <stdio.h>
using namespace std;
int main()
{
unsigned int count = 0;
int index = 0; // used to fill elements in below arrays
int Numbers[10] = {0}; // storing unique numbers like 1,2,4,5,7...
int Count[10] = {0}; // storing their counts like 1,3,2,2,2...
int listint[10] = {1, 2, 2, 2, 4, 4, 5, 5, 7, 7};
for(int i = 0; i < sizeof(listint) / sizeof(listint[0]); i++)
{
count++;
if (listint[i] != listint[i+1]) {
Numbers[index] = listint[i];
Count[index] = count;
count=0;
index++;
}
}
for(int i=0; i<index; i++)
{
cout << "multi hit of "<<Numbers[i]<<" is " << Count[i]<<endl;
}
return 0;
}
First of all, im a c++ noob! Ok with that being said, i need to declare a function that initializes a grid. The function takes an array of int as the input and needs to return an array of int. I have:
array<int> InitializeGrid (array<int>)
{
const int NB_ROWS = 10;
const int NB_COLUMN = 10;
const int WATER = 0;
int grid[NB_ROWS][NB_COLONN];
for (int i = 0; i < NB_ROWS; i++)
{
for (int j = 0; j < NB_COLONN; j++)
{
grid[i][j] = WATER;
cout << grid[i][j] << " ";
}
cout << endl;
}
return ??
}
You don't need to return anything if you pass the array by reference:
#include <array>
#include <iostream>
static const int NB_ROWS = 10;
static const int NB_COLUMN = 10;
static const int WATER = 0;
void InitializeGrid (std::array<std::array<int, NB_COLUMN>, NB_ROWS> &grid)
{
for (auto &row : grid)
{
for (auto &col : row)
{
col = WATER;
std::cout << col << " ";
}
std::cout << '\n';
}
}
int main()
{
std::array<std::array<int, NB_COLUMN>, NB_ROWS> grid;
InitializeGrid(grid);
}
btw, if your WATER is 0 it is sufficive to write
std::array<std::array<int, NB_COLUMN>, NB_ROWS> grid{};
to initialize all elements to zero.
I'm trying to write a function that calculates the sum of an array, but when i declare int size = 0; , the function runs 0 times because i=0 ; i
int arraChec(int arra[]) {
int size = 0;
int sum = 0;
for (int i = 0; i < size; i++) {
sum = sum + arra[i];
}
return sum;
}
int main() {
int arra1[7] = { 2,3,5,7,8,9,1 };
cout << arraChec(arra1) << endl;
system("pause");
}
Pass in the array size as a parameter:
#include <iostream>
int arraChec(int arra[], int size) {
int sum = 0;
for (int i = 0; i < size; i++) {
sum += arra[i];
}
return sum;
}
int main() {
int arra1[7] = { 2, 3, 5, 7, 8, 9, 1 };
std::cout << arraChec(arra1, 7) << std::endl;
}
Or use std::vector:
#include <iostream>
#include <vector>
int arraChec(std::vector<int>& arra) {
int sum = 0;
for (int i = 0; i < arra.size(); i++) {
sum += arra[i];
}
return sum;
}
int main() {
std::vector<int> arra1 = { 2, 3, 5, 7, 8, 9, 1 };
std::cout << arraChec(arra1) << std::endl;
}
If you are referring to some C style (sizeof(arra) / sizeof(*arra)) construct I suggest you refrain from using it.
You need to pass two arguments to the function--either the beginning of the array plus the size, or the beginning and (one past the) end, as is conventional in C++:
int arraChec(int* begin, int* end) {
int sum = 0;
for (int* it = begin; it < end; ++it) {
sum += *it;
}
return sum;
}
int main() {
int arra1[7] = { 2,3,5,7,8,9,1 };
cout << arraChec(std::begin(arra1), std::end(arra1)) << endl;
system("pause");
}
Of course, you can implement is using the standard library:
cout << std::accumulate(std::begin(arra1), std::end(arra1), 0) << endl;
Use std::array instead of fixed size C-style array.
#include <iostream>
#include <array>
#include <numeric>
using namespace std;
int main() {
array<int, 7> arr = { 2, 3, 5, 7, 8, 9, 1 };
cout << accumulate(arr.begin(), arr.end(), 0) << endl;
return 0;
}
Output
35
Read more about std::accumulate.
Another way not mentioned yet is:
template<size_t N>
int arraChec(int (&arra)[N]) {
int sum = 0;
for (size_t i = 0; i < N; i++) {
sum = sum + arra[i];
}
return sum;
}
Suppose I have an object
class Obj {
public:
int a;
int b;
int c;
}
And an array of objects
Obj o[N];
I want to copy each Obj.a into an int array and I know other languages allow me to make a function that might look like this in C++
int & fun(Obj os[], T key, int N){
int a[N];
for (int i=0; i<N; i++) {
a[i] = os[i].key;
}
return a;
}
Is there any reusable way to do this in C++? For reference, Obj's code can't be modified.
This is what the std::transform function is for. All you need to provide is a function to get the desired element from an Obj. This example shows how to do it with std::mem_fn:
#include <algorithm>
#include <functional>
#include <iterator>
#include <iostream>
struct Obj { int a, b, c; };
int main() {
Obj o[3] = {{1, 2, 3}, {11, 22, 33},{111, 222, 333}};
int a[3];
std::transform(std::begin(o), std::end(o),
std::begin(a),
std::mem_fn(&Obj::a));
for (auto e : a)
std::cout << e << ' ';
std::cout << std::endl;
};
Output:
1 11 111
This can all be wrapped up in a helper function to allow the caller to set the attribute to extract. But note if you really want a function to return an array, you'll need to use a copyable type such as std::array or std::vector. In C++ plain arrays are not copyable so can't be returned by value from a function.
Here's a slightly modified version of your code:
#include <cstddef>
#include <iostream>
using std::size_t;
struct Obj {
int a;
int b;
int c;
};
static void fun(const Obj *os, size_t N, int Obj::*const key) {
for (size_t i = 0; i < N; i++) {
std::cout << os[i].*key << '\n';
}
}
int main() {
Obj o[] = { {1, 2, 3}, {4, 5, 6} };
fun(o, sizeof o / sizeof o[0], &Obj::b);
}
I changed the return type of fun because your version doesn't typecheck. For demonstration purposes fun simply outputs the elements.
The key here is that you can abstract over class fields by using member pointers.
You can use pointer-to-member syntax:
#include <iostream>
#include <memory>
struct Obj {
int a;
int b;
};
std::unique_ptr<int[]>
fn(Obj* os, size_t N, int Obj::*member)
{
auto arr = std::make_unique<int[]>(N);
for (size_t i = 0; i < N; ++i) {
arr[i] = os[i].*member;
}
return arr;
}
int main() {
Obj os[] { { 1, 10 }, { 2, 20 } };
auto a1 = fn(os, 2, &Obj::a);
auto a2 = fn(os, 2, &Obj::b);
for (size_t i = 0; i < 2; ++i) {
std::cout << i << ": " << a1[i] << ", " << a2[i] << '\n';
}
}
Demo: http://ideone.com/cQMyh3
Or you could use a lambda.
#include <iostream>
#include <memory>
struct Obj {
int a;
int b;
};
std::unique_ptr<int[]>
fn(Obj* os, size_t N, std::function<int(const Obj&)> keyFn)
{
auto arr = std::make_unique<int[]>(N);
for (size_t i = 0; i < N; ++i) {
arr[i] = keyFn(os[i]);
}
return arr;
}
int main() {
Obj os[] { { 1, 10 }, { 2, 20 } };
auto a1 = fn(os, 2, [](const Obj& o){ return o.a; });
auto a2 = fn(os, 2, [](const Obj& o){ return o.b; });
for (size_t i = 0; i < 2; ++i) {
std::cout << i << ": " << a1[i] << ", " << a2[i] << '\n';
}
}
http://ideone.com/9OvTzl
Or the more generic:
template<typename KeyFn>
std::unique_ptr<int[]>
fn(Obj* os, size_t N, KeyFn keyFn)
{
auto arr = std::make_unique<int[]>(N);
for (size_t i = 0; i < N; ++i) {
arr[i] = keyFn(os[i]);
}
return arr;
}
Other changes to consider:
Use a standard container, e.g. vector or array to house your Obj's,
Consider passing iterators over the ranges rather than a pointer and a size,
Using range library you may simply do
for (int e : objs | ranges::v3::view::transform(&Obj::a)) {
std::cout << e << " ";
}
Demo
A possible transcription of your example in C++ could be:
#include <functional>
int* fun(Obj os[], std::function<int(Obj)> get_key, int N){
int* a = new int[N];
for (int i=0; i<N; i++) {
a[i] = get_key(os[i]);
}
return a;
}
Use:
func(os, [](Obj obj){return obj.a;}, N);
You must declare a dynamic array because the size is variable. But with a raw pointer, you may obtain memory leak or segmentation fault. A version with managed pointers (only working in C++14):
#include <memory>
#include <functional>
std::unique_ptr<int[]> fun(Obj os[], std::function<int(Obj)> get_key, int N){
std::unique_ptr<int[]> a = std::make_unique(N);
for (int i=0; i<N; i++) {
a[i] = get_key(os[i]);
}
return a;
}
Or with stl container (no memory allocation):
#include <vector>
#include <functional>
std::vector<int> fun(Obj os[], std::function<int(Obj)> get_key, int N){
std::vector<int> a(N);
for (int i=0; i<N; i++) {
a[i] = get_key(os[i]);
}
return a;
}
But it's often a bad idea to "translate" from one language to another ;)