#include #include #include #include /// /// Структура представляет собой модель одночлена. /// struct term { term(UCHAR _n = 0, float _a = 0, term *_next = NULL) : n(_n), a(_a), next(_next) { } /// /// Степень. /// UCHAR n; /// /// Коэффициент. /// float a; /// /// Указатель на следующий одночлен полинома. /// term *next; }; /// /// Функция возвращает знак числа. /// /// Число, у которого нужно определить знак. /// '+' или '-'. char sign(float n); /// /// Функция возвращает модуль числа. /// /// Число. /// Модуль числа. float abs(float n); /// /// Выводит полином на консоль. /// /// Указатель на первый одночлен полинома. /// Имя полинома. void printPolynomial(term *p, char c); /// /// Функция складывает 2 полинома друг с другом. /// /// Указатель на первый полином. /// Указатель на второй полином. /// Указатель на полином, который будет результатом сложения первого и второго полиномов. term * addPolynomials(term *a, term *b); /// /// Функция считывает из определенного файла 2 полинома. /// /// Путь к файлу. /// Указатель на указатель, в который нужно записать первый одночлен одного полинома. /// Указатель на указатель, в который нужно записать первый одночлен другого полинома. void scanPolynomials(const char *path, term **p, term **q); int main() { setlocale(0, ""); term *P = new term(), *Q = new term(), *R; scanPolynomials("D:/polynomials.txt", &P, &Q); R = addPolynomials(P, Q); printPolynomial(P, 'P'); printPolynomial(Q, 'Q'); printPolynomial(R, 'R'); return 0 * _getch(); } void scanPolynomials(const char *path, term **p, term **q) { FILE *stream; fopen_s(&stream, path, "r"); if (stream) { // sign нужен для определения знака коэффициента, end - "флаг", обозначающий, что полином прочитан в файле до конца, если end = '\n'. char sign = '+', end = ' '; float a = 0; // Коэффициент только что прочитанного одночлена. UCHAR N = 0, n = 0; // N - наибольшая степень одночлена любого полинома, n - степень только что прочитанного одночлена. bool p_end = false; // Означает, что полином p построен. // r - указатель, с помощью которого осуществляется доступ к каждому одночлену полинома p или q. Читаем каждый одночлен полиномов отдельно, пока не дойдем до конца файла (EOF). for (term *r = new term(); fscanf_s(stream, " %c %fx^%hhi%c", &sign, 1, &a, &n, &end, 1) != EOF; ) { // Если степень у прочитанного одночлена больше ранее зафиксированной, то зафиксировать эту степень, как новый максимум. if (N < n) N = n; // Если перед одночленом стоит знак '-', отрицаем коэффициент. if (sign == '-') a *= -1; // Если первый одночлен полинома меньше n, то в полином нужно добавить этот одночлен с большей степенью в самое начало полинома. if (n > r->n) { // Добавляем новые одночлены в полином на первое место, пока не добавим тот, чья степень стала максимальной для этого полинома. for ( ; r->n != n; ) r = new term(r->n + 1, 0, r); // Совершен переход к нужному одночлену, прибавляем его коэффициент. *Такой способ задания коэффициента (+=) для одночлена позволяет складывать подобные одночлены. r->a += a; } else // Иначе, значит, что прочитанный одночлен имеет равную или меньшую степень относительно первого одночлена полинома. { term *t = r; // Указатель нужен, чтобы не сбить ссылку на первый одночлен у r. for ( ; t->n != n; t = t->next); // Перемещаемся по полиному r от начала до одночлена со степенью равной n. t->a += a; // Совершен переход к нужному одночлену, прибавляем его коэффициент. } // Если уже дочитали до конца первого полинома, говорим, что первый полином построен, и переназначаем r, чтобы заполнять второй полином. if (end == '\n' && !p_end) { p_end = true; r = new term(); } p_end ? *q = r : *p = r; // Обновляем полином p или q, в зависимости от того, заполнен ли уже полином p. } // Если степень одного из полиномов (p1) больше, чем степень другого (p2), то добавляем одночлены в начало полинома p2, пока степень p2 < p1. for (term **z = (*p)->n < N ? p : (*q)->n < N ? q : NULL; z && (*z)->n < N; ) *z = new term((*z)->n + 1, 0, *z); fclose(stream); } } term * addPolynomials(term *a, term *b) { // Указатель на первый элемент полинома суммы. term *r = new term(); // На каждой итерации переходит к следующему элементу каждого полинома, пока не дойдет до последнего, у которого указатель на следующий равен NULL. for (term *p = r; a; p = p->next, a = a->next, b = b->next) { p->n = a->n; p->a = a->a + b->a; p->next = a->next ? new term() : NULL; } return r; } void printPolynomial(term *p, char c) { bool f = false; // Индикатор "есть одночлен перед текущим". printf_s("%cn(x) = ", c); for ( ; p; p = p->next) { if (p->n && p->a) // Если степень != 0 и коэф != 0, то { if (abs(p->a) != 1) // если |коэф| != 1, то // если есть предодночлен, пишем " %с |%а|", иначе пишем "%а". f ? printf_s(" %c %g", sign(p->a), abs(p->a)) : printf_s("%g", p->a); // иначе, если есть предодночлен пишем " %с ", иначе, "%с". else printf_s(f ? " %c " : "%c", sign(p->a)); // если степень больше 1, то пишем "x^%n", иначе - "х". p->n > 1 ? printf_s("x^%d", p->n) : printf_s("x"); f = true; } else if (!p->n) // иначе, если степень == 0, то { if (p->a && f) // если коэф != 0 и есть предодночлен, то printf_s(" %c %g", sign(p->a), abs(p->a)); else if(!f) printf_s("%g", p->a); // иначе, если нет предодночлена, "%a". printf_s(".\n"); } } } char sign(float n) { return n > 0 ? '+' : '-'; } float abs(float n) { return sign(n) == '-' ? -1 * n : n; }