1

在学习java之后我正在尝试学习c++。有人告诉我,这些结构很像 java 中具有实例变量的类。在 isDivisible 函数中,fraction 结构中的“整体”值似乎从 1 随机变为 0。为什么会这样?请不要吝啬细节。谢谢您的帮助

#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;
}
4

3 回答 3

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++ 允许通过值传递结构,这可能会让您在学习时更轻松.

于 2013-08-29T17:54:13.200 回答
1

wholeFunction返回局部变量的地址。

 struct fraction now = { (frac->numerator) - whole*(frac->denominator),
            (frac->denominator), whole};
 return &now;

以上导致未定义的行为。

于 2013-08-29T17:54:19.623 回答
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;
}
于 2013-08-29T18:20:11.360 回答