如何调试一个C程序为什么输出错误?

qgelzfjb  于 12个月前  发布在  其他
关注(0)|答案(3)|浏览(112)

我试着用C解决这个leetcode question,这是我得到的代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

#include <math.h>

struct ListNode *addTwoNumbers(struct ListNode *l1, struct ListNode *l2) {
    struct ListNode *temp;
    struct ListNode *sum = NULL;  
    int num1 = 0;
    int num2 = 0;
    temp = l1;
    int n = 0;
    int i = 0;
    while (temp != NULL) {
        num1 = num1 + (temp->val * pow(10, i));
        i++;
        temp = temp->next;
    }
    temp = l2;
    i = 0;
    while (temp != NULL) {
        num2 = num2 + (temp->val * pow(10, i));
        i++;
        temp = temp->next;
    }
    int add = num1 + num2;
    int tem = add;
    i = 0;
    for (i = 0; tem > 0; i++) {
        tem = tem / 10;
    }
    if (add == 0) {
       struct ListNode *new = malloc(sizeof(struct ListNode));  
       new->val = 0;
       new->next = sum;
       sum = new;
    }
    while (add > 0 && i > 0) {
       struct ListNode *new = malloc(sizeof(struct ListNode));  
       new->val = add / pow(10, (i - 1));
       new->next = sum;
       i--;
       add = add % (int)(pow(10, i));
       sum = new;
    }
    return sum;
}

字符串
我不明白为什么测试用例l1 = [9]; l2 = [1,9,9,9,9,9,9,9]的输出为空。在许多测试用例中,这是正确的,但问题似乎在于add是10的倍数(可能)的测试用例。

vdgimpew

vdgimpew1#

使用ListNode的目的是支持任意大的值。当您将值存储在int num1int num2中时,整个目的都失败了,因为它仅限于INT_MAX,在我的系统上是2147483647(10位),并且大于num2。带符号溢出是未定义的行为。
由于每个数字包含的信息少于4位,因此我对每个ListNode::val使用了unsigned char(1字节)而不是int(在我的系统中为4字节)。
(Not修复)createDigit()可以离开依赖于调用者初始化next。在这种情况下,createNumber()addTwoNumbers()将在返回之前执行tail->next = NULL。这将更快,但不太安全。
(Not固定)free()两个参数和main()addTwoNumbers()的返回值。

#include <stdio.h>
#include <stdlib.h>

// head of list is the least significant digit
struct ListNode {
    unsigned char val;
    struct ListNode *next;
};

struct ListNode *createDigit(struct ListNode *prev, unsigned char val) {
    struct ListNode *newNode = malloc(sizeof *newNode);
    if(!newNode) {
        fprintf(stderr, "malloc failed\n");
        return NULL;
    }
    newNode->val = val;
    newNode->next = NULL;
    if(prev) prev->next = newNode;
    return newNode;
}

struct ListNode *createNumber(size_t n, const unsigned char vals[n]) {
    if(!n) return NULL;
    struct ListNode *head = NULL;
    for(struct ListNode *tail = NULL; size_t i = 0; i < n; i++) {
        tail = createDigit(tail, vals[i]);
        if(!head) head = tail;
    }
    return head;
}

void printNumber(const struct ListNode *n) {
    for(; n; n = n->next)
        printf("%d", n->val);
    printf("\n");
}

struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {
    struct ListNode *head = NULL;
    unsigned char carry = 0;
    for(struct ListNode *tail = NULL; l1 || l2 || carry; l1 = l1 ? l1->next : NULL, l2 = l2 ? l2->next : NULL) {
        unsigned char sum = (l1 ? l1->val : 0) +
            (l2 ? l2->val : 0) +
            carry;
        tail = createDigit(tail, sum % 10);
        if(!head) head = tail;
        carry = sum / 10;
    }
    return head;
}

int main(void) {
    printNumber(
        addTwoNumbers(
            createNumber(1, (unsigned char []) {9}),
            createNumber(10, (unsigned char []) {1,9,9,9,9,9,9,9,9,9})
        )
    );
}

字符串
和示例输出:

00000000001

cnjp1d6j

cnjp1d6j2#

你的方法不够:该列表可能表示一个超出类型int范围的数字,或者所有可用的整数类型,因为该列表被指定为具有多达100个节点。将列表转换为它所表示的数字对于长于9或10个节点的列表将具有未定义的行为。使用浮点函数(如pow)来执行整数计算通常是不合适的,并且容易出错。
相反,您应该为每个数字分配一个节点的新列表,包含参数列表的相应数字的总和,模10缩减并将进位传播到下一个节点。
当你到达其中一个列表的末尾时,继续传播另一个列表的进位,当你到达该列表的末尾时停止,分配一个额外的进位节点仍然是非零的。
注意,问题语句is没有指定你应该分配一个新的列表,因为参数没有指定为const struct ListNode *,你可以决定修改其中一个列表,并返回一个指向它的头节点的指针。这将通过指定其中一个参数为const而不是另一个参数来变得更加明确。
这里有一个简单的解决方案:

struct ListNode {
    int val;
    struct ListNode *next;
};

struct ListNode *addTwoNumbers(struct ListNode *l1, struct ListNode *l2) {
    struct ListNode *head = NULL;  
    struct ListNode *tail = NULL;  
    int carry = 0;
    while (l1 || l2 || carry) {
        struct ListNode *node = malloc(sizeof(*node));
        if (node == NULL) {
            /* allocation error: free partially allocated number and
             *  return NULL.
             */
            while (head) {
                node = head;
                head = head->next;
                free(node);
            }
            break;
        }
        node->next = NULL;
        /* compute the value of the sum digit and update the carry */
        int digit = carry;
        if (l1) {
            digit += l1->val;
            l1 = l1->next;
        }
        if (l2) {
            digit += l2->val;
            l2 = l2->next;
        }
        node->val = digit % 10;
        carry = digit / 10;
        /* append the node */
        if (head == NULL) {
            head = node;
        } else {
            tail->next = node;
        }
        tail = node;
    }
    return head;
}

字符串

vaqhlq81

vaqhlq813#

如果你看一下清单,然后一个接一个地浏览,就更容易了,没有必要用权力等把它弄得复杂。

ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
    ListNode* result = nullptr;
    ListNode* last = nullptr;
    int val{0};
    int carry{0};
    while (l1 || l2)
    {
      val = carry; 
      if (l1) val += l1->val;
      if (l2) val += l2->val;
      carry = 0;

      if (val > 9)
      {
        carry = 1;
        val -= 10;
      }

      auto* r = new ListNode(val);
      if (result == nullptr) 
      { 
        result = last = r; 
      }
      else
      {
        last->next = r;
        last = r;
      }
      if (l1) l1 = l1->next;
      if (l2) l2 = l2->next;
    }
    if (carry)
    {
      last->next = new ListNode(m_carry);
    }
    return result;
}

字符串

相关问题