CS50 credit doesn't run for some numbers - c

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.

Related

while function C programing

I'm a first year collage student and I'm working on an exercise with a while function.
my current objective is to identify the lowest and highest value digits in a given number.
this is my code so far:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
void main() {
printf("enter an integer\n");
int one,onemax,onemin, min=9, max=0;
scanf("%d", &one);
onemax = one;
onemin = one;
while (onemax >= 0) {
if (max <= onemax % 10) {
max = onemax % 10;
onemax=onemax / 10;
if (onemax == 0) {
break;
}
}
else {
onemax=onemax / 10;
}
}
while (onemin != 0) {
if (min >= onemin % 10) {
min = onemin % 10;
onemin=onemin / 10;
if (onemin == 0) {
break;
}
}
else {
onemin=onemin / 10;
}
}
printf("min = %d max = %d", min, max);
}
now I know I'm stuck in a loop here and I need help getting out.
when onemax reaches 0 you are done. You should change the >= condition to >:
while (onemax > 0) {
// Here ------^

A recursive function that determines whether the digits of a number are in ascending order

I'm practicing recursion and my solution to the problem doesn't seem to work.
I'm trying to write a recursive code that will determine if the digits of a number are in ascending order or not. here's my code:
#include <stdio.h>
int isAscending(int num);
int main(){
int result;
result = isAscending(123);//Should print "The number is in ascending order!"
if (result == 0) {
printf("The number is in ascending order!\n");
}
else {
printf("The number is not in ascending order!\n");
}
}
int isAscending(int num) {
int new = num / 10;
int result = 0;
if ((num % 10) == 0) {
return 0;
}
else if ((num % 10) > (new % 10)) {
result += isAscending(num / 10);
return result;
}
else {
return 1;
}
}
Here's another (bare-bones) way to go about it. The basic idea is that if we have a single digit, we return affirmative, else we check if the rightmost number is greater than the one just to it's left. And we do this for the remaining digits.
#include <stdio.h>
int isAsc(int i)
{
int rem = i % 10; // remainder
int quo = i / 10; // quotient
if (rem == i)
return 1;
else if (rem <= (quo % 10))
return 0;
else
return 1 && isAsc(quo);
}
int main(void)
{
int i = 123123;
if (isAsc(i))
printf("%s\n", "Ascending");
else
printf("%s\n", "Not ascending");
return 0;
}
Can you please try below recurrsive code:
`
boolean isascending(int num){
if(num == 0) return true;
if(num%10>num%100) return isascending(num/10);
else return false;
}`
or you can use while loop:
while(num>0){
if(num%10 > num%100){
num = num/10;
continue;
} return false;
} return true;
It would be better to use another parameter to store the last digit, which is going to be "dropped" in the current iteration.
So I came up with the following recursive logic:
use a parameter which stores the last digit dropped
base case: if the number is 0, return 0 (true)
calculate the current last digit of the number (number%10)
if the current last digit is greater than the last digit dropped: is this case, return 1 (false)
if not, return isAscendingRecursive() on the new number dropping the current last digit and pass it as the next iteration last digit.
Code:
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char** args){
int num=0;
printf("Insert a number:\n");
scanf("%d",&num);
if(isAscending(num)==0)
printf("Ascending\n");
else
printf("Not ascending\n");
}
int isAscending(int num){
return isAscendingRecursive(num,9);
}
int isAscendingRecursive(int num, int lastDigit){
if(num == 0)
return 0;
int temp = num%10;
if(temp > lastDigit)
return 1;
else
return isAscendingRecursive(num/10, temp);
}
This solution returns 0 on failure otherwise some other integer on success. It seems that isDescending() is easier to write when returning 0 as a failure value but I contorted this accordingly:
#include <stdio.h>
#include <stdlib.h>
int isAscending(int num) {
int quotient = num / 10;
int remainder = num % 10;
if (quotient != 0) {
int result = isAscending(quotient);
if (result == 0 || result >= remainder) {
return 0;
}
}
return remainder;
}
int main(int argc, char **argv) {
if (isAscending(atoi(argv[1]))) {
printf("The number is in ascending order!\n");
} else {
printf("The number is not in ascending order!\n");
}
return 0;
}
TESTS
% ./a.out 123
The number is in ascending order!
% ./a.out 321
The number is not in ascending order!
% ./a.out 101
The number is not in ascending order!
%
No, it doesn't handle negative numbers! It also doesn't handle '0' correctly as an input -- other single digit numbers are fine.
Again, isDescending() is easier to write but unfortunately, !isDescending() != isAscending()
Your tests are incorrect. You should return true for numbers with a single digit, false if the last digit is less or equal to the previous one and recurse for the rest:
int isAscending(int num) {
int new = num / 10;
if (new == 0) {
return 1;
} else
if (num % 10 <= new % 10) {
return 0;
} else {
return isAscending(new);
}
}
This kind of recursion is called tail recursion as you return the result of the recursive call. Good compilers will generate iterative code equivalent to this:
int isAscending(int num) {
for (;;) {
int new = num / 10;
if (new == 0) {
return 1;
}
if (num % 10 <= new % 10) {
return 0;
}
num = new;
}
}
I fixed my code and it works, thanks for the help!:
#include <stdio.h>
int isAscending(int num);
int main(){
int result;
result = isAscending(2589);//Should print "The number is in ascending order!"
if (result == 0) {
printf("The number is in ascending order!\n");
}
else {
printf("The number is not in ascending order!\n");
}
}
int isAscending(int num) {
int new = num / 10;
int result = 0;
if ((num % 10) == 0) {
return 0;
}
else if ((num % 10) > (new % 10)) {
return isAscending(num / 10);
}
else {
return 1 + isAscending(num / 10);
}
}

Unusual Floating point exception (core dumped) Error with C

I am currently a student, trying to get factorials to print out as prime numbers multiplied to certain exponents like so:
5! = (2^3)(3^1)(5^1)
However, I keep getting an unusual error, which occurs right after using scanf to retrieve my input (By the way, I would really appreciate someone showing me how to retrieve multiple inputs from an exterior file to do this using input redirection, since that's how we were supposed to retrieve our inputs for this).
Anyway, I'm assuming this error is somewhere in the specification for my while loop. I would greatly appreciate any help/tips/pointers. Thank you!
#include <stdio.h> //headers
#include <stdbool.h>
//function prototypes - I will be using functions inside of each other
int find_prime_count (int prime, int num);
int find_next_prime (int prime);
bool is_prime (int num);
int main(void) //main function
{
int primeCount[100] = {0}, prime = 2, fact, i = 2, temp = 2, currentPrimeCount, printCount = 0;
printf ("Enter number: ");
scanf ("%d", &fact);
while (i <= fact)
{
printf ("i is less than factorial");
while (temp != 1)
{
printf ("Temp is not equal to one");
currentPrimeCount = find_prime_count (prime, temp);
printf ("currentPrimeCount calculated");
temp = temp / (currentPrimeCount * prime);
printf ("Temp updated");
primeCount[prime + 1] += currentPrimeCount;
printf ("primeCount[prime + 1] updated");
prime = find_next_prime (prime);
printf ("Next prime found");
}
i += 1;
temp = i;
}
printf ("%3d! = ", fact);
i = 0;
while (i < 100)
{
if (primeCount[i] != 0)
{
if (printCount == 0)
{
printf ("(%d^%d)", i, primeCount[i]);
}
else if (printCount != 0)
{
printf (" * (%d^%d)", i, primeCount[i]);
}
printCount += 1;
if ((printCount % 9) == 0)
{
printf ("/n");
}
if ((printCount > 9) && ((printCount % 9) == 0))
{
printf (" ");
}
}
}
return 0;
}
bool is_prime (int num)
{
bool check = true; //sets check variable to true
int i = 2; //starts counter variable at 2 (will test all numbers >=2 && <num)
while (i < num && check == true)
{
if ((num % i) == 0) //if it is divisible by any number other than 1 and itself
{
check = false; //it is not a prime number and the check becomes false
}
i += 1; //increasing counter
}
return check; //returns boolean value
}
int find_next_prime (int prime)
{
int i = prime;
bool check = false;
printf ("find_next_prime starts.");
while (check == false)
{
i += 1;
check = is_prime (i);
}
printf ("find_next_prime ends.");
return i;
}
int find_prime_count (int prime, int num)
{
int count = 0;
printf ("find_prime_count starts.");
while ((prime % num) == 0)
{
count += 1;
num = num / prime;
}
printf ("find_prime_count ends.");
return count;
}
Using gdb, I can tell that it is a divide by zero error in prim % num.
Hints:
Compile with the -g flag
Run using gdb
Set a breakpoint ...

Breaking out of a loop without a break statement [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.

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