Why is my base case being (erroneously) triggered immediately? - c

I am trying to implement a merge sort algorithm in C. In the recursive array split function, my base case is occurring infinitely, despite the return statement, and the merge function is never called. Here is my code:
#include <stdio.h>
const int MAX = 1000;
int getArray(int unsorted[MAX], int upperBound)
{
int i;
for(i = 0; i <= upperBound; ++i)
{
printf("Now enter integer number %d: ", i + 1);
scanf("%d", &unsorted[i]);
while((getchar()) != '\n');
}
printf("\n");
return 0;
}
int merge(int unsorted[MAX], int sorted[1000], int lowerLeft, int lowerRight)
{
if(lowerLeft == lowerRight)
return 0;
int j = lowerRight;
for(int i = lowerLeft; i < lowerRight; ++i)
{
if(unsorted[i] <= unsorted[j])
{
sorted[i] = unsorted[i];
++j;
}
else
{
sorted[i] = unsorted[j];
++j;
}
}
return 1;
}
int split(int unsorted[MAX], int sorted[1000], int lowerBound, int upperBound)
{
printf("%d is the lBound and %d is the uBound\n", lowerBound, upperBound);
if(lowerBound == upperBound)
{
printf("\nBase case triggered.");
getchar();
return 0;
}
int middle = upperBound/2;
split(unsorted, sorted, 0, middle);
split(unsorted, sorted, middle + 1, upperBound);
merge(unsorted, sorted, lowerBound, middle);
return 1;
}
int main()
{
int unsorted[MAX];
int sorted[MAX];
int lowerBound = 0;
int upperBound;
printf("First enter the number of integers you wish to sort: ");
scanf("%d", &upperBound);
while((getchar()) != '\n');
printf("\n");
upperBound = upperBound - 1;
getArray(unsorted, upperBound);
split(unsorted, sorted, lowerBound, upperBound);
printf("\n");
for(int c = 0; c < upperBound; ++c)
{
printf("%d, ", sorted[c]);
}
return 0;
}
Why won't the merge function be called after reaching the base case? Sorry if I didn't phrase the question conveniently, hoping someone can help me out here, thanks.

Your base case is being triggered because that's how recursive algorithms work. You keep calling split() over and over again with a lower and lower gap between lowerBound and upperBound, so eventually your base case gets triggered. And that should be a good thing, since triggering the base case lets you know that your input "arrays" (singletons) are sorted and can be merged.
The reason it gets triggered "immediately" is that it must: split() gets called continually until the base case is met, so the first print statement you'll see is the base case one.

Related

A little problem with functions and arrays

I'm doing a program that check if 5 numbers that the user insert are even or odd, then they will be stored into an array and finally these values will be printed out on screen. In order to do this i've divided this program in two functions just to understand how the functions and the arrays works together, but it doesn't print the values that i've putted in. Why?
int check_even_and_odd(int number, int list[]){
printf("Insert the numbers\n");
scanf("%d", &list[number]);
if (number % 2 == 0) {
printf("Even\n");
}
else{
printf("Odd\n");
}
return 0;
}
int main () {
int k;
int i = 0;
int list2[5] = {0};
while (i < 5) {
i++;
k = check_even_and_odd(i, &list2[i]);
}
i = 0;
while (i < 5) {
i++;
printf("\n%d\n", list2[i]);
}
return 0;
}
Edit: Now that the main issue is gone, I want to add a little improvement to this little project. I want that the program tells to me how many Even or Odd number are in the array, but i don't know how to do it. I was thinking about adding 2 counters into the if statement (one for the even number and one for the odd numbers) but once i do this i don't know how to continue.
The program with the counters is this:
void check_even_and_odd(int number, int list[]){
int even = 0;
int odd = 0;
printf("Insert the numbers\n");
scanf("%d", &list[number]);
if (number % 2 == 0) {
even++;
}
else{
odd++;
}
printf("Even numbers are: %d\n", even);
printf("Odd numbers are: %d\n", odd);
}
int main () {
int i = 0;
int list2[5] = {0};
while (i < 5) {
i++;
check_even_and_odd(i, list2);
}
i = 0;
while (i < 5) {
i++;
printf("\n%d\n", list2[i]);
}
return 0;
}
Obviously it isn't complete, but as i have already said, i don't know how to continue
Your function expects an array argument but you are passing the address of individual elements of the array, so it won't work properly, you'll just need to use the correct argument:
k = check_even_and_odd(i, list2);
Quibble: k is never used so you don't really need it. You can just make your function void and remove the variable:
void check_even_and_odd(int number, int list[]){
printf("Insert the numbers\n");
scanf("%d", &list[number]);
if (number % 2 == 0){
printf("Even\n");
}
else{
printf("Odd\n");
}
}
int main(){
int i = 0;
int list2[5] = {0};
while (i < 5){
i++;
check_even_and_odd(i, list2);
}
i = 0;
while (i < 5){
i++;
printf("\n%d\n", list2[i]);
}
return 0;
}
Your fault is in line scanf("%d", &list[number]); just need to change it to scanf("%d", &list); but i think you are miss understanding whole array and pointer logic. You can't pass list as argument and if you do that, The compiler will changed it to pointer automatically. So if you want to tell a function about your list you just have to pass it your list address in memory (pointer). So you should do it like:
#include <stdio.h>
int How_Many_Odd = 0;
int How_Many_Even = 0;
void Add_To_List(int Number, int *ListIndex){
printf(
"Number %d is %s\n",
Number,
(Number % 2 == 0)? "Even": "Odd" // check if is odd or even
);
if(Number % 2 == 0)
How_Many_Even++;
else
How_Many_Odd++;
// changing value of pointer ListIndex to Number
*ListIndex = Number;
}
int main(){
// first creating integer array with size of 5
int List[5];
for(int i=0; i < 5; i++){
// waiting for user to enter number
int value;
scanf("%d", &value);
// changing value of index 0 to 3
Add_To_List(value, &List[i]);
}
// showing how many odds and how many evens
printf("%d numbers are even and %d numbers are odd\n", How_Many_Even, How_Many_Odd);
// you can show every index value too
for(int i=0; i < 5; i++)
printf("value of index %d is %d\n", i, List[i]);
return 0;
}
I recommend you to learn about pointer that will fix your issues
Here is your code fixed:
#include <stdio.h>
void check_even_and_odd(int number, int list[], unsigned int *even_count)
{
printf("Insert the numbers\n");
scanf("%d", &list[number]);
if (number % 2 == 0) {
printf("Even\n");
*even_count += 1;
}
else
{
printf("Odd\n");
}
}
int main()
{
unsigned int even_count;
int i = 0;
int list2[5] = {0};
while (i < 5)
{
check_even_and_odd(i, list2, &even_count);
i++;
}
i = 0;
while (i < 5)
{
printf("\n%d\n", list2[i]);
i++;
}
printf("There are %d even numbers and %d odd ones.\n", even_count, 5 - even_count);
return 0;
}
Basically, your main problem is in passing the list to the function in k = check_even_and_odd(i, &list2[i]);, as you should be passing the entire list, not a specific number in the list.
regarding:
if (number % 2 == 0) {
This is checking the passed in parameter rather than the value entered by the user. Suggest:
...
if( (list[number] % 2) == 0 )
{
printf( "%s\n", "number is even" );
....

Delete last input even number from array using stack

I'm a beginner at C programming. I'm making a program that will input numbers and delete the last input even number from the array using stack or the push-pop method.
The problem is I can't pop the last even number and I don't know what is wrong.
#include <stdio.h>
#include <stdlib.h>
#define MAX 100
int top = -1;
int stack[MAX];
void deleteEven(int num[], int i);
int main() {
int num[100];
int i, size;
printf("\n-----------------\n\n");
printf("Enter size of array: ");
scanf("%d", &size);
for (i = 0; i < size; i++) {
printf("Enter number: ");
scanf("%d", &num[i]);
top++;
stack[top] = num[i];
}
printf("\nList: ");
for (i = 0; i < size; i++) {
printf("%d, ", num[i]);
}
printf("\n");
printf("Even: ");
for (i = 0; i < size; i++) {
if (num[i] % 2 == 0) {
printf("%d, ", num[i]);
}
}
deleteEven(num, i);
return 0;
}
void deleteEven(int num[], int i) {
printf("\nAnswer: ");
if (num[i] % 2 == 0) {
stack[top--];
}
for (int j = top; j >= 0; --j) {
printf("%d, ", stack[j]);
}
}
I have implement the working one in C with implementing on your code, you can see below. I added int checkEven(int stack[], int stackSize) function which control the array if there is any even number or not. If not, so end the problem with returning 0 or whatever your error code is, other side if there is even number it returns the index of it and deleteEven function swipe the array (stack). It working for size of 5 array but you can fix it. I use 5 for easy testing.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAX 5
int top = -1;
int stack[MAX];
void deleteEven(int num[], int indexOfEven);
int checkEven(int stack[], int stackSize);
int main() {
int num[5];
int i, size;
printf("\n-----------------\n\n");
printf("Enter size of array: ");
scanf("%d", &size);
for (i = 0; i < size; i++) {
printf("Enter number: ");
scanf("%d", &num[i]);
top++;
stack[top] = num[i];
}
printf("\nList: ");
for (i = 0; i < size; i++) {
printf("%d, ", num[i]);
}
printf("\n===stack===");
for( i = 0; i <size; i++){
printf("%d ", stack[i]);
}
int indexOfEven = checkEven(stack,5);
if(indexOfEven >= 0){
printf("This sequence has even number");
printf("the index => %d ",indexOfEven);
deleteEven(stack, indexOfEven);
}else{
printf("this sequence has no even number");
/*
no even number
exit
*/
return 0;
}
return 0;
}
int checkEven(int stack[], int stackSize){
for(int i = stackSize - 1; i >= 0; i--){
if(stack[i] % 2 == 0){
return i;
}
}
return -1;
}
void deleteEven(int num[], int indexOfEven) {
int simpleArray[5];
for(int t = 0; t < 5; t++){
simpleArray[t] = num[t];
}
int c;
for (c = indexOfEven; c < 4; c++)
simpleArray[c] = num[c+1];
for (c = 0; c < 4; c++){
printf("\n%d\n", simpleArray[c]);
}
}
So far you see the O(n) implementation of it with array but you describe that you want to implement it with push() - pop() - peek() stack mechanism. I want to write sudo code for fully Stack implementation.
let it inputs be 1 - 2 - 3 - 5 - 7
describe inputSize
describe mainStack
describe helperStack
read inputs to mainStack
show stacks
mainStack -> [1-2-3-5-7]
helperStack -> []
while mainStack.peek() != NULL :
if mainStack.peek() % 2 == 0: // even number
mainStack.pop()
break the loop
else:
describe popValue = mainStack.pop()
helperStack.push( popValue )
if inputSize == helperStack:
// no even number
// so nothing break the loop, every value is odd so, all there is another stack
// finish program with error code or return main array / inputs
show stacks
mainStack -> [ 1 ]
helperStack -> [ 3 5 7 ]
now pop() the all helperStack and push it to mainStack
while helperStack.peek() != NULL:
mainStack.push( helperStack.pop() )
show stacks
mainStack -> [ 1 3 5 7 ]
helperStack -> [ ]
Return mainStack as array format.
It seems that the last loop before the call to deleteEven will increment i until the end of the stack array regardless the last number is even or not, because all you do is checking if the current number is even and then printing it, and right after that going to the next one. that will iterate through all the numbers which will result in calling deleteEven with the last index of the array.
how about going from the last element of the array to index 0 (backwards) and printing the first encounter with even number?
Also, not really sure why you're using two different arrays and copying elements one by one after using scanf.

C recursive program to print all prime factors of a given number from the biggest factor to the smallest

i'm trying to write a program that print the prime factors of a given number ,but i need to print them from the biggest factor to the smallest, for example:
for the input 180 the output will be: 5*3*3*2*2,
any suggestions? here is what i got for now :
#include<stdio.h>
void print_fact(int n)
{
if (n==1)
return;
int num=2;
while (n%num != 0)
num++;
printf("*%d",num);
print_fact (n/num);
}
int main ()
{
int n;
printf("please insert a number \n");
scanf("%d",&n);
print_fact(n);
}
for this code the output is :
*2*2*3*3*5
You can simply print the output after the recursive call returns. You need to slightly modify how you display the *, which I leave to you.
#include<stdio.h>
void print_fact(int n)
{
if (n==1)
return;
int num=2;
while (n%num != 0)
num++;
// printf("*%d",num); // remove from here
print_fact (n/num);
printf("%d ",num); // put here
}
int main ()
{
int n;
printf("please insert a number \n");
scanf("%d",&n);
print_fact(n);
}
The output this gives on input 180 is:
5 3 3 2 2
Aside, there are much more efficient ways of actually finding the numbers though.
It is much faster to find them in the ascending order, mathematically speaking. Much, much faster.
The solution, if you don't want to bother yourself with dynamic arrays, is recursion. Find the lowest prime factor, recurse on the divided out number (num /= fac), and then print the earlier found factor, which will thus appear last.
to change the order in which they are printed, you could put the printf statement after the print_fact statement. To get rid of thew leading *, you would probably want to store the results and display them after computation
well, i'm trying to optimize my algorithm
this is my code for now:
functions code
#include "prime_func.h"
int divisors(int x) /* Function To set the maximum size of the future array,
Since there is no way to find the number of primary factors
without decomposing it into factors,
we will take the number of total number divisors
(which can not be greater than the number of primary factors) */
{
int limit = x;
int numberOfDivisors = 0;
if (x == 1) return 1;
for (int i = 1; i < limit; ++i) {
if (x % i == 0) {
limit = x / i;
if (limit != i) {
numberOfDivisors++;
}
numberOfDivisors++;
}
}
return numberOfDivisors;
}
void find_fact(int n, int *arr, int size, int i) //func to find the factors and apply them in allocated array
{
int num = 2;
if (n < 2)
{
printf("error\n");
return;
}
while (n%num != 0)
num++;
arr[i++] = num;
find_fact(n / num, arr, size, i);
}
void print_fact(int *arr, int size) // func to print the array in reverse
{
int i = 0;
int first;
first = FirstNumToPrint(arr, size);
for (i = first; i>0; i--)
printf("%d*", arr[i]);
printf("%d", arr[0]);
}
int FirstNumToPrint(int *arr, int size) // func to find the first number to print (largest prime factor)
{
int i;
for (i = 0; i < size; i++)
if (arr[i] == 0)
return i - 1;
}
int first_prime(int num) // for now i'm not using this func
{
for (int i = 2; i<sqrt(num); i++)
{
if (num%i == 0)
{
if (isprime(i));
return(i);
}
}
}
bool isprime(int prime) // for now i'm not using this func
{
for (int i = 2; i<sqrt(prime); i++)
{
if (prime%i == 0)
return(false);
}
return(true);
}
main code
#include "prime_func.h"
int main()
{
int n,i=0; // first var for input, seconde for index
int *arr; // array for saving the factors
int size;//size of the array
printf("please insert a number \n");// asking the user for input
scanf("%d", &n);
size = divisors(n); //set the max size
arr = (int *)calloc(size,sizeof(int)); //allocate the array
if (arr == NULL) // if the allocation failed
{
printf("error\n");
return 0;
}
find_fact(n, arr,size,i);// call the func
print_fact(arr,size); //print the result
free(arr); // free memo
}
#WillNess #GoodDeeds #mcslane

While loop with user input validation to fill array, then search array for largest number.

I am working on a program that will accept user input to fill an array and then quit when the user enters q. Next the array is passed to a function that finds the largest value in the array. My program seems like it would work, but I believe that user input for the array is incorrect and I am not sure how to solve it.
#include <stdio.h>
#define SIZE 30
int maxnum(int userarray[], int maxx);
int main()
{
int i;
int nums[SIZE];
int largest;
printf("Type integer numbers (up to 30), followed by q to quit:\n");
while(scanf("%d", &nums[i]) == 1)
{
for(i = 0; i < SIZE; i++)
{
//blank
}
}
largest = maxnum(nums, SIZE);
printf("The largest number is: %d\n", largest);
return 0;
}
int maxnum(int userarray[], int maxx)
{
int i;
int maxnumber;
maxnumber = userarray[0];
for(i = 1; i < maxx; i++)
{
if(maxnumber < userarray[i])
{
maxnumber = userarray[i];
}
}
return maxnumber;
}
First i is unitialized.
Then your inner for loop is strange (why someone would do that??) and sets i to SIZE in the end, which is not good.
I don't give more details, but the value of i is trash all the time because of those 2 mistakes it should be:
int i = 0;
while((i<SIZE) && (scanf("%d", &nums[i]) == 1))
{
i++;
}
so you read one by one, and protect against array out of bounds by the second condition.
After that you're passing NUMS
largest = maxnum(nums, SIZE);
whereas the array could contain fewer valid values. Just pass
largest = maxnum(nums, i);
Here is another solution for your problem.
In main() function
int n,i=0;
while(scanf("%d",&n) == 1){
nums[i++] = n;
}
n = maxnum(nums, i);
printf("The largest number is: %d\n", n);
Note : Initialize the value of i=0, Then input and update nums[] array
In maxnum() function
for(i = 0; i < maxx; i++) {
if(maxnumber < userarray[i]){
maxnumber = userarray[i];
}
}
Note: Start i=0 and find the max mumber and return the value

high low values in array print in between

code is used to scan integers into an array the loop is to stop scanning when 0 is input.
after values are scanned in the highest and lowest values inside the array are to be found
after finding high and low , print the values between the the array indexs of high and low
so if input 5,2,8,7,6,12,6,4,5
output should be 2,7,6,12
my program fails after it scans in the input values and 0 is input to end the loop
#include <stdio.h>
int main(){
int high=4;
int low,i;
int array[25];
int count=0;
printf("Please input numbers for array:");
for(i=0;array[i]!=0;i+=1){
scanf("%d",&array[i]);
count+=1;
}
for(i=0;i<count;i+=1){
if(array[i]>array[high]){
high=i;
}
}
low=high;
for(i=0;i<count;i+=1){
if(array[i]<array[low]){
low=i;
}
}
for(i=low;low<=high;i+=1){
printf("%d,",array[i]);
}
}
The for loop checks the condition before each iteration, so in
array[i]!=0
you are checking uninitalized value, before reading in array[i]. If it doesn't happen to find a zero hanging around somewhere in memory, this can go on reading more than 25 values, it can even go on and on till you get a stack overflow.
Also, in the other for loops, you probably meant
i < count
The condition
low<high
is just really not appropriate.
Here is a version that should work more like expected:
#include <stdio.h>
int main(){
int high;
int low,i;
int array[25];
int count=0;
int start;
int end;
printf("Please input numbers for array:");
for (i = 0; scanf("%d", &array[i]), array[i] != 0; i += 1) {
count+=1;
if (i >= 25) {
printf("Unable to handle more than 25 input values\n");
break;
}
}
high = 0;
for (i = 1; i < count; i += 1) {
if (array[i] > array[high]) {
high = i;
}
}
low = 0;
for (i = 1; i < count; i += 1) {
if (array[i] < array[low]) {
low=i;
}
}
if (low < high) {
start = low;
end = high;
}
else {
start = high;
end = low;
}
for (i = start; i <= end; i += 1) {
printf("%d", array[i]);
if (i != end) {
printf(",");
}
else {
printf("\n");
}
}
}
#include <stdio.h>
int main(){
int low, high, array[25];
int i, count=0;
printf("Please input numbers for array:");
for(i=0;i<25;++i){
int data;
scanf("%d", &data);
if(data==0)
break;
array[count++]=data;
}
low = high = 0;
for(i=1;i<count;++i){
if(array[i]<array[low])
low=i;
if(array[i]>array[high])
high=i;
}
for(i=low;i <= high;i++){
printf("%d,", array[i]);
}
}
I've got your code working after some minor changes
#include <stdio.h>
int main()
{
int high=0; // high value assumed to be zero for ease of understanding
int low=0,i; // low value assumed to be zero for ease of understanding
int array[25];
int count=0;
printf("Please input numbers for array:");
for(i=0;;i+=1){
scanf("%d",&array[i]);
count+=1;
if(array[i]==0) // Whenever is zero is read the loop is immediately exited, otherwise looping is continued
break;
}
count--; // decrement one count (count of zero)
for(i=1;i<count;i+=1){
if(array[i]>array[high]){
high=i;
}
}
for(i=1;i<count;i+=1){
if(array[i]<array[low]){
low=i;
}
}
for(i=low;i<=high;i+=1){ //printing from low value upto high value
printf("%d,",array[i]);
}
}

Resources