C - using to pointer to function yield no result - c

I am creating a program which uses a pointer to function to allow the user to select from 2 options to perform on an array of integers: reverse or randomise. However, the program yield no output when executed. Where did I go wrong?
void reverseArray(int arraySize, int a[]);
void randomiseArray(int arraySize, int a[]);
void printArray(int arraySize, int a[], void (*arrayFunction)(int arraySize, int a[]));
int main ()
{
srand(time(NULL));
int selection;
int myArray[] = {2,4,6,8,10,12,14,16,18,20};
printf("Enter 0 for reverse, 1 for randomise.\n");
scanf("%d",&selection);
if (selection == 0)
printArray(sizeof(myArray)/sizeof(myArray[0]),myArray,reverseArray);
else if (selection == 1)
printArray(sizeof(myArray)/sizeof(myArray[0]),myArray,randomiseArray);
else
printf("Please make a valid selection\n");
return 0;
}
void reverseArray(int arraySize, int a[])
{
int i,j=arraySize,swap=0;
for (i=0;i<arraySize/2;i++)
{
swap = a[i];
a[i] = a[j];
a[j] = swap;
--j;
}
}
void randomiseArray(int arraySize, int a[])
{
int i,j,swap;
for (i=0;i<arraySize;i++)
{
j = rand()%(i+1);
if (j!=i)
{
swap = a[i];
a[i] = a[j];
a[i] = swap;
}
}
}
void printArray(int arraySize, int a[], void (*arrayFunction)(int arraySize, int a[]))
{
arrayFunction(arraySize, a);
for (int i = 0; i < arraySize; i++)
{
printf("%d ", a[i]);
}
printf("\n");
}
The user selects when function they want to perform by typing either 0 for reverse or 1 for randomise. Based on the decision, a printArray function is called with the respective choice.
reverseArray is just a generic swap function, and randomiseArray uses a Fisher-Yates shuffling algorithm.
I am assuming that the source of my error lies in the printArray fucntion, yet I cannot correct it.

Two errors
in reverseArray, j should start at arraysize - 1 or you will be writing one element past the end of the array
void reverseArray(int arraySize, int a[])
{
int i, j = arraySize - 1, swap = 0;
for (i = 0; i<arraySize / 2; i++)
{
swap = a[i];
a[i] = a[j];
a[j] = swap;
--j;
}
}
And in randomizearray(), you assign to a[i] twice, instead of using a[j] for the final assignment.
void randomiseArray(int arraySize, int a[])
{
int i, j, swap;
for (i = 0; i<arraySize; i++)
{
j = rand() % (i + 1);
printf("%d %d\n", i, j);
if (j != i)
{
swap = a[i];
a[i] = a[j];
a[j] = swap;
}
}
}
The first error causes undefined behavior when reversing, the second causes the array to stay the same. Other than that, the function pointers are setup fine and work correctly.

In reverseArray() your index j is out of range, it should he j=arraySize-1
Other than that it works for me.

You are accessing outside the bounds of your array, causing UB and in this case "no output":
In reverseArray, you must initialize j=arraySize-1. Without the -1 you go out of bounds.

Related

I'm having issues with getting MergeSort to work in C

I'm having issues with getting my mergeSort algorithm to work properly. The code is below, but I'll briefly summarize what I have tried and what I know is not wrong with the code.
The mergeSort function takes a pointer to an array and the array's size as arguments. If the size of the array is less than 2, it returns immediately. I'm sure that this works, because I debugged this part several times. It returns 8 times, which is what I expected it to do.
Next, a variable mid is created as an index to split the array by. I tested it, and I'm pretty confident that mid is correct across all recursions. Then, two arrays are created, the first containing the elements from the indexes 0...mid-1 and the second containing the elements from the indexes mid to n. Next, the sizes of each of these arrays are computed. I tested this too, and the sizes seem correct across all recursions as well. mergeSort is called on the left array and the right array, and then merge is called.
The actual merge function takes a pointer to the original array, a pointer to the left array, a pointer to the right array, and two integer values which are the sizes of each of the left and right arrays. Then, it compares the elements in L and R and copies the smaller of the two into A, in order.
My output, however, is [2] [4] [1] [6] [8] [5] [3] [7]
My expected output is: [1] [2] [3] [4] [5] [6] [7] [8]
I'm genuinely not sure why the code isn't working. There's probably something I'm overlooking, but I've been trying to solve it for an hour and figured I'd ask for help.
If you take the time to answer, or attempt to answer this question, thank you for your time.
My code is below:
#include <stdio.h>
#include <stdlib.h>
void mergeSort(int *, int);
void merge(int *, int *, int, int *, int);
void print(int *, int);
int main() {
int A[8] = { 2, 4, 1, 6, 8, 5, 3, 7 };
int arraySize = sizeof(A) / sizeof(A[0]);
mergeSort(A, arraySize);
print(A, arraySize);
}
void mergeSort(int *A, int n) {
if (n < 2) {
return;
}
int mid = n / 2;
int L[mid];
int R[n - mid];
for (int i = 0; i < mid; i++) {
L[i] = A[i];
}
for (int j = mid; j < n; j++) {
R[j - mid] = A[j + mid + 1];
}
int leftSize = sizeof(L) / sizeof(L[0]);
int rightSize = sizeof(R) / sizeof(R[0]);
mergeSort(L, leftSize);
mergeSort(R, rightSize);
merge(A, L, leftSize, R, rightSize);
}
void merge(int *A, int *L, int leftSize, int *R, int rightSize) {
int i, j, k;
while (i < leftSize && j < rightSize) {
if (L[i] < R[j]) {
A[k] = L[i];
k++;
i++;
} else {
A[k] = R[j];
k++;
j++;
}
}
}
void print(int *A, int n) {
for (int i = 0; i < n; i++) {
printf("[%d] ", A[i]);
}
printf("\n");
}
There are multiple problems:
the intialization loop for R is incorrect: you should copy A[j] instead of A[j + mid + 1]
the merge function should copy the remaining elements from the left or right arrays once the test i < leftSize && j < rightSize fails.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
void mergeSort(int *, int);
void merge(int *, int *, int, int *, int);
void print(const int *, int);
int main() {
int A[8] = { 2, 4, 1, 6, 8, 5, 3, 7 };
int arraySize = sizeof(A) / sizeof(A[0]);
mergeSort(A, arraySize);
print(A, arraySize);
return 0;
}
void mergeSort(int *A, int n) {
if (n < 2) {
return;
}
int mid = n / 2;
int L[mid];
int R[n - mid];
for (int i = 0; i < mid; i++) {
L[i] = A[i];
}
for (int j = mid; j < n; j++) {
R[j - mid] = A[j];
}
int leftSize = sizeof(L) / sizeof(L[0]);
int rightSize = sizeof(R) / sizeof(R[0]);
mergeSort(L, leftSize);
mergeSort(R, rightSize);
merge(A, L, leftSize, R, rightSize);
}
void merge(int *A, int *L, int leftSize, int *R, int rightSize) {
int i, j, k;
while (i < leftSize && j < rightSize) {
if (L[i] <= R[j]) {
A[k++] = L[i++];
} else {
A[k++] = R[j++];
}
}
while (i < leftSize) {
A[k++] = L[i++];
}
while (j < rightSize) {
A[k++] = R[j++];
}
}
void print(const int *A, int n) {
for (int i = 0; i < n; i++) {
printf("[%d] ", A[i]);
}
printf("\n");
}

Error in merge sort program

I am doing a merge sort program in C but I'm getting some unexpected output.
Can anyone find out error in the program?
#include<stdio.h>
int array[100],n;
void merge(int l,int m,int h);
void mergesort(int start,int end);
main(){
int i;
printf("Enter Size: ");
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%d",&array[i]);
}
mergesort(0, n-1);
for(i=0;i<n;i++){
printf("%d\n",array[i]);
}
}
void mergesort(int start,int end){
int mid;
if(start<end){
mid=(start+end)/2;
mergesort(start,mid);
mergesort(mid+1,end);
merge(start,mid,end);
}
}
void merge(int start,int mid,int end){
int i,j,k;
int a1[100],a2[100];
for(k=0,i=start;i<=mid;i++,k++){
a1[k]=array[i];
}
for(k=0,j=i;j<=end;j++,k++){
a2[k]=array[j];
}
a1[mid]=999;
a2[j]=999;
i=0;j=0;
for(k=start; k <=end; k++)
{
if(a1[i]<=a2[j])
array[k]=a1[i++];
else
array[k]=a2[j++];
}
}
Output:
Enter Size: 5
1 2 3 2 3
2
2
3
3
-1818025592
For larger arrays, the output is more scrambled. I think there is an error in merge() function.
You are terminating your a1 and a2 arrays at the wrong location.
Try changing:
for(k=0,i=start;i<=mid;i++,k++){
a1[k]=array[i];
}
for(k=0,j=i;j<=end;j++,k++){
a2[k]=array[j];
}
a1[mid]=999;
a2[j]=999;
to
for(k=0,i=start;i<=mid;i++,k++){
a1[k]=array[i];
}
a1[k]=999;
for(k=0,j=i;j<=end;j++,k++){
a2[k]=array[j];
}
a2[k]=999;
When you create your temporary arrays:
for (k = 0, i = start; i <= mid; i++, k++) {
a1[k] = array[i];
}
a1[i] = 999;
you put a sentinel value with a high value at the end. But i is the index into the original array. You must use k, the index of the temporary array a1:
for (k = 0, i = start; i <= mid; i++, k++) {
a1[k] = array[i];
}
a1[k] = 999;
Even so, the double control structure with k and i is clumsy. And there's no need to guess a high number; <limits.h> has constants defined for the min and max values of most types:
k = 0;
for (i = start; i <= mid; i++) {
a1[k++] = array[i];
}
a1[k] = INT_MAX;
Here, you increment k when an item is appended. This works even when the assignment happens conditionally, i.e. not in all iterations.
Finally, I would recommend to use exclusive upper bounds. That's the natural way to express ranges in C. mid would then be both the exclusive upper bound of the left array and the inclusive lower bound of the right array.
I have solved it
a[mid + 1]=999
a[k]=999

Boubble sorting with arrays with C

#include <stdio.h>
int main(){
void sorting(){
int a[4];
a[0]=1;
a[1]=6;
a[2]=15;
a[3]=3;
a[4]=19;
int size = 4;
int t =1;
if (size ==0) return; // ie if you reach to the end stop
int i;
for (i=0;i<size-1;i++){
if(a[i+1] >a[i]) { //if the +1 element is bigger than before it do the swap
int j;
j= a[i+1];
a[i+1]=a[i]; //swap
a[i] = j; //swap
}
}
sorting(*a,size - 1);//recursion
void print_int() {
int i; // Loop counter
for (i = 0; i < 4; i++) {
printf("%d\n", a[i]);
}}
}
It compiles ok but when I try to run the file nothing appears? My intentions were to create an array sort them then display them.
Also, the code where the recursion happened "sorting(*a,size - 1);//"
if I tried to replace *a with a[] an error will happen. Why is that?
the error is "error expected expression before ']' token"!
thank you.
int a[4];
But you access a[4]=19; index 4 that is out of bound. You can access highest index 3.
I think function void sorting() should be defined outside main .Nested functions are GNU extensions in GCC.
Your code has to many problems. Here is a working Array sort:
#include <stdio.h>
void bubble_sort(int *array, int length){
int i,j, k, temp;
for (i = 0 ; i < length-1; i++){
for (k = 0 ; k < length-i-1; k++){
if (array[k] > array[k+1]){
temp = array[k];
array[k] = array[k+1];
array[k+1] = temp;
}
}
}
printf("The sorted Array List:\n\n");
for ( j = 0 ; j < length ; j++ ){
printf("%d ", array[j]);
}
}
int main(void){
int array[] = {1,6,15,3,19};
int length = sizeof array / sizeof array[0];
bubble_sort(array, length);
printf("\n");
return 0;
}
You should read about functions declarations and definitions.
About arrays you should know that if you declare:
int array[4];
Your working array is from 0 to 3 and not from 0 to 4.
Take a look at the following:
int main(void){
int array[] = {1,6,15,3,19};
int size = 5;
int i;
for(i=0;i<size;i++){
printf("%d ",array[i]);
}
return 0;
}
I have size=5 and not size=4- like you tried. You should be careful about number of Array elements.
Aside from all the problems spotted by others, you must repeatedly execute the for loop until no more exchanges are made, which is the standad way of bubbling. As you use recursion, it is of course nonsense to declare the array to be sorted (and its size) inside the function called recursively.

Function to remove an element from a sorted array

I have some problem with removing an element from a sorted array (all instances of an element must be removed). When I run my program, I get a segmentation fault. I have no idea why that happens, because the function remElem(int*, int*, int) where 1st arg is an array, 2nd arg is a length of an array (which changes when elements are removed) and 3rd arg is an element to be removed -- worked properly before I expanded the program with switch statement and onther functions like shuffle(int*, int) (for shuffling elements of an array) and insElem(int*, int*, int) (for inserting an element into a sorted array. I have no idea what went wrong, please help. I will provide the code with comments. There are also some other minor questions provided with the comments. Thank you in advance :)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX_LEN 1000
void initArray(int*, int);
void printArray(int*, int);
void swap(int*, int*);
void insSort(int*, int);
void insElem(int*, int*, int);
void remElem(int*, int*, int);
void shuffle(int*, int);
int main() {
int array[MAX_LEN];
int len, elem, comm;
srandom(time(NULL));
printf("Number of elements? >> ");
scanf("%d", &len);
initArray(array, len);
do {
printf("Command? (6 for help) >> ");
scanf("%d", &comm);
switch (comm) {
case 1:
printArray(array, len);
break;
case 2:
shuffle(array, len);
break;
case 3:
insSort(array, len);
break;
case 4:
printf("Insert element? >> ");
scanf("%d", &elem);
insElem(array, &len, elem);
break;
case 5:
printf("Remove element? >> ");
scanf("%d", &elem);
remElem(array, &len, elem);
break;
case 6:
printf("Help:\n");
printf("1 - Print\n");
printf("2 - Shuffle\n");
printf("3 - Sort\n");
printf("4 - Insert element\n");
printf("5 - Remove element\n");
printf("6 - Help (this screen)\n");
printf("0 - Quit\n");
break;
case 0:
break;
default :
printf("Wrong input! Repeat!\n");
}
} while (comm);
return EXIT_SUCCESS;
}
/*Initializes array with n random numbers from 0 to 9 (including)*/
void initArray(int a[], int n) {
int i;
for (i = 0; i < n; i++)
a[i] = random() % 10;
}
/*Prints n elements of an array*/
void printArray(int a[], int n) {
int i;
for (i = 0; i < n; i++)
printf("%d ", a[i]);
putchar('\n');
}
/*Swaps the values of two variables*/
void swap(int *i, int *j) {
*i = *i + *j;
*j = *i - *j;
*i = *i - *j;
/*I saved up some memory yaaaaaaay :3 */
/*I spent some processing time nooooo :| */
/*Which is better... with or without tmp variable???*/
/*I suppose it depends on application... clearly, this
method doesnt work with structures, for example*/
}
/*Sorts the elements of an array using insertion sort algorythm*/
void insSort(int a[], int n) {
int i, j;
for (i = 1; i < n; i ++)
for (j = i; j > 0 && a[j] < a[j-1]; j--)
swap(&a[j], &a[j-1]);
}
/*Inserts an element into a sorted array*/
/*Wassn meant to be working with unsorted arrays
in that case unpreddictable results*/
void insElem(int a[], int *n, int e) {
int i, j;
(*n)++;
for (i = 0; a[i] < e && a[i+1] < e; i++);
for (j = *n; j > i + 1; j--)
a[j] = a[j-1];
a[i+1] = e;
}
/*Removes an element from a sorted array*/
/*Wassn meant to be working with unsorted arrays
in that case unpreddictable results*/
void remElem(int a[], int *n, int e) {
int i, j;
for (i = 0; i < *n; i++) {
while (a[i] == e) {
for (j = i; j < *n; j++)
a[j] = a[j+1];
(*n)--;
}
}
}
/*Shuffles the elements of an array*/
/*I just did this on the fly...
are there any known algorythms for doing this*/
void shuffle(int a[], int n) {
int i;
for (i = 0; i < n; i++)
swap(&a[rand()%n], &a[rand()%n]);
}
The following can result in out-of-bounds access, leading to undefined behaviour:
for (j = i; j < *n; j++)
a[j] = a[j+1];
Consider what happens to a[j+1] when j == (*n)-1.
As to the swap() function, your clever-looking implementation is at risk of integer overflow and consequently undefined behaviour. Just use a temporary variable and let the compiler worry about efficiency.
In this cycle:
for (j = i; j < *n; j++)
a[j] = a[j+1];
When j = *n - 1, you will access memory that is outside of the array's bounds. This invokes undefined behavior and the result may be anything and so I believe it explains your crash. As for way the program did not crash before - well as this can do anything it may also have no negative effect.

QuickSort doesn't work for large inputs

Can anyone spot a problem with my quick sort implementation below? It seems to fail on arrays with more than 10 or so elements.
void swap(int *p1, int *p2)
{
int temp = *p1;
*p1 = *p2;
*p2 = temp;
}
void generateRandom(int arr[], int size)
{
srand(time(NULL));
int i;
for (i = 0; i < size; i++)
{
arr[i] = rand() % 100;
}
}
int partition(int arr[], int start, int end)
{
int i = start, j = end;
int pivot = arr[start];
for (;;)
{
for (; arr[i] < pivot; i++);
for (; arr[j] > pivot; j--);
if (i < j)
{
swap(&arr[i], &arr[j]);
}
else
{
return j;
}
}
}
void quickSort(int arr[], int start, int end)
{
int part;
if (start < end)
{
part = partition(arr, start, end);
quickSort(arr, start, part);
quickSort(arr, part + 1, end);
}
}
int main()
{
generateRandom(arr, 100);
for (i = 0; i < 100; i++)
{
printf("%d ", arr[i]);
}
printf("\n\n");
quickSort(arr, 0, 99);
for (i = 0; i < 100; i++)
{
printf("%d ", arr[i]);
}
printf("\n\n");
return 0;
}
First, you code doesn't compile. When I made the corrections to make it compile (adding stdio.h, and definitions for arr and i in main) it infinite looped, which it will do if the partition starts and ends with the pivot. You need to increment and decrement before the comparisons rather than after. You can do that by starting with i = start-1 and j = end+1 and changing your inner loops to increment or decrement first, or you can leave them as is and just do an i++ and j-- after the swap -- I did that and the sort works.
Note that your pivot choice is poor for already sorted arrays; you really should be picking the median of 3 or even 9 values.
P.S. Other desirable optimizations: 1) Switch to an insertion sort for small partitions -- the optimal cutoff point is machine-dependent. Another approach is to not sort partitions below a certain size, and then do an insertion sort on the whole array after quicksort is done. It's also possible to use heapsort instead of insertion sort if done carefully; google introsort. 2) quicksort does two recursive calls; eliminate the second one by setting start = part + 1 and looping. 3) Avoid the possibility of stack overflow by quicksorting the larger partition first. 4) Eliminate the first recursive call by using an explicit stack. 5) Inline swap() and partition(). 6) Don't bother with any of that and just call the qsort library routine. :-)
I had the same problem,
but I changed my while loop to do..while and it worked.
This is my new code now.
int partition(int a[], int lo, int hi) {
int v = a[lo], i = lo, j = hi;
do {
do {
i++;
} while(a[i] < v) ;
do {
j--;
}while(a[j] > v) ;
if(i < j) interchange(&a[i], &a[j]);
}while(i < j);
interchange(&a[lo], &a[j]);
return j;
}

Resources