function always return true - c

I have troubles with writing a function, that checks if a credit card is valid, using Luhn's Algorithm (multiply every other digit by 2, starting with second-to-last; add the sum of the digits than weren't multiplied by 2; if the total's last digit is 0, the number is valid).
When I started to write a code, I checked these lines:
long number2 = ((card % x) / y)\*2;
long number1 = ((card % (x/10)) / (y/10));
and they seem to work right. When I try to check again now it kind of ignores the following lines:
printf("%li", number1);
printf("%i", sum)
And function always returns true. Also, is it okay that I declare variable digits two times?
#include <stdio.h>
#include <cs50.h>
bool luhns_algorithm (long, int);
int number_of_digits(long);
int main (void)
{
int digits = 0;//if i remove this then on line 15 appears mistakes
long card = get_long("credit card: ");
number_of_digits(card);
luhns_algorithm(card, digits);//use of undeclared identifier 'digits'; variable 'digits' is uninitilazed when used here
}
int number_of_digits(long card)
{
int digits = 0;//cant be used in do while loop if undeclared and uninitialized so I need to write it twice
do
{
digits++;
card = card/10;
} while(card != 0);
printf("%i\n", digits);
return digits;
}
bool luhns_algorithm (long card, int digits)//always valid for some reason
{
int sum = 0;
long x = 100;
long y = 10;
for (int i = 0; i < digits/2; i++)
{
long number2 = (card % x)/y;
long number1 = (card % (x/10))/(y/10);
printf("%li\n", number1);//doesn't work
printf("%li\n", number2);//doesn't work
sum = sum + number2 + number1;
printf("%i\n", sum);//doesn't work
x = x*100;
y= y*100;
}
if((sum/10) == 0)
{
printf("VAlID\n");
return true;
}
printf("INVALID\n");
return false;
}

The result of the function number_of_digits is discarded. This means that the digits in your main() is always zero. You need to store the result into digits :
#include <stdio.h>
#include <cs50.h>
bool luhns_algorithm (long, int);
int number_of_digits(long);
int main (void)
{
int digits;
long card = get_long("credit card: ");
digits = number_of_digits(card); //FIXED
luhns_algorithm(card, digits);
}
As you noticed, if digits is unitialised then an error appearse. Unititialised variables declared inside a function have an unkown value and the compiler will show a warning if you try to use them before assigning a value.
Also, is it okay that I declare variable digit two times?
In C, as with most languages, variables have scopes. Every variable is only visible in its own scope and below. Because your two digits variables are in different scopes, they are not visible in the other scope. Your main() digits is totally independant from your number_of_digits() digits. See this explanation on variable scope for more informations.
Also note that you actually declare it 3 times. A function parameter behaves exaclty like a variable, with the only difference being that it is initialised with the value passed to the parameters when the function was called.

Related

recursive Function, to find even or odd digits inside given number

Basically, its printing only one instance when it happens, and i don't understand why, maybe has something to do with the code reseting every time and starting the variable at 0 again, and i got another question if someone can help me with, i have to return both values when its odd and even, like how many digits are even and odd at the same time, i'm having a little trouble figuring out how to do it
#include <stdio.h>
int digits(int n)
// function that checks if the given value is odd or even, and then add
// + 1 if it's even, or odd, it's supposed to return the value of the quantity
// of digits of the number given by the main function
{
int r;
int odd = 0;
int even = 0;
r = n % 10;
if (r % 2 == 0) // check if given number is even
{
even = even + 1;
}
if (r % 2 != 0) // check if its odd
{
odd = odd + 1;
}
if (n != 0) {
digits(n / 10); // supposed to reset function if n!=0 dividing
// it by 10
}
if (n == 0) { return odd; }
}
int
main() // main function that sends a number to the recursive function
{
int n;
printf("type number in:\n ");
scanf("%d", &n);
printf("%d\n", digits(n));
}
odd and even variables are local in your code, so they are initialized by zero every time.
I think they should be declared at caller of the recursive function, or be declared as global variables.
#include <stdio.h>
void digits(int n, int *even, int *odd)//function
{
int r;
r = n % 10;
if (r % 2 == 0)//check if given number is even
{
*even = *even + 1;
}
else //otherwise, its odd
{
*odd = *odd + 1;
}
n /= 10;
if (n != 0)
{
digits(n, even, odd);//supposed to reset function if n!=0 dividing it by 10
}
}
int main()
{
int n, even = 0, odd = 0;
printf("type number in:\n ");
scanf("%d", &n);
digits(n, &even, &odd);
printf("even: %d\n", even);
printf("odd: %d\n", odd);
return 0;
}
Maybe I found the problem you are facing. You you initialized you odd and even variable as zero. every time you call the function it redeclares their value to zero again. You can use pointer caller or use those as your global variable so that every time they don't repeat their initial values again.
Implementing a function that counts the number of odd and even digits in a number, is not to be done using recursive. That is simply a wrong design choice.
But I assume that it's part of your assignment to use recursion so ... okay.
You want a function that can return two values. Well, in C you can't!! C only allows one return value. So you need another approach. The typical solution is to pass pointers to variables where the result is to be stored.
Here is the code:
void count_odd_even(const int n, int *even, int *odd)
{
if (n == 0) return;
if (((n % 10) % 2) == 1)
{
*odd += 1;
}
else
{
*even += 1;
}
count_odd_even(n/10, even, odd);
}
And call it like
int odd = 0;
int even = 0;
count_odd_even(1234567, &even, &odd);

Why is the number declared in the double function not used? (C)

#include <stdio.h>
double calculate_average (int number)
{
static int numberInput = 0; //counter
static int sum = 0;
sum = sum + numberInput;
numberInput++;
return sum / numberInput;
// calculate and return average so far.
}
int main(void)
{
double average;
while (1)
{
int number;
scanf("%d", &number);
if (number == 0)
break; //stops if number == 0
else
average = calculate_average(number);
}
printf("%.1f\n", average);
return 0;
}
As I can personally tell, the function is trying to calculate the average. But why does the main function not use the number in the calculate_average function?
As written, your calculate_average function does not use its given number argument because, nowhere in that function, do you instruct it to do so. Most likely, your sum = sum + numberInput; should really be sum = sum + number; (thus adding that given number to the running total).
A couple of other points:
You should initialize your average variable (to 0.0), otherwise you'll get a crazy result if you give your program an empty list (i.e. give zero as the first entry).
As your function returns a double, it is best to have the sum variable also as a double; otherwise, you are performing integer arithmtic in your calculation, and all returned values will be truncated to integers (losing any fractional parts).
Others will likely point out that you should always check the value returned by your scanf call (it will be 1 if the read operation succeeds) and add code to handle any error; however, addressing that point here is, IMHO, beyond the 'remit' of this question, but see this answer to How validate user input when the expected value is of type int and the entered value is not of type int?.
Here's a possible working version:
#include <stdio.h>
double calculate_average(int number)
{
static int numberInput = 0; //counter
static double sum = 0.0;
sum = sum + number;
numberInput++;
return sum / numberInput;
// calculate and return average so far.
}
int main(void)
{
double average = 0.0; // Always best to initialize variables!
while (1) {
int getal;
scanf("%d", &getal);
if (getal == 0)
break; //stops if getal == 0
else
average = calculate_average(getal);
}
printf("%.1f\n", average);
return 0;
}
Please feel free to ask for any further explanation and/or clarification.

why is my variable storing value from previous recursion runs?

the first image is of the Program with regular recursion format, I am returning values for both cases but self call to the function is made only when the argument is a natural number. The result is as expected
in the second program, however, I am not returning any value for natural numbers, the only return case is when the argument is 0.
Ideally, (taking 5 as the input) recursion will happen till num value equals 0. First with
sum = 5 + add(5-1);
sum = 4 + add(4-1);
sum = 3 + add(3-1);
sum = 2 + add(2-1);
sum = 1 + add(1-1);
At this stage, the function will return 0 as flow moves to else block,and value of sum for that loop is 0.
Now, with 0 being returned we rise one step up and 0 will take place of add(1-1) in the line
sum = num + add(num-1);
it should look like
sum = 1 + 0;
the function add(num) should terminate now, after assigning 1 to variable sum.
Two main questions.
No value should rise up for sum = 2 + add(2-1), as in the previous step no value is returned. for add(1), after getting value from add(0), summation of 1 and returned value is stored in variable sum and then exits out of function body.
Every time recursion occurs new variable sum is declared and initiated to 0, so, I don't see why the computer is storing the values of the sum from previous calls to the function, when instead it should start a fresh new variable sum.
to me, after completion of code, the value of variable sum in add() should be 1.
Please someone, if you can make sense of this code. Let me know. Much appreciated
P.s: you can try this on any online C compiler as well. Here is the code:
#include <stdlib.h>
#include <stdio.h>
int add(int num);
int main(){
int number,sum;
printf("enter a number of your choice: ");
scanf("%d",&number);
sum = add(number);
printf("SUM = %d",sum);
}
int add(int num){
int sum = 0;
if(num != 0)
sum = num + add(num-1);
else
return sum;
}
sum = add(number);
Using the return value of a function that flowed off the end without explicitly returning a value is undefined behavior. UB means anything is allowed to happen, including giving you the (false) illusion that a variable is "storing value from previous recursion runs". Quoting from C11 6.9.1/12:
If the } that terminates a function is reached, and the value of the function call is used by the caller, the behavior is undefined.
A function declared to return an int must always return a value (i.e. an int value). Your code doesn't.
int add(int num){
int sum = 0;
if(num != 0)
// If the execution gets in here
sum = num + add(num-1);
else
return sum;
// it will continue here (when the recursion ends).
// And here it is WITHOUT a returned value - that's bad.
}
You probably want:
int add(int num){
int sum = 0;
if(num != 0)
sum = num + add(num-1);
return sum;
}
or
int add(int num){
if(num != 0)
return num + add(num-1);
else
return sum;
}
or (more clear and secure):
int add(int num){
if(num <= 0)
{
return 0;
}
return num + add(num-1);
}

Nonhypotenuse number

A non-hypotenuse number is a natural number whose square cannot be written as the sum of two non-zero squares.
Given two integers a and b, the task is to find the sum of all odd length non-hypotenuse numbers within the range [L, R], where 𝐿=𝑎 and 𝑅=𝑏²−2^𝑎.
For example, if a=2 and b=5 then L=2 and R=5²−2²=21.The non-hypotenuse numbers of this range are: 2, 3, 4, 6, 7, 8, 9, 11,12, 14, 16, 18, 19, 21. But since we only include odd length numbers in our summation the final result is: 39 = 2 + 3 + 4 + 6 +7+ 8 +9.
For the the input 5 25, it returns 65590; however it is supposed to return 72483. It works for the inputs 2 5 and 4 100. What am I doing wrong?
Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
//function, that returns 1 if it is a nonHypoNum
int isNonHypo(int x){
double temp;
for (int i=1; i<x; i++){ //iterates through the possible lengths of one leg of the triangle
temp=sqrt((double)(x*x-i*i)); //calculate third leg
if (temp==(int)temp) //if the third is a whole number
return 0;
}
return 1;
}
//function, that tells weather it has an odd number off digits
int isOddLength(int x){
int digits=0;
while (x){
digits++;
x/=10;
}
return (digits%2==0?0:1);
}
//function, that returns the power of two
int powTwo(int exp){
int x=2;
for (;exp>0;exp--){
x*=2;
}
return (x);
}
int main(){
int a,b,sum=0;
scanf("%d%d",&a,&b);
for (int Hypo=a; Hypo<=(b*b-powTwo(a)); Hypo++){ //try out numbers in range [a,b²-2^a]
if (isOddLength(Hypo)&&isNonHypo(Hypo))
sum+=Hypo;
}
printf("%d",sum);
return 0;
}
There are some numerical issues with this line in your code
temp = sqrt((double)(x*x-i*i)); // where 'temp', 'x' and 'i' are int
Both x*x and i*i may overflow. It doesn't matter if the result is casted to double, because it happens after the product are performed. You should use a bigger type, like long long and cast the values before the multiplications. In that case, the cast to double may even introduce some rounding errors.
Assigning the result of sqrt to an int may also introduce some unwanted rounding errors. You may use round() to prevent those.
In this particular case, you may instead avoid sqrt and save some iterations using a different algorithm:
#include <stdbool.h>
static inline long long sq(int x)
{
return (long long)x * x;
}
bool is_nonhypotenuse(int x)
{
long long square_x = sq(x);
// Meet in the middle, instead of going up to x
for (int i = 1, j = x - 1; i <= j; i++)
{
long long square_j, target = square_x - sq(i);
// Iterates, instead of calculating the square root
while ( (square_j = sq(j)) > target )
--j;
if ( square_j == target )
return false;
}
return true;
}
Edit
The other problem (probably the most important, given the input data) lies in the function used to calculate the powers of 2.
int powTwo(int exp) {
int x=2; // <-- It should start from 1, here
for (;exp>0;exp--) {
x*=2;
}
return (x); // <-- Effectively returns 2^(exp + 1)
}
You may consider this more general approach, instead.
long long int_pow(int base, int exp)
{
long long result = 1;
while ( exp )
{
if (exp & 1)
result *= base;
exp /= 2;
base *= base;
}
return result;
}
Or, given that the base is 2, just use a bit shift
int R = b * b - (1 << a);
With those modifications, your program should output the desired value. See e.g. here.

Why is the last element not appending to my array of digits?

Hi I am new to "C" I have a question on some output I got.
The number we are working with as data is: [4003600000000014].
I have every element appended to this array except for one I am not sure how to get the last number to print.
I am curious about the number 6422180 I am not sure what it is can someone explain.
// This is an example of Luhn's algorithm.
#include <stdio.h>
#include <ctype.h>
#define MAX_CRED_LEN 16
// Function prototypes.
void payment_method();
int main(void)
{
payment_method();
return 0;
}
long long int get_credit_card_num()
/*
Gets the users credit card number.
*/
{
long long int d;
do
{
printf("\nPlease enter in your credit card number: ");
if (scanf("%lld", &d) == 1)
{
printf("\nYour credit card number: (%lld)\n%s", d,
"------------------------\n\n");
continue;
}
else
{
printf("\n\tINVALID INPUT CHARACTER ENTERED PLEASE TRY AGAIN!\n%s",
"\t*************************************************");
fflush(stdin); // Clear input buffer of any characters!
get_credit_card_num(); // Start the function again to prompt user.
}
} while (d < 0);
return d;
}
int num_of_ccdigits()
/*
Counts the amount of digits the user entered. Then compares the number of
digits to a specific length offered by cardholders they are 13, 15, and 16
digits long.
*/
{
long long int cc_num = get_credit_card_num();
int digits = 0, arr[MAX_CRED_LEN];
// Count how many digits the user entered then compare the length.
while (cc_num != 0)
{
cc_num /= 10;
arr[digits] = cc_num % 10;
digits++;
}
// Display the number of digits that the user entered.
printf("\nNumber of digits: [%i]", digits);
int a = 0, i;
for (i = 0; i < digits; i++)
{
printf("\n[%d]:\tYOUR DIGIT ARRAY: %i", a, arr[i - 1]);
++a;
}
printf("\n\nARRAY WITHOUT LINE BREAKS: %i", arr);
// Check to see if this is a valid credit card number or a supported one.
if ((digits != 13) && (digits != 15) && (digits != 16))
{
printf("\n\tMUST BE AT LEAST 13, 15, AS HIGH AS 16 DIGITS.\n%s",
"\t**********************************************\n");
// if no 13, 15, or 16 digits long restart loop.
num_of_ccdigits();
}
return digits; // return the amount of digits in the credit card number.
}
void payment_method()
{
int num_of_digits = num_of_ccdigits();
}
I see a few issues here. For your first question, the code is indexing out of bounds of arr, causing undefined behavior:
for (i = 0; i < digits; i++)
{
printf("\n[%d]:\tYOUR DIGIT ARRAY: %i", a, arr[i - 1]);
++a;
}
On the first iteration, i = 0 and we proceed to index into arr[0 - 1] or arr[-1]. Whoops. This might produce a garbage value or cause a crash (or anything else).
By the way, a is redundant here--just use i to get the index (having to resort to a to get the index smells like something is off). The arr[i - 1] trick might have been done to compensate for another bug:
while (cc_num != 0)
{
cc_num /= 10;
arr[digits] = cc_num % 10;
digits++;
}
The problem here is that cc_num /= 10; says "move on to the next digit". But this skips the first digit completely. This should be:
while (cc_num != 0)
{
arr[digits] = cc_num % 10;
digits++;
cc_num /= 10;
}
Another problem which can be identified by turning on warnings is
ARRAY WITHOUT LINE BREAKS: -1747166688
Here, the compiler tells us the problem:
$ clang-7 -o main main.c
main.c:67:49: warning: format specifies type 'int' but the
argument has type 'int *' [-Wformat]
printf("\n\nARRAY WITHOUT LINE BREAKS: %i", arr);
~~ ^~~
1 warning generated.
To dump the array's values, use a loop and print each element individually.
Other remarks:
Invalid user entries cause an infinite loop.
Good job breaking things into functions, but try to avoid side effects in functions, especially printing. For example num_of_ccdigits does quite a lot more than simply getting the number of credit card digits. It also does validation and I/O. If you remove the print statements and make it responsible for purely counting the digits in a number, you can rename it count_digits(long long int num) and make it reusable on any long long int. Then, handle printing and validation elsewhere, say, print_digits(long long int num) and validate_cc_digit_length(long long int num). Check out single responsibility principle.
I'm a bit confused by the purpose of the function
void payment_method()
{
int num_of_digits = num_of_ccdigits();
}
Function names are typically actions, describing what the function does, rather than nouns, which are typically variables. Consider something like get_payment_method().
Also, since num_of_ccdigits calls itself recursively on bad data, it can potentially cause the stack to overflow. Using a while loop is a better way to handle bad input that can go on unbounded.
For initialization like:
int digits = 0, arr[MAX_CRED_LEN];
prefer:
int digits = 0;
int arr[MAX_CRED_LEN];
which is easier to read.

Resources