gpt4 book ai didi

c - 为什么我的 for 循环增量变化很大?

转载 作者:太空宇宙 更新时间:2023-11-04 02:25:50 25 4
gpt4 key购买 nike

我正在写一个使用指针摊销的小程序

#include <stdio.h>
#include <string.h>

double power(double a, double b);

int main(void)
{
int loanAmount, number_of_payments, i = 0;
double interestRate, monthlyInterestRate, monthlyPayment;
printf("Enter amount of loan : $ ");
scanf(" %i",&loanAmount);
printf("Enter Interest rate per year : ");
scanf(" %lf",&interestRate);
printf("Enter number of payments : ");
scanf(" %i",&number_of_payments);

monthlyInterestRate = ((interestRate / 100) / 12); //AKA 'r' or rate.
monthlyPayment = (monthlyInterestRate) * (loanAmount/(1 - 1/(power((1 +
monthlyInterestRate), number_of_payments))));

double interest[7] = {0}; //Arbitrarily set to 7 - assuming less payments.
double principal[7] = {0};
double balance[7] = {0};
balance[0] = loanAmount;
double *ipoint,*ppoint,*bpoint,*bpointprev;

ipoint = &interest[0];
ppoint = &principal[0];
bpoint = &balance[0];
bpointprev = bpoint;

printf("Monthly payment should be $ %lf\n",monthlyPayment);
printf("# \t Payment \t Principal \t Interest \t Balance \n");
for (i = 1; i <= number_of_payments; i++) {
ipoint += i;
bpoint += i;
ppoint += i;

*ipoint = *bpointprev * monthlyInterestRate;
*ppoint = monthlyPayment - *ipoint;
*bpoint = *bpointprev - *ppoint;

printf("%i \t %.2f \t %.2f \t\t %.2f \t\t %.2f\n",i,monthlyPayment,*ppoint,*ipoint,*bpoint);

bpointprev += i; //Iterates after logic for next calculation.
}

return 0;
}

double power(double a, double b)
{
double i, sum = 1;
for (i = 0; i < b; i++) {
sum = sum * a;
}
return sum;
}

遇到了一个问题,我正在编写的 IDE 运行程序正常:

在 Cloud9 IDE 上:

on Cloud9 IDE, Correct

但是在 Unix 终端上,我的 for 循环中的增量变量在似乎是任意计数之后跳转:

在 Unix 终端上:

on Unix Terminal, Error

我相当确定它与我四处游荡的所有指针引用有关,但我不知道为什么它会影响 for 循环中的 int 变量 i 或为什么 IDE 会处理错误干净地。请多多指教!

最佳答案

您的代码存在大量问题,它们正等着引起问题。正如您所发现的,您未能通过使用 ptr += i 递增指针来保护数组边界。导致您通过访问和写入数组存储之外的内存来调用未定义的行为

interest为例和 ipoint :

double interest[7] = {0};
ipoint = &interest[0];

因此您的索引在 interest 内数组如下和ipoint初始化为指向 interest 中的第一个元素:

            +---+---+---+---+---+---+---+
interest | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
+---+---+---+---+---+---+---+
^
|
ipoint

在你的循环中你正在前进 ipoint += i .在循环的第一次迭代中,您前进了 ipoint一个:

            +---+---+---+---+---+---+---+
interest | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
+---+---+---+---+---+---+---+
^
|
ipoint

你的第二次迭代,你前进了两倍:

            +---+---+---+---+---+---+---+
interest | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
+---+---+---+---+---+---+---+
^
|
ipoint

你的第三次迭代,你前进了三:

            +---+---+---+---+---+---+---+
interest | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
+---+---+---+---+---+---+---+
^
|
ipoint

i = 4你提前ipoint超出数组末尾,并在为 ipoint 赋值时调用未定义行为并尝试将值存储在您不拥有的内存中:

            +---+---+---+---+---+---+---+---+---+---+---+
interest | 0 | 1 | 2 | 3 | 4 | 5 | 6 | out of bounds |
+---+---+---+---+---+---+---+---+---+---+---+
^
|
ipoint

注意:当未定义的行为被调用时,您的代码可能看起来正常工作,或者它可以 SEGFAULT (或介于两者之间的任何东西),您的代码操作只是未定义,从那时起就不能依赖了。

您需要做的是将每个指针前进 1 , 不是 'i' .这将确保您不会超出数组范围进行写入。您可以通过简单地更改 'i' 来解决问题。至 1对于每个,例如

        ipoint += 1;
bpoint += 1;
ppoint += 1;

还有许多其他地方可能会引发未定义行为。您未能检查 scanf返回 .如果您输入(不小心,或键盘的猫步)不是数字值,匹配失败将发生,将不会从stdin中读取任何字符。并且将跳过所有进一步的提示,然后您将继续处理不确定值,这将调用未定义的行为

此外,如果输入超过 7对于 number_of_payments或者您调用未定义行为 的小于零的值。 (number_of_payments = 0 的结果也相当无趣)当接受输入时,您不仅必须验证转换是否成功,还必须验证结果值是否在可用范围内——以避免未定义的行为,例如

    printf ("Enter number of payments : ");
if (scanf (" %i", &number_of_payments) != 1) {
fprintf (stderr, "error: invalide no. of payments.\n");
return 1;
}
/* validate no. pmts in range */
if (number_of_payments < 1 || number_of_payments > MAXPMTS) {
fprintf (stderr, "error: no. of payments exceed MAXPMTS (%d)\n",
MAXPMTS);
return 1;
}

最后,您可以自由地初始化 ipoint = &interest[0]; , 没有必要。访问数组时,数组被转换为指向其第一个元素的指针,因此 ipoint = interest;是所有需要的。下面的评论中还解决了其他问题,但总而言之,您可以执行类似以下操作以确保在整个代码中定义行为:

#include <stdio.h>
#include <string.h>

#define MAXPMTS 32 /* if you need a constant, define one (or more) */

double power (double a, double b);

int main (void)
{
int loanAmount = 0, /* initialize all variables */
number_of_payments = 0,
i = 0;
double interestRate = 0.0,
monthlyInterestRate = 0.0,
monthlyPayment = 0.0;

/* numeric conversions consume leading whitespace (as does %s)
* the ' ' in the conversion doesn't hurt, but isn't required.
*/

printf ("Enter amount of loan : $ ");
if (scanf (" %i", &loanAmount) != 1) { /* validate conversion */
fprintf (stderr, "error: invalid loan amount.\n");
return 1;
}

printf ("Enter Interest rate per year : ");
if (scanf (" %lf", &interestRate) != 1) {
fprintf (stderr, "error: invalid interest rate.\n");
return 1;
}

printf ("Enter number of payments : ");
if (scanf (" %i", &number_of_payments) != 1) {
fprintf (stderr, "error: invalide no. of payments.\n");
return 1;
}
/* validate no. pmts in range */
if (number_of_payments < 1 || number_of_payments > MAXPMTS) {
fprintf (stderr, "error: no. of payments exceed MAXPMTS (%d)\n",
MAXPMTS);
return 1;
}

monthlyInterestRate = ((interestRate / 100) / 12); //AKA 'r' or rate.
monthlyPayment = (monthlyInterestRate) * (loanAmount/(1 - 1/(power((1 +
monthlyInterestRate), number_of_payments))));

double interest[MAXPMTS] = {0};
double principal[MAXPMTS] = {0};
double balance[MAXPMTS] = {0};
balance[0] = loanAmount;
double *ipoint = NULL,
*ppoint = NULL,
*bpoint = NULL,
*bpointprev = NULL;

ipoint = interest;
ppoint = principal;
bpoint = balance;
bpointprev = bpoint;

printf ("Monthly payment should be $ %lf\n", monthlyPayment);
printf ("# \t Payment \t Principal \t Interest \t Balance \n");

/* standard loop is from 0 to i < number_of_payments */
for (i = 0; i < number_of_payments; i++) {
ipoint += 1;
bpoint += 1;
ppoint += 1;

*ipoint = *bpointprev * monthlyInterestRate;
*ppoint = monthlyPayment - *ipoint;
*bpoint = *bpointprev - *ppoint;

/* adjust 'i + 1' for payment no. output */
printf ("%i \t %.2f \t %.2f \t %.2f \t\t %.2f\n",
i + 1, monthlyPayment, *ppoint, *ipoint, *bpoint);

bpointprev += 1; //Iterates after logic for next calculation.
}

return 0;
}

double power(double a, double b)
{
double i, sum = 1;
for (i = 0; i < b; i++) {
sum = sum * a;
}
return sum;
}

(注意:您是从 i=1 循环到 i <= number_of_payments 还是从 i=0 循环到 i < number_of_payments 很大程度上取决于您,但循环变量跟踪保护数组边界的有效数组索引。如上所述,支付编号的输出只需调整 i + 1 即可生成所需的 1,2,3... )

(另请注意:在实践中,您要避免对货币使用浮点数学。当您因舍入错误而亏损时,人们会非常沮丧。整数数学消除了这个问题)

仔细检查一下,如果您还有其他问题,请告诉我。

关于c - 为什么我的 for 循环增量变化很大?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51406889/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com