Advertisement
Guest User

Untitled

a guest
Feb 28th, 2020
157
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.56 KB | None | 0 0
  1. #include <stdio.h>
  2.  
  3. struct Polinom {
  4.     int pow;
  5.     float cof;
  6.     Polinom* next;
  7. };
  8.  
  9. Polinom* Summ(Polinom* P, Polinom* Q);
  10. int read(const char* filePath, Polinom** P);
  11. void write(const char* filePath, Polinom* R);
  12.  
  13. int main() {
  14.  
  15.     Polinom* P, * Q, * R; // Объявление полиномов P, Q, R
  16.     R = nullptr;        // Каждый из них по умолчанию nulltpr, т.к. если файлы с P  и/или Q пусты,
  17.     P = nullptr;        // то при инициализации через new Polinom их поля заполнятся какой-то
  18.     Q = nullptr;
  19.     if (!read("1.txt", &P)) // 1.txt - файл с полиномом P в формате a b, a - степень, b - коэффициент
  20.         return 1;
  21.     if (!read("2.txt", &Q)) // 2.txt - файл с полиномом Q
  22.         return 1;
  23.     R = Summ(P, Q); // Вычисление R
  24.  
  25.     write("result.txt", R);
  26.  
  27.     // p.s если ругается на unicode, надо удалить смешную шутку на 17 строке
  28.  
  29.     return 0;
  30. }
  31.  
  32. Polinom* Summ(Polinom* P, Polinom* Q) {
  33.     // Сначала читать комментарии к read (или нет)
  34.  
  35.     /* Общая схема такая же, как в read. Самое главное - понимать, почему temp необходим.
  36.        Нам нужно, чтобы "последний элемент"->next был nullptr. Первое, что приходит в голову - это
  37.          current->next = nullptr;
  38.          current = current->next;
  39.        И если current не последний, то на следующей итерации цикла
  40.          current = new Polinom;
  41.        Это не сработает, т.к. current до этой строчки и current после нее - это два разных указателя, соответственно элемент R, копией которого являлся current,
  42.        остался равным nullptr, т.о. R будет состоять из одного элемента, а остальные будут разбросанными по памяти и никак не связаны с R
  43.  
  44.        Использование temp позволяет current всегда быть не nullptr, а current->next всегда nullptr
  45.     */
  46.     Polinom* temp = nullptr;
  47.     Polinom* current = nullptr;
  48.     Polinom* R = nullptr;
  49.  
  50.     while (P || Q) { // Если в P или в Q есть элементы
  51.         temp = new Polinom;
  52.         temp->next = nullptr; // Тут все ясно
  53.  
  54.         if (P && Q) { // Если элементы присутствуют в обоих списках
  55.             if (Q->pow == P->pow) { // степени равны, возможны 2 случая: коэффициенты не противоположны и коэффициенты противоположны
  56.                 if (P->cof != -(Q->cof)) { // Не противоположны
  57.                     temp->pow = P->pow;
  58.                     temp->cof = P->cof + Q->cof;
  59.                 }
  60.                 else
  61.                     temp = nullptr; // До этого temp был равен new Polinom и его значения были случайны.
  62.                 P = P->next;
  63.                 Q = Q->next; // Все понятно
  64.             }
  65.             else { // 2 случая: степень P > Q или степень Q > P
  66.                 if (P->pow > Q->pow) {
  67.                     temp->pow = P->pow;
  68.                     temp->cof = P->cof;
  69.                     P = P->next;
  70.                 }
  71.                 else if (Q->pow > P->pow) {
  72.                     temp->pow = Q->pow;
  73.                     temp->cof = Q->cof;
  74.                     Q = Q->next;
  75.                 }
  76.             }
  77.         }
  78.         else { // Остался лишь один не просмотренный список
  79.             P = P ? P : Q; // Это уловный тернарный оператор. Что-то типо if(P) { P = P; } else { P = Q; }
  80.             if (P) { // Не факт что есть хотя бы один не просмотренный список
  81.                 temp->pow = P->pow;
  82.                 temp->cof = P->cof;
  83.                 P = P->next;
  84.             }
  85.         }
  86.         if (temp) {
  87.             if (!R) { // Тут все также как в read
  88.                 R = new Polinom;
  89.                 R = temp;
  90.                 current = R;
  91.             }
  92.             else {
  93.                 current->next = temp;
  94.                 current = current->next;
  95.             }
  96.         }
  97.     }
  98.     return R;
  99.     // P.S переделал это, теперь оно функция как она и просила.
  100. }
  101.  
  102.  
  103. int read(const char* filePath, Polinom** P) {
  104.     FILE* file;
  105.     errno_t error = fopen_s(&file, filePath, "r"); // Попытка отрыть файл, если не удалось, error = 1
  106.  
  107.     if (error) {
  108.         printf("Failed to open the file \"%s\".", filePath); // Если error = 1, то функция возвращает 0, что завершает выполнение main с кодом 1
  109.         return 0;
  110.     }
  111.  
  112.     /* Всего понадобится 3 полинома: *P - указатель на голову списка
  113.                                       current - текущее считываемое слагаемое (всегда не nullptr!)
  114.                                       temp - вспомогательное звено полинома, необходимое, чтобы у последнего элемента из P следующий всегда был равен nullptr
  115.     */
  116.     Polinom* current = nullptr;  // Почти всегда
  117.     Polinom* temp = new Polinom;
  118.     // Проверяем является ли текущая строка файла последней, попутно записывая её значения в соответствующие поля temp
  119.     while (fscanf_s(file, "%d%f", &temp->pow, &temp->cof) != EOF) {
  120.         temp->next = nullptr;
  121.         if (!(*P)) { // Это условие выполнится единожды, на первой строке файла.
  122.             *P = new Polinom; // Мы уже знаем что файл не пустой и инициализируем *P
  123.             *P = temp;        // Тута все понятно
  124.             current = *P;     // И здеся тоже
  125.         }
  126.         else { // Это условие выполняется после считывания каждой строки кроме первой
  127.             current->next = temp;
  128.             current = current->next; // В результате current->next, а соответственно и (*P)->next равны nullptr (т.к. temp->next = nullptr)
  129.         }
  130.         temp = new Polinom; // иначе 1) содержимое P и current будут меняться 2) список станет циклическим
  131.     }
  132.     delete temp;
  133.     fclose(file);
  134.     return 1;
  135. }
  136.  
  137. void write(const char* filePath, Polinom* R) {
  138.     FILE* file;
  139.     errno_t error = fopen_s(&file, filePath, "w+");
  140.     if (error) {
  141.         printf("Failed to open the file \"%s\".", filePath); // Аналогично  функции read
  142.         return;
  143.     }
  144.     while (R) { // Поскольку у последнего элемента R next = nullptr, данный список просматривает все содержимое R
  145.         fprintf(file, "%d %.3f\n", R->pow, R->cof);
  146.         R = R->next;
  147.     }
  148.     fclose(file);
  149. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement