C Program, function sorting through pointers - c

This program is supposed to take an array, and sort it from lowest to highest value. My program won't sort any values though. I believe the error is in the selectionSort. The values i and j are present in the function, I printed them out inside the function but they are not passed into the swap function. I tried making i and j pointers but it didn't work. I just have no clue on what to do next. Any help would be appreciated.
#include <stdio.h>
#define N 5
void selectionSort(int *a, int n);
int *findLargest(int *a, int n);
void swap(int *p, int *q);
int main(void)
{
int i;
int a[N];
printf("Enter %d numbers: ", N);
for (i = 0; i < N; i++) {
scanf("%d", &a[i]);
}
selectionSort(a, N);
printf("In sorted order:");
for (i = 0; i < N; i++) {
printf(" %d", a[i]);
}
printf("\n");
return 0;
}
void selectionSort(int *a, int n)
{
int *p = a;
int i;
int j;
if (n == 1) {
return;
}
i = *(p+n-1);
j = *findLargest(a, n);
swap(&i, &j);
selectionSort(a, n - 1);
}
int *findLargest(int *a, int n)
{
int *p;
int *p_max = a;
for(p = a + 1; p < a + n - 1; p++) {
if ( *p > *p_max)
p_max = p;
}
return p_max;
}
void swap(int *p, int *q)
{
int temp = *(p-1);
*(p-1) = *q;
*q = temp;
}

The problem is in your call of swap: you swap the content of two local variables
int i;
int j;
... // Some other code, then
swap(&i, &j);
This has no effect on the original array. You should be passing p+n-1 and findLargest(a, n) directly, or store their results in pointers, not in ints:
swap(p+n-1, findLargest(a, n));
In addition, your swap is broken: rather than swapping the content of two pointers, it assumes that p points one element past the target location. This is a bad assumption to make in a general-purpose function, such as swap, and it also leads to undefined behavior in your program.
void swap(int *p, int *q) {
int temp = *p;
*p = *q;
*q = temp;
}

Related

Passing pointer to an array as a parameter to a function

I tried to build a heap and finally print the elements in the form of an array.
Here it is the code (I know this doesn't really make sense but I just wanted to test my knowlwdge of heap and dynamic arrays):
#include <stdio.h>
#include <stdlib.h>
void heapiify(int *arr,int n, int i)
{
int largest=i;
int l=2*i+1; // left node
int r= 2*i+2; // right node
if(l<=n && *arr[l]>=*arr[i])
largest=l;
if (r <=n && *arr[r]<=*arr[i])
largest= r;
if(largest !=i)
{
int temp=*arr[i];
*arr[i]=*arr[largest];
*arr[largest]=temp;
}
heapify(*arr,n,largest);
}
void buildh(int *arr,int n,int r,int c)
{
int i;
for(i=n/2-1;i>=0;i--)
heapify(*arr,n,i);
output(*arr,r,c);
}
void output(int *arr,int r,int c)
{
int i,j;
for(i=0;i<r;i++)
{
for(j=0;j<c;j++)
{
printf("%d",*arr[i*c+j]);
}
printf("\n");
}
}
int main()
{
int i,j,r,c;
printf("enter the number of rows");
scanf("%d",&r);
printf("enter the number of columns");
scanf("%d",&c);
int n=r*c;
int *arr=malloc(n*sizeof(int));
for(i=0;i<r;i++)
{
for(j=0;j<c;j++)
scanf("%d",&arr[i*c+j]);
}
buildh(*arr,n,r,c);
}
I'm getting 9 errors which are all the same
invalid argument type of unary '*'( have int)
Your arr variable is of type pointer to int:
int *arr=malloc(n*sizeof(int));
So when you call buildh, which takes the same type, you have to pass it as-is:
buildh(arr,n,r,c);
Same for the other cases.
The problem is the dereference of arr, across your funtions in multiple places, and the passing of dereferenced *arr in your functions to int * parameters, you should pass arr, try:
//...
void heapify(int *arr, int n, int i)
{
int largest = i;
int l = 2 * i + 1; // left node
int r = 2 * i + 2; // right node
if (l <= n && arr[l] >= arr[i]) //here
largest = l;
if (r <= n && arr[r] <= arr[i]) //here
largest = r;
if (largest != i)
{
int temp = arr[i]; //here
arr[i] = arr[largest]; //here
arr[largest] = temp; //here
}
heapify(arr, n, largest); //here
}
void buildh(int *arr, int n, int r, int c)
{
int i;
for (i = n / 2 - 1; i >= 0; i--)
heapify(arr, n, i); //here
output(arr, r, c); //here
}
void output(int *arr, int r, int c)
{
int i, j;
for (i = 0; i < r; i++)
{
for (j = 0; j < c; j++)
{
printf("%d", arr[i * c + j]); //here
}
printf("\n");
}
}
int main()
{
//...
buildh(arr, n, r, c); //here
}

min heap program stopped working

I am doing a simple minheap program but when size of heap is 4 i get an error program stopped working.
i checked heap size 2,3,5,6,7 program is working fine.
Why am i getting this error only when heapsize is 4?
I am using codeblocks 16.01, windows 10, gcc compiler.
minHeap.c
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
void MinHeapfy(int A[], int i, int N)
{
int l,r,temp,smallest;
l = 2*i;
r = 2*i + 1;
if((l<=N) && (A[l]<A[i]))
{
smallest = l;
}
else
{
smallest = i;
}
if((r<=N) && (A[r]<A[smallest]))
{
smallest = r;
}
if(smallest != i)
{
temp = A[smallest];
A[smallest] = A[i];
A[i] = temp;
MinHeapfy(A,smallest,N);
}
}
void BuildHeap(int A[],int N)
{
int i;
int f = floor(N/2);
printf("f %d", f);
for(i=f;i>=1;i--)
{
printf("i %d\n",i);
MinHeapfy(A,i,N);
}
}
int main()
{
int *A,N,T,data,q,i=1;
scanf("%d",&N);
A = (int *)calloc(N,sizeof(int));
for(i=1;i<=N;i++)
{
scanf("%d",&data);
A[i]=data;
}
BuildHeap(A,N);
for(i=1;i<=N;i++)
{
printf("%d ",A[i]);
}
return 0;
}
I can share some things that I learned till now:
void BuildHeap(int *A, int N);
void MinHeapfy(int *A, int i, int N);
In this 2 functions you just send a pointer not an array(difference between int *A and int A[5])
int main()
{
/*here it is better for you to declare like this
to see more easier which is which pointer and variable
(PS: at the moment you don't use q)*/
int N,T,data,i;//,q
int *A;
scanf("%d",&N);
A = (int *)calloc(N,sizeof(int));
for(i=0;i<N;i++)
{
scanf("%d",&data);
A[i]=data;
}
BuildHeap(A,N);
for(i=0;i<N;i++)
{
printf("%d ",A[i]);
}
return 0;
}
The 2 fors that you use must start from 0 to N
When you write:
A[0] <=> address pointed by A + 0 * sizeof(data type of A)
So 0 is the first address of the array
and the last address is N-1
A[N-1] <=> address pointed by A + (N-1) * sizeof(data type of A)

sorting arrays in c with pointers

I am trying to sort an array from least to greatest using pointers instead of array subscripts. I am not sure where the problem is but when i run this code, the values are returned in the same order that they were entered. The find_largest and swap functions both do exactly what they say. The selection_sort function uses a for loop to sort the numbers from right to left (greatest to smallest, right to left). I have been staring at this for a while now and it looks like it should work fine but like i said, for some reason the numbers are returned in the same order they were entered.
Here is my code:
#include <stdio.h>
#define N 5
void selection_sort(int *a, int n);
int *find_largest(int *a, int n);
void swap(int *p, int *q);
int main(void)
{
int i;
int a[N];
printf("Enter %d numbers to be sorted: ", N);
for (i = 0; i < N; i++)
scanf("%d", (a+i));
selection_sort(a, N);
printf("In sorted order:");
for (i = 0; i < N; i++)
printf(" %d", *(a+i));
printf("\n");
return 0;
}
void selection_sort(int *a, int n)
{
int i = 0;
int *largest;
for(i = 0; i < n; i++){
largest = find_largest(a, n-i);
swap(largest, a+(n-1-i));
}
}
int *find_largest(int *a, int n){
int *p = a;
int *largest = p;
for(p = a; p < a+n-1; p++){
if(*(p+1) > *p){
largest = (p + 1);
}
}
return largest;
}
void swap(int *p, int *q){
int *temp;
temp = p;
p = q;
q = temp;
}
There are two mistakes in your code.
One, logical in the find_largest function:
int *find_largest(int *a, int n){
int *p = a;
int *largest = p;
for(p = a; p < a+n-1; p++){
if(*(p+1) > *largest){ <---- //here you were checking for *(p)
largest = (p + 1);
}
}
return largest;
}
the other is with pointers in swap function:
void swap(int *p, int *q){
int temp;
temp = *p;
*p = *q;
*q = temp;
}
As John Bollinger mentioned in the comments, swap() does not function correctly - all it does is reassign pointers that quickly go out of scope.
Here is a rewrite of that function that does work. Just swap it in and it fits perfectly.
void swap(int *p, int *q){
int temp;
temp = *p;
*p = *q;
*q = temp;
}
Thanks to John Bollinger.

C - How to make function return a pointer?

This function should return a pointer to the first occurrence of the largest int in an array without using the index operator. It can find and print the largest int, but how do I make it return a pointer? And how do I test if it was successful?
int *arr_first_max(const int *a, size_t n) {
const int *k;
int largest = 0;
for (k = a; *k != '\0'; k++) {
if (*k > largest) {
largest = *k;
}
}
printf("%d\n", largest);
return &largest;
}
Edit: size_t n is supposed to be used but I'm not sure how to include it.
And another answer assuming:
n is length of array a (in terms of elements, not bytes)
You want to iterate through the whole array a
Then code is:
const int *arr_first_max(const int *a, size_t n) {
const int *largest = a;
while(n--) {
if(*a>*largest)
largest = a;
a++;
}
printf("%d\n", *largest);
return largest;
}
In all functions n is assumed to be >0.
Just keep your logic, but instead of storing the max, store the index to the max, in order to return a pointer to the array at that index.
int *arr_first_max(const int *a, size_t n) {
int i,l;
for (l=i=0 ; i<n ; i++)
if (a[i] > a[l]) l = i;
return a+l;
}
Edit Pointer only version (based on comments) which does n-1 iterations
const int *arr_first_max(const int *a, size_t n) {
const int *most;
for (most=a++ ; --n ; a++) if (*a > *most) most = a;
return most;
}
And since I misread the question, a recursive bonus!
const int *arr_first_max_r(const int *most, const int *a, size_t n) {
if (*a > *most) most = a;
return --n ? arr_first_max_r(most, ++a, n) : most;
}
to be called like this
printf("Biggest int is : %d\n", *arr_first_max_r(a, a, n));
This works. You detect the largest number like you did then run the same loop again to see where the number is then return that address. I also changed some data types from int to const int and I removed the 2nd parameter because you're checking for null characters.
#include <stdio.h>
#include <stdlib.h>
const int *arr_first_max(const int *a) {
const int *k;
int largest=0;
for (k = a; *k != '\0'; k++) {
if (*k > largest){
largest = *k;
}
}
for (k = a; *k != '\0'; k++) {
if (*k == largest){
return k;
}
}
}
int main(){
int nums[6]={7,2,1,5,4,6};
const int* y=arr_first_max(nums);
printf("%d\n", *y);
}
Assuming
the function's signature is correct and complete (arr_first_max alludes that you search in an array for the first max element)
and thus int* a is the pointer to the first element (i.e. equivalent to int a[] in a signature); I'll leave the const specifier in this case, though I think you could omit/discard it if the exercise permits that
size_t n is the size of the array or, in other words, the number of elements in the array
you want to return a pointer to largest element in the array without using the subscript [] operator
then this would be a solution
int *arr_first_max(const int *a, size_t n) {
int *largest, *k;
for (largest = k = a; (k - a) < n; k++)
if (*k > *largest)
largest = k;
return largest;
}
That is because I quote from The C Programming Language:
Pointer subtraction is also valid: if p and q point to elements of
the same array, and p<q, then q-p+1 is the number of elements from
p to q inclusive.
i won't guess what size_t n is for
int *arr_first_max( int *a, size_t n) {
int *largest = a;
while(*a){
a++;
if(*a>*largest) largest=a;
}
return largest;
}

Nothing works - references, pointers

void load(int *n, int *x, int **arr)
{
arr = (int**)malloc(sizeof(int*)*(*n));
for(int i = *n; i >= 0; i--)
{
scanf("%d", &arr[i]);
}
}
int main()
{
int n = 0, x = 0;
int *arr;
load(&n, &x, &arr);
printf("%d", arr[1]);
return EXIT_SUCCESS;
}
The program compiles properly, but it throws windows error during the printf() in main function. Displaying just "arr" gives random big numbers. What is wrong here?
arr = (int**)malloc(sizeof(int*)*(*n));
doesn't change anything in main, it only overwrites the copy of the pointer (address of arr in main) that load receives.
What the function should do is change arr in main, for that, you have to dereference the argument,
*arr = (int*)malloc(sizeof(int)*(*n)); // cast for C++ compiler left in
to change the value of arr in main. (The object that the argument arr of load points to, that is arr in main, needs to be changed, hence you need to modify *arr in load.)
The scans should then be
scanf("%d", &(*arr)[i]);
or (equivalent)
scanf("%d", *arr + i);
#include <stdio.h>
#include <stdlib.h>
void load(int *n, int *x, int **arr)
{
int i = 0;
*arr = (int*) malloc(*n * sizeof(int));
if(!*arr) {
perror("Can not allocate memory!");
return;
}
for(i = *n; i >= 0; i--)
{
scanf("%d", *arr + i);
}
return;
}
int main()
{
int n = 0, x = 0;
int *arr;
int i;
/* You probably need to initialize n */
n = 5;
load(&n, &x, &arr);
for(i = n; i >= 0; i--)
{
printf("%d - %d\n", i, arr[i]);
}
return EXIT_SUCCESS;
}

Resources