Swapping structures - c

# include <stdio.h>
# include <stdlib.h>
typedef struct
{
int Employee_id;
char Employee_Name[50];
float Employee_salary;
} employee;
void swap(employee *a,employee *b);
int main(int argc,char* argv[])
{
int n;
int iter,iter2,iter3,iter4;
scanf("%d",&n);
employee *start = (employee *)malloc(n*sizeof(employee));
employee temp;
for (iter = 0; iter < n;iter++)
{
scanf("%d",&((*(start+iter)).Employee_id));
scanf("%s",(*(start+iter)).Employee_Name);
scanf("%f",&((*(start+iter)).Employee_salary));
}
//USING BUBBLE SORT TO SORT ON BASIS OF IDS
for (iter2 = 1; iter2 <=n; iter2++)
{
for (iter3 = 0; iter3 <n-iter2 ; iter3++)
{
if ((start[iter3]).Employee_id > (start[iter3+1]).Employee_id)
{
swap(&start[iter3+1],&start[iter3]);
}
}
}
//PRINTING
for (iter4 = 0; iter4 < n; iter4++)
{
printf("%d\n",(*(start+iter4)).Employee_id);
printf("%s\n",(*(start+iter4)).Employee_Name);
printf("%f\n",(*(start+iter4)).Employee_salary);
printf("\n");
}
free(start);
return EXIT_SUCCESS;
}
void swap(employee *a,employee *b)
{
employee temp = *a;
*a = *b;
*b = temp;
}
I am trying to swap structures on the basis of employee id,I get no errors on compilation.But when I try to swap structures the program terminates abruptly. The same swap works well for ints and other basic types but not for structs.Thanks for help.

In your for loop for sorting.
for (iter2 = 0; iter2 <n; iter2++)
{
for (iter3 = 0; iter3 <n-iter2 ; iter3++) //LINE A
{
if ((start[iter3]).Employee_id > (start[iter3+1]).Employee_id)
{
swap(&start[iter3+1],&start[iter3]);
}
}
}
At LINE A, when iter2 is 0, then inner loop will from 0 to n-1. When, iter3 is n-1, you are accessing an item at n which will lead to undefined behaviour (out of bound index).
So, change your code as follows:
for (iter2 = 0; iter2 <n; iter2++)
{
for (iter3 = 0; iter3 <n - 1 -iter2 ; iter3++)
{
if ((start[iter3]).Employee_id > (start[iter3+1]).Employee_id)
{
swap(&start[iter3+1],&start[iter3]);
}
}
}
Please make sure that at any iteration of the loop, there should be not out of bound access.

Pay attention to this line, where n is being used without initialization.
employee *start = malloc(n*sizeof(employee));
To solve this, you need to swap these two lines:
employee *start = malloc(n*sizeof(employee));
scanf("%d",&n);
In addition, you need to add explicit type casting here, change this line to:
employee *start = (employee *)malloc(n*sizeof(employee));
Edit: swap() is no problem. See the following test:
employee a, b;
a.Employee_id = 1;
a.Employee_Name[0] = 'a';
a.Employee_salary = 10.0;
b.Employee_id = 2;
b.Employee_Name[0] = 'b';
b.Employee_salary = 20.0;
swap(&a, &b);
After this, a.Employee_id=2 and b.Employee_id=1, etc.

This line
swap(&start[iter3+1], ...
accesses the array start out of bounds for iter3==n (iter2 == 0).
So the program invokes undefined behaviuor.

Related

Bubble sort in C: Function not changing array data

Code:
#include <stdio.h>
void testSort(int values[], int n);
int main(void)
{
int hs[] = {5,3,2,1,4};
printf("Unsorted: %i %i %i %i %i\n", hs[0], hs[1], hs[2], hs[3], hs[4]);
testSort(hs, 5);
printf("Sorted: %i %i %i %i %i\n", hs[0], hs[1], hs[2], hs[3], hs[4]);
}
void testSort(int values[], int n)
{
for (int i = 0; i < n-1; i++)
{
int hold;
int current = values[i];
int next = values[i + 1];
if (current > next)
{
hold = current;
current = next;
next = hold;
}
}
return;
}
I'm trying to do bubble sort and right now it goes through the array once, but my question is: Why isn't my hs[] updating after calling function? The second printf shows that it remained the same.
EDIT:
As mentioned, turns out I was changing data but of the copies. For some reason I when I created the variables current/next I felt as if they were representing values[i]/values[i+1] but in reality I was just creating new variable and passing the value of values[0] which is 5 and assigning it to current. Obviously leaving values[] unchanged. Thanks everyone
The problem is that you're only modifying the function's local variables, not the array's elements.
It's the same principle as why this program will print 1 and not 2:
int main()
{
int array[] = {1};
int x = array[0];
x = 2;
printf("array[0] = %d\n", array[0]);
return 0;
}
You need to assign values to the array's elements:
void testSort(int values[], int n)
{
for (int i = 0; i < n-1; i++)
{
if (values[i] > values[i+1])
{
int hold = values[i];
values[i] = values[i+1];
values[i+1] = hold;
}
}
}
Once you've fixed this, you will notice that this function only works for some inputs.
Solving that bug is left as an exercise.
Please try below code:-
void bubble_sort(int list[], int n){
int c, d, t;
for (c = 0 ; c < ( n - 1 ); c++)
{
for (d = 0 ; d < n - c - 1; d++)
{
if (list[d] > list[d+1])
{
t = list[d];
list[d] = list[d+1];
list[d+1] = t;
}
}
}
}

assigned value to dynamic array created in void function doesnt return the same value in main()

I have a problem with dynamic arrays in C. My program was working perfectly, but I was asked to put the creation of dynamic array into a seperate void. I did it, and it still worked great, but then I had to assign a value to a certain point of the created array in void, and make it return the said value, however, what I get is a random value. The function works by sending a pointer and the lenght of required array into void, and then makes the pointer into a dynamic array.
#include <stdio.h>
#include <stdlib.h>
#define MAX 255
void ieskom (int skaiciai[],int n, int *de, int *me, int *n1, int *n2)
{
int i = 0;
int j = 0;
int nr1 = 0;
int nr2 = 0;
int temp = 0;
int temp1 = 0;
int eile = 0;
int eile1 = 0;
int *did;
did = (int*)calloc(n,sizeof(int));
if (did==NULL)
{
printf("Nepriskirta atminties.");
exit(0);
}
int *maz;
maz = (int*)calloc(n,sizeof(int));
if (maz==NULL)
{
printf("Nepriskirta atminties.");
exit(0);
}
i = 0;
for (i = 0; i < n; i++)
{
if (skaiciai[i] < skaiciai[i+1])
{
did[j] = did[j] + 1;
if (did[j] > temp)
{
eile = j;
temp = did[j];
nr1 = i+1;
}
}
else
{
did[j] = did[j] + 1;
if (did[j] > temp)
{
eile = j;
temp = did[j];
nr1 = i+1;
}
j = j + 1;
}
}
j = 0;
for (i = 0; i < n; i++)
{
if (skaiciai[i] > skaiciai[i+1])
{
maz[j] = maz[j] + 1;
if (maz[j] > temp1)
{
eile1 = j;
temp1 = maz[j];
nr2 = i+1;
}
}
else
{
maz[j] = maz[j] + 1;
if (maz[j] > temp1)
{
eile1 = j;
temp1 = maz[j];
nr2 = i+1;
}
j = j + 1;
}
}
*de = did[eile];
*me = maz[eile1];
*n1 = nr1;
*n2 = nr2;
free(did);
free(maz);
}
/*int masyvas(x)
{
int y;
y = (int*)malloc(x*sizeof(int));
return y;
}*/
void *masyvas (int *skaiciai, int n)
{
*skaiciai = (int*)malloc(n*sizeof(int));
skaiciai[2] = 5;
return skaiciai;
}
int main()
{
int n1 = 0;
int n2 = 0;
int de = 0;
int me = 0;
int i = 0;
int n = 0;
int *skaiciai;
scanf("%d", &n);
// skaiciai = masyvas(n); // naudojant int
masyvas(&skaiciai, n);
printf("2 = %d", skaiciai[2]);
if (skaiciai==NULL)
{
printf("Nepriskirta atminties.");
exit(0);
}
for (;i < n; i++)
{
scanf("%d", &skaiciai[i]);
}
ieskom (skaiciai, n, &de, &me, &n1, &n2);
if (de > me)
{
printf("Elementu numeriai:");
printf(" %d", n1-de+1);
printf(" %d\n", n1);
printf("\nAtstumas tarp ju: %d", de-2);
}
else
{
printf("Elementu numeriai:");
printf(" %d", n2-me+1);
printf(" %d\n", n2);
printf("\nAtstumas tarp ju: %d", me-2);
}
free(skaiciai);
getchar();
getchar();
return 0;
}
The problem is in void masyvas and printf skaicia[2] - I assign a certain value to skaiciai[2], yet it prints a random one. How do I fix it?
EDIT: Thank you for your answers and explanations, it really helped me a lot! I know have solved my problem, and most importantly, I know why it was a problem in the first place.
First of all, you should translate variables and texts to english (your code lack of comments, this should apply to them too).
Next your masyvas() function returns a pointer to the allocated array (why void* ?!) but when you call it you don't get the returned value.
You have to choose: either you pass a pointer to your function (an array is a pointer, to if you want an array to be allocated from a function you have to pass a pointer to the pointer, so a int **), or you use the returned value.
Allocating with returned value:
// this function allocates a int* tab of size n and set one value
int *allocate_tab(int n) {
int *tmp;
tmp = malloc(n*sizeof(int));
if (tmp == NULL) {
return(NULL); // failed
}
tmp[2] = 5;
return(tmp);
}
// in main (or other function)
int *mytab;
mytab = alloc_tab(45);
Allocating by passing a pointer to the array:
void alloc_tab(int **tab, int n) {
*tab = malloc(n*sizeof(int));
if (*tab == NULL) {
return;
}
(*tab)[2] = 5;
}
// in main (or other)
int *mytab;
alloc_tab(&mytab, 45);
If you can't understand this stuff I guess you should read more about memory, allocation and pointers.
You need to pass a pointer-to-pointer here and do not need to return anything.
void masyvas (int **skaiciai, int n)
{
*skaiciai = (int*)malloc(n*sizeof(int));
(*skaiciai)[2] = 5;
}
When you declare int *skaiciai, the variable is a pointer to type int. skaiciai holds the address that points to an int. When you pass &skaiciai, you're passing the address of the address that points to an int. So because this is an address of an address, its a double pointer.

Arrays of pointer dereferencing

I want to a function named sortPointers() that sets an array of integer pointers to point to the elements of another array in ascending order.
What I have done so far is
void sortP(int src[], int *ptrs[], int n)
{
int temp;
for(int i = 0; i< n ; i++)
{
ptrs[i] = & src[i]; // assign the address of each number in the src[] to the array of pointers
}
while (1)
{
int flag = 0;
for(int i = 0; i< n;i++)
{
if ( *(ptrs[i]) > *(ptrs[i+1])) //bubble sort
{
temp = *(ptrs[i]);
*(ptrs[i]) = *(ptrs[i+1]);
*(ptrs[i+1]) = temp;
flag = 1;
}
}
if(flag == 0);
break;
}
for(int i = 0; i< n;i++)
{
printf("%i\n",ptrs[i]);
}
}
In main function , I call this function
main()
{
int a[5] = {5,4,3,2,1};
int *ptrs[5]= {&a[0],&a[1],&a[2],&a[3],&a[4]};
sortP(a, *ptrs, 5);
}
My result are addresses, If I want to print out the actual value that the pointers point to (1,2,3,4,5) ,what should I change in the printf()?
THanks
P.S. I try *ptrs[i] before , but I got strange number though , not the ones in src[]..
My result are addresses
Technically, your results are undefined behavior, because %i expects an int, not an int*.
Fixing this problem is simple: add a dereference operator in front of ptrs[i], like this:
for(int i = 0; i< n;i++) {
printf("%i\n", *ptrs[i]);
}
I got strange number though , not the ones in src[]
The real problem with your code is that you are swapping pointers incorrectly. In fact, you can tell that it's incorrect simply by looking at temp: it needs to be int*, not int and the dereferences on the swap need to go away.
see annotations :
void sortP(int src[], int *ptrs[], int n)
{
int temp;
for(int i = 0; i< n ; i++)
{
ptrs[i] = & src[i]; // assign the address of each number in the src[] to the array of pointers
}
while (1)
{
int flag = 0;
// check if i < n-1, not n
for(int i = 0; i< n-1;i++)
{
if ( *(ptrs[i]) > *(ptrs[i+1])) //bubble sort
{
temp = *(ptrs[i]);
*(ptrs[i]) = *(ptrs[i+1]);
*(ptrs[i+1]) = temp;
flag = 1;
}
}
if(flag == 0)
break;
}
for(int i = 0; i< n;i++)
{
//*ptrs[i] instead of ptrs[i]
printf("%i ",*ptrs[i]);
}
}
int main(void)
{
int a[5] = {5,4,3,2,1};
int *ptrs[5];//= {&a[0],&a[1],&a[2],&a[3],&a[4]};
sortP(a, ptrs, 5);
}

Simple c prog. error: invalid type arguement of unary '*'

this is my first post here and I'm very new to C.
I want to write a program that is able to print matrixes. It should look like:
----
-o--
ooo-
----
So i want that to be printed for the beginning.
My current code is:
// 4. Exercise
// Learn 2d arrays
#include <stdio.h>
char z;
char s;
char m1_ptr;
void createMatrix()
{
for(z = 0; z != 4; z++)
{
for (s = 0; s != 4; s++)
{
printf("%c", *m1_ptr);
}
printf("\n");
}
}
//------------------------------------------------------------------
int main()
{
char o = o;
char c = '-';
// And some variables for the matrix count:
char matrix_1 [4][4] ={{c,c,c,c},{c,o,c,c},{o,o,o,c},{c,c,c,c}};
char *m1_ptr = &matrix_1 [z][s];
createMatrix(matrix_1 [0][0]);
/* for(z = 0; z != 4; z++)
{
for (s = 0; s != 4; s++)
{
printf("%c", matrix_1 [z][s]);
}
printf("\n");
}
*/
return 0;
}
It works if I put the void function into the main, but since there are much more matrixes coming I want to do that in an extra function to make it more readable.
If I compile that I get the error message:
"Line17: Error: invalid type argument of unary '*' ('have int')"
(edit: line 17 is where it says "printf("c......")
I looked at other questions, but since I only understand super simple programs yet that didn't work out for me.
Does anyone know how that could be fixed?
(It would be nice if the answer explains why, since I have very little experience with pointers)
I think your looking for something like this:
#include <stdio.h>
#define ROW 4
#define COLUMN 4
void printMatrix(int rowLength, int columnLength, char matrix[rowLength][columnLength]) {
int rowCount, columnCount;
for(rowCount = 0; rowCount < rowLength; rowCount++) {
for(columnCount = 0; columnCount < columnLength; columnCount++)
printf("%c", matrix[rowCount][columnCount]);
printf("\n");
}
}
int main() {
char o = 'o';
char c = '-';
char matrix_1 [ROW][COLUMN] = {
{c,c,c,c},
{c,o,c,c},
{o,o,o,c},
{c,c,c,c}
};
printMatrix(ROW, COLUMN, matrix_1);
return 0;
}
It prints the pattern you want
#include <stdio.h>
void displayMatrix( char pMatrix[rCount][cCount], int rCount, int cCount )
{
for(int i = 0; i < rCount; i++ ) // one loop for each row
{
for (int j = 0; j < cCount; j++) // one loop for each column
{
printf("%c", pMatrix[i][j]);
}
printf("\n"); // prep for next row
}
}
//------------------------------------------------------------------
static const o = 'o';
static const c = '-';
int main()
{
// And some variables for the matrix count:
char matrix_1 [][] ={{c,c,c,c},{c,o,c,c},{o,o,o,c},{c,c,c,c}};
displayMatrix(matrix_1,
sizeof( matrix_1) / sizeof(matrix_1[0]), // = number of rows
sizeof( matrix_1[0]) ); // = number of columns
return 0;
}

Sorting elements in struct

I have a struct:
struct points{
int i;
int x;
int y;
};
And I made an array of the struct and put elements in it. The i element indicates the label of a certain point. Suppose I have 1 2 3 as an input in the array. 1 corresponds to the label of the point (2, 3). Then I tried to sort the x elements:
for (a=0; a < i; a++){
for (b = 0; b < i; b++){
if (pt[b].x > pt[b+1].x){
temp1 = pt[b].x;
pt[b].x = pt[b+1].x;
pt[b+1].x = temp1;
}
}
}
It was sorted correctly. Now when I printed the i (label), it did not correspond with the x element when sorted. In short, only the x element moved. I want to make the i and y move with the x as it is sorted. What should I do?
Instead of just swapping x you need to swap all the data so that the entire array of structures gets sorted.
You could do this with a separate function, for clarity:
void swap_points(struct points *pa, struct points *pb)
{
const struct points tmp = *pa;
*pa = *pb;
*pb = tmp;
}
Then call that instead of the three inner-most lines of code in your sort.
You really should just use qsort() to do this, it's much simpler:
static int compare_points(const void *va, const void *vb)
{
const struct points *pa = va, *pb = vb;
return pa->i < pb->i ? -1 : pa->i > pb->i;
}
qsort(pt, i, sizeof pt[0], compare_points);
You are actually sorting the array, but only the values for i, not the whole structure!
You'll want to use C's qsort here:
#include <stdlib.h>
#include <stdio.h>
struct points
{
int i;
int x;
int y;
};
int compare(const struct points *a, const struct points *b)
{
if (a->i < b->i) return -1;
if (a->i == b->i) return 0;
if (a->i > b->i) return 1;
}
int main(void)
{
int i;
struct points p[3] = { { 4, 2, 1 }, { 1, 3, 5 }, { 2, 8, 1 } };
qsort(p, 3, sizeof(struct points),
(int (*)(const void*, const void*)) compare);
printf("{ ");
for (i=0; i<3; ++i)
{
printf("{ %d, %d, %d }", p[i].i, p[i].x, p[i].y);
if (i < 2) printf(", ");
}
printf(" }\n");
}
See http://www.cplusplus.com/reference/cstdlib/qsort/
You have to copy the other elements in the struct too.
I suppose you to write a function which replace the values of an element, like this:
void copyPoints(point1* a, point2* b)
{
int temp = a->i;
a->i = b->i;
b->i = temp;
temp = a->x;
a->x = b->x;
b->x = temp;
temp = a->y;
a->y = b->y;
b->y = temp;
}
Then modify the code like this:
for (a=0; a < i; a++)
{
for (b = 0; b < i; b++)
{
if (pt[b].x > pt[b+1].x)
copyPoints(&(pt[b]),&(pt[b+1]));
}
}

Resources