在C中使用链接列表时出现指针问题

时间:2018-10-18 05:48:16

标签: c pointers gcc linked-list polynomials

我正在使用c编程代码,除多项式乘法部分外,大多数代码都工作正常。它有一个运行时错误。请帮助我从多项式乘法中删除此运行时错误,我找不到错误,我认为它在第三个for循环中。 谢谢... 如果您解决错误,那就太好了

#include<math.h>
#include<stdio.h>
#include<stdlib.h>
#define MAX 17

typedef struct node
{
    int coeff;
    struct node *next;
}node;

node * init();
void read(node *h1);
void print(node *h1);
node * add(node *h1,node *h2);
node * multiply(node *h1, node *h2);

void main()
{
    node *h1=NULL,*h2=NULL,*h3=NULL;
    int option;
    do
    {
        printf("\n1 : create 1’st polynomial");
        printf("\n2 : create 2’nd polynomial");
        printf("\n3 : Add polynomials");
        printf("\n4 : Multiply polynomials");
        printf("\n5 : Quit");
        printf("\nEnter your choice :");
        scanf("%d",&option);
        switch(option)
        {
            case 1:
                h1=init();
                read(h1);
                break;

            case 2:
                h2=init();
                read(h2);
                break;

            case 3:
                h3=add(h1,h2);
                printf("\n1’st polynomial -> ");
                print(h1);
                printf("\n2’nd polynomial -> ");
                print(h2);
                printf("\n Sum = ");
                print(h3);
                break;

            case 4:
                h3=multiply(h1,h2);
                printf("\n1’st polynomial -> ");
                print(h1);
                printf("\n2’nd polynomial -> ");
                print(h2);
                printf("\n Product = ");
                print(h3);
                break;
        }
    }while(option!=5);
}

void read(node *h)
{
    int n,i,j,power,coeff;
    node *p;
    p=init();
    printf("\n Enter number of terms :");
    scanf("%d",&n);
    /* read n terms */
    for (i=0;i<n;i++)
    {
        printf("\nenter a term(power coeff.)");
        scanf("%d%d",&power,&coeff);
        for(p=h,j=0;j<power;j++)
            p=p->next;
        p->coeff=coeff;
    }
}

void print(node *p)
{
    int i;
    for(i=0;p!=NULL;i++,p=p->next)
        if(p->coeff!=0)
            printf("%dX^%d ",p->coeff,i);
}

node * add(node *h1, node *h2)
{
    node *h3,*p;
    h3=init();
    p=h3;
    while(h1!=NULL)
    {
        h3->coeff=h1->coeff+h2->coeff;
        h1=h1->next;
        h2=h2->next;
        h3=h3->next;
    }
    return(p);
}

node * multiply(node *h1, node *h2)
{
    node *h3,*p,*q,*r;
    int i,j,k,coeff,power;
    h3=init();
    for(p=h1,i=0;p!=NULL;p=p->next,i++)
        for(q=h2,j=0;q!=NULL;q=q->next,j++)
        {
            coeff=p->coeff * q->coeff;
            power=i+j;
            for(r=h3,k=0;k<power;k++)
                r=r->next;
            r->coeff=r->coeff+coeff;
        }
    return(h3);
}

node * init()
{
    int i;
    node *h=NULL,*p;
    for(i=0;i<MAX;i++)
    {
        p=(node*)malloc(sizeof(node));
        p->next=h;
        p->coeff=0;
        h=p;
    }
    return(h);
}

3 个答案:

答案 0 :(得分:0)

multiply函数中至少存在一个问题:

...
for (r = h3, k = 0; k < power; k++)
  r = r->next;

r->coeff = r->coeff + coeff;
...

在某个时候,r变成NULL,并在下一步使用r取消引用r->coeff时(r现在是NULL)您的程序将导致未定义的行为(在大多数平台上为段错误)。

答案 1 :(得分:0)

有几个问题:

  1. 内存已泄漏:确保每个free都指向一个malloc

  2. read正在创建一个新列表,但泄漏了该列表,并且从未更新过h1h2中的数据。

  3. add未检查NULL h2

  4. 不必要地保留了加/乘结果。

  5. 一个任意数量的最大值为17个节点-链表的整个要点是这样,因此无需保持这样的任意限制。

  6. 变量的范围太大。这是2011年:人们可以在使用点附近而不是在代码块的开头声明变量。

  7. 使用scanf是非惯用的,不适用于交互式的面向行的输入。对于此类输入,请阅读完整的行并解析它们,而不是stdin流。在stdin流中,换行符是字段分隔符,我认为您不希望这样。

  8. 没有任何断言:防御性地编程,断言您认为正确的内容。

这有效并且应该正确,并且在所有情况下都没有不确定的行为。

// https://github.com/KubaO/stackoverflown/tree/master/questions/c-linked-debug-52867729
#include <assert.h>
#include <math.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Node {
   int power;  // primary key for sorting
   int coeff;
   struct Node *next;
} Node;

Node *new_node(Node *prev, Node *next, int power);
Node *get_node(Node **head, Node *hint, int power);
void delete_nodes(Node *head);

Node *read(void);
void print(const Node *head);
Node *add(const Node *head1, const Node *head2);
Node *multiply(const Node *head1, const Node *head2);

void print_nodes(const Node *n1, const Node *n2, const char *extra_label,
                 const Node *extra);
const char *arity_suffix(int n);
bool parse_line(int max_length, const char *fmt, int count, ...);

static void *guarded_malloc(size_t size) {
   void *result = malloc(size);
   if (!result) {
      fprintf(stdout, "Memory allocation has failed: exiting.");
      abort();
   }
   return result;
}

int main() {
   Node *h1 = NULL, *h2 = NULL;
   int option;
   do {
      printf("\n1 : Create 1'st polynomial");
      printf("\n2 : Create 2'nd polynomial");
      printf("\n3 : Print polynomials");
      printf("\n4 : Add polynomials");
      printf("\n5 : Multiply polynomials");
      printf("\n6 : Quit");
      printf("\nEnter your choice: ");
      if (!parse_line(10, "%d", 1, &option)) continue;
      switch (option) {
         case 1:
            delete_nodes(h1);
            h1 = read();
            break;

         case 2:
            delete_nodes(h2);
            h2 = read();
            break;

         case 3:
            print_nodes(h1, h2, NULL, NULL);
            break;

         case 4: {
            Node *sum = add(h1, h2);
            print_nodes(h1, h2, "Sum", sum);
            delete_nodes(sum);
            break;
         }
         case 5: {
            Node *prod = multiply(h1, h2);
            print_nodes(h1, h2, "Product", prod);
            delete_nodes(prod);
            break;
         }
      }
   } while (option != 6);
   delete_nodes(h1);
   delete_nodes(h2);
}

Node *read() {
   int n;
   printf("\n Enter number of terms: ");
   if (!parse_line(10, "%d", 1, &n)) return NULL;
   /* read n terms */
   Node *head = NULL;
   for (int i = 0; i < n;) {
      int power, coeff;
      printf("\nEnter the %d%s term (power coeff): ", i + 1, arity_suffix(i + 1));
      if (!parse_line(80, "%d%d", 2, &power, &coeff) || !coeff) continue;
      Node *p = get_node(&head, NULL, power);
      if (!p->coeff) i++;  // count only new terms
      p->coeff = coeff;
   }
   return head;
}

void print(const Node *p) {
   for (; p; p = p->next) printf("%dX^%d ", p->coeff, p->power);
}

void add_to(Node **sum, const Node *h) {
   Node *r = NULL;
   for (; h; h = h->next) {
      r = get_node(sum, r, h->power);
      r->coeff += h->coeff;
   }
}

Node *add(const Node *h1, const Node *h2) {
   Node *sum = NULL;
   add_to(&sum, h1);
   add_to(&sum, h2);
   return sum;
}

Node *multiply(const Node *h1, const Node *h2) {
   Node *prod = NULL;
   for (const Node *p = h1; p; p = p->next) {
      Node *r = NULL;
      for (const Node *q = h2; q; q = q->next) {
         int power = p->power + q->power;
         r = get_node(&prod, r, power);
         r->coeff += p->coeff * q->coeff;
      }
   }
   return prod;
}

Node *new_node(Node *prev, Node *next, int power) {
   assert(!prev || prev->power < power);
   assert(!next || next->power > power);
   Node *node = guarded_malloc(sizeof(Node));
   node->power = power;
   node->coeff = 0;
   node->next = next;
   if (prev) prev->next = node;
   return node;
}

void delete_nodes(Node *head) {
   while (head) {
      Node *p = head;
      head = head->next;
      free(p);
   }
}

static bool list_contains(Node *head, Node *elt) {
   for (; head; head = head->next)
      if (head == elt) return true;
   return false;
}

Node *get_node(Node **head, Node *hint, int power) {
   Node *node = hint;
   Node *next = hint ? hint->next : head ? *head : NULL;
   assert(!hint || !*head || list_contains(*head, hint));
   assert(!hint || hint->power <= power);
   assert(!node || !next || node->power < next->power);

   while (next && next->power <= power) {
      node = next;
      next = next->next;
   }
   if (!node || node->power != power) {
      assert(!node || node->power < power);
      Node *n = new_node(node, next, power);
      if (!node) *head = n;
      node = n;
   }
   return node;
}

void print_nodes(const Node *h1, const Node *h2, const char *extra_label,
                 const Node *extra) {
   printf("\n1'st polynomial -> ");
   print(h1);
   printf("\n2'nd polynomial -> ");
   print(h2);
   if (extra_label) {
      printf("\n %s = ", extra_label);
      print(extra);
   }
   printf("\n");
}

const char *arity_suffix(int n) {
   if (n == 0) return "st";
   if (n == 1) return "nd";
   return "rd";
}

bool parse_line(int max_length, const char *fmt, int count, ...) {
   bool result = false;
   int const buf_size = max_length + 2;  // include \n and zero termination
   char *const buf = guarded_malloc((size_t)buf_size);
   char *const str = fgets(buf, buf_size, stdin);
   if (str) {
      size_t n = strlen(str);
      if (str[n - 1] == '\n') {  // we must have read a whole line
         str[n - 1] = '\0';      // remove the newline
         va_list ap;
         va_start(ap, count);
         int rc = vsscanf(buf, fmt, ap);
         va_end(ap);
         result = rc == count;
      }
   }
   free(buf);
   return result;
}

答案 2 :(得分:-3)

我认为您应该在读取方法中使用内存复制

    void read(node *h)
    {
      int n,i,j,power,coeff;
      node *p;
      p=init();
      printf("\n Enter number of terms :");
      scanf("%d",&n);
     /* read n terms */
     for (i=0;i<n;i++)
      {
       printf("\nenter a term(power coeff.)");
       scanf("%d%d",&power,&coeff);
       for(p=h,j=0;j<power;j++)
       p=p->next;
       p->coeff=coeff;
      }

      memcpy (h, p, sizeof(node))
   }