把那些有公分母的分数加起来

Add up those fractions that have a common denominator

我有一个包含分数的文件。我必须将它的分数写成一个结构。然后我需要创建一个动态数据结构以添加那些具有共同分母的分数,但我不应该使用动态数组。你能帮我解决分数加法部分吗? (link 包含带分数的文件照片和我想要得到的结果,但现在我只能在屏幕上显示分数,但不能将它们相加) enter image description here

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

using namespace std;

struct fraction {
    int numerator, denominator;
};

struct Node {
    fraction fr;
    Node* next;
};

Node* newNode(fraction fr) {
    Node* p;
    p = new Node;
    p->fr.numerator = fr.numerator;
    p->fr.denominator = fr.denominator;
    p->next = NULL;
    return p;
}

void addNode(Node* curr, Node** head, Node** tail) {
    if (*head == NULL) {
        *head = *tail = curr;
        //        *tail = curr;
    }
    else {
        (*tail)->next = curr;
        *tail = curr;
    }
}

void outList(Node* head) {
    Node* curr;
    curr = head;
    while (curr != NULL) {
        cout << curr->fr.numerator << "/" << curr->fr.denominator << endl;;
        curr = curr->next;
    }
}

int main() {
    fraction fr;
    int n;
    Node* curr = NULL;
    Node* head = NULL;
    Node* tail = NULL;
    FILE* f;
    fopen_s(&f, "testfile.txt", "r");

    if (f) {
        while (!feof(f)) {
            fscanf_s(f, "%d", &n);
            for (int i = 0; i < n; i++) {
                fscanf_s(f, "%d", &fr.numerator);
                fscanf_s(f, "%d", &fr.denominator);
                curr = newNode(fr);
                addNode(curr, &head, &tail);
            }
        }

        fclose(f);
        outList(head);
    }
}

我建议先打基础,分数 class。如果你需要编写代码来访问成员,可能你违反了封装规则或紧耦合规则。

class Fraction
{
    int   m_numerator;
    int   m_denominator;
    public:  
    Fraction();  // Default constructor, creates 0/1 fraction.
    Fraction(int numerator, int denominator);
    Fraction(const Fraction& f);  // Copy constructor
    bool  Equal_Denominators(const Fraction& f);
    friend std::ostream& operator<<(std::ostream& out, const Fraction& f);
};

Fraction::Fraction()
: m_numerator(0), m_denominator(1)
{ ; }

Fraction::Fraction(int numerator, int m_denominator)
: m_numerator(numerator), m_denominator(denominator)
{
    if (m_denominator == 0)
    {
       // Throw an exception
    }
}

Fraction::Fraction(const Fraction& f)
: m_numerator(f.m_numerator), m_denominator(f.m_denominator)
{ ; }

bool  Fraction::Equal_Denominators(const Fraction& f)
{
    return m_denomenator == f.m_denomenator;
}

std::ostream& operator<<(std::ostream& out, const Fraction& f)
{
    out << "(" << f.m_numerator << "/" << "f.m_denominator" << ")";
    return out;
}

以上代码片段给出了比较两个分母相等的分数、构造分数和打印分数的方法。

当您遍历列表时,您可以这样做:

if (p->fr.Equal_Denominators(fr))
{
    // Add the fractions
}

您还可以通过这样做添加一些调试:

while (p != nullptr)
{
    std::cout << p->fr << "\n";
}

O.P 的推荐任务:

  1. 重载 operator>> 以从 std::cin 或文件中读取分数。
  2. 重载 operator+= 以添加和分配分数。
  3. 超载operator=

如果你从头开始构建它并使用构造函数和运算符,它可以变成这样:

#include <string>
#include <iostream>
#include <cassert>

struct Fraction {
    // construct a Fraction from whole number or n, d
    constexpr Fraction(int n, int d=1) noexcept : numerator(n), denominator(d) { }

    // add other Fraction with matching denominator
    constexpr Fraction operator +=(const Fraction &other) noexcept {
        assert(denominator == other.denominator);
        numerator += other.numerator;
        return *this;
    }

    // denominator may not change but numerator does
    int numerator;
    const int denominator;
};

// print Fraction nicely
std::ostream & operator <<(std::ostream &out, const Fraction &fr) {
    out << "(" << fr.numerator << " / " << fr.denominator << ")";
    return out;
}

struct List {
    struct Node {
        // create Node containing fraction and attach to parent
        constexpr Node(Node **parent, const Fraction &fr_) noexcept : next{*parent}, fr(fr_) {
            *parent = this;
        }

        // printing node just prints fraction
        std::ostream & print(std::ostream &out) const {
            return out << fr;
        }

        // Nodes are always constructed as tail so initialize to nullptr
        Node *next{nullptr};
        Fraction fr;
    };

    // construct empty List
    List() { }

    // no copying List
    List(const List &) = delete;

    // no copy asignment
    List & operator =(const List &) = delete;

    // move construct List by taking over Nodes from other
    List(List && other) : head(other.head) {
        other.head = nullptr;
    }

    // move assign List by swapping Nodes with other
    List & operator =(List &&other) {
        std::swap(head, other.head);
        return *this;
    }

    // deconstruct List by deleting all Nodes
    ~List() noexcept {
        while(head) {
            Node *t = head;
            head = head->next;
            delete t;
        }
    }

    // print List as sum of fractions
    std::ostream & print(std::ostream &out) const {
        for (Node *node = head; node; node = node->next) {
            node->print(out);
            if (node->next) out << " + ";
        }
        return out;
    }

    // add Fraction to list: Either adds to existing Fraction or
    // adds new Node. Fractions are sorted by denominator.
    List & operator +=(const Fraction &fr) {
        Node **tail;
        for (tail = &head; *tail; tail = &((*tail)->next)) {
            int d = (*tail)->fr.denominator;
            if (d > fr.denominator) break; // denominator too large, insert Fraction before
            if (d == fr.denominator) { // denominator matched, += Fraction
                (*tail)->fr += fr;
                return *this;
            }
        }
        // no matching denominator, add new node
        new Node(tail, fr);
        return *this;
    }

    // add Fraction to List and move result to return value 
    List && operator +(const Fraction &other) && {
        (*this) += other;
        return std::move(*this);
    }

    // initialize as empty list
    Node *head{nullptr};
};

// print list
std::ostream & operator <<(std::ostream &out, const List &list) {
    return list.print(out);
}

// sum of 2 fraction gives a List    
List operator +(const Fraction &lhs, const Fraction &rhs) {
    return List{} + lhs + rhs;
}

// tired of typing so much, shorten name
using F = Fraction;

int main() {
    // You can just print sums of fractions like this
    // std::cout << F{1, 5} + F{4, 7} + F{3, 5} + F{1, 2} + F{2, 2} + F{2, 5} << std::endl;

    // or read from stdin
    List list;
    int count;
    std::cin >> count;
    while(count-- > 0) {
        int n, d;
        std::cin >> n >> d;
        list += F{n, d};
    }
    std::cout << list << std::endl;
}