I can post the whole code if you guys want, but here is the essence of my problem:
typedef struct
{
CardT cards[DECK_SIZE];
int count;
}DeckT;
void shuffleDeck(DeckT *deck){
int k=50;
DeckT *randCard = deck;
DeckT *startCard = deck;
while (k>0){
int r = k % 25;
int i = 0;
for(i=0; i < r; i++, randCard++){
printf("%i %i",i,r);
}
CardT A; //do I declare A to be a Card Struc or a pointer to the array of cards?
A = *randCard; //this is where my program locks up.
*randCard = *startCard; //swapping pointers seems pointless [hehe]
*startCard = A;
printf(" yo yo yo shuffle\n"); //doesn't print this line at all, locks up before
k--;
*startCard++;
}
I understand that I need to swap the actual elements and not the pointers, but I am unsure how to do it. Basic flow of the function is to declar two pointers to my deck, which point to the array of cards [ do i need to specify this?] then swap cards based on the k%25.
I'm not to worried about the actual randomness of the swapping right now, i just want to know how to swap two cards[which are themselves structs].
Your
DeckT *startCard
should be
CardT *startCard = &deck->cards[0];
Ditto for randCard but this variable can/should be moved in the inner loop
You got confused about which pointers to use. Deck* points to a deck structure. If you add 1 to it, it will point to a Deck immediately following the first one (as if you had an array of decks). I'm pretty sure you didn't mean that.
You want to operate on CardT. There's no need to use the pointers. If you have two indices to swap, let's say i and j, just operate directly on the cards array:
CardT temp = deck->cards[i];
deck->cards[i] = deck->cards[j];
deck->cards[j] = temp;
Related
I'm working on a CS assignment, where I have to use p_threads to compute an array's prefix sum. The professor told us to use the Hillis and Steele algorithm. I found some pseudocode on wikipedia (here), specifically:
I'm a little stuck on implementing this in real code. The way our program is supposed to work, the user passes in an array through a file or stdin, then the next 2 arguments are the size of the input array, and how many threads we need to use.
So, I assume "n" in this picture is "amount of threads we need to use".
Then, I'm not sure what the notation on the x's mean. Wikipedia says "In the above, the notation ... means the value of the jth element of array x in timestep i." but...what? How do I implement this "timestep"? I assumed that it meant: "do j to the i+1th power, then find that index element in array x". With that assumption, I wrote this code:
void scan(int numThreads, int* vector, pthread_t* threads){
for(int i = 0; i < logbase(numThreads, 2); i++){
for(int j = 0; j < numThreads - 1; j++){
// create a thread here to perform parallel()
int* args = calloc(3,sizeof(int));
args[0] = i;
args[1] = j;
args[2] = *vector;
pthread_create(&threads[j], NULL, parallel, (void*)args);
free(args);
}
}
}
// each thread runs this function
void* parallel(void *arg){
int i = ((int*)arg)[0];
int j = ((int*)arg)[1];
int* vector = ((int**)arg)[2];
if(j < pow(2, i)){
// store current element (jth element of array x to the power of i)
// in the jth element of array x to the power of i + 1
vector[(int)pow(j, i+1)] = vector[(int)pow(j, i)]; // ISSUE IS HERE
}
else{
// store current element plus element at j-2^i ^i in current^i+1
vector[(int)pow(j, i+1)] = vector[(int)pow(j, i)] + vector[(int)pow(j -
pow(2, i), i)];
}
return NULL;
}
The line commented "ISSUE IS HERE" segfaults. I can step through in gdb and figure out why it's segfaulting myself, but I want to know if I'm even doing this right. This is my first time doing anything with multithreading. We're also supposed to create our own barriers using a combination of locks and condition variables, but I'm not even sure how to do that.
Also, some code isn't pictured, such as my "logbase" function and the function that reads in the input array. I know those work fine.
Thank you for your time.
You problem is here, you are trying to pass a pointer to vector
args[2] = *vector;
but instead you just pass in the first element and then treat it as a pointer after wards, that wont work. You need to pass in the pointer but that probably wont fit in the space you have reserved.
If you have to pass the args like that (as opposed to simply creating some static globals) then you should do this
struct args_t
{
int i;
int j;
int * vector;
};
then
struct args_t *args = malloc(sizeof(struct args_t));
args->i = i;
args->j = j;
args->vector = *vector;
pthread_create(&threads[j], NULL, parallel, (void*)args);
then add corresponding code at the receiving side
I am trying to shift the elements in a dynamically created 3d array by one index, so that each element [i][j][k] should be on [i+1][j][k].
This is how my array creation looks like
typedef struct stencil{
int ***arr;
int l;
int m;
int n;}matrix;
void createMatrix(matrix *vector){
vector->arr = (int***) malloc(sizeof(int**) * (vector->l+2));
for (int i = 0; i< vector->l+2; ++i) {
vector->arr[i] = (int**) malloc(sizeof(int*) * (vector->m+2));
for (int j = 0; j < vector->m+2; ++j) {
vector->arr[i][j] = (int*) calloc((vector->n+2),sizeof(int));
}
}
}
This is basically what I want to achieve with memmove
for(int i = vector->l-1; i >= 0; --i){
for(int j = vector->m; j >= 0; --j){
for(int k = vector->n; k >= 0; --k){
vector->arr[i+1][j][k] = vector->arr[i][j][k];
}
}
}
for some reason memmove shifts 2 indices.
memmove(&(vector->arr[1][1][1]), &(vector->arr[0][1][1]), (vector->l+2)*(vector->m+2)*(vector->n)*sizeof(int*));
Could anyone give me a hint?
When you create a dynamic multi-dimensional array like this, the array contents are not contiguous -- each row is a separate allocation. So you can't move it all with a single memmov().
But you don't need to copy all the data, just shift the pointers in the top-level array.
int **temp = arr[l-1]; // save last pointer, which will be overwritten
memmov(&arr[1], &arr[0], sizeof(*arr[1]));
arr[0] = temp;
I've shifted the last element around to the first, to avoid having two elements that point to the same data. You could also free the old last element (including freeing the arrays it points to) and create a new first element, but this was simpler.
Compile with a higher optimization level (-O3). Obtain a direct reference on vector->arr instead of forcing dereferencing on every single array access.
Your call to memmove looks half correct under the assumption that you allocated arr as continuous memory. However, since you said "dynamic", I very much doubt that. Plus the size calculation appears very much wrong, with the sizeof(int*).
I suppose arr is not int arr[constexpr][constexpr][constexpr] (single, continuous allocation), but rather int ***arr.
In which case the memmove goes horribly wrong. After moving the int** contents of the arr field by one (which actually already did the move), it caused a nasty overflow on the heap, most likely by chance hitting also a majority of the int* allocations following.
Looks like a double move, and leaves behind a completely destroyed heap.
Simply doing this would work (Illustrating in a 3d array)
memmove(arr[1], arr[0], Y*Z*sizeof(int));
where Y and Z denotes the other 2 dimensions of the 2d array.
Here arr[X][Y][Z] is the int array where X>=2.
In case of dynamically allocated memory you need to do each continuous chunk one by one. Then it would work.
I have had a look around but have not been able to find an answer to this question already. I am trying to create a hash table of which each element is a struct. In each struct is a variable to let the program know if the cell has been occupied, for this to work I need to set all of them to zero. The thing is it worked fine but now and then (seemingly randomly) I'd get an access violation. I thought I fixed it but when I come to grow my array the error creeps up again, leading me to believe that I have made an error. My pointer knowledge is not that good at all, so any help would be appreciated. This is what the function looks like:
HashTableCell *initialiseTable(HashTableCell *hashTable, int *tableSizePtr)
{
int i = 0;
int totalSize = *tableSizePtr * sizeof(HashTableCell);
HashTableCell *tempStartingcell;
tempStartingcell = (HashTableCell*)malloc(sizeof(HashTableCell));
*tempStartingcell = *hashTable;
while (i <= *tableSizePtr)
{
/*we keep moving forward, need to use the first entry*/
*hashTable = *(tempStartingcell + (i * sizeof(HashTableCell)));
hashTable->isOccupied = 0;
i++;
}
free(tempStartingcell);
return hashTable;
}
And before I malloced some space for the table and passed it in another function like so:
HashTableCell *hashTable;
hashTable = (HashTableCell*)malloc((sizeof(HashTableCell)*tableSize));
hashTable = initialiseTable(hashTable, tableSizePtr);
The idea is to start at the beginning and move along the correct number of spaces along per iteration of the while loop. When I come to resize I merely make a new array with double the malloced space and pass it to the initialise function but this throws up an access violation error at seemingly random indexes.
I am using VS2015 if that helps anything.
Thank you for your help.
The problem is in this line:
*hashTable = *(tempStartingcell + (i * sizeof(HashTableCell)));
When you are adding an integer to a pointer, C and C++ already take into account the size of the array elements, so you should not multiply with sizeof(HashTableCell), but rather do:
*hashTable = *(tempStartingcell + i);
Otherwise, your extra multiplication will cause an access outside of the tempStartingCell array. It makes even more sense to write it like this:
*hashTable = tempStartingcell[i];
But there is more wrong with your code; if you just want to set isOccupied to zero for each element in hashTable, just do:
void initialiseTable(HashTableCell *hashTable, int tableSize)
{
for (int i = 0; i < tableSize; i++)
hashTable[i].isOccupied = 0;
}
I am new to C and was writing a function to insert an element to sorted list. But my code does not display the last digit correctly. Though i know there are variety of ways to correct it but i want to know why my code isnt working, here's the code
#include <stdio.h>
int insert(int array[],int val);
int main (void)
{
int arr[5],j;
for (j = 0; j<5; j++)
{
scanf("%d",&arr[j]);
}
insert(arr,2);
for(j = 0;j<6;j++)
printf("%d",arr[j]);
return(0);
}
int insert(int array[],int val)
{
int k,i;
for (k = 0;k<5;k++)
if(val<array[k])
break;
for (i = 4; i>=k;i--)
{
array[i+1] = array[i];
}
array[k] = val;
return(1);
}
You are writing out of the range of the array here:
for (i = 4; i>=k;i--)
{
array[i+1] = array[i];
Where i+1 == 5 and you array has a range of 0 ...
4
Then you try to print the array but you go out of bounds again:
for(j = 0;j<6;j++)
printf("%d",arr[j]);
First make sure your array is large enough.
When you give a static / auto array to a function for insertion of elements, you must give: Address, Valid length, and Buffer Space unless guaranteed large enough.
When giving a dynamically allocated array, you must give pointer and valid length, you might give buffer space or guarantee enough space left to avoid reallocations.
Otherwise, you risk a buffer overrun, and UB means anything may happen, as in your example.
You're trying to make arr[6] out of arr[5] adding one val - it's impossible in C using statically allocated arrays.
To accomplish what you're trying to do you'd need to use dynamical arrays allocation:
int *arr;
int N = 5;
arr = (int *)malloc(N*sizeof(int));
then you use this arr same way as you did with arr[5] for loading data here via scanf.
And later on , while adding extra value to array - you'd need to reallocate your arr to make it bigger (read about malloc/realloc C functions):
arr = (int *)realloc((N+1)*sizeof(int));
Now your arr is of 6 int-s size.
Unfortunately if you don't know array sizes (number of elements) a priori you would need to deal with dynamical memory allocations in C.
Don't forget to release that memory in the end of the main() function:
free(arr);
You have to increase your array size from 5 to 6 as you are inserting one new element in your array, so there should be some space for that.
int arr[6];
you can also find more information in the link below:
https://learndswithvishal.blogspot.com/2020/06/insert-element-in-sorted-array.html
I need to write a function that sums monoms with the same power,
the monoms are defined by the following struct:
typedef struct monom {
int coefficient;
int power;
}MONOM;
And the function I wrote from the job is:
int sumMonomsWithSamePower(MONOM** polynomial, int size)
{
int i, powerIndex = 0;
for (i = 0; i < size; i++)
{
if ((polynomial[powerIndex])->power == (polynomial[i])->power)
{
if (powerIndex != i)
(polynomial[powerIndex])->coefficient += (polynomial[i])->coefficient;
}
else
powerIndex++;
}
powerIndex++;
*polynomial = (MONOM*)realloc(polynomial, powerIndex);
return powerIndex;
}
Which is being called with the following call:
*polySize = sumMonomsWithSamePower(&polynomial, logSize);
polynomial array is being sent to the function as a sorted array of MONOMs (sorted ascending by powers).
My problem is that on the 7th line of sumMonomsWithSamePower() the function crashes since it can't see the elements in the array by the following way. When I put the elements of the array in Watch list in my debugger I also can't see them using polynomial[i], but if I use (polynomial[0]+i) I can see them clearly.
What is going on here?
I assume outside sumMonomsWithSamePower() you have allocated polynomial with something like polynomial = malloc( size * sizeof(MONOM) ); (everything else wouldn't be consistant to your realloc()). So you have an array of MONOMs and the memory location of polynomial[1] is polynomial[0] + sizeof(MONOM) bytes.
But now look at polynomial in sumMonomsWithSamePower() In the following paragraph I will rename it with ppoly (pointer to polynomial) to avoid confusing it with the original array: here it is a MONOM **, so ppoly[1] addresses the sizeof(MONOM *) bytes at the memory location ppoly[0] + sizeof(MONOM *) and interpretes them as pointer to a MONOM structure. But you have an array of structs, not an array of pointers. Replace your expressions by (*ppoly)[i].power (and all the others accordingly of course) and that part will work. By the way that's excactly the difference of the two debugger statements you have mentioned.
Besides, look at my comments concerning the use of powerIndex