I am coding for the Ludum Dare right now and I was trying to make a separate class that would give me an array as the return type of a function. I have an array set up, but I can't figure out how to make the return type an array so that I can use it in the main function. How would I go about returning an array and setting a variable in the main.cpp to that array?
Here are a couple of examples, each with their own advantages:
#include <iostream>
// C++11 #include <array>
#include <vector>
void myVectorFunc1(std::vector<int>& data)
{
for (unsigned i = 0; i < data.size(); ++i)
data[i] = 9;
data.push_back(1);
data.push_back(2);
data.push_back(3);
}
std::vector<int> myVectorFunc2(void)
{
std::vector<int> data;
data.push_back(1);
data.push_back(2);
data.push_back(3);
return data;
}
/* C++ 11
template<std::size_t S>
void myArrayFunc1(std::array<int, S>& arr)
{
for (auto it = arr.begin(); it != arr.end(); ++it)
*it = 9;
}
std::array<int,5> myArrayFunc2(void)
{
std::array<int,5> myArray = { 0, 1, 2, 3, 4 };
return myArray;
}
*/
int main(int argc, char** argv)
{
// Method 1: Pass a vector by reference
std::vector<int> myVector1(10, 2);
myVectorFunc1(myVector1);
std::cout << "myVector1: ";
for (unsigned i = 0; i < myVector1.size(); ++i)
std::cout << myVector1[i];
std::cout << std::endl;
// Method 2: Return a vector
std::vector<int> myVector2 = myVectorFunc2();
std::cout << "myVector2: ";
for (unsigned i = 0; i < myVector2.size(); ++i)
std::cout << myVector2[i];
std::cout << std::endl;
/* C++11
// Method 3: Pass array by reference
std::array<int, 3> myArray1;
std::cout << "myArray1: ";
myArrayFunc1(myArray1);
for (auto it = myArray1.begin(); it != myArray1.end(); ++it)
std::cout << *it;
std::cout << std::endl;
// Method 4: Return an array
std::cout << "myArray2: ";
std::array<int,5> myArray2 = myArrayFunc2();
for (auto it = myArray2.begin(); it != myArray2.end(); ++it)
std::cout << *it;
std::cout << std::endl;
*/
return 0;
}
# include <iostream>
int * func1()
{
int* array = (int *)malloc(sizeof(int) * 2);
array[0] = 1;
array[1] = 5;
return array;
}
int main()
{
int * arrayData = func1();
int len = sizeof(arrayData)/sizeof(int);
for (int i = 0; i < len; i++)
{
std::cout << arrayData[i] << std::endl;
}
}
Please check https://stackoverflow.com/a/5503643/1903116 to know why not to do this. and quoting from that answer
Functions shall not have a return type of type array or function,
although they may have a return type of type pointer or reference to
such things.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1905.pdf Page 159 - Section 6
Related
This question already has answers here:
How to return an array from a function?
(5 answers)
Closed 2 years ago.
Why is it necessary to define an array as a global variable when returning an array in a function?
int v[10] = { 1,2,3,44,55,66,77,8,9,1 };
auto fun()->int(*)[10]
{
//int v[10] = { 1,2,3,44,55,66,77,8,9,1 };/
return &v;
}
int main()
{
auto t = fun();
for (int i = 0; i <= 10; i++)
cout << (*t)[i] << endl;
}
First, your code is C++ and not C, so I'll respond accordingly.
You can return a C++-style std::array, which is an object rather than a C-style array and thus can be returned by value:
#include <iostream>
#include <array>
int v[10] = { 1,2,3,44,55,66,77,8,9,1 };
auto fun()->std::array<int, 10>
{
std::array<int, 10> v;
v[0] = 5;
v[1] = 32;
//int v[10] = { 1,2,3,44,55,66,77,8,9,1 };/
return v;
}
int main()
{
auto v = fun();
for(size_t i = 0; i < 10; i++) {
std::cout << v[i] << std::endl;
}
}
You could have dynamically allocated the array instead, in which case you return a pointer and the caller is responsible for freeing it:
auto fun2()->int*
{
auto v = new int[10];
v[0] = 1;
// assign other elements
return v;
}
int main()
{
auto t2 = fun2();
for (int i = 0; i < 10; i++)
std::cout << t2[i] << std::endl;
delete[] t2;
}
You're simply not allowed to allocate the array on the stack and then return it, because the lifetime of stack variables is over as soon as your function returns. With that said, this example is valid because the array is allocated in main's stack frame and outlives all of its uses:
void fillIn(int* ar, size_t len) {
for (size_t i = 0; i < len; i++) {
ar[i] = 32; // or whatever logic you want
}
}
int main()
{
int x[10];
fillIn(x, 10);
for (int i = 0; i < 10; i++) {
std::cout << x[i] << std::endl;
}
}
I got stuck in many problems where I was trying to store values in 2D vectors.
So I have written this simple code.
I am just storing and printing my values :
int main()
{
vector<vector<int>> vec;
vector<int> row{1,3,5,7,9,12,34,56};
int i,n,m,rs,vs;
rs=row.size();
cout<<"rs = "<<rs<<endl;
for(i=0;i<(rs/2);i++)
{
vec[i].push_back(row.at(i));
vec[i].push_back(row.at(i+4));
}
vs=vec.size();
cout<<vs<<endl;
for(n=0;n<vs;n++)
{
for(m=0;m<2;m++)
{
cout<<vec[n][m]<<" ";
}
cout<<endl;
}
return 0;
}
First you should read Why is “using namespace std;” considered bad practice?.
Declare variables when you use them and not at the beginning of your program.
The vector vec is empty at the beginning. In the loop
for(i=0;i<(rs/2);i++)
{
vec[i].push_back(row.at(i));
vec[i].push_back(row.at(i+4));
}
you are taking a reference to the i-th element in vec with
vec[i]
but this element does not exist. This is undefined behavior and can result in a segmentation fault. You can fix it by constructing the vector with the needed elements
#include <iostream>
#include <vector>
int main()
{
std::vector<int> row{1,3,5,7,9,12,34,56};
int rs = row.size();
std::vector<std::vector<int>> vec(rs / 2);
std::cout << "rs = " << rs << '\n';
for(int i = 0; i < rs / 2; ++i)
{
vec[i].push_back(row.at(i));
vec[i].push_back(row.at(i + 4));
}
int vs = vec.size();
std::cout << vs << '\n';
for(int n = 0; n < vs; ++n)
{
for(int m = 0; m < 2; ++m)
{
std::cout << vec[n][m] << " ";
}
std::cout << '\n';
}
return 0;
}
In this example the line
std::vector<std::vector<int>> vec(rs / 2);
constructs a vector containing rs / 2 default constructed elements. Alternatively you can start with an empty vector and push back elements in the loop
#include <iostream>
#include <vector>
int main()
{
std::vector<int> row{1,3,5,7,9,12,34,56};
int rs=row.size();
std::vector<std::vector<int>> vec;
std::cout << "rs = " << rs << '\n';
for(int i = 0; i < rs / 2; ++i)
{
vec.push_back({row.at(i), row.at(i+4)});
//
// is similar to:
// vec.push_back({});
// vec.back().push_back(row.at(i));
// vec.back().push_back(row.at(i+4));
//
// is similar to:
// vec.push_back({});
// vec[i].push_back(row.at(i));
// vec[i].push_back(row.at(i+4));
}
int vs = vec.size();
std::cout << vs << '\n';
for(int n = 0; n < vs; ++n)
{
for(int m = 0; m < 2; ++m)
{
std::cout << vec[n][m] << " ";
}
std::cout << '\n';
}
return 0;
}
I recommend the first solution. It's better to allocate memory for all elements and work with it instead of allocate memory in each loop iteration.
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.
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 ;)
The idea of the program is to input elements in an array. Then give the integer 'x' a value. If 'x' is 3 and the array a[] holds the elements {1,2,3,4,5,6}, we must "split" a[] into two other arrays. Lets say b[] and c[].
In b[] we must put all values lower or equal to 3 and in c[] all values greater than 3.
My question is- How can i express the 3 elements in b[i]?
#include <iostream>
using namespace std;
int main()
{
int a[6];
int b[6];
int c[6];
int d;
for (int i = 0; i < 6; i++) {
cin >> a[i];
}
cin >> d;
for (int i = 0; i < 6; i++) {
if (d >= a[i]) {
b[i] = a[i]; // if d is 3, then i have 3 elements. How can i express them?
}
}
for (int i = 0; i < 6; i++) {
if (d< a[i]) {
c[i] = a[i];
}
}
for (int i = 0; i < 3; i++) {
cout << b[i];
}
cout << endl;
for (int i = 3; i < 6; i++) {
cout << c[i];
}
return 0;
}
I think all you're trying to do is have a way to determine how many int values you're copying from a[] to either b[] or c[]. To do that, introduce two more counters that start at zero and increment with each item copied to the associated array:
Something like this:
#include <iostream>
using namespace std;
int main()
{
int a[6];
int b[6], b_count=0; // see here
int c[6], c_count=0; // see here
int d;
for (int i = 0; i < 6; i++) {
cin >> a[i];
}
cin >> d;
for (int i = 0; i < 6; i++) {
if (d >= a[i]) {
b[b_count++] = a[i]; // see here
}
}
for (int i = 0; i < 6; i++) {
if (d< a[i]) {
c[c_count++] = a[i]; // see here
}
}
for (int i = 0; i < b_count; i++) { // see here
cout << b[i];
}
cout << endl;
for (int i = 3; i < c_count; i++) { // and finally here
cout << c[i];
}
return 0;
}
Now, if you want b[] or c[] to be dynamic in their space allocation, then dynamic-managed containers like st::vector<> would be useful, but I don't think that is required for this specific task. Your b[] and c[] are already large enough to hold all elements from a[] if needed.
WhozCraigs answer does a good job showing what you need to solve this using traditional arrays according to your tasks requirements.
I'd just like to show you how this can be done if you were allowed the full arsenal of the standard library. It is why people are calling for you to use std::vector. Things gets simpler that way.
#include <algorithm>
#include <iostream>
int main()
{
int a[6] = {1, 2, 3, 4, 5, 6 }; // Not using input for brevity.
int x = 3; // No input, for brevity
// Lets use the std:: instead of primitives
auto first_part = std::begin(a);
auto last = std::end(a);
auto comparison = [x](int e){ return e <= x; };
auto second_part = std::partition(first_part, last, comparison);
// Print the second part.
std::for_each(second_part, last, [](int e){ std::cout << e; });
// The first part is first_part -> second_part
}
The partition function does exactly what your problem is asking you to solve, but it does it inside of the array a. The returned value is the first element in the second part.
use std::vectors. do not use int[]s.
with int[]s (that are pre-c++11) you could, with a few heavy assumptions, find array length with sizeof(X)/sizeof(X[0]); This has, however, never been a good practice.
in the example you provided, probably you wanted to:
#define MAX_LEN 100
...
int main() {
int a[MAX_LEN];
int b[MAX_LEN];
int c[MAX_LEN];
int n;
std::cout << "how many elements do you want to read?" << std::endl;
std::cin >> n;
and use n from there on (these are common practice in programming schools)
Consider a function that reads a vector of ints:
std::vector<int> readVector() {
int n;
std::cout << "how many elements do you want to read?" << std::endl;
std::cin >> n;
std::vector<int> ret;
for (int i=0; i<n; i++) {
std::cout << "please enter element " << (i+1) << std::endl;
int el;
std::cin >> el;
ret.push_back(el);
}
return ret;
}
you could use, in main, auto a = readVector(); auto b = readVector(); a.size() would be the length, and would allow to keep any number of ints
Here's an example of how you'll approach it once you've a little more experience.
Anything you don't understand in here is worth studying here:
#include <iostream>
#include <vector>
#include <utility>
std::vector<int> get_inputs(std::istream& is)
{
std::vector<int> result;
int i;
while(result.size() < 6 && is >> i) {
result.push_back(i);
}
return result;
}
std::pair<std::vector<int>, std::vector<int>>
split_vector(const std::vector<int>& src, int target)
{
auto it = std::find(src.begin(), src.end(), target);
if (it != src.end()) {
std::advance(it, 1);
}
return std::make_pair(std::vector<int>(src.begin(), it),
std::vector<int>(it, src.end()));
}
void print_vector(const std::vector<int>& vec)
{
auto sep = " ";
std::cout << "[";
for (auto i : vec) {
std::cout << sep << i;
sep = ", ";
}
std::cout << " ]" << std::endl;
}
int main()
{
auto initial_vector = get_inputs(std::cin);
int pivot;
if(std::cin >> pivot)
{
auto results = split_vector(initial_vector, pivot);
print_vector(results.first);
print_vector(results.second);
}
else
{
std::cerr << "not enough data";
return 1;
}
return 0;
}
example input:
1 2 3 4 5 6
3
expected output:
[ 1, 2, 3 ]
[ 4, 5, 6 ]