How can i return an array c++? - c++

I am trying to generate some lotto numbers and return the array that contain these numbers but I cant go any further; Help please
void getLotto(int rad[7]) {
int numbers[7];
for (int i = 0; i < 7; i++) {
numbers[i] = rand() % 35 + 1;
}
for (int j = 0; j < 7; j++) {
int n = rand() % 35 + 1;
if (n == numbers[j]) {
numbers[j] = rand() % 35 + 1;
return;
}
}
}

Arrays can't be returned by functions. A common thing to do is to dynamically allocate the array and return a pointer to its first element. This will work in your case but will generate a requirement for the caller to manage the memory (delete[] the new[]'ed memory). That's why C++ provides us with standard array classes: Use and return a std::vector. If you have C++11 support, return std::array.

Following may help, using Fisher–Yates_shuffle:
// Fisher–Yates_shuffle
// http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
std::vector<int> FisherYatesShuffle(std::size_t size, std::size_t max_size, std::mt19937& gen)
{
assert(size < max_size);
std::vector<int> res(size);
for(std::size_t i = 0; i != max_size; ++i) {
std::uniform_int_distribution<> dis(0, i);
std::size_t j = dis(gen);
if (j < res.size()) {
if (i != j) {
res[i] = res[j];
}
res[j] = 1 + i;
}
}
return res;
}
Live example

std::vector and std::array are better than regular arrays, but if you want to use regular arrays you can modify your function as follows:
// Arguments: renamed the array, added N (# of array elements)
void getLotto(int numbers[], size_t N) {
//int numbers[7]; // commented out local variable
for (int i = 0; i < N; i++) {
numbers[i] = rand() % 35 + 1;
}
for (int j = 0; j < N; j++) {
int n = rand() % 35 + 1;
if (n == numbers[j]) {
numbers[j] = rand() % 35 + 1;
return;
}
}
}
The brackets in int numbers[] indicates that the argument is an array, and what is actually passed is a pointer to the first element of the array. Modifying numbers in getLotto() modifies the array passed to the function.
The second argument is of type size_t because it is the platform-dependent alias for the unsigned integral type used by your system to represent the size of objects (like arrays).
This isn't as safe in that the function has to trust that numbers actually has N elements, but this is how you have a function modify a regular array instead of a container like std::vector.
You would call the function like this:
size_t N;
int numbers[N];
getLotto(numbers, N);

C++ does not allow to return an entire array as an argument to a function. However, you can return a pointer to an array by specifying the array's name without an index.
If you want to return a single-dimension array from a function, you would have to declare a function returning a pointer as in the following example:
int * myFunction()
{
.
.
.
}
Second point to remember is that C++ does not advocate to return the address of a local variable to outside of the function so you would have to define the local variable as static variable.
Now, consider the following function, which will generate 10 random numbers and return them using an array and call this function as follows:
#include <iostream>
#include <ctime>
using namespace std;
// function to generate and retrun random numbers.
int * getRandom( )
{
static int r[10];
// set the seed
srand( (unsigned)time( NULL ) );
for (int i = 0; i < 10; ++i)
{
r[i] = rand();
cout << r[i] << endl;
}
return r;
}
// main function to call above defined function.
int main ()
{
// a pointer to an int.
int *p;
p = getRandom();
for ( int i = 0; i < 10; i++ )
{
cout << "*(p + " << i << ") : ";
cout << *(p + i) << endl;
}
return 0;
}
When the above code is compiled together and executed, it produces result something as follows
624723190
1468735695
807113585
976495677
613357504
1377296355
1530315259
1778906708
1820354158
667126415
*(p + 0) : 624723190
*(p + 1) : 1468735695
*(p + 2) : 807113585
*(p + 3) : 976495677
*(p + 4) : 613357504
*(p + 5) : 1377296355
*(p + 6) : 1530315259
*(p + 7) : 1778906708
*(p + 8) : 1820354158
*(p + 9) : 667126415

There are two main ways of accomplishing this.
note: I'm not sure what your second for loop is doing. I guess the intention was to ensure that the numbers are all unique? You might want to take a look at it as that is not what it is doing.
For the purposes of this question, I've cut it down to just generating the random numbers to populate the array.
The first is to take your code and fix it to put the generated numbers into the array that was passed in:
#include <iostream>
void getLotto(int numbers[7]) {
for (int i = 0; i < 7; i++)
{numbers[i] = rand() % 35 + 1;}
return;
}
int main()
{
srand(time(0));
int lotto_numbers[7];
getLotto(lotto_numbers);
for (int i = 0; i < 7; i++)
{std::cout<<lotto_numbers[i]<<std::endl;}
}
numbers isn't actually passed in as an int[] but instead as an int* pointing to the array. This means that any changes you make to it in the function are changed in the original data.
Bear in mind that you need to keep track of your array bounds though, as the array could be defined as
int lotto_numbers[6]
which means that
numbers[7]
would be out of bounds.
The second method is to create the array on the heap. This means that you don't need to pass in an array but you can instantiate it in the function
I'm not actually going to provide the code for this here. Mainly because for something simple like this, the memory management is more trouble than it is worth. (you need to remember to call delete[] for everything created on the heap etc).
Instead, lets use something with memory management built in:
#include <iostream>
#include <vector>
std::vector<int> getLotto() {
std::vector<int> numbers;
numbers.reserve(7);
for (int i = 0; i < 7; i++) {
//numbers[i] = rand() % 35 + 1;
//would work, but is unsafe as you could potentially reference somthing out of range
//this is safer:
numbers.push_back(rand() % 35 + 1);
}
return numbers;
}
int main()
{
srand(time(0));
std::vector<int> lotto_numbers = getLotto();
for (auto i = lotto_numbers.begin(); i != lotto_numbers.end(); i++)
{
std::cout<<*i<<std::endl;
}
}
The vector handles the memory management for you. The vector can be returned, and the returned vector will still point at the allocated memory on the heap we have just populated. We don't need to free it as this will be done automatically when the vector goes out of scope.

Related

My question is about array.How do we store even numbers in an array without initializing array at first and store them in consecutive memory locations

Write a C++ program to Input 6 even numbers in an array and then
display them one by one.
I wrote this C++ program:
#include <iostream>
using namespace std;
int main() {
int num[6];
int i, ;
for (i = 1; i <= 12; i++) {
if (i % 2 == 0) {
num[i] = i;
cout << num[i] << endl;
}
}
return 0;
But the mistake here is I have to store all the even values in consecutive memory locations like num[1], num[2], num[3] to num[5] but with this method the values will store in even arrays only like num[2], num[4], num[6], etc.
What could be the real solution? My scope is only in C++.
This for loop
for(i=1;i<=12;i++)
{
if(i%2==0)
{
num[i]=i;
cout<<num[i]<<endl;
}
}
is incorrect because there is used an invalid index to access elements of the array. For example when i is equal to 12 you are trying to access 13-th element of the array that does not exist (indices in C++ start from 0).
Just write
for( i = 0; i < 6; i++ )
{
num[i] = 2 * ( i + 1 ) ;
cout<<num[i]<<endl;
}
Pay attention to that it is a bad programming practice to use magic numbers as 6. Instead you should introduce a named constant.
If your compiler supports C++ 20 then you could write for example using the range-based for loop
const size_t N = 6;
int num[N];
for ( int value = 1; auto &item : num )
{
item = 2 * value++;
}
If your compiler does not support C++ 20 then just place the declaration of the variable value before the range-based for loop
const size_t N = 6;
int num[N];
int value = 1;
for ( auto &item : num )
{
item = 2 * value++;
}

Pointer Indexing: Getting Unexpected Values

#include <iostream>
using namespace std;
int* computeSquares(int& n)
{
int arr[10];
n = 10;
for (int k = 0; k < n; k++)
arr[k] = (k + 1) * (k + 1);
return arr;
}
void f()
{
int junk[100];
for (int k = 0; k < 100; k++)'
junk[k] = 123400000 + k;
}
int main()
{
int m;
int* ptr = computeSquares(m);
f();
for (int i = 0; i < m; i++) {
cout << ptr[i] << ' ';
}
}
The above code should print:
1 4 9 16 25 36 49 64 81 100
However, it instead prints random integer values that don't make any sense, at least after the first one. After running the code through the debugger, the ptr address is deleted right after the first run of the for loop in the main method and I cannot fathom why. Additionally, I have no idea what the purpose of the f() method is, I don't think it should change anything but when I remove it from the main the first value returns accurately (everything after is still wrong.) What is going on?
Try this:
int *computeSquares(int &n) {
int *arr = new int[10];
n = 10;
for (int k = 0; k < n; k++)
arr[k] = (k + 1) * (k + 1);
return arr;
}
The memory of "int arr[10]" is released after computeSquares finished running.
You are getting this result because you are misunderstanding basic language features. In addition to MsrButterfly's answer, who pointed out the most important problem already, let me please give you the following advices:
forget about using raw pointers; it is dangerous practice, very hard to maintain and extend, and will for sure lead you to write code with memory leaks. You will be better off having a look at some STL documentation which possesses e.g. the std::vector container that you could use instead of your array arr
your computeSquares method is dangerous in the sense that you take a variable n a argument which should be your array's size. In your method, you first define arr with a hard-coded size of 10 and then you set n = 10; I'd suggest you avoid that kind of constructs as you have in this case to maintain two variables that depend on that number 10.

Convert multiple vectors to array, or return them (c++)

In order to get more familiar with C++, I have started working on some algebraic problems. Now, I have created an algorithm which generate a combination of numbers, with some constraints, based on an input number:
void abc(const int n) {
std::vector<int> aOut, bOut, cOut; // creating vectors to store values (dynamic int arrays)
for (int a = 9; a <= n - 2; a++) {
for (int b = a + 1; b <= n - 1; b++) {
for (int c = b + 1; c <= n; c++) {
aOut.push_back(a);
bOut.push_back(b);
cOut.push_back(c);
// std::cout << "a = " << a << " b = " << b << " c = " << c << std::endl;
}
}
}
Now, I need to continue working with these vectors, so I need to return them somehow. I have tried to create an int array of the size: int ABC[N][3], where const int N = cOut.size();. This does not work, as N is not accepted as a constant.
I also tried making a counter in the loop where I generate the vectors, which I then transferred to a string which I then transferred to a constant integer - this did not work either.
I tried making a pointer to a constant int, and using it to change the constant in the loop, which did not work either.
I even found a way to calculate the size based on my loops:
const int n = 20;
const int n1 = n - 10; // Manipulating input
const int N = n1*(n1 + 1)*(n1 + 2) / 6; // Size of vectors
And then passing the value to the function as:
void abc(const int n, const int N) { // same code as before }
But nothing works. I am honestly out of ideas (and losing my head). I have browsed trough the forum and google, but without luck. If someone could point me in the right direction, I would be forever grateful.
Of cause the solution includes changing the void to a function that returns the parameters. I added the void as I would like to check if the values were printed correctly.
How about creating an element (container) which encapsulates your 3 vectors as a return element?
The problem you're having is that functions (like Mathemematicians want to) return one value, but this can be any value :).
You could use a class or a struct which will has the vectors as attributes:
struct returnElement { // choose an adequate name
std::vector<int> aOut, bOut, cOut;
};
so now your abc function would return the returnElement struct. It could look something like this:
returnElement abc (const int n) {
returnElement ret; // creating vectors to store values (dynamic int arrays)
for (int a = 9; a <= n - 2; a++) {
for (int b = a + 1; b <= n - 1; b++) {
for (int c = b + 1; c <= n; c++) {
ret.aOut.push_back(a);
ret.bOut.push_back(b);
ret.cOut.push_back(c);
}
}
return ret;
}
Why not have an std::array of std::vector?
std::array<std::vector<int>, 3> abc(int const n)
{
std::array<std::vector<int>, 3> outArray;
for (int a = 9; a <= n - 2; a++)
{
for (int b = a + 1; b <= n - 1; b++)
{
for (int c = b + 1; c <= n; c++)
{
outArray[0].push_back(a);
outArray[1].push_back(b);
outArray[2].push_back(c);
}
}
}
return outArray;
}
To answer your question concerning array sizes,
I have tried to create an int array of the size: int ABC[N][3], where const int N = cOut.size();. This does not work, as N is not accepted as a constant.
The size of an array (whether raw or std::array) must be compile-time constant. If the size is not known at compile-time you must either create a dynamic array (using new) or use an std::vector.
If you know how large the vector is to be, you can reserve space in it for your elements, like so:
std::vector<int> yourVec;
yourVec.reserve(100); // reserve space for 100 ints
or
std::vector<int> yourVec;
yourVec.resize(100, 0); // populates yourVec with 100 ints with value 0
See Choice between vector::resize() and vector::reserve() for the differences between reserve and resize.

Passing integers to arrays within functions (without pointers)

I'm trying to create a magic square that will print four different grid sizes (5x5, 7x7, 9x9, 15x15). The error I'm having is the array magsquare within the function tells me it needs a constant integer. (I can't use pointers) This is a class assignment.
#include <iostream>
#include <iomanip>
using namespace std;
void magicSquare(int n){
int magsquare[n][n] = { 0 }; /*THIS is the error with [n][n]*/
int gridsize = n * n;
int row = 0;
int col = n / 2;
for (int i = 1; i <= gridsize; ++i)
{
magsquare[row][col] = i;
row--;
col++;
if (i%n == 0)
{
row += 2;
--col;
}
else
{
if (col == n)
col -= n;
else if (row < 0)
row += n;
}
}
for (int i = 0; i < n; i++){
for (int j = 0; j < n; j++){
cout << setw(3) << right << magsquare[i][j];
}
cout << endl;
}
}
int main(){
int n = 5;
magicSquare(n);
return 0;
}
Indentation may look incorrect, but it's right. Sorry.
The failure is because standard C++ cannot allocate dynamically sized array on the stack, as you are trying to do.
int magsquare[n][n];
As far as magicSquare is concerned n is only known at runtime and for an array to be allocated on the stack it's size must be known at compile time.
Use a 15 x 15 array.
int magsquare[15][15];
As long as you know this is the largest you'll ever need, you should be ok.
Alternatives (which you've already said you can't use)
Use new to declare a 2d array of the required dimensions. (Remember to delete[] it though)
Use std::vector
It may also be a good idea to add a check that n values over 15 or under 1 are rejected, otherwise you'll face undefined behaviour if any values outside of 1-15 are passed into the function.

Filling an array with integers

I'm trying to fill an array with numbers 1111 to 8888, with each integer in the number being between 1 and 8 in c++. However, when I run it, it's only outputting large negative numbers indicating an error. I honestly have clue what the error is so it would be appreciated if you could help me out. Thanks!
int fillArray()
{
int arrayPosition;
int guesses[4096];
arrayPosition = 0;
for (int i = 1; i <= 8; i++)
for (int j = 1; j <= 8; j++)
for (int k = 1; k <= 8; k++)
for (int m = 1; m <= 8; m++)
{
guesses[arrayPosition] = ((i * 1000) + (j * 100) + (k *10) + m);
cout << guesses[arrayPosition];
arrayPosition++;
}
return guesses[4096];
}
Your return type is wrong. int fillArray(), but you're trying to return an int[4096] that was declared on the stack... What you're actually doing with return guesses[4096]; is returning the first memory location after your array in memory, which is probably just garbage, hence your issue with large negative numbers.
You can fix it by allocating your array in the heap, and returning a pointer to the start of that array:
int * fillArray()
{
int arrayPosition;
int * guesses = new int[4096];
// other stuff stays the same...
return guesses;
}
However, since your function is called fillArray, it would make more sense to pass in an array and fill it rather than creating the array in the function. (If you wanted to do that, might call it something like make_1_to_8_array instead, to make it more clear that you're constructing something that will need to be deleted later.) Giving an int* as the first argument would allow you to pass in the base address of your array that you want filled:
void fillArray(int * guesses)
{
int arrayPosition;
// other stuff stays the same...
}
Or, if you want to verify that the you're using an array of the exact size:
void fillArray(int (&guesses)[4096])
{
int arrayPosition;
// other stuff stays the same...
}
Note that the function now returns void since you just update the array that was passed in, and you don't need to return anything new.
Your for-loops look correct, but your array handling is off, as is highlighted by other answers.
It is more usual in C++ to use std::vector and to pass this in by reference as an argument. This saves you having to handle memory allocations and deallocations. Here's an example, including the output in the for-loops:
#include <iostream>
#include <vector>
int fillArray(std::vector<int>& guesses)
{
for (int i = 1; i <= 8; i++)
for (int j = 1; j <= 8; j++)
for (int k = 1; k <= 8; k++)
for (int m = 1; m <= 8; m++)
{
guesses.push_back((i * 1000) + (j * 100) + (k * 10) + m);
std::cout << guesses.back() << std::endl;
}
return guesses.back();
}
int main()
{
std::vector<int> guesses;
std::cout << fillArray(guesses) << std::endl;
}
You are creating your array locally then attempting to return it. If you try printing (to debug) out the result of your array prior to returning, you will see it is ok. However, once you return, the array is no linger valid. Try passing in an array into your function instead.