为什么这个程序会出现故障?
我从 8 月 14 日开始学习编程,并选择了 C 作为开始。
我写了这个程序,它可以工作,但它出现故障。它只允许我输入第一个值(贷款金额),立即开始计算并为付款提供零值。
请告诉我我犯过的错误。这是源代码:
#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;
}
示例运行如下:
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
回答
不要.2f用于您的scanf格式说明符。
虽然它对 有效printf,但它不适用于scanf。对于后者,您可以只使用%f. 任何体面的编译器都应该告诉你,比如:
prog.c: In function ‘main’:
prog.c:12:13: warning: unknown conversion type character ‘.’ in format [-Wformat=]
12 | scanf("%.2f",&a);
| ^
它只让您输入第一个值的原因可能是因为scanf调用没有读取任何内容。我说“可能”是因为根据标准,实际行为是未定义的(意味着任何事情都是允许的)C11 7.21.6.2 The fscanf function /13:
顺便说一句(在帮助新人时我总是喜欢超越自我),还有其他几种方法可以改进您的程序,其中包括:
- 更具描述性(和更少)的变量名称;
- 检查可能失败的事情;和
- 重构出通用代码。
例如,看看下面的例子:
#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 ");
}
如果您想要一个适应性更强的程序,允许更多个月,您可以使用以下内容:
#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;
}
}
此变体还允许您输入每月付款的次数,正确处理利息(a)的申请,甚至在提前还清贷款时退出。
它在打印数字月份而不是“第一”、“第二”等方面确实有缺点。这可以通过一个接受整数值并返回字符串表示的函数来解决,但这在这里可能会过度。不过,如果您需要它,我之前已经提供了有关如何执行此类操作的答案。
如果您在 C 中需要它,或者在将其转换为 generate{ first, second, ... }而不是 时{ one, two, ... }遇到问题,只需提出另一个问题,SO swarm 将提供:-)
(a)这是基于您的原始代码,其中在每年开始之前应用利息,但在现实中这是不寻常的。