I was not sure, about the title of the question, but here's the problem.
I have an array of structures, now I pass it by reference to a function, where in, I have a priority queue, of the same structures.
Now, I process my array, by making use of the priority queue, and in the end of the process, I will have two of the attributes(say A and B) of my structure, in array changed, while I want only one of the change(A) to be reflected outside the function, and I want the other(B) change to be restored, the way it was before passing the array. I have to do it, because for the second time when I have to process the same array, but with different parameters, I want the changes of A to remain, but B to not.
What I do right now is that, after the process, once I am out of the function, I process the entire array, and where ever I have the value changed for attribute B I revert it back to the initial value. Now this is obviously a O(n2) operation which is no good for me.
Can I do something to make it more efficient.
I am working with C.
If your B is of type bool for example, you can create a bool array in the function. Use the indices of the input array (integers) in the priority queue instead of structures. Use the bool array to access the Bs of the input array:
void func(Type *Input, size_t n)
{
bool B[n];
queue<size_t> pqueue;
for (size_t i = 0; i < n; i++)
B[i] = Input[i].B;
size_t index;
while (index = pqueue.front()) {
// do something with Input[index]
// B[index] = false;
// rest of the function
}
}
Related
i was working on pset4 speller using trie. i wanted to use recursion to find the size of the dictionary loaded. But nothing is working. According to what debugger is doing, i think that it is probably not returning to what sizer was pointing previously. For example in a dictionary of :
a
aa
aab
ab
the size is able to read the first three. but when i am returning the counter to the previous size, it does not read the letter b after a. I think it is still checking the array in which it is reading aab. what can i do ???
unsigned int size(void)
{
int ctr = 0;
for (int i = 0; i < N; i++)
{
if (sizer -> children[i] == NULL)
{
continue;
}
else
{
// do i need to use a pointer here to point
// to sizer before changing it
sizer = sizer -> children[i];
if ((sizer -> is_word) == true)
{
ctr ++;
}
int x = size();
ctr += x;
}
}
// Before returning ctr should i use the pointer to change sizer to
// what it was previously . Can it work???
return ctr;
}
I think it is still checking the array in which it is reading aab. what can i do ???
I think you're right.
Consider how you update the value of global variable sizer in this code. The only way you ever do that is this:
sizer = sizer -> children[i];
Since you only ever set sizer to point to one of the children of the current node, never restoring it to a previous value, the program follows exactly one path from the root to a leaf, and then it's exhausted its capabilities. With different inputs you can demonstrate for yourself that this is what is happening. For example,
a
b
ba
will report a count of 1, since it traverses node "a" first, and it's a leaf.
Global variables can very easily get you into trouble, especially modifiable ones. Start now cultivating a habit of avoiding their use. Prefer to convey information to functions via arguments, instead.
Also prefer to avoid recursion under most circumstances, and don't even consider combining recursion with modifiable global variables until you have a lot more experience (which at that point will tell you "I want no part of that").
It's unclear what is the type of sizer, but suppose it is struct sizer *. In that case, consider what other changes would be needed to change the function signature to
unsigned int size(const struct sizer *node_sizer);
That's not just a style thing. Done properly, it will resolve your functional issue, too.
I have to go through each index of a 2d array and find what the neighbor values are and then update the index of the array based on that. My code below does all that but when I have to update the array it updates the existing array so the next index produces the incorrect output. I tried creating a new array but when I use the new array nothing is updated and it stays the same. This is what I have right now.
void ch(int **b, int w, int h)
{
int x,y,i,ct=0;
int **up;
up=malloc(sizeof(int *) * h);
for(i = 0; i<h; i++){
up[i]=malloc(sizeof(int)*w);
}
for (x=0;x<h;x++)
{
for(y=0;y<w;y++)
{
//...Computes Count Here(It Works)
//UPDATE BOARD - Does not update the board
if(b[x][y]==1 && ct<2)
{
up[x][y]=0;
}
else if(b[x][y]==1 && (ct==2 || ct==3))
{
up[x][y]=1;
}
else if(b[x][y]==1 && ct>3)
{
up[x][y]=0;
}
else if(b[x][y]==0 && ct==3)
{
up[x][y]=1;
}
ct=0;
}
}
b=up;
}
I tried updating the 2d array b by doing the changes on itself and it changes the array but it's not the output I am looking for. It changes the output at each iteration so output for other indexes changes but I want it so that another array keeps track of the output so that it does not update the b at every iteration and gives a correct out. What am I doing wrong that is not letting me update the up? What's the best approach to solve this issue?
Make a copy of the original array and use that as a reference. Then you can update your original array directly.
void ch(int **b)
{
int **up = malloc(sizeof(*int)*h);
int i;
for (i = 0; i < w; i++)
{
up[i] = malloc(sizeof(int) * w);
memcpy(up[i], b[i], w * sizeof(int));
}
//
if (up[x][y] == 1)
b[x][y] = 0;
}
// free up
This may be easier to maintain, than having an additional level of indirection as in
void ch(int ***b)
{
int **up = *b;
// do everything else as you intended
// finalize with
*b = up;
// free up
}
Also when making the copy, you can increase the performance a bit by allocating the temporary copy as a linear array
int *up = malloc(sizeof(int) * w * h);
if (up[y * w + x] == 0)
b[y][x] = 1;
C pass arguments by value.
so you can do this way
int* pass(int *p){
//return new pointer; and later assign
}
or get address
void pass(int **p)
{
*p=//new pointer
}
For your situation it is better to modify the same array inside without allocating new
I cannot modify the same array
You can work on copy of array as suggested then update previous array from copy
Or just return that copied array as suggested by me
Worth a look:
C Faq question related on your issue
C Faq ways for allocating multidimensional array
At the end of your function, where you have b=up;, you set b to point to your new array but that only changes your function's copy (b) and not the copy in the calling function... so the caller still sees the original array.
However, since you're using an array of pointers to arrays, rather than actual 2D arrays, you can replace the contents of b (the int *'s to the arrays making up the additional dimension)... and that will avoid having to copy all of your new array's data into the original array.
So instead of:
b=up;
try:
for(i = 0; i < h; i++) {
free(b[i]);
b[i] = up[i];
}
free(up);
That way each row of the original array gets replaced with the corresponding row from the new one, by changing the pointers in the original array of rows.
This is only a good idea, however, if the rows of the original array were dynamically allocated like the ones in your new array were, and if there are no other pointers to the rows floating around (outside of the array of rows passed as b) that might still point to the old memory afterward.
I use gcc (gnu99) under linux.
Assume I have a simple function that computes (say, prints) some values.
To fix ideas without resorting to factorial, let me propose this little toy function:
void rec(int val, int nd)
{
val *= 10; nd++;
for (int u=0; u<=9; u++, val++)
if (val && 0==(val%(nd*nd)))
{
printf("%d\n",val);
rec(val,nd);
}
}
which called as rec(0,0), will print the 86 positive numbers with the property that every their prefix of length k is divisible by k^2 (largest is 6480005).
Q: is there a standard way to turn it into a routine which can be called repeatedly and each time returns a new value until it signals in some way that there are no more values ?
In practice, I need a way to call rec(), getting back a value, and then be able to resume execution from where it was, to get next value and so on.
I thought about using a combination of setjmp(), longjmp(), setcontext() and the like, but the examples on these topics confused me a little.
Thanks.
Without resorting to setjmp() and its likes, I would think of two possibilities to achieve your objective.
Define a structure and functions that operate on it
You can define a structure that contains the state you are interested in:
struct S {
int * numbers;
size_t length;
size_t current;
}
and a set of functions that operate on it:
// Basically your rec(val,nd) function
int initialize(int val, int nd, S* s);
// Get the next value
int getNextValue(const S* s);
...
// Free memory
void Sfree(S* s);
Embed a state into your own function
In this case you embed a persistent state (using some static variable) directly into your function rec(). Being persistent this state will be preserved across different calls to the function, and permit you to keep track of how many times the function was called and of any other information you may need. Beware that this solution requires a particular care if used inside multi-threaded environments.
In C++ this is done via a class that holds a the state (variables).
In C, the preferred method of operation is to pass this state or context to the function.
Do not use a global state as later on you'll find that it causes too many issues.
Example:
int foo(struct fooContext* c, int arg1, int arg2) {
}
I am trying to write 2 functions in C, one of which would add an element to the end of my array that i pass as an argument, and the other function which would delete an element from the array passed as an argument.
I am not really familiar with C, and not good into pointers arithmetic.
I have tried with something like this, but it seems not to be working properly:
void remove_element(type *elements, type element, int size){
int i;
int index = 0;
for(i=0; i<size; i+=1){
if(equals(elements[i], element)) index = i;
}
for(i=index; i<size-1; i+=1){
elements[i] = elements[i+1];
}
}
void add_element(type *elements, type element, int size){
elements = realloc(elements, size*sizeof(element));
elements[size-1] = element;
}
That is how I want to call the functions:
add_element(elements, new_element, size);
remove_element(elements, element_to_remove, size);
Theses two lines may cause undefined behavior:
cvorovi = realloc(elements, size*sizeof(element));
elements[size-1] = cv;
The realloc function is not guaranteed to return a pointer to the same area you want to reallocate, meaning that elements may not point to the allocated area after the call. You must use the returned pointer.
This will most likely cause problems with the code calling this function, as that code will not know anything about the change of the pointers. Either pass elements by reference (i.e. a pointer to pointer) or return the new pointer.
Also, after seeing your edit, you do remember to pass in a larger size than the current size when you call add_element? Otherwise it will just reallocate the same size over and over again, and overwriting the last inserted element each call. You may want to consider making a structure keeping track of these, and and special set of functions that takes this structure as argument and handles all the things (like keeping track of the size) internally.
I'm new to programing and was given a task of making a function that puts one array into the other with the following criteria: a variable in the destination array will repeat only once and the source and destination array will be of the same size.
the function i came up with is:
int RemoveDup (int src[],int dst[])
//recive two array compare them and copy the src array to dst,and only the none reacuring
//numbers,the arrays must be from the same size
{
int size_src;
int size_dst;
int i,n=0;
size_src = sizeof(src)/sizeof(int);//determine the size of source array
size_dst = sizeof(dst)/sizeof(int);//determine the size of destination array
if (size_src = size_dst);//checks that the array are in the same size
{
for(i = 0;i < size_src;i++)//the loop for advancing the copying process
{
dst[i] = src[i];
}
while (i<size_dst)
{
dst[i] = dst[i++];
if (dst[i] = dst[i++])//relay on the fact that if the function will find a similar varibale, the tested varibale will be set to 0 and the other one will come out clean in the check
dst[i] = 0;//eliminating the varibale in that specific address
}
}
return dst [i];
but it doesn't seems to work and have no idea where it is going wrong.
any help or clue will be appreciated .
I noticed that you're using sizeof(src) within a function that takes int src[] as a parameter. This is not doing what you think it is doing. In C, the size of arrays is not passed to functions along with the array itself (unlike some other languages you may be familiar with). You will have to pass the actual size as a separate parameter.
Also, some printf() statements will definitely help your debugging efforts. Make sure values are what you think they should be. Hopefully you have access to an interactive debugger, that would probably be really useful for you too.
In C you cannot declare a function that takes a parameter that is an array. When you use an array declarator as a function parameter the type is silently adjusted to the corrsponding pointer type. Any explicit array size (if specified) is discarded.
In other words, when you use this:
int RemoveDup (int src[],int dst[])
it is exactly equivalent to this:
int RemoveDup( int *src, int *dst )
It should now be obvious why sizeof(src)/sizeof(int) doesn't do the calculation that you wanted it to do.
well in fact it is possible to make a function recieve an array and not a pointer (given of course the size of the array is pre-defined).
so you can use:
int RemoveDup(int src[M],int dst[N]){
.
.
.
return whatever;
I will agree though that using pointers is better.
In my opinion you should write a recursive function to do that using of course pointers.
so that the next call is (*src+1) so you look at the next cell.
the exit condition is then:
if (sizeof(src) == 0) {
//exit recursion statement.
}