Breaking out of a loop without a break statement [C] - c

How do you break out of a loop without a break statement? My professor HATES break statements and tells us not to use it. I'm just curious how would I break out of the while-loop if the number I got WAS NOT a prime number?
Here's my code:
#include <stdio.h>
#include <stdlib.h>
/* Prototypes */
void primeChecker(int num1);
int main() {
int num1 = 5;
primeChecker(num1);
return 0;
}
void primeChecker(int num1) {
int i, flag = 0;
printf("Enter a number to check for prime numbers: ");
scanf("%d", &num1);
/* Number to start with */
i = 2;
while (i <= num1/2) {
if (num1 % i == 0) {
flag = 1;
} else {
i++;
}
}
if (flag == 0) {
printf("The number is a prime number!");
} else {
printf("The number is NOT a prime number!");
}
}

Or
int prime = 1;
while (i <= num1/2 && prime) {
if (num1 % i == 0){
prime = 0;
} else {
i++;
}
}
if(prime){
printf("The number is a prime number!");
}else{
printf("The number is not prime.");
}
I mean, you almost had it:
while (i <= num1/2 && !flag){
would have done the trick as well

You can do
while (i <= num1/2) {
if (num1 % i == 0) {
i = num1;
} else {
i++;
}
}
This makes i larger then num1/2 and the while loop exits.
You probably need some more changes to make this work.

In your case, you can use the value of flag as condition:
while (flag == 0 && i <= num1/2) {
if (num1 % i == 0) {
flag = 1;
} else {
i++;
}
}
But that looks like Pascal rather than C. A better solution might be to refactor the loop so that it is in a separate function:
int is_prime(int num1)
{
int i = 2;
while (i <= num1/2) {
if (num1 % i == 0) return 0;
i++;
}
return 1;
}
This makes the code simpler and separates the input stuff in primeChecker from the actual prime checking.

Related

CS50 credit doesn't run for some numbers

My code seems to work on some credit card numbers but for others it doesn't even run. I've tried to use long long for the credit card number but it didn't worked. I've spent like 2 hours trying to solve this issue but I can't figure it out. All help is welcomed :)
int main(void)
{
// Get credit card number
long num = get_cc_number();
// Check if the credit card number is valid
valid = check_sum(num);
// Check the length of the credit card number
length = check_length(num);
// Get the first two digits of the credit card number and first number of VISA
digits = get_first_digits(num);
digit_visa = digits / 10;
// Check if the card is American Express, Mastercard, Visa or Invalid
if (valid == 1)
{
if (length == 16)
{
if (digits <= 55 && digits >= 51)
{
printf("MASTERCARD\n");
}
else if (digit_visa == 4)
{
printf("VISA\n");
}
else
{
printf("INVALID\n");
}
}
else if (length == 15)
{
if (digits == 34 || digits == 37)
{
printf("AMEX\n");
}
else
{
printf("INVALID\n");
}
}
else if (length == 13)
{
if (digit_visa == 4)
{
printf("VISA\n");
}
else
{
printf("INVALID\n");
}
}
}
else
{
printf("INVALID\n");
}
}
long get_cc_number(void)
{
long cc_number;
cc_number = get_long("Credit Card Number: ");
return cc_number;
}
int check_sum(int num)
{
int num1 = num;
while (num1 >= 10)
{
sec_to_last = num1 % 100;
double_sec_to_last = sec_to_last * 2;
if (double_sec_to_last >= 10)
{
first_dig = double_sec_to_last / 10;
sec_dig = double_sec_to_last % 10;
first_sum += first_dig;
first_sum += sec_dig;
}
else
{
first_sum += double_sec_to_last;
}
num1 = num1 / 100;
}
int num2 = num;
while (num2 >= 10)
{
last = num2 % 10;
second_sum += last;
}
second_sum += first_sum;
if (second_sum % 10 == 0)
{
return 1;
}
else
{
return 0;
}
}
long check_length(long num)
{
long num_length = floor(log10(labs(num))) + 1;
return num_length;
}
long get_first_digits(long num)
{
long i = num;
while (i >= 100)
{
i /= 10;
}
return i;
}
A while back, I reviewed an issue like this where the user was getting tripped up on acquiring a credit card check digit. With that, I wrote a small proof-of-principle test program that allows validation of credit card numbers using the Luhn algorithm. Following, is that code snippet.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int check_valid(char * num)
{
int sum = 0;
int work = 0;
char card[20];
if ((strlen(num) %2 == 0)) /* Even numbers - do not need a leading zero */
{
strcpy(card, num);
}
else /* Odd numbers - add a leading zero to evaluate */
{
strcpy(card, "0");
strcat(card, num);
}
printf("Length of number is: %d\n", (int)strlen(num));
for (int i = 0; i < strlen(card); i++)
{
work = card[i] - '0';
if ((i %2) == 0)
{
work = (card[i] - '0') * 2;
if (work > 9)
{
work = work - 9;
}
}
sum = sum + work;
printf("Digit is: %d Value is: %d Sum is %d\n", (card[i]- '0'), work, sum);
}
return ((sum % 10) == 0);
}
int main()
{
char number[20];
int x = -1;
printf("Enter a number: ");
x = scanf("%s", number);
x = check_valid(number);
if (x == 0)
printf("Invalid\n");
else
printf("Valid\n");
return 0;
}
It doesn't identify the card issuer, just verifies that the number is valid.
As noted in the comments, one probably would want to utilize a string entry as this code snippet does rather than trying to utilize a very large integer. You might try going that route with a string as well. Give this a try and see if it allows you to progress.

In C, can i use scanf with just one %d input but get 2 variables with that same input?

By the time i finish counting the digits(K) with a while/do loop, the original N number is lost and its now 0. So i cant rly go to step 4). Thats why i thought id create 2 variables with the same input so i can just do the 4) step as a seperate process entirely.
(CONTEXT
basically the task is to make a program that 1) read a number N (1<=N<=999999999) with scanf,
2) if the number is out of mentioned bounds, make message "Wrong Input" appear,
3) make it count the digits of said number, (digits as K),
4) If N includes K as a digit, make message "Yes" appear, otherwise make "No" appear.)
int main()
{
int K,N;
scanf("%d", &N);
if (N<=1 || N>=999999999)
{
printf("Wrong Input\n");
}
else
{
do
{
N=N/10;
K++;
}
while(N!=0);
}
return 0;
}
else
{
int M = N;
do
{
M=M/10;
K++;
}
while(M!=0);
}
You can just create a new local variable and store the value of N to be used later
#include <stdio.h>
int main() {
// initializing with 0 because 0 = false and 1 = true, to use true or false you need the bool.h header file
int containsDigit = 0;
int K, N, digits = 0;
scanf("%d", &N);
K = N;
if (N <= 1 || N >= 999999999) {
printf("Wrong Input\n");
} else {
while (N != 0) {
N /= 10;
digits++;
}
while(K != 0) {
int cdigit = K % 10;
if (cdigit == digits) {
containsDigit = 1;
break;
}
K /= 10;
}
if (containsDigit) printf("yes");
else printf("No");
}
return 0;
}

finding prime numbers between a range in C

I am trying to find the prime numbers in a range using C language. My code does not give an output and I think there is a logical error here which I cannot figure out. Can anyone please help?
#include <stdio.h>
int main() {
int lowerLevel;
int upperLevel;
int i; //counter variable
int prime = 0;
int flag = 0;
printf("Enter the lower limit and upper limit of the range followed by a comma :");
scanf("%d %d", &lowerLevel, &upperLevel);
for (i = 2; i <= upperLevel; ++i) {
if (i % 2 == 0) {
flag = 1;
break;
}
}
if (flag == 0) {
printf("%d", i);
++i;
}
return 0;
}
Your code does not check for prime numbers, it merely checks that there is at least one even number between 2 and upperlevel, which is true as soon as upperlevel >= 2. If there is such an even number, nothing is printed.
You should instead run a loop from lowerlevel to upperlevel and check if each number is a prime and if so, print it.
Here is a modified version:
#include <stdio.h>
int main() {
int lowerLevel, upperLevel;
printf("Enter the lower limit and upper limit of the range: ");
if (scanf("%d %d", &lowerLevel, &upperLevel) != 2) {
return 1;
}
for (int i = lowerLevel; i <= upperLevel; ++i) {
int isprime = 1;
for (int p = 2; p <= i / p; p += (p & 1) + 1) {
if (i % p == 0) {
isprime = 0;
break;
}
}
if (isprime) {
printf("%d ", i);
}
}
printf("\n");
return 0;
}
This method is simplistic but achieves the goal. More efficient programs would use a sieve to find all prime numbers in the range without costly divisions.
Optimal method with Sieves of Eratosthenes
You should use the sieves of Eratostenes algorithm, it is way more efficient to get the different prime number.
it does so by iteratively marking as composite (i.e., not prime) the multiples of each prime, starting with the first prime number, 2
Basically you consider all numbers prime by default, and then you will set as false the prime number, see below code:
#include <stdio.h>
/// unsigned char saves space compared to integer
#define bool unsigned char
#define true 1
#define false 0
// https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
void printPrimesRange(int lowerLevel, int n) {
if (lowerLevel < 0 || n < lowerLevel) // handle misused of function
return ;
bool isPrime[n + 1];
memset(isPrime, true, n + 1);
int cnt = 0; // NB: I use the counter only for the commas and final .\n, its optional.
if (lowerLevel <= 2 && n >= 2) { // only one even number can be prime: 2
++cnt;
printf("2");
}
for (int i = 3; i <= n ; i+=2) { // after what only odd numbers can be prime numbers
if (isPrime[i]) {
if (i >= lowerLevel) {
if (cnt++)
printf(", ");
printf("%d", i); // NB: it is better to print all at once if you can improve it
}
for (int j = i * 3; j <= n; j+=i*2) // Eratosthenes' Algo, sieve all multiples of current prime, skipping even numbers
isPrime[j] = false;
}
}
printf(".\n");
}
int main(void) {
int lowerLevel;
int upperLevel;
printf("Enter the lower limit and upper limit of the range with a space in-between:"); // space, not comma
scanf("%d %d", &lowerLevel, &upperLevel);
printPrimesRange(lowerLevel, upperLevel);
return 0;
}
Let's follow the logic of your code:
#include <stdio.h>
#include <string.h>
int main() {
int lowerLevel;
int upperLevel;
int i; //counter variable
int prime = 0;
int flag = 0;
printf("Enter the lower limit and upper limit of the range followed by a comma :");
scanf("%d %d", &lowerLevel, &upperLevel);
for (i = 2; i <= upperLevel; ++i) {
if (i % 2 == 0) {
flag = 1;
break;
}
}
if (flag == 0) {
printf("%d", i);
++i;
}
return 0;
}
First of all, you have a loop:
for (i = 2; i <= upperLevel; ++i) {
if (i % 2 == 0) {
flag = 1;
break;
}
}
this loop tries to find a number i that is a multple of 2, because as soon you get one, you jump out of the loop. So your loop can be expressed better as:
for (i = 2; i <= upperLevel && i % 2 != 0; ++i) {
}
/* i > upperLevel || i % 2 == 0 */
if (i <= upperLevel && i % 2 == 0) {
flag = 1;
}
We still need to check if i <= upperLevel && i % 2 == 0 to set the variable flag = 1 if we exited the loop because i was a multiple of 2, but the break; is not necessary because we are already out of the loop.
Now let's check that the first value we initialize i is, indeed 2 (which is a multiple of 2) and the consecuence of this is that the loop is never going to be entered. Se we can eliminate it completely, giving to:
i = 2;
if (i <= upperLevel && i % 2 == 0) {
flag = 1;
}
now, the second clause of the if test is always true, so we can take it off, giving:
i = 2;
if (i <= upperLevel) {
flag = 1;
}
Now, let's append the second part:
i = 2;
if (i <= upperLevel) {
flag = 1;
}
if (flag == 0) {
printf("%d", i);
++i;
}
return 0;
so, the first thing we see here is that your ++i; statement is nonsense, as it is the last statement to be
executed before exiting the program, so we can also take it off.
i = 2;
if (i <= upperLevel) {
flag = 1;
}
if (flag == 0) {
printf("%d", i);
}
return 0;
Now we see that you print the value of i only if the value of flag is zero, but flag only conserves its zero value if the value of i > upperLevel, and as i is fixed, the printing of i only occurs if you input a value of upperlevel that is less than 2.
We can rewrite the above code as this:
if (2 > upperLevel) {
printf("%d", 2);
}
Your program will print 2 only if you provide a value of upperLevel less than 2.

Different output between compilers

I am doing the first problem on Project Euler.
I have the following code:
#include <stdio.h>
int main() {
int number;
int sum;
while (number < 1000) {
if (number % 3 == 0 || number % 5 == 0) {
sum += number;
number++;
}
else {
number++;
}
}
printf("The answer is %d", sum);
return 0;
}
When I compile this via compileonline.com, I get 233168. When I compile this in gcc I get 2686824. What causes this difference?
Compileonline probably initializes the variables.
You have to initialize them manually.
#include <stdio.h>
int main() {
int number = 0;
int sum = 0;
while (number < 1000) {
if (number % 3 == 0 || number % 5 == 0) {
sum += number;
number++;
}
else {
number++;
}
}
printf("The answer is %d", sum);
return 0;
}

Primes less than an integer

I wrote a program to find all primes less that a user-input integer. However, it just hangs. I assume using all these continues and whatnot is a mess and I have made spaghetti code...can anyone help me?
/*takes integer input, displays all primes less than that integer*/
#include <stdio.h>
int main(void) {
unsigned int num_in, test_num = 0, divisor = 0;
_Bool primestate = 0;
printf("Please enter an integer.\n");
scanf("%d", &num_in);
while(test_num < num_in) {
while(divisor < test_num) {
if(test_num % divisor == 0) {
primestate = 1;
}
test_num++;
}
if(primestate == 1) {
printf("%d is prime and less than %d.\n", test_num, num_in);
} else {
continue;
}
}
return 0;
}
You never increment test_num or divisor, so it gets stuck in one of the loops.
while(test_num < num_in) {
while(divisor < test_num) {
if(test_num % divisor == 0) {
primestate = 1;
}
divisor++; // NEW LINE
}
if(primestate == 1) {
printf("%d is prime and less than %d.\n", test_num, num_in);
} else {
continue;
}
test_num++; // NEW LINE
}
You also have a possible division by 0 (when divisor equals 0) on this line:
if(test_num % divisor == 0) {
#include <stdio.h>
#include <stdbool.h>
int main(void) {
unsigned int num_in, test_num, divisor;
bool primestate;
printf("Please enter an integer.\n");
scanf("%u", &num_in);
if(2 < num_in)
printf("\n%u\n", 2);
for(test_num = 3; test_num < num_in; test_num += 2){
primestate = true;
for(divisor=3; divisor * divisor <= test_num ; divisor += 2) {
if(test_num % divisor == 0) {
primestate = false;
break;
}
}
if(primestate) {
printf("%u\n", test_num);
}
}
return 0;
}

Resources