-1

I've started learning programming since August 14, and have chosen C as a start.

I wrote this program, it works but it malfunctions. It only allows me to enter the first value (the amount of the loan), the immediately starts the calculations and gives values of zero for the payments.

Please tell me the mistakes I've made. Here is the source code:

#include<stdio.h>
int main(void)
{
    float a, b, c, d, e, f, g;

    printf("enter amount of loan:\n");
    scanf("%.2f",&a);

    printf("enter interest rate:\n");
    scanf("%.2f",&b);

    printf("enter monthly payment:\n");
    scanf("%.2f",&c);

    d=a*(1+b/100.00f);
    e=d-c;
    f=e-c;
    g=f-c;

    printf("balance remaining after first payment:%.2f\n",e);
    printf("balance remaining after second payment:%.2f\n",f);
    printf("balance remaining after third payment:%.2f\n",g);

    return 0;
}

A sample run is below:

enter amount of loan:
1000
enter interest rate:
enter monthly payment:
balance remaining after first payment:0.00
balance remaining after second payment:0.00
balance remaining after third payment:0.00
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 5
    It would be good if you provided some example input, the expected output for that input and the output you are actually getting. Btw, `%.2f` should be just `%f` – Ted Lyngmo Aug 28 '21 at 09:40
  • 1
    Possible duplicates https://stackoverflow.com/questions/3730019/why-not-use-double-or-float-to-represent-currency https://stackoverflow.com/questions/588004/is-floating-point-math-broken?r=SearchResults&s=1|3235.4805 – chtz Aug 28 '21 at 09:45
  • 3
    Good job on starting to program. A big part of working in software is learning to communicate about software. Please see [ask] and [mcve] for ideas on what sort of information is expected in a properly posed question. It's a process, and I think you'll find that improving precision in communication about programming will improve your communication skills everywhere. – Mad Physicist Aug 28 '21 at 09:54
  • 1
    @chtz: both of those proposed dupes are about floating point precision. OP hasn't even gotten to that point yet due to the format specifier issue. – paxdiablo Aug 28 '21 at 09:54
  • @paxdiablo You are right. I should have asked to clarify what OP meant by "not working" (or try to run it) instead of guessing ... – chtz Aug 28 '21 at 13:38

1 Answers1

5

Don't use .2f for your scanf format specifiers.

While it's valid for printf, it is not for scanf. For the latter, you can just use %f. Any decent compiler should have told you that, with something like:

prog.c: In function ‘main’:
prog.c:12:13: warning: unknown conversion type character ‘.’ in format [-Wformat=]
   12 |     scanf("%.2f",&a);
      |             ^

The reason it's only letting you enter the first value is probably because the scanf calls are reading nothing. I say "probably" because the actual behaviour is undefined (meaning anything is allowed), as per the standard, C11 7.21.6.2 The fscanf function /13:

If a conversion specification is invalid, the behavior is undefined.


As an aside (I always like to go above and beyond when helping out newcomers), there are several other ways your program could be improved, among them:

  • more descriptive (and fewer) variable names;
  • checking things that can fail; and
  • refactoring out common code.

For example, have a look at the following as an example:

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

// Function to prompt for and get a float value, exits
// program with error if invalid.

float get_float(const char *thing) {
    float input_value;
    printf("Enter %s: ", thing);
    if (scanf("%f", &input_value) != 1) {
        fprintf(stderr, "Invalid input, terminating.\n");
        exit(1);
    }
    return input_value;
}

// Given current amount and indicator, prints and returns
// new amount.

float adjust(float current, float delta, const char *indicator) {
    current -= delta;
    printf("Balance remaining after %s payment: %.2f\n",
        indicator, current);
    return current;
}

// Loan tracker program. Gives balance of loan remaining
// based on entered values for initial amount, annual
// interest rate, and monthly payment.
// Assumptions are:
// 1/   Initial interest payment deducted in full, before
//      any payments are made.
// 2/   Only gives first three months of data, so no need
//      to worry about second interest payment coming due
//      at month 13.

int main(void) {
    // Get all info from user.

    float initial_amount  = get_float("amount of loan ");
    float interest_rate   = get_float("interest rate  ");
    float monthly_payment = get_float("monthly payment");

    // Calculate initial amount (includes first interest hit).

    float running_amount = initial_amount * (1 + interest_rate / 100);

    // Calculate and print first three months.

    running_amount = adjust(running_amount, monthly_payment, "first ");
    running_amount = adjust(running_amount, monthly_payment, "second");
    running_amount = adjust(running_amount, monthly_payment, "third ");
}

If you wanted a more adaptable program, allowing for more months, you could use something like:

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

// Function to prompt for and get a float value, exits
// program with error if invalid.

float get_float(const char *prompt) {
    float input_value;
    printf("Enter %s: ", prompt);
    if (scanf("%f", &input_value) != 1) {
        fprintf(stderr, "Invalid input, terminating.\n");
        exit(1);
    }
    return input_value;
}

// Function to prompt for and get a non-negative integer
// value, exits program with error if invalid.

unsigned get_int(const char *prompt) {
    unsigned input_value;
    printf("Enter %s: ", prompt);
    if (scanf("%u", &input_value) != 1) {
        fprintf(stderr, "Invalid input, terminating.\n");
        exit(1);
    }
    return input_value;
}

// Loan tracker program. Gives balance of loan remaining
// based on entered values for initial amount, annual
// interest rate, monthly payment, and number of months.
// Assumptions are:
// 1/   Initial interest payment deducted in full, before
//      any payments are made.
// 2/   Subsequent interest payments deducted in full,
//      before relevant month (after 12n payments, n > 0).

int main(void) {
    float    initial_amount  = get_float("amount of loan    ");
    float    interest_rate   = get_float("interest rate     ");
    float    monthly_payment = get_float("monthly payment   ");
    unsigned month_count     = get_int  ("number of payments");

    float running_amount = initial_amount;

    for (int month = 0; month < month_count; ++month) {
        if (month % 12 == 0) {
            running_amount = running_amount * (1 + interest_rate / 100);
        }
        running_amount -= monthly_payment;
        if (running_amount < 0) running_amount = 0;
        printf("Balance remaining after payment # %d: %.2f\n", month + 1, running_amount);
        if (running_amount == 0) break;
    }
}

This variant allows you to also enter the number of monthly payments you will make, correctly handles the application of interest(a), and even exits if the loan is paid off early.

It does have the disadvantage in printing out numeric months rather than "first", "second", and so on. That could be fixed with a function that takes integral values and return the string representations, but that's possibly over-kill here. Still, if you need it, I've provided answers on how to do that sort of thing before.

If you need it in C, or have trouble converting it to generate { first, second, ... } rather than { one, two, ... }, just ask another question and the SO swarm will provide :-)


(a) This is based on your original code where interest is applied before each year starts, however unusual that would be in reality.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • Worth noting: The invalid `.2` in this case is not to be confused with the maximum field width used when scanning for strings. `char foo[10]; scanf("%9s", foo);` is perfectly valid. – Ted Lyngmo Aug 28 '21 at 09:45