Home > Back-end >  How can assign only the three largest integers from a for loop in C into three separate variables?
How can assign only the three largest integers from a for loop in C into three separate variables?

Time:04-21

I am trying to make a program that takes two user inputs (x and y), checks all numbers in the interval for all prime numbers, and then prints only the three largest prime numbers if available. So far, my code checks all the prime numbers in an interval starting from the largest to the smallest.

My code:

#include <stdio.h>
#include <stdlib.h>

void inputXY(int *x, int *y) {
    printf("Enter value of x: ");
    scanf("%d", x);
    printf("Enter value of y: ");
    scanf("%d", y);
}

void swap(int*x, int*y){
    int temp;
    temp = *x;
    *x=*y;
    *y=temp;
}

int primechecker(int divisor,int dividend){ 
    if(dividend==divisor) return 1; 
    else if(dividend%divisor==0) return 0;
    else primeChecker(divisor 1,dividend);
    }

void largestonly(int*counter, int*largest1, int*largest2, int*largest3){
    int temp;
    temp=*counter;
    if (temp>*largest1&&*largest2) ///incomplete attempt
}

void printlargest(int *x, int *y, int*largest1, int*largest2, int*largest3){ ///I do not know if this would work, since I have not equated largest1, largest2, and largest3 to zeroes. My idea here is that, if any specific variables are empty, different specific lines  should be printed.
    if (*largest1==0&&(*largest2&&*largest3!=0)) {
        printf("There are two prime numbers: ");
        printf("%d, %d", *largest2, *largest3);
    }
    else if (*largest1&&*largest2==0&&*largest3!=0){
        printf("There is only one prime number: ");
        printf("%d", *largest3);
    }
    else if (*largest1&&*largest2&&largest3!=0){
        printf("The three largest prime numbers between %d and %d are: ", *x, *y);
        printf("%d, %d, %d", *largest1, *largest2, *largest3);
    }
    else if (*largest1&&*largest2&&largest3==0){
        printf("No prime numbers found!");
    } 

}
int main(){
    int x,y,largest1, largest2, largest3, counter, divisor, dividend, i;
    divisor=2;
    dividend=counter;
    inputXY(&x, &y);
    if ((x&&y==0),(x&&y==1)) printf("Invalid range!\n");
    if (x>y) swap(&x, &y);
    for (i=0; i<=3; i  ){
        for(counter=y;counter>=x;counter--) {
            if (primechecker(divisor,counter)==1) largestonly(&counter, &largest1, &largest2, &largest3);
        }
    }
    printlargest(&x, &y, &largest1, &largest2, &largest3);
    return 0;
}

I have yet to successfully write a working function that can sort all the integers produced by the for loop in main(). It is the largestonly() function as seen above. In relation to that, my printlargest() function undoubtedly does not work. My idea in here is that if largest1 does not contain any value (or is equal to 0 or some other more appropriate value that I could not think of), the function will only print the two largest prime numbers found. Relatively, if both largest1 and largest2 are empty, only the largest prime number will be printed. If all variables are empty, it should print "No prime numbers found!". I am very lost with what to do with my code at the moment so any type of help will be greatly appreciated. Thank you.

CodePudding user response:

First, define how you would check for a prime number:

bool is_prime(int num)
{
    if (num < 2)
        return false;
    
    for (int i = 2; i <= num / i;   i)
        if (num % i == 0)
        return false;
    
    return true;
}

Then, define a function that returns the 3 largest prime numbers in a given interval:

void get_max_3_in_range(int lo, int hi, int *max1, int *max2, int *max3)
{
    *max1 = 0; // smallest
    *max2 = 0;
    *max3 = 0; // largest
    
    int round = 0;
    
    for (int i = lo; i <= hi;   i) {
        if (is_prime(i)) {
            if (round % 3 == 0) *max1 = i;
            if (round % 3 == 1) *max2 = i;
            if (round % 3 == 2) *max3 = i;
              round;
        }
    }
    
    if (*max1 > *max2) swap_int(max1, max2);
    if (*max2 > *max3) swap_int(max2, max3);
}

Here is your swap():

void swap_int(int *v1, int *v2)
{
    int tmp = *v1;
    *v1 = *v2;
    *v2 = tmp;
}

Driver program:

int main(void)
{
    int x, y;
    inputXY(&x, &y);
    
    int max1, max2, max3;
    get_max_3_in_range(x, y, &max1, &max2, &max3);
    
    printf("x = %d\ty = %d\n", x, y);
    printf("max1 = %d\tmax2 = %d\tmax3 = %d\n", max1, max2, max3);
}

Output:

Enter value of x: 0
Enter value of y: 100
x = 0   y = 100
max1 = 83   max2 = 89   max3 = 97

You can choose what to output in case one or more of the maximums is/are zero. Here, I chose to print them all.


Side note: Your inputXY() is very error-prone. Because if the user enters a string, your code will break. scanf() returns a value that you must check.

Following is a better version:

void inputXY(int *x, int *y)
{
    for(;;) {
        printf("Enter value of x: ");
        if (scanf("%d", x) != 1)
            flush_stdin();
        else
            break;
    }
    
    flush_stdin();
    
    for(;;) {
        printf("Enter value of y: ");
        if (scanf("%d", y) != 1)
            flush_stdin();
        else
            break;
    }
}

And flush_stdin() (Never do fflush(stdin)!!) will clear what remained in the buffer, in case the user didn't enter (just) a number:

void flush_stdin(void)
{
    scanf("%*[^\n]");
}

CodePudding user response:

There are a few things to do here.

First, pay attention to the line 21, you call a primeChecker() function that doesn't exist. It will raise an error when compiling.

Second, you don't have to "sort" anything. You only have to store the prime numbers into the variables as they arrive. I noticed you consider largest3 to be the first one that has to be filled (at least it is what can be understood from printlargest()), this gives us the following:

void largestonly(int counter, int* largest1, int* largest2, int* largest3){
    if(*largest3 == 0) 
        *largest3 = counter;
    else if(*largest2 == 0)
        *largest2 = counter;
    else if(*largest1 == 0)
        *largest1 = counter;
}

Additionally, there is no need to pass the address of counter in the first place, as you won't need to modify it.

Lastly, in the main() function, you don't need a double loop. Think of it this way. If you were to do the exercise mentally, you'd go down the numbers, check if they were primes, and write them down if they satisfy the conditions: being primes and being the first, second or third. You wouldn't need to do it 3 times. Hence:

int main(){
    int x,y;
    inputXY(&x, &y);
    int largest1 = 0;
    int largest2 = 0;
    int largest3 = 0;
    int divisor = 2;
    if ((x&&y==0),(x&&y==1)) printf("Invalid range!\n");
    if (x>y) swap(&x, &y);
    for(int counter=y;counter>=x;counter--) {
        if (primechecker(divisor,counter)==1) 
            largestonly(counter, &largest1, &largest2, &largest3);
    }
    printlargest(&x, &y, &largest1, &largest2, &largest3);
    return 0;
}

Also, the way you declared your variables without initializing them can sometimes be dangerous. In this case, as largest1, largest2 and largest3 weren't set to 0, you'd have had no chance to trigger any of the printlargest() cases. It may be because you were stuck on a part of your program you thought would also handle that but I still want to point it out, just in case.

EDIT: you could also add a condition in the for loop such that if largest1 is not equal to 0, it exits the loop. It would prevent the program to loop through (potentially) big amount of numbers when you already have everything you need. It would look like this (with the existing for loop, for context):

for(int counter=y;counter>=x;counter--) {
    if (primechecker(divisor,counter)==1) 
        largestonly(counter, &largest1, &largest2, &largest3);
    if(largest1 != 0)
        break;
}

Hope this clears out the issues you had, feel free to ask anything if necessary, or to point out things I'd have misunderstood in your question.

Here's the full code:

#include <stdio.h>
#include <stdlib.h>

void inputXY(int *x, int *y) {
    printf("Enter value of x: ");
    scanf("%d", x);
    printf("Enter value of y: ");
    scanf("%d", y);
}

void swap(int*x, int*y){
    int temp;
    temp = *x;
    *x=*y;
    *y=temp;
}

int primechecker(int divisor,int dividend){ 
    if(dividend==divisor) return 1; 
    else if(dividend%divisor==0) return 0;
    else primechecker(divisor 1,dividend);
    }

void largestonly(int counter, int* largest1, int* largest2, int* largest3){
    if(*largest3 == 0) 
        *largest3 = counter;
    else if(*largest2 == 0)
        *largest2 = counter;
    else if(*largest1 == 0)
        *largest1 = counter;
}

void printlargest(int *x, int *y, int*largest1, int*largest2, int*largest3){ ///I do not know if this would work, since I have not equated largest1, largest2, and largest3 to zeroes. My idea here is that, if any specific variables are empty, different specific lines  should be printed.
    if (*largest1==0&&(*largest2&&*largest3!=0)) {
        printf("There are two prime numbers: ");
        printf("%d, %d", *largest2, *largest3);
    }
    else if (*largest1&&*largest2==0&&*largest3!=0){
        printf("There is only one prime number: ");
        printf("%d", *largest3);
    }
    else if (*largest1&&*largest2&&largest3!=0){
        printf("The three largest prime numbers between %d and %d are: ", *x, *y);
        printf("%d, %d, %d", *largest1, *largest2, *largest3);
    }
    else if (*largest1&&*largest2&&largest3==0){
        printf("No prime numbers found!");
    } 

}
int main(){
    int x,y;
    inputXY(&x, &y);
    int largest1 = 0;
    int largest2 = 0;
    int largest3 = 0;
    int divisor = 2;
    if ((x&&y==0),(x&&y==1)) printf("Invalid range!\n");
    if (x>y) swap(&x, &y);
    for(int counter=y;counter>=x;counter--) {
        if (primechecker(divisor,counter)==1) 
            largestonly(counter, &largest1, &largest2, &largest3);
    }
    printlargest(&x, &y, &largest1, &largest2, &largest3);
    return 0;
}
  •  Tags:  
  • c
  • Related