我在学习java之后想学习c ++。我被告知结构很像java中带有实例变量的类。分数结构中的“整数”值似乎在isDivisible函数中从1随机变为零。为什么会这样?请不要遗漏细节。谢谢你的帮助
#include <stdio.h>
#include <math.h>
#include <iostream>
using namespace std;
#define LARGEST(a,b) ((a > b) ? 1 : 0)
struct fraction {
int numerator;
int denominator;
int whole;
};
fraction* wholeNumber(fraction * frac){
if (LARGEST((frac->numerator), (frac->denominator)) == 1){
double w = (((double) (frac->numerator)) / ((double) (frac->denominator)));
int whole = floor(w);
struct fraction now = { (frac->numerator) - whole*(frac->denominator),
(frac->denominator), whole};
return &now;
}
return frac;
}
int toCheck[4] = {2,3,5,7};
int isDivisible(fraction * frac){
double newNum = (double) frac->numerator;
double newDen = (double) frac->denominator;
// The value of whole seems to change right about here after the two doubles are declared
for(int i = 0; i < 4; ++i){
if (( (newNum / toCheck[i]) == (frac->numerator / toCheck[i]) ) ? true : false &&
((newDen / toCheck[i]) == (frac->numerator / toCheck[i]) ) ? true : false)
return toCheck[i];
}
return 0;
}
fraction* simplifier(fraction * frac){
frac = wholeNumber(frac);
while(isDivisible(frac) != 0){
int factor = isDivisible(frac);
frac->numerator = frac->numerator / factor;
frac->denominator = frac->denominator / factor;
}
return frac;
}
int main (int argc, char ** argv){
struct fraction frac = {55, 50, 0}; // fraction declared, 0 55/50
struct fraction * final = simplifier(&frac);
printf("%d %d/%d\n", final->whole, final->numerator, final->denominator);
return 0;
}
答案 0 :(得分:5)
编译时是否收到此警告(或类似内容)?
example.cpp:20:17: warning: address of stack memory associated with local
variable 'now' returned [-Wreturn-stack-address]
return &now;
^~~
返回指向堆栈变量的指针是个坏消息。如果您的编译器没有警告您,您需要打开一些警告标志(或者获得更好的编译器 - 我上面的引用来自clang,它有非常好的错误消息和对于初学者来说可能是一个很好的选择,因为那个。)
问题的长短是now
在函数结束时超出范围。这意味着访问返回的指针会导致未定义的行为。
您可能希望在程序中使用更少的指针 - 如果您使用的是C ++,则可以访问引用,但除此之外,C和C ++允许结构按值传递,这可能会使您的生活学习时更容易。
答案 1 :(得分:1)
wholeFunction
返回局部变量的地址。
struct fraction now = { (frac->numerator) - whole*(frac->denominator),
(frac->denominator), whole};
return &now;
以上导致未定义的行为。
答案 2 :(得分:0)
C ++是一种具有价值语义的语言,它使语言与具有引用语义的Java或C#有着截然不同的感觉。您可以在C ++中使用引用,但它们是显式的。您的代码存在许多问题,问题的核心是价值语义的概念。而不是单独检查每一个,我重构你的代码是更惯用的C ++。它绝不是完美的,但它已经删除了你的错误,并希望能为你提供一些关于如何用C ++做事的见解。
struct fraction
{
int numerator;
int denominator;
int whole;
};
fraction wholeNumber(const fraction& frac)
{
if (frac.numerator > frac.denominator)
{
double w = ((double)frac.numerator) / ((double)frac.denominator);
int whole = floor(w);
fraction now = { frac.numerator - whole * frac.denominator, frac.denominator, whole};
return now;
}
return frac;
}
int toCheck[4] = {2,3,5,7};
int isDivisible(const fraction& frac)
{
double newNum = (double) frac.numerator;
double newDen = (double) frac.denominator;
for(int i = 0; i < 4; ++i)
{
if ( (newNum / toCheck[i]) == (frac.numerator / toCheck[i]) &&
(newDen / toCheck[i]) == (frac.numerator / toCheck[i]))
return toCheck[i];
}
return 0;
}
fraction simplifier(const fraction& frac)
{
fraction new_frac = wholeNumber(frac);
int factor = isDivisible(new_frac);
while(factor)
{
new_frac.numerator = new_frac.numerator / factor;
new_frac.denominator = new_frac.denominator / factor;
int factor = isDivisible(new_frac);
}
return new_frac;
}
int main (int argc, char ** argv){
struct fraction frac = {55, 50, 0}; // fraction declared, 0 55/50
struct fraction final = simplifier(frac);
std::cout << final.whole << " " << final.numerator << "/" << final.denominator;
return 0;
}