本站动态:

C实现的一元多项式运算[2]--链表运算

上一次《C实现的一元多项式运算》完成了一元多项式的基本操作,接上一次的工作,本次完成了乘法的运算和将多项式运算的过程输出到HTML文件的功能。另外定义了PRINTF_ARGL和FPRINTF_ARGL宏,用来同时向屏幕和文件输出。

因为多项式的表示是通过单向链表来完成的,多项式的运算也是通过链表的操作来完成的(结点动态申请),所以内存的分配和释放尤为重要。为检测分配和释放状况,代码统一使用宏Create_ENTITY和FREEIF来分配和释放,在宏中输出分配释放情况。

DEBUG_MEMORY宏值如果定义为0,则关闭输出链表结点输出的情况,定义为非0值(如1)则输出当前是在分配结点还是在释放结点,并输出分配或释放结点后剩余的结点数。所以当程序运行结束后,结点数为0则表示为链表分配的内存已经全部释放。

代码中的函数基础的放在前面,提供后面的函数使用,而没用使用函数原型声明,这样可以少贴几行到网页(实际编程时最好不要如此,以来很难控制函数的调用关系,二来如果将函数申明放在一起,用户可以很容易看到该源文件提供哪些函数,主要完成什么功能等)。

main函数被用来创建log文件,用户请在UserMain函数中编写代码。

头文件和源文件本应分开,为方便贴出,暂将其放在一块。

还少一个将字符串如“5y^3 + 3y^2 - 4y -1”parse成一个链表的函数,以后补上。等该功能完成后,可再增加命令行功能,如:“polynomial 5y^3+3y^2-4y-1 * 3y^4-4y-2”。

下载:
源文件
生成的log文件
生成的HTML文件(运算过程)

 

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <assert.h>
  4.  
  5. //You can set DEBUG_MEMORY to either 0 if do not wanna test whether there is
  6. //momery leak or 1(just other than 0) to check.
  7. #define DEBUG_MEMORY 1
  8. #define WRITE_SCREEN_TO_FILE 1
  9. //Write strings(written by PRINTF_ARGL) to the file besides the screen.
  10. //this is only used when WRITE_SCREEN_TO_FILE != 0
  11. #define SCREEN_LOG_FILE "D:\\PolyLog.txt"
  12.  
  13. #if defined NULL
  14.     #undef NULL
  15. #endif
  16. #define NULL 0
  17.  
  18. #define CHECK_NONNULL_POINT(p) assert(NULL != p)
  19. #define CHECK_SAME_VALUE(a,b) assert((a) == (b))
  20.  
  21. #define _ARGL(r) r##,
  22. #define _ARGLEND(r) r
  23.  
  24. //when use PRINTF_ARGL() or FPRINTF_ARGL(), please do not forget to add {}
  25. //even if there is only one statement in it, especially when it is after "if".
  26. #if WRITE_SCREEN_TO_FILE
  27.     FILE* gpLogFile = NULL;
  28.     #define PRINTF_ARGL(s) printf(s); \
  29.             if (NULL != gpLogFile) \
  30.                 fprintf(gpLogFile, s)
  31.     #define FPRINTF_ARGL(fp, s) printf(s); \
  32.             if (NULL != gpLogFile) \
  33.                 fprintf(gpLogFile, s); \
  34.             fprintf(fp, s)
  35. #else
  36.     #define PRINTF_ARGL(s) printf(s)
  37.     #define FPRINTF_ARGL(fp, s) printf(s); \
  38.             fprintf(fp, s)  
  39. #endif
  40.  
  41. //We can only create one Create_ENTITY in one area,
  42. //declaration of variables must be ahead of it.
  43. #if DEBUG_MEMORY
  44.     int gMemNodeNum = 0;
  45.     #define Create_ENTITY(type, name) \
  46.             type* name = (type*) malloc(sizeof(type)); \
  47.             assert(NULL != name); \
  48.             gMemNodeNum++; \
  49.             /* PRINTF("\n[Create_ENTITY: %d, 0x%p] ", ++gMemNodeNum, name)*/ \
  50.             PRINTF_ARGL(_ARGL("\n[Create_ENTITY: %d, 0x%p] ") \
  51.                         _ARGL(gMemNodeNum)_ARGLEND(name))
  52.  
  53.     #define FREEIF(p) \
  54.             if (NULL != p)  \
  55.             {               \
  56.                 gMemNodeNum--; \
  57.                 /* PRINTF("\n[FREE: %d, 0x%p] ", --gMemNodeNum, p); */ \
  58.                 PRINTF_ARGL(_ARGL("\n[FREE: %d, 0x%p] ") \
  59.                         _ARGL(gMemNodeNum)_ARGLEND(p)); \
  60.                 free(p);   \
  61.             }   \
  62.             p = NULL
  63. #else
  64.     #define Create_ENTITY(type, name) \
  65.             type* name = (type*) malloc(sizeof(type)); \
  66.             assert(NULL != name)                    
  67.  
  68.     #define FREEIF(p) \
  69.             if (NULL != p)  \
  70.             {               \
  71.                 free(p);   \
  72.             }   \
  73.             p = NULL    
  74. #endif
  75.  
  76.  
  77.  
  78. typedef unsigned int uint;
  79. typedef char BOOL;
  80. #define FALSE 0
  81. #define TRUE 1
  82.  
  83. typedef int QType; //use int to simplize
  84. typedef int IType;
  85.  
  86. //多项式中的项
  87. typedef struct _ItemNode ItemNode;
  88. struct _ItemNode
  89. {
  90.     ItemNode*   pNext;     //指向下一项
  91.     QType       quotiety;  //系数
  92.     IType       index;     //指数
  93. };
  94.  
  95. typedef struct _Polynomial
  96. {
  97.     ItemNode*   pHeader;   //多项式中的第一项
  98.     ItemNode*   pLast;     //多项式中的最后一项
  99.     char        pronumeral; //未知数名,如x,y,z
  100.     uint        ItemNum;   //项数
  101. } Polynomial;
  102.  
  103. //Create one empty polymonial
  104. Polynomial* CreateEmptyPolynomial(char name)
  105. {
  106.     Create_ENTITY(Polynomial, pPoly);
  107.     pPoly->pHeader = pPoly->pLast = NULL;
  108.     pPoly->pronumeral = name;
  109.     pPoly->ItemNum = 0;
  110.     return pPoly;
  111. }
  112.  
  113. //Create one polynomial with one item
  114. Polynomial* CreatePolynomial(char name, ItemNode* head)
  115. {
  116.     Polynomial* pPoly = CreateEmptyPolynomial(name);
  117.     pPoly->pHeader = pPoly->pLast = head;
  118.     pPoly->ItemNum = 1;
  119.     return pPoly;
  120. }
  121.  
  122. //Create one Item Node
  123. ItemNode* CreateItemNode(QType quotiety, IType index)//系数,指数
  124. {
  125.     Create_ENTITY(ItemNode, pItem);
  126.     pItem->quotiety = quotiety;
  127.     pItem->index = index;
  128.     pItem->pNext = NULL;
  129.     return pItem;
  130. }
  131.  
  132. //Duplicate an ItemNode
  133. ItemNode* DuplicateItemNode(ItemNode* pItem)
  134. {
  135.     Create_ENTITY(ItemNode, pNewItem);
  136.     pNewItem->index = pItem->index;
  137.     pNewItem->quotiety = pItem->quotiety;
  138.     pNewItem->pNext = pItem->pNext;
  139.     return pNewItem;
  140. }
  141.  
  142. void FreeItemNode(ItemNode* pItem)
  143. {
  144.     FREEIF(pItem);
  145. }
  146.  
  147.  
  148. void FreePolynomial(Polynomial* pPoly)
  149. {
  150.     ItemNode *temNode;
  151.     CHECK_NONNULL_POINT(pPoly);
  152.  
  153.     temNode = pPoly->pHeader;
  154.     while (NULL != temNode)
  155.     {
  156.         //we cannot simply use temNode = temNode->pNext after call FreeItemNode
  157.         //because the struct has been freed and we would not get proper value
  158.         //of temNode->pNext, although temNode isn't NULL
  159.         pPoly->pHeader = temNode->pNext;
  160.         FreeItemNode(temNode);
  161.         temNode = pPoly->pHeader;
  162.     }
  163.     FREEIF(pPoly);
  164. }
  165.  
  166. //Add one Item to polynomial,and return the ItemNode Num.
  167. int AddItemToPolynomial(Polynomial* pPoly, ItemNode* pItem)
  168. {
  169.     CHECK_NONNULL_POINT(pPoly);
  170.     CHECK_NONNULL_POINT(pItem);
  171.     if (NULL != pPoly->pLast) //this means pPoly->pHeader != NULL
  172.     {
  173.         if (NULL == pPoly->pHeader->pNext) //when there is only one item
  174.             pPoly->pHeader->pNext = pPoly->pLast;
  175.         pPoly->pLast->pNext = pItem;
  176.     }
  177.     else //the first item node
  178.     {
  179.         pPoly->pHeader = pItem;
  180.     }
  181.     pPoly->pLast = pItem;
  182.     pPoly->pLast->pNext = NULL;
  183.     return ++pPoly->ItemNum;
  184. }
  185.  
  186. //add one item to a formatted polynomial, and return the itemnode num.
  187. //please ensure that pPoly is formatted, namely its index is in Desc order.
  188. //pItem must be new built(is not a member of another polynomial)
  189. int AddItemToFormattedPolynomial(Polynomial* pPoly, ItemNode* pItem)
  190. {
  191.     CHECK_NONNULL_POINT(pPoly);
  192.     CHECK_NONNULL_POINT(pItem);
  193.     if (NULL == pPoly->pHeader)
  194.     {
  195.         pPoly->pHeader = pPoly->pLast = pItem;
  196.     }
  197.     else
  198.     {
  199.         ItemNode* pTemItem = pPoly->pHeader;
  200.         ItemNode* pLastValidItem = pTemItem; //this cannot be NULL
  201.         while (NULL != pTemItem && pTemItem->index > pItem->index)
  202.         {
  203.             pLastValidItem = pTemItem;
  204.             pTemItem = pTemItem->pNext;
  205.         }
  206.         if (NULL == pTemItem) //insert it to the end
  207.         {
  208.             pLastValidItem->pNext = pItem;
  209.             pPoly->pLast = pItem;
  210.         }
  211.         else if (pTemItem->index == pItem->index) //no insert it
  212.         {
  213.             pTemItem->quotiety += pItem->quotiety;
  214.             //remember to free pItem, for we have not added it to the pPoly
  215.             FreeItemNode(pItem);
  216.         }
  217.         else //insert it normally
  218.         {
  219.             pLastValidItem->pNext = pItem;
  220.             pItem->pNext = pTemItem;
  221.         }
  222.     }
  223.  
  224.     pPoly->pLast->pNext = NULL;
  225.     return ++pPoly->ItemNum;
  226. }
  227.  
  228. //Create a Formatted Polynomial from a non-formatted polynomial by index DESC
  229. Polynomial* CreateFormattedPolynomial(Polynomial* pPoly)
  230. {
  231.     Polynomial* pFmtPoly;
  232.     ItemNode* pTemNode;
  233.     CHECK_NONNULL_POINT(pPoly);
  234.     pFmtPoly = CreateEmptyPolynomial(pPoly->pronumeral);
  235.     pTemNode = pPoly->pHeader;
  236.     while (NULL != pTemNode)
  237.     {
  238.         AddItemToFormattedPolynomial(pFmtPoly, 
  239.                 DuplicateItemNode(pTemNode));
  240.         pTemNode = pTemNode->pNext;
  241.     }
  242.     return pFmtPoly;
  243. }
  244.  
  245. //Create a Formatted Polynomial and delete the old one
  246. Polynomial* CreateFormattedAndDelOldPolynomial(Polynomial* pPoly)
  247. {
  248.     Polynomial* pFmtPoly;
  249.     ItemNode* pTemNode;
  250.     ItemNode* pCurNode;
  251.     CHECK_NONNULL_POINT(pPoly);
  252.     pFmtPoly = CreateEmptyPolynomial(pPoly->pronumeral);
  253.     pTemNode = pPoly->pHeader;
  254.     while (NULL != pTemNode)
  255.     {
  256.         //it is the defference between this function and
  257.         //CreateFormattedPolynomial concerning the freedom of pTemNode.
  258.         pCurNode = pTemNode->pNext;
  259.         AddItemToFormattedPolynomial(pFmtPoly, pTemNode);
  260.         pTemNode = pCurNode;
  261.     }
  262.     FREEIF(pPoly);
  263.     return pFmtPoly;
  264. }
  265.  
  266. //Create a new ItemNode with quotiety and index first,
  267. //and then insert the node to pPoly at the tail(non-formatted).
  268. int AddItemToPolynomialEx(Polynomial* pPoly, QType quotiety, IType index)
  269. {
  270.     return AddItemToPolynomial(pPoly, CreateItemNode(quotiety, index));
  271. }
  272.  
  273. /***************************** + - * operations ******************************/
  274. //pLeftPoly and pRightPoly can be either formatted or non-formatted in these
  275. //three functions, but the new created polynomial(return value) is formatted.
  276. //+: pLeftPoly + pRightPoly
  277. Polynomial* PolynomialAdd(Polynomial* pLeftPoly, Polynomial* pRightPoly)
  278. {
  279.     Polynomial* pOutPoly;
  280.     CHECK_NONNULL_POINT(pLeftPoly);
  281.     CHECK_NONNULL_POINT(pRightPoly);
  282.     CHECK_SAME_VALUE(pLeftPoly->pronumeral, pRightPoly->pronumeral);
  283.     //pOutPoly = CreateEmptyPolynomial(pLeftPoly->pronumeral);
  284.     //just link two polynomials to simplize the actions.
  285.     pLeftPoly->pLast->pNext = pRightPoly->pHeader;
  286.     //calculating pLeftPoly->ItemNum is not needed,
  287.     //just for further consideration
  288.     pLeftPoly->ItemNum += pRightPoly->ItemNum;
  289.     pOutPoly = CreateFormattedPolynomial(pLeftPoly);
  290.     //set back
  291.     pLeftPoly->ItemNum -= pRightPoly->ItemNum;
  292.     pLeftPoly->pLast->pNext = NULL;
  293.     return pOutPoly;
  294. }
  295.  
  296. //-: pLeftPoly - pRightPoly
  297. Polynomial* PolynomialSubtract(Polynomial* pLeftPoly, Polynomial* pRightPoly)
  298. {
  299.     Polynomial* pOutPoly;
  300.     ItemNode* pTemNode;
  301.     ItemNode* pNewNode;
  302.     CHECK_NONNULL_POINT(pLeftPoly);
  303.     CHECK_NONNULL_POINT(pRightPoly);
  304.     CHECK_SAME_VALUE(pLeftPoly->pronumeral, pRightPoly->pronumeral);
  305.     pOutPoly = CreateFormattedPolynomial(pLeftPoly);
  306.     pTemNode = pRightPoly->pHeader;
  307.     while (NULL != pTemNode)
  308.     {
  309.         pNewNode = DuplicateItemNode(pTemNode);
  310.         pNewNode->quotiety = -pNewNode->quotiety;
  311.         AddItemToFormattedPolynomial(pOutPoly, pNewNode);
  312.         pTemNode = pTemNode->pNext;
  313.     }
  314.     return pOutPoly;
  315. }
  316.  
  317. //*: pLeftPoly * pRightPoly
  318. Polynomial* PolynomialMultiply(Polynomial* pLeftPoly, Polynomial* pRightPoly)
  319. {
  320.     Polynomial* pOutPoly;
  321.     ItemNode *pCurLeft;
  322.     ItemNode *pCurRight;
  323.     ItemNode *pOutItem;
  324.     CHECK_NONNULL_POINT(pLeftPoly);
  325.     CHECK_NONNULL_POINT(pRightPoly);
  326.     CHECK_SAME_VALUE(pLeftPoly->pronumeral, pRightPoly->pronumeral);
  327.     
  328.     pCurLeft = pLeftPoly->pHeader;
  329.     pOutPoly = CreateEmptyPolynomial(pLeftPoly->pronumeral);
  330.     while (pCurLeft)
  331.     {
  332.         pCurRight = pRightPoly->pHeader;
  333.         while (pCurRight)
  334.         {
  335.             pOutItem = CreateItemNode(
  336.                 pCurLeft->quotiety * pCurRight->quotiety,
  337.                 pCurLeft->index + pCurRight->index);
  338.             AddItemToFormattedPolynomial(pOutPoly, pOutItem);
  339.             pCurRight = pCurRight->pNext;
  340.         }
  341.         pCurLeft = pCurLeft->pNext;
  342.     }
  343.     return pOutPoly;
  344. }
  345.  
  346. /********************Write Processes to HTML File in Detail*******************/
  347. BOOL HTMLItemNode(FILE* pHTMLFile, ItemNode* pItem, char cPronum, BOOL bHead)
  348. {
  349.     CHECK_NONNULL_POINT(pItem);
  350.     CHECK_NONNULL_POINT(pHTMLFile);
  351.     if (0 == pItem->quotiety)
  352.         return FALSE;
  353.     if (bHead)
  354.     {
  355.         if (1 == pItem->quotiety)
  356.         {
  357.         }
  358.         else if (-1 == pItem->quotiety)
  359.         {
  360.             FPRINTF_ARGL(pHTMLFile, "-");
  361.         }
  362.         else
  363.         {
  364.             FPRINTF_ARGL(pHTMLFile, _ARGL("%d")_ARGLEND(pItem->quotiety));
  365.         }
  366.     }
  367.     else
  368.     {
  369.         if (1 == pItem->quotiety)
  370.         {
  371.             FPRINTF_ARGL(pHTMLFile, " + ");
  372.         }
  373.         else if (-1 == pItem->quotiety)
  374.         {
  375.             FPRINTF_ARGL(pHTMLFile, " - ");
  376.         }
  377.         else
  378.         {
  379.             QType quot = pItem->quotiety;
  380.             char op = '+';
  381.             if (quot < 0)
  382.             {
  383.                 quot = - quot;
  384.                 op = '-';
  385.             }
  386.             FPRINTF_ARGL(pHTMLFile, _ARGL(" %c %d")_ARGL(op)_ARGLEND(quot));
  387.         }
  388.     }
  389.     if (0 != pItem->index)
  390.     {
  391.         FPRINTF_ARGL(pHTMLFile, _ARGL("%c")_ARGLEND(cPronum));
  392.         if (1 != pItem->index)
  393.         {
  394.             FPRINTF_ARGL(pHTMLFile,
  395.                     _ARGL("<sup>%d</sup>")_ARGLEND(pItem->index));
  396.         }
  397.     }
  398.     return TRUE;
  399. }
  400.  
  401. BOOL HTMLPolynomial(FILE* pHTMLFile, Polynomial* pPoly)
  402. {
  403.     ItemNode* pItem;
  404.     BOOL bEmpty = TRUE;
  405.     CHECK_NONNULL_POINT(pPoly);
  406.     pItem = pPoly->pHeader;
  407.     
  408.     //print first item node
  409.     while (NULL != pItem)
  410.     {
  411.         if (HTMLItemNode(pHTMLFile, pItem, pPoly->pronumeral, TRUE))
  412.         {
  413.             bEmpty = FALSE;
  414.             pItem = pItem->pNext;
  415.             break;
  416.         }
  417.         pItem = pItem->pNext;
  418.     }
  419.     //print other item node
  420.     while (NULL != pItem)
  421.     {
  422.         HTMLItemNode(pHTMLFile, pItem, pPoly->pronumeral, FALSE);
  423.         pItem = pItem->pNext;
  424.     }
  425.     
  426.     //pPoly is empty
  427.     if (bEmpty)
  428.     {
  429.         FPRINTF_ARGL(pHTMLFile, "0");
  430.         return FALSE;
  431.     }
  432.     return TRUE;
  433. }
  434.  
  435. Polynomial* HTMLPolynomialAdd(FILE* pHTMLFile,
  436.             Polynomial* pLeftPoly, Polynomial* pRightPoly)
  437. {
  438.     Polynomial* pTemPoly;
  439.     ItemNode* pTemNode;
  440.     CHECK_NONNULL_POINT(pHTMLFile);
  441.     CHECK_NONNULL_POINT(pLeftPoly);
  442.     CHECK_NONNULL_POINT(pRightPoly);
  443.     CHECK_SAME_VALUE(pLeftPoly->pronumeral, pRightPoly->pronumeral);
  444.     // (a + b) + (c + d)
  445.     FPRINTF_ARGL(pHTMLFile, "\n<hr><b>&nbsp;&nbsp;(");
  446.     HTMLPolynomial(pHTMLFile, pLeftPoly);
  447.     FPRINTF_ARGL(pHTMLFile, ") + (");
  448.     HTMLPolynomial(pHTMLFile, pRightPoly);
  449.     FPRINTF_ARGL(pHTMLFile, ")</b>");
  450.     //=ac + ad + bc +bd(formatted)
  451.     pTemPoly = CreateEmptyPolynomial(pLeftPoly->pronumeral);
  452.     pTemNode = pLeftPoly->pHeader;
  453.     while (NULL != pTemNode)
  454.     {
  455.         AddItemToFormattedPolynomial(pTemPoly, DuplicateItemNode(pTemNode));
  456.         pTemNode = pTemNode->pNext;
  457.     }
  458.     pTemNode = pRightPoly->pHeader;
  459.     while (NULL != pTemNode)
  460.     {
  461.         AddItemToFormattedPolynomial(pTemPoly, DuplicateItemNode(pTemNode));
  462.         pTemNode = pTemNode->pNext;
  463.     }
  464.     FPRINTF_ARGL(pHTMLFile, "<br>\n<b>=</b>&nbsp;");
  465.     HTMLPolynomial(pHTMLFile, pTemPoly);
  466.     return pTemPoly;
  467. }
  468.  
  469. Polynomial* HTMLPolynomialSubtract(FILE* pHTMLFile,
  470.                               Polynomial* pLeftPoly, Polynomial* pRightPoly)
  471. {
  472.     Polynomial* pTemPoly;
  473.     ItemNode* pTemNode;
  474.     CHECK_NONNULL_POINT(pHTMLFile);
  475.     CHECK_NONNULL_POINT(pLeftPoly);
  476.     CHECK_NONNULL_POINT(pRightPoly);
  477.     CHECK_SAME_VALUE(pLeftPoly->pronumeral, pRightPoly->pronumeral);
  478.     // (a + b) - (c + d)
  479.     FPRINTF_ARGL(pHTMLFile, "\n<hr><b>&nbsp;&nbsp;(");
  480.     HTMLPolynomial(pHTMLFile, pLeftPoly);
  481.     FPRINTF_ARGL(pHTMLFile, ") - (");
  482.     HTMLPolynomial(pHTMLFile, pRightPoly);
  483.     FPRINTF_ARGL(pHTMLFile, ")</b>");
  484.     //=ac + ad - bc - bd
  485.     FPRINTF_ARGL(pHTMLFile, "<br>\n<b>=</b>&nbsp;");
  486.     pTemPoly = CreateEmptyPolynomial(pLeftPoly->pronumeral);
  487.     pTemNode = pLeftPoly->pHeader;
  488.     while (NULL != pTemNode)
  489.     {
  490.         AddItemToPolynomial(pTemPoly, DuplicateItemNode(pTemNode));
  491.         pTemNode = pTemNode->pNext;
  492.     }
  493.     pTemNode = pRightPoly->pHeader;
  494.     while (NULL != pTemNode)
  495.     {
  496.         ItemNode* pDupItem = DuplicateItemNode(pTemNode);
  497.         pDupItem->quotiety = -pDupItem->quotiety;
  498.         AddItemToPolynomial(pTemPoly, pDupItem);
  499.         pTemNode = pTemNode->pNext;
  500.     }
  501.     HTMLPolynomial(pHTMLFile, pTemPoly);
  502.     //format, pTemPoly(out) != pTemPoly(in)
  503.     pTemPoly = CreateFormattedAndDelOldPolynomial(pTemPoly);
  504.     FPRINTF_ARGL(pHTMLFile, "<br>\n<b>=</b>&nbsp;");
  505.     HTMLPolynomial(pHTMLFile, pTemPoly);
  506.     return pTemPoly;
  507. }
  508.  
  509. Polynomial* HTMLPolynomialMultiply(FILE* pHTMLFile,
  510.                             Polynomial* pLeftPoly, Polynomial* pRightPoly)
  511. {
  512.     Polynomial* pOutPoly;
  513.     ItemNode *pCurLeft;
  514.     ItemNode *pCurRight;
  515.     ItemNode *pOutItem;
  516.     CHECK_NONNULL_POINT(pHTMLFile);
  517.     CHECK_NONNULL_POINT(pLeftPoly);
  518.     CHECK_NONNULL_POINT(pRightPoly);
  519.     CHECK_SAME_VALUE(pLeftPoly->pronumeral, pRightPoly->pronumeral);
  520.     
  521.     // (a + b) * (c + d)
  522.     FPRINTF_ARGL(pHTMLFile, "\n<hr><b>&nbsp;&nbsp;(");
  523.     HTMLPolynomial(pHTMLFile, pLeftPoly);
  524.     FPRINTF_ARGL(pHTMLFile, ") * (");
  525.     HTMLPolynomial(pHTMLFile, pRightPoly);
  526.     FPRINTF_ARGL(pHTMLFile, ")</b>");
  527.  
  528.     //= ac + ad + bc + bd
  529.     pCurLeft = pLeftPoly->pHeader;
  530.     pOutPoly = CreateEmptyPolynomial(pLeftPoly->pronumeral);
  531.     while (pCurLeft)
  532.     {
  533.         pCurRight = pRightPoly->pHeader;
  534.         while (pCurRight)
  535.         {
  536.             pOutItem = CreateItemNode(
  537.                 pCurLeft->quotiety * pCurRight->quotiety,
  538.                 pCurLeft->index + pCurRight->index);
  539.             AddItemToPolynomial(pOutPoly, pOutItem);
  540.             pCurRight = pCurRight->pNext;
  541.         }
  542.         pCurLeft = pCurLeft->pNext;
  543.     }
  544.     FPRINTF_ARGL(pHTMLFile, "<br>\n<b>=</b>&nbsp;");
  545.     HTMLPolynomial(pHTMLFile, pOutPoly);
  546.     //format
  547.     pOutPoly = CreateFormattedAndDelOldPolynomial(pOutPoly);
  548.     FPRINTF_ARGL(pHTMLFile, "<br>\n<b>=</b>&nbsp;");
  549.     HTMLPolynomial(pHTMLFile, pOutPoly);
  550.     return pOutPoly;
  551. }
  552.  
  553. /*****************************************************************************/
  554. //print pItem, this function should be changed if the type of
  555. //pronumeral or index changs
  556. BOOL PrintItemNode(ItemNode* pItem, char cPronum, BOOL bHead)
  557. {
  558.     CHECK_NONNULL_POINT(pItem);
  559.     if (0 == pItem->quotiety)
  560.         return FALSE;
  561.     if (bHead)
  562.     {
  563.         if (1 == pItem->quotiety)
  564.         {
  565.         }
  566.         else if (-1 == pItem->quotiety)
  567.         {
  568.             PRINTF_ARGL("-");
  569.         }
  570.         else
  571.         {
  572.             PRINTF_ARGL(_ARGL("%d")_ARGLEND(pItem->quotiety));
  573.         }
  574.     }
  575.     else
  576.     {
  577.         if (1 == pItem->quotiety)
  578.         {
  579.             PRINTF_ARGL(" + ");
  580.         }
  581.         else if (-1 == pItem->quotiety)
  582.         {
  583.             PRINTF_ARGL(" - ");
  584.         }
  585.         else
  586.         {
  587.             QType quot = pItem->quotiety;
  588.             char op = '+';
  589.             if (quot < 0)
  590.             {
  591.                 quot = - quot;
  592.                 op = '-';
  593.             }
  594.             PRINTF_ARGL(_ARGL(" %c %d")_ARGL(op)_ARGLEND(quot));
  595.         }
  596.     }
  597.     if (0 != pItem->index)
  598.     {
  599.         PRINTF_ARGL(_ARGL("%c")_ARGLEND(cPronum));
  600.         if (1 != pItem->index)
  601.         {
  602.             PRINTF_ARGL(_ARGL("^%d")_ARGLEND(pItem->index));
  603.         }
  604.     }
  605.     return TRUE;
  606. }
  607.  
  608. // print the Polynomial
  609. BOOL PrintPolynomial(Polynomial* pPoly)
  610. {
  611.     ItemNode* pItem;
  612.     BOOL bEmpty = TRUE;
  613.     CHECK_NONNULL_POINT(pPoly);
  614.     pItem = pPoly->pHeader;
  615.  
  616.     //print first item node
  617.     while (NULL != pItem)
  618.     {
  619.         if (PrintItemNode(pItem, pPoly->pronumeral, TRUE))
  620.         {
  621.             bEmpty = FALSE;
  622.             pItem = pItem->pNext;
  623.             break;
  624.         }
  625.         pItem = pItem->pNext;
  626.     }
  627.     //print other item node
  628.     while (NULL != pItem)
  629.     {
  630.         PrintItemNode(pItem, pPoly->pronumeral, FALSE);
  631.         pItem = pItem->pNext;
  632.     }
  633.     
  634.     //pPoly is empty
  635.     if (bEmpty)
  636.     {
  637.         PRINTF_ARGL("Empty Polynomial!!!");
  638.         return FALSE;
  639.     }
  640.     return TRUE;
  641. }
  642.  
  643. //user function to code
  644. int UserMain(int argc, char *argv[])
  645. {
  646.     Polynomial* pPoly = CreateEmptyPolynomial('x');
  647.     Polynomial* pPoly1;
  648.     Polynomial* pPoly2;
  649.     FILE* pHTMLFile = fopen("D:\\test.html", "a+");
  650.     CHECK_NONNULL_POINT(pHTMLFile);
  651.     AddItemToPolynomialEx(pPoly, -1, 5);
  652.     AddItemToPolynomialEx(pPoly, -3, 0);
  653.     AddItemToPolynomialEx(pPoly, +5, 2);
  654.     AddItemToPolynomialEx(pPoly, -33, -1);
  655.     AddItemToPolynomialEx(pPoly, -31, 2);
  656.     
  657.     PRINTF_ARGL("\npPoly: \n");
  658.     PrintPolynomial(pPoly);
  659.     PRINTF_ARGL("\n");
  660.     pPoly1 = CreateFormattedPolynomial(pPoly);
  661.     PRINTF_ARGL("\nFormatted pPoly1: \n");
  662.     PrintPolynomial(pPoly1);
  663.     PRINTF_ARGL("\n");
  664.  
  665.     AddItemToPolynomialEx(pPoly1, 4, 0);
  666.     AddItemToPolynomialEx(pPoly1, 0, 2);
  667.     AddItemToPolynomialEx(pPoly1, 0, 0);
  668.     AddItemToPolynomialEx(pPoly1, 1, 1);
  669.     PRINTF_ARGL("\nnew pPoly1: \n");
  670.     PrintPolynomial(pPoly1);
  671.     PRINTF_ARGL("\n");
  672.     //+
  673.     pPoly2 = PolynomialAdd(pPoly, pPoly1);
  674.     PRINTF_ARGL("\nAdd pPoly2: \n");
  675.     PrintPolynomial(pPoly2);
  676.     PRINTF_ARGL("\n");
  677.     FreePolynomial(pPoly2);
  678.     //-
  679.     pPoly2 = PolynomialSubtract(pPoly, pPoly1);
  680.     PRINTF_ARGL("\nSub pPoly2: \n");
  681.     PrintPolynomial(pPoly2);
  682.     PRINTF_ARGL("\n");
  683.     FreePolynomial(pPoly2);
  684.     //*
  685.     pPoly2 = PolynomialMultiply(pPoly, pPoly1);
  686.     PRINTF_ARGL("\nMulti pPoly2: \n");
  687.     PrintPolynomial(pPoly2);
  688.     PRINTF_ARGL("\n");
  689.     FreePolynomial(pPoly2);
  690.     //HTML +
  691.     pPoly2 = HTMLPolynomialAdd(pHTMLFile, pPoly, pPoly1);
  692.     FreePolynomial(pPoly2);
  693.     //HTML -
  694.     pPoly2 = HTMLPolynomialSubtract(pHTMLFile, pPoly, pPoly1);
  695.     FreePolynomial(pPoly2);
  696.     //HTML *
  697.     pPoly2 = HTMLPolynomialMultiply(pHTMLFile, pPoly, pPoly1);
  698.     FreePolynomial(pPoly2);
  699.     FreePolynomial(pPoly);
  700.     FreePolynomial(pPoly1);
  701.     return 0;
  702. }
  703.  
  704. int main(int argc, char *argv[])
  705. {
  706.     int runRslt;
  707. #if WRITE_SCREEN_TO_FILE
  708.     gpLogFile = fopen(SCREEN_LOG_FILE, "w+");
  709. #endif
  710.  
  711.     runRslt = UserMain(argc, argv);
  712.  
  713. #if WRITE_SCREEN_TO_FILE
  714.     fclose(gpLogFile);
  715. #endif
  716.     return runRslt;
  717. } 


[本日志由 shosh 于 2008-09-28 10:23 PM 编辑]
文章来自: Shosh原创
引用通告: 查看所有引用 | 我要引用此文章
Tags: 一元多项式 链表 单向链表 运算
相关日志:
评论: 2 | 引用: 0 | 查看次数: 1834
回复回复shosh[2008-12-29 05:36 PM | del]
[face51]当时发表评论的时候没有仔细检验,说“变参数的宏定义似乎原来不用搞这么复杂的,只需要再嵌套个括号就OK的”,今天发现其实那是错误的,如果那样做,那参数中的逗号将变成逗号运算符,实际上只相当传递了最后一个参数(运算的结果)。
可使用下面的代码验证:
#include <stdio.h>

#define DBGPRINTF_LEVEL 0
#define DBGPRINTF_EX_FORMAT "%d\t%d\t%s\t\t"
#define PRINTF(x) printf(x), printf(x)
#define DBGPRINTF(x) printf(DBGPRINTF_EX_FORMAT,DBGPRINTF_LEVEL, __LINE__, __FILE__), PRINTF(x)

int main(void)
{
        DBGPRINTF(("%d,%s", 3, "shosh:"));
        printf("\n");
        return 0;
}
回复回复shosh[2008-09-29 01:28 AM | del]
狂晕,变参数的宏定义似乎原来不用搞这么复杂的,只需要再嵌套个括号就OK的。不过还没来得及在VC上测试过。

晚上将该代码在Turbo C上测试,除行注释外,发现Turbo C还不支持我这种嵌套的用于实现变参数的宏定义方法,估计是替换的先后顺序问题。

UserMain函数的参数是main函数传递过来的参数,也就是命令行参数,本来是想让用户输入参数,然后自动对输入的两个多项式进行运算并输出的。因为目前还没有实现,所以会有说参数没有使用的警告。
发表评论
昵 称:
密 码: 游客发言不需要密码.
内 容:
验证码: 验证码
选 项:
虽然发表评论不用注册,但是为了保护您的发言权,建议您注册帐号.
字数限制 1000 字 | UBB代码 开启 | [img]标签 关闭