Recursion differences in backtracking with a global value? - c

Taking this as an example:
bool SolveSudoku(int grid[N][N])
{
int row, col;
// If there is no unassigned location, we are done
if (!FindUnassignedLocation(grid, row, col))
return true; // success!
// consider digits 1 to 9
for (int num = 1; num <= 9; num++)
{
// if looks promising
if (isSafe(grid, row, col, num))
{
// make tentative assignment
grid[row][col] = num;
// return, if success, yay!
if (SolveSudoku(grid))
return true;
// failure, unmake & try again
grid[row][col] = UNASSIGNED;
}
}
return false; // this triggers backtracking
}
The grid is always passed as a parameter to the recursive call, so there is a new copy of the grid in each iteration.
I can't seem to conceptualize if there is any difference on working with a global grid, using the same logic.
After a failure condition, the variable is set to "unmake & try again"- shouldn't this take care of any "undoing" in backtracking?
What difference would there be in this recursive backtracking if the grid was a global, why send and extra copy each time?

The grid is always passed as a parameter to the recursive call, so
there is a new copy of the grid in each iteration.
No, there is a new copy of the reference (pointer) to the grid in each iteration. The actual work is done on the same grid over and over.
Have a look at this code snap for example:
#include <stdlib.h>
#include <stdio.h>
void foo(int arr[], int n) {
arr[0] = 1;
}
int main() {
int myArray[5] = {0,0,0,0,0};
foo(myArray,5);
printf("%d",myArray[0]);
return 0;
}
Note that no copy was made, and a change to arr in foo() was reflected to myArray.
Once this is clear, I believe it automatically answers the rest of your questions (It is basically the same as working with global, but global variables are usually bad practice, sending the reference to the array is a better practice).

In C/C++ arrays are passed as pointers to the beginning of array. Take a look at this example:
#include <iostream>
static const int N = 10;
void test(int a[N][N])
{
std::cout << a << std::endl;
}
int main(int argc, char **argv)
{
int a[N][N];
std::cout << a << std::endl;
test(a);
return 0;
}
If you run it you will get the same value printed on stdout:
$ ./test
0x7fff0c669930
0x7fff0c669930
That's the value of a pointer to the beginning of the array, so the same pointer is used in main() and test().
This means you would not get any performance gain by letting the grid be a global variable. Instead you would loose modularity by introducing a global.

Related

How to pass the user value for the size of an array into a function implemented in another code file?

I have no idea what to do. Whenever I try to insert read_num[size] it does not work. My debugger shows the value as 0. I want to take a value for the size of the array from the user. Then I want to use the value in another file.
So what I want to do is, I will do a printf to ask the user to give a value so that I can pass it as the size of the array. I did and it didn't work. Then I decided to write a direct value [36]. But I want user to insert 36.
This is what I have tried:
main.c
int main(void)
{
int numbers[ARR_SIZE] = { 0 };
int size = 36; // I am doing directly but I want to take the value from the user but it just does not work.
double mean = 0;
double stddev = 0;
read_array(size);
}
file.c
int read_array(int a[36]) //placing 36 directly, I want it to be placed by the user
{
int num_read[36]; int i = 0; // I have no clue whats i am doing. I just want to pass the value from the user.
while (i < a)
{
printf("Enter number");
scanf_s("%d", &num_read[i]);
++i;
}
}
header file
#include <stdio.h>
#include <math.h>
#define ARR_SIZE 100
int read_array(int arr[ARR_SIZE]);
double calc_mean(int arr[], int size);
double calc_stddev(int arr[], int size);
void print_array(int arr[], int size);
In you main.c file you want to decide the value of size and use that value in a call to the function read_array().
You do so by calling read_array(size);, which makes sense to me.
Sadly your shown code lacks the details of whether or not you include your header file (and others). I assume that it does.
However, if what you are doing inside main() is actually what you want to do (I assume so), then the header file and the implementation of read_array() does not match that intention.
This int read_array(int arr[ARR_SIZE]), in your header and your implementation, means
"Dear compiler, this function takes an array (or a pointer to 100 consecutive ints)."
That does not match your plan of "I will give a single int as the parameter to the function."
To match that plan, use a prototype of int read_array(int a);.
The implementation code as shown should then work.
If you want the local array to actually be of the size given by the user and arriving via the parameter a, then change
int num_read[36]; to int num_read[a];.
However, I suspect that you then intend to return the array which you filled with input from the user.
That is neither possible with a prototype of int read_array(int a); nor with one of int read_array(int arr[ARR_SIZE]);. Both mean "This function will return a single int.".
I assume you will need help with that, but you need to ask a separate question on how to return a new array from a C function - or better first search StackOverflow for a duplicate.
To pass the size of the array to the function (it does not matter if it is defined in the same or another compilation units) you need to have an additional parameter to the function. There is no other way of doing it in C language
int *doSomethingWithArray(int *array, size_t size)
{
/* ... */
}
But I want user to insert 36.
The user can only enter something using I/O functions and has no access to the C code.
int *initArray(int *array, const size_t size)
{
for(size_t index = 0; index < size; index ++)
array[index] = rand();
return array;
}
int *printArray(int *array, const size_t size)
{
for(size_t index = 0; index < size; index ++)
printf("array[%3zu] = %d\n", index, array[index]);
return array;
}
int main(void)
{
size_t array_size;
srand(time(NULL));
if(scanf("%zu", &array_size) == 1) // user enters the size of the array
{
int array[array_size];
initArray(array, array_size);
printArray(array, array_size);
}
}
https://godbolt.org/z/xjh9qGcrz

Passing an array from a method in file 1 to a method in file 2 without using a extra parameter in a method

I am getting all Zeroes in global_array_of_file2.Idea is to get the updated values from file1.c
========================file1.c===========================
#include <stdio.h>
#include <string.h>
int global_array_of_file1[10];
void func1(int a1,int b)
{
int array1_of_func1[10] = {0};
int a;
array1_of_func1[5] = 23;
array1_of_func1[6] = 34;
memcpy(global_array_of_file1,array1_of_func1,10*sizeof(int));
for (a = 0; a < 9; a++)
{
printf("from func_1 : global_array = %d \n " , global_array_of_file1[a]);
}
}
void init_pointer(int *tmp)
{
tmp = global_array_of_file1;
}
~
==========================file2.c======================
#include<stdio.h>
#include "file1.h"
int global_array_of_file2[10] = {0};
int main()
{
int i;
init_pointer(global_array_of_file2);
func1(3,4);
for(i = 0; i < 9 ; i++)
{
printf("global_array_of_file2 = %d \n" , global_array_of_file2[i]);
}
return 0;
}
========================file1.h===========================
void init_pointer(int *tmp);
void func1(int a,int b);
There are two issues here:
First issue is:
the code for init_pointer does nothing:
void init_pointer(int *tmp)
{
tmp = global_array_of_file1;
}
as tmp variable is a copy of the input variable (called by value), it does nothing.
To have it work correctly it should be something like this:
void init_pointer(int **tmp)
{
*tmp = global_array_of_file1;
}
However, as the global_array_of_file2 is declared as array, it is actually a static pointer which cannot be changed, so you cannot modify its value using statement like **tmp= global_array_of_file1.
Therefor to make it work, you should call memcpy within the init pointer method:
like this:
void init_pointer(int *tmp)
{
memcpy( tmp, global_array_of_file1, 10 * sizeof(int) );
}
The second issue, is that the code at main, first call the init_pointer (which does nothing), then it calls 'func1' which initialize the array. the order shall be the opposite. first call func1 to set the array with the appropriate values, then call the init_array method to copy this information to global array 2.
so instead of
init_pointer(global_array_of_file2);
func1(3,4);
it shall be
func1(3,4);
init_pointer(global_array_of_file2);
This is all if you want to have a copy of the global_array_file1 at file2.
If you want, you can have the same array shared between files, to do so:
at file1.h declare the array as extern:
extern int global_array_of_file1[10];
Then you can simply use it at file2.c which include file1.h
Ok I think this can be fixed easily by doing the below :
declare extern int global_array_of_file1[10] in file1.c
define int global_array_of_file1[10] = {0}; in file2.c
I then dont even need to initialize the pointer from file2.c ( no need to call init_pointer) and extra RAM too will be saved :) !
The memcpy is wrong. You just copy 10 bytes.
An int is usually 4 Bytes long (32 bit), thus you only copy parts of the array, namely the first ten bytes, thus you copy just the ints with index 0,1,2 and half of 4.
You need to copy 10 * sizeof(int)

Keep getting a Debug Assertion Failed! Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

I've been searching this problem for a couple days now and nothing I try seems to work. I'm getting it when my program ends, otherwise the program runs just fine so I "think" it has something to do with the Destructor. But I've tried looping through arrPtr and deleting all the elements first and it doesn't fix it. I'm using Visual Studio.
I'm just including a partial of my code. Basically the ComputerPlayer::computer takes in a 2D array that is declared and initialized in main. It then assigns it to an allocated array so that the rest of the Class functions can look at it and decide which element to change. Once it decides it makes a change to the allocated array pointer which changes the original array element in main.
I was hoping thinking the Destructor would "unallocate" the array once the program ended as I can't see where else to do it.
Thanks,
Mike
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
class ComputerPlayer
{
private:
static const int ROWS = 3; // holds # of array rows.
static const int COLS = 3; // Sets # of array columns.
char(*arrPtr)[COLS] = new char[ROWS][COLS]; // Dynamically allocate 2D array
bool isBlockOrWin();
void blockChoiceRow(int, int);
void blockChoiceCol(int, int);
void blockChoiceDiag(char);
void randomSelect();
void sendArrMod(int, int);
public:
ComputerPlayer();
~ComputerPlayer();
void computer(char(&)[ROWS][COLS]);
};
ComputerPlayer::ComputerPlayer()
{}
ComputerPlayer::~ComputerPlayer()
{
delete[] arrPtr;
}
void ComputerPlayer::computer(char (&temp)[ROWS][COLS])
{
// Assign the argument to the dynamically allocated array pointer.
arrPtr = temp;
if (isBlockOrWin())
{ }
else randomSelect();
}
void ComputerPlayer::sendArrMod(int r, int c)
{
cout << "The Computer 'c' selects: " << r + 1 << " " << c + 1 << endl;
arrPtr[r][c] = 'c'; //Modify the array in main with the computers choice.
}

Understanding strange return syntax: return(*scriptFunction[x])(arguments);

I know the title for this is horrendous and for this I am sorry; I honestly had no idea how to ask my question as I am not well educated on this matter. Below there is a small bit of code that my question concerns as I have NO idea what is going on or if it is even valid! Although, I suspect it is valid.
return(*scriptFunction[x])(arguments);
From my understanding, you can only return 1 value in C (you can have multiple return statements but that is different and off topic). What is the above statement actually doing?
The code:
return(*scriptFunction[x])(arguments);
actually is only returning one value.
The variable scriptFunction will be an array of function pointers(1). You look up element number x of that array, and call that function, passing the argument arguments. Then the return value from that function is what you return to your caller.
Other than the function pointer aspect, it's no different to return sqrt(42).
By way of example, the following program demonstrates how this can be done:
#include <stdio.h>
// Two simple functions which add a fixed value.
int fnPlus3 (int n) { return n + 3; }
int fnPlus7 (int n) { return n + 7; }
// An array holding those two functions.
int (*scriptFunction[])(int) = { fnPlus3, fnPlus7 };
int main (void) {
// Call first function in array.
int x = 0;
printf ("%d\n", (*scriptFunction[x])(100));
// Then call second one.
x = 1;
printf ("%d\n", (*scriptFunction[x])(100));
return 0;
}
Although it prints the return value from the function rather than returning it again, it still uses the same expression and you can see it calls a different function based on the value of x:
103
107
(1) Or some form of equivalent, such as a pointer to an array of function pointers, or a pointer to a single function pointer (assuming x is always set to zero in that latter case).
Presumably scriptFunction is an array of pointers to functions. *scriptfunction[x] is then the dereferenced pointer to function (the x-th one). Finally, *scriptfunction[x](arguments) represents the invocation of that function applied to arguments, so the result of that function is what's returned in the end.
Side comment: the * is not really necessary. A pointer to function does not need to be dereferenced to call the function, i.e. you can use
return scriptFunction[x](arguments);
instead.
From the looks of it, it seems the line return (*scriptFunction[x])(arguments); scriptFunction is an array of function pointers, and this is simply invoking the function at position indexed by variable x and sending arguments variable contents as its input.
The return value of this invoked function is what ultimately gets returned.
This working example should be useful:
#include <iostream>
using namespace std;
void func_a(int i)
{
cout << "func_a: " << i << endl;
}
void func_b(int i)
{
cout << "func_b: " << i << endl;
}
int main()
{
void (*funcs[])(int) = { func_a, func_b };
for(int i = 0; i < 2; ++i)
(*funcs[i])(i+1);
return 0;
}
The output is below:
➜ /tmp g++ test.cpp -o test
➜ /tmp ./test
func_a: 1
func_b: 2
Also, for future reference, you should consult: How to ask good questions?

Using variables from later function in main, C

I am having trouble getting the ROBX and ROBY variables to print in the main function. This is a small portion of my program and I do not know what I am doing wrong. Thanks!
#include <stdio.h>
#include <time.h>
#define ROW 8
#define COLUMN 8
int robot (int m[ROW][COLUMN], int ROBX, int ROBY);
int ROBX;
int ROBY;
int main(void)
{
printf("%d %d\n", ROBX, ROBY);
return 0;
}
int robot (int m[ROW][COLUMN], int ROBX, int ROBY)
{
// ensure different output each time program is run
srand ( time(NULL) );
// Pick a random spot to place the robot
int placed = 0;
int ROBX;
int ROBY;
while(placed == 0)
{
int t = rand() % ROW;
int y = rand() % COLUMN;
if(m[t][y] == 0)
{
m[t][y] = -2;
placed = 1;
ROBX = t;
ROBY = y;
}
return ROBX, ROBY;
}
}
There are several problems with your code.
For one thing, you never call robot, so none of those modifications to your variables are happening.
For another, you're not allowed to return multiple values from a function: The line return ROBX, ROBY; is NOT doing what you think it's doing.
Finally, your function doesn't make a lot of sense. You intend to pass in ROBX and ROBY as parameters. That won't work the way you think it will, but it's not a terrible idea in general. But when you create local variables also called ROBX and ROBY. As commenters have noted, that will hide both the global variables and the parameters, so you end up only modifying those locally-defined variables.
There are two ways you can fix this:
Don't create local variables and don't pass parameters. Just modify the global variables directly.
Still don't create local variables, and make your function accept two int * parameters. This will allow you to pass in the global variables when you call robot, so you can modify those parameters in a persistent way. See this question for more details.
In either case, you will need to actually call your robot function.

Resources