I'm having some trouble with a function that I'm trying to write as part of a project in C. I'm trying to write a function that not only resizes an array, but also assigns values to the new elements of the array.
For example if A = [a, b, c] and it needs to be doubled. The array needs to be re-sized to
[a, a+b/2, b, b+c/2, c, 3c/2]. If A = [a, b, c, d, e, f] the array should be re-sized to [a, c, e]. Any re-factoring of arrays is by some multiple of 2.
This is the offending bit of code.
void re_size_array(double *A, long n, long nx){
double *T;
long i, j;
long m;
T = (double *)malloc(sizeof(double)*nx);
if(nx > n){
m = nx/n;
double k;
for(i = 0; i < n - 1; i++){
k = (A[i+1] - A[i])/m;
for(j = 0; j < m; j++){
T[i*m + j] = A[i] + j*k;
}
}
k = A[n-1]/m;
for(i = 0; i < m; i++){
T[(n-1)*m + i] = A[n-1] + i*k;
}
A = (double*)realloc(A, sizeof(double)*nx);
if(A == NULL){
printf("Array has failed to re-size\n");
exit(1);
}
double *tmp = T;
A = T;
T = tmp;
free(T);
}
if(nx < n){
m = n/nx;
for(i = 0; i < nx; i++){
T[i] = A[i*m];
}
A = (double*)realloc(A, sizeof(double)*nx);
if(A == NULL){
printf("Array has failed to re-size\n");
exit(1);
}
double *temp = T;
A = T;
T = temp;
free(T);
}
}
I'm stuck as to why this doesn't work, I've printed out the values which are supposed to be assigned and they are all correct. I have tried swapping the pointers differently but I still get no viable result.
Instead when I try to re-size the data to a larger nx it results in the same process as A = realloc(A, nx*sizeof(double)). If I try to decrease the size, nothing happens.
Two things here:
A = T is not visible outside of the function. If you want that, then pass a pointer to the double pointer (double **) in your function signature.
You should return A; at the very end and call the function like A = re_size_array(A, n, nx)
hth :)
Related
I wanted to sort this problem in C with something like bubble sort ... anyone can help
Implement a list with 5 struct Point (Being this a point w/ X, y);
Sort the 5 struct point (first evaluate x then y).
Example:
// The points
p[0]={2,3}
p[1]={4,5}
p[2]={1,5}
p[3]={4,3}
p[4]={1,2}
// Should become
p[0]={1,2}
p[1]={1,5}
p[2]={2,3}
p[3]={4,3}
p[4]={4,5}
If you want to sort structures, you still have to break it down into comparing numeric types. With this in mind, let's take your example with the points:
struct tagPoint
{
int x;
int y;
};
typedef struct tagPoint Point;
Now, let's suppose you have an array of Point and you want it sorted. You can take two approaches:
1. Straightforward function which sorts the array:
Just make the function to sort the array:
void SortPointArray(Point* Points, unsigned int n)
{
/* This will sort the points with priority on the x and then the y value in ascending order. */
for(unsigned int i = 0; i < n-1; i++)
for(unsigned int j = i+1; j < n; j++)
{
if (Points[i].x > Points[j].x)
{
Point aux = Points[i];
Points[i] = Points[j];
Points[j] = aux;
}
else if ((Points[i].x == Points[j].x) && (Points[i].y > Points[j].y))
{
Point aux = Points[i];
Points[i] = Points[j];
Points[j] = aux;
}
}
}
2. Wrap the algorithm in a generic function and use callbacks for each type you want to sort:
This is a little more complicated, but it will save you some time if you use it frequently. Here, this function uses the same algorithm as the one above, but can sort any types.
void Sort(void* lpArray, unsigned int n, size_t cbSize, int (*Cmp)(void*, void*), void (*Swap)(void*, void*))
{
for(unsigned int i = 0; i < n-1; i++)
for(unsigned int j = i+1; j < n; j++)
/* Cast void* to char* to get rid of warning with pointer arithmetic... */
if ( Cmp( ((char*)lpArray) + i*cbSize, ((char*)lpArray) + j*cbSize) )
Swap( ((char*)lpArray) + i*cbSize, ((char*)lpArray) + j*cbSize );
}
As you can see, it requires 2 more functions passed as parameters. If you want this Sort function to know how to sort the Point array, you must define a Comparrison function and a Swapping function and tell the Sort function to use them.
Here is how i implemented them:
/** This function return 1 if p1 should be swapped with p2. */
int ComparePoints(void* vp1, void* vp2)
{
Point *p1, *p2;
p1 = vp1;
p2 = vp2;
if (p1->x > p2->x)
return 1;
else if ((p1->x == p2->x) && (p1->y > p2->y))
return 1;
return 0;
}
/** This will swap 2 points. */
void SwapPoints(void* vp1, void* vp2)
{
Point p = *(Point*)vp1;
*(Point*)vp1 = *(Point*)vp2;
*(Point*)vp2 = p;
}
How do you use them?
If you only want to use the first SortPointArray function, this is enough:
int main()
{
Point Array[10];
/* Read the points. */
for(unsigned int i = 0; i < 10; i++)
scanf("%d %d", &Array[i].x, &Array[i].y);
SortPointArray(Array, 10);
/*Print the points.*/
for(unsigned int i = 0; i < 10; i++)
printf("%d %d\n", Array[i].x, Array[i].y);
return 0;
}
But if you want to use the generic Sort function (which i recommend only if you have multiple types you want to sort like Points, Lines etc) you have to define the two callbacks (ComparePoints and SwapPoints)
int main()
{
Point Array[10];
/* Read the points. */
for(unsigned int i = 0; i < 10; i++)
scanf("%d %d", &Array[i].x, &Array[i].y);
Sort(Array, 10, sizeof(Point), ComparePoints, SwapPoints);
/*Print the points.*/
for(unsigned int i = 0; i < 10; i++)
printf("%d %d\n", Array[i].x, Array[i].y);
return 0;
}
The OP is asking for a C solution, so here you go:
void bsortDesc(struct yourStruct list[80], int s)
{
int i, j;
struct yourStruct temp;
for (i = 0; i < s - 1; i++)
{
for (j = 0; j < (s - 1-i); j++)
{
if (list[j].marks < list[j + 1].marks)
{
temp = list[j];
list[j] = list[j + 1];
list[j + 1] = temp;
}
}
}
}
Also, here's what I got it from: here.
This struct allows representing arbitrary size matrices, where M is the number of rows, N is the number of columns and data is a pointer to M*N values of type double stored by rows.
struct matrix {
size_t M, N;
double *data;
};
struct matrix *mat_directsum(const struct matrix *a, const struct matrix *b);
The function mat_directsum accepts two pointers to arrays as a parameter and should return to the direct sum, dynamically allocated on the heap.
Example:
A.M = 2
A.N = 3
A.data = (1, 1, 2, 0, 1, -3)
Example of direct sum function
I just need a few tips on how to set the function, just to see how others work with arrays of this type, because the only way that comes to mind is an iterative methods with many loops, however, it is enough work long and ingenious, I would like to know if there are easier method to solve it. Thank you
ps.
(memory allocation is not a problem of course)
EDIT
I solved like that:
struct matrix *mat_directsum(const struct matrix *a, const struct matrix *b) {
struct matrix *c = malloc(sizeof(struct matrix));
c->M = a->M + b->M;
c->N = a->N + b->N;
int n = c->M * c->M;
double *dati = calloc(n, sizeof(double));
int t = 0;//index new array
int y = 0;//index first mat
int z = 0;//index second mat
for (int i = 0; i < c->N; i++) {
if (i < a->N) {//first mat
for (int j = 0; j < c->M; j++) {
if (j < a->M) {
dati[t] = a->data[y];
y++;
}
t++;
}
} else {//second mat
for (int j = 0; j < c->M; j++) {
if (j >= a->M) {
dati[t] = b->data[z];
z++;
}
t++;
}
}
}
c->data = dati;
return c;
}
I don't know how to do it which only one for loop
//macro which will point to an element indexed at [xe][ye]
#define ELEMENT(data,rows,columns,xe,ye) (data+((xe)*(columns)+(ye)))
struct matrix
{
size_t M, N;
double *data;
};
//won't mind changing the return type from "struct matrix*" to "struct matrix"
struct matrix mat_directsum(const struct matrix *a, const struct matrix *b)
{
int x;
struct matrix res;
res.M = a->M + b->M;
res.N = a->N + b->N;
//using calloc will set the memory to zero i.e all the bytes will be set to zero.
res.data = (double*)calloc(res.M * res.N, sizeof(double));
if(res.data == NULL)
{
return res;
}
for(x = 0; x < a->M; ++x)
{
memcpy(ELEMENT(res.data, res.M, res.N, x, 0), ELEMENT(a->data, a->M, a->N, x, 0), a->N * sizeof(double));
}
for(x = 0; x < b->M; ++x)
{
//note the offset by [a->M][a->N] while accessing elements of res.
memcpy(ELEMENT(res.data, res.M, res.N, x + a->M, a->N), ELEMENT(b->data, b->M, b->N, x, 0), b->N * sizeof(double));
}
return res;
}
struct matrix res = mat_directsum(&a, &b);
if(res.data != NULL)
{
free(res.data);
}
Besides the error n = c->M * c->M, spotted by M.M (what a coincidence of Ms!), your solution has another error in the for loops: You confused the row and column numbers M and N - since the values are stored by rows, the outer loop has to be for (int i = 0; i < c->M; i++) and the inner loops have to be for (int j = 0; j < c->N; j++), so all M and N in those loops (also in the ifs) have to be swapped. Apart from that and the missing allocation error checks, your solution is fine.
I don't know how to do it which only one for loop
If you want to see an alternative approach, here's one with a helper function to insert the matrices into the sum matrix:
#include <string.h>
void mat_insert(const struct matrix *s, struct matrix *d, int r, int c)
{ // copy source matrix s to destination matrix d at row r, column c
for (int i = 0; i < s->M; i++) // for each row
memcpy(d->data+(r+i)*d->N+c, s->data+i*s->N, s->N*sizeof*s->data);
}
struct matrix *mat_directsum(const struct matrix *a, const struct matrix *b)
{
struct matrix *c = malloc(sizeof *c); if (!c) return NULL;
c->M = a->M + b->M;
c->N = a->N + b->N;
int n = c->M * c->N;
c->data = calloc(n, sizeof *c->data); if (!c->data) return free(c), NULL;
mat_insert(a, c, 0, 0); // copy a to c at row 0, column 0
mat_insert(b, c, a->M, a->N); // copy b to c at row a->M, column a->N
return c;
}
I'm working through an algorithms MOOC and have a small program that takes an array A of ints in arbitrary order, counts the number of inversions (an inversion being the number of pairs (i,j) of array indices with i<j and A[i] > A[j]).
Below is the code I've written. I'm trying to tackle it using a "divide and conquer" approach where we recursively split the input array into two halves, sort each half individually while counting the inversions and then merge the two halves.
The trick is I need to keep track of the number of inversions and sort the arrays, so I pass the original array around the various recursive calls as an argument to the function and pass the count of inversions as a return value.
The code executes correctly through the first set of recursive calls that successively divide and sort [1,5,3], however when I get to the 3rd invocation of mergeAndCountSplitInv it crashes at the line:
sortedArrayLeft = realloc(sortedArrayLeft, sizeof(int)*(rightLen + leftLen));
with the error:
malloc: *** error for object 0x100103abc: pointer being realloc'd was not allocated
I can't see where I'm not using malloc correctly and I've combed through this checking to see I'm doing the pointer arithmetic correctly and can't spot any errors, but clearly error(s) exist.
Any help is appreciated.
// main.c
// inversionInC
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// function to help with debugging array/pointer arithmetic
void logArrayLenAndContents (char *arrayName, int arrayToPrint[], int arrayLen){
printf("%s\n", arrayName);
printf("len:%d\n", arrayLen);
for (int idx = 0; idx < arrayLen; idx++) {
printf("array[%d]: %d\n", idx, arrayToPrint[idx]);
}
}
int mergeAndCountSplitInv(int sortedArrayLeft[], int leftLen, int sortedArrayRight[], int rightLen)
{
printf("Calling mergeAndCount with sortedArrayLeft:\n");
logArrayLenAndContents("left Array", sortedArrayLeft, leftLen);
printf("...and sortedArrayRight:\n");
logArrayLenAndContents("right Array", sortedArrayRight, rightLen);
int i = 0;
int j = 0;
int k = 0;
int v = 0; // num of split inversions
int* outArray;
outArray = malloc((leftLen + rightLen) * sizeof(int));
while (i < leftLen && j < rightLen) {
if (sortedArrayLeft[i] < sortedArrayRight[j]) {
outArray[k] = sortedArrayLeft[i];
i++;
} else{
outArray[k] = sortedArrayRight[j];
v += leftLen - i;
j++;
}
k++;
}
// if at the end of either array then append the remaining elements
if (i < leftLen) {
while (i < leftLen) {
outArray[k] = sortedArrayLeft[i];
i++;
k++;
}
}
if (j < rightLen) {
while (j < rightLen) {
outArray[k] = sortedArrayRight[j];
j++;
k++;
}
}
printf("Wrapping up mergeAndCount where outArray contains:\n");
logArrayLenAndContents("outArray", outArray, k);
sortedArrayLeft = realloc(sortedArrayLeft, sizeof(int)*(rightLen + leftLen));
return v;
}
int sortAndCount(int inArray[], int inLen){
printf("Calling sortAndCount with:\n");
logArrayLenAndContents("inArray", inArray, inLen);
if (inLen < 2) {
return 0;
}
int inArrayLenPart1 = ceil(inLen/2.0);
int inArrayLenPart2 = inLen - inArrayLenPart1;
int* rightArray = malloc(sizeof(int) * inArrayLenPart2);
rightArray = &inArray[inArrayLenPart1];
int x = sortAndCount(inArray, inArrayLenPart1);
printf("sortAndCount returned x = %d\n\n", x);
int y = sortAndCount(rightArray, inArrayLenPart2);
printf("sortAndCount returned y = %d\n\n", y);
int z = mergeAndCountSplitInv(inArray, inArrayLenPart1, rightArray, inArrayLenPart2);
printf("mergeAndCount returned z = %d\n", z);
return x+y+z;
}
int main(int argc, const char * argv[])
{
static int* testArray;
testArray = malloc(5 * sizeof(int));
for (int i = 0; i<=4; i++) {
testArray[0] = 1;
testArray[1] = 5;
testArray[2] = 3;
testArray[3] = 2;
testArray[4] = 4;
}
int x = sortAndCount(testArray, 5);
printf("x = %d\n", x);
return 0;
}
This happens because the value of sortedArrayLeft gets lost as soon as the function returns. The realocated value does not make it to the caller, so inArray of the sortAndCount may be pointing to freed memory if realloc needs to reallocate and copy.
In order to fix this, pass a pointer to the pointer, letting sortedArrayLeft to propagate back to inArray of sortAndCount:
int mergeAndCountSplitInv(int **sortedArrayLeft, int leftLen, int sortedArrayRight[], int rightLen) {
...
*sortedArrayLeft = realloc(*sortedArrayLeft, sizeof(int)*(rightLen + leftLen));
return v;
}
...
int sortAndCount(int **inArray, int inLen) {
...
int z = mergeAndCountSplitInv(inArray, inArrayLenPart1, rightArray, inArrayLenPart2);
}
...
int x = sortAndCount(&testArray, 5);
I am still new to pointers in C and have been trying to make string functions. This one is supposed to concatenate two strings, but when I try to run it, it crashes.
void concatenate (char *a, char *b, int size_a, int size_b) {
char *c, *d, *e;
c = a;
d = b;
int i, j, k;
int l = 1;
for(i = 0; i<size_a; i++) {
*(e+i) = *(c+i);
}
for (j = size_a; j<size_a+size_b; j++) {
*(e+j) = *(d+(j-(j-l)));
l++;
}
for (k = 0; k< size_a+size_b; k++){
printf("%c",*(e+k));
}
}
What am I doing wrong?
You are trying to access the memory where uninitialized pointer e points to, which leads to undefined behavior.
Your function should look like this:
char* concatenate (const char *a, const char *b, int size_a, int size_b) {
// create new string:
char* newStr = malloc (size_a + size_b + 1);
int i, j;
// copy first string into it:
for (i = 0; i<size_a; i++)
newStr[i] = a[i];
// copy second string into it:
for (j = 0; j < size_b; j++)
newStr[i + j] = b[j];
newStr[i + j] = '\0';
return newStr;
}
Note that function doesn't change strings that are passed to it, thus they can be passed as const. The size_a and size_b are expected to be equal to strlen(a) and strlen(b), which also means that in case you always pass null-terminated strings into this function, you can calculate their length on your own within its body (so you can get rid of last 2 arguments).
e is an uninitialized pointer, which means it is pointing to some random place in memory. When you start writing to it as if it were a pointer to a character array, your program will crash (or worse, change some state mysteriously causing unspecified behavior later on).
Your code seems obfuscated for no reason. The problem is that you're assigning to e, which is uninitialized. The following is, pretty much, your code in a more readable form and with e allocated. I haven't tested it, though.
void concatenate (char *c, char *d) {
char *e;
e = calloc(strlen(c) + strlen(d) + 1, sizeof(char));
int i, j;
int l = 1;
for(i = 0; c[i]; i++) {
e[i] = c[i];
}
l = i;
for (j = 0; d[j]; j++) {
e[l + j] = d[j];
}
e[l + j] = '\0';
printf("%s", e);
free(e);
}
So I'm trying to multiply matrices in c. However when I try to multiply the numbers in the two arrays, and put them in an answer array its always zero. heres the code for the method, thanks.
My matrix struct:
typedef struct matrix {
int r;
int c;
double **mat;
} *matrix_t;
My matrix multiplying method:
matrix_t mat_mult(matrix_t a, matrix_t b)
{
int i, j, k;
double x, temp1, temp2;
double tempsol = 0.0;
x = temp1 = temp2 = 0;
matrix_t answer;
if(a -> c == b -> r)
{
answer = mat_new(a -> r, b -> c);
for(i = 0; i < a -> r; i++)
for( j = 0; j < b -> c; j++)
{
for( k = 0; k < a -> c; k++)
{
tempsol += a->mat[i][k] * b->mat[k][j];
answer-> mat[i][j] = tempsol;
}
}
return answer;
}
else if(a -> r == b -> c)
{
answer = mat_new(a -> c, b -> r);
return answer;
}
else
{
printf("Matrices could not be multiplied");
exit(1);
return;
}
}
heres the code for my mat_new as well
matrix_t mat_new(int r,int c)
{
int i = 0;
double **a;
matrix_t matrix_a;
a = (double**)malloc(r *sizeof(double *));
for(i = 0; i < r; i++)
{
a[i] = (double*)malloc(c *sizeof(double));
}
matrix_a = (matrix_t) malloc ( sizeof(struct matrix));
matrix_a -> mat = a;
matrix_a -> r = r;
matrix_a -> c = c;
return matrix_a;
}
You need to free your objects. You need to reset tempsol. But most importantly, you need to review your mat_mult().
matrix_t mat_mult(matrix_t a, matrix_t b)
{
/* ... */
if(a -> c == b -> r)
{
/* ... */
}
else if(a -> r == b -> c)
{
/* BZZZZT! */
answer = mat_new(a -> c, b -> r); /* BZZZZT! mat_mult(b, a); */
/* BZZZZT! */
return answer;
}
else
{
/* ... */
}
}
Seems like all your issues stem from reading in matrix values as integers rather than doubles. Everything works fine if you change temp in read_mat() to an int, then cast it to a double when you're putting it in the matrix.
This should work for your example:
matrix_t mat_new(int r,int c)
{
matrix_t new = malloc(sizeof*new);
new->r = r;
new->c = c;
new->mat = malloc( r*c*sizeof(double) );
return new;
}
Your code doesn't contain any obvious errors. Perhaps the problem lies in your mat_new(). The way you defined mat in your matrix structure as double **mat;, which I wouldn't recommend, may be causing some problems.
To allocate a 2x2 matrix to mat, you would need to do:
mat = new (double*)[2];
mat[0] = new double[2];
mat[1] = new double[2];
or a n by m matrix:
mat = new (double*)[n];
for (int i=0;i<n;i++) {
mat[i] = new double[m];
}
Is this what you are doing?