Возврат связанного списка из функции приводит к ошибке: «Доступ к участнику по неправильному адресу» происходит в несуществующей строке

У меня проблема в Leetcode: мне нужно добавить два числа из связанного списка, а затем вернуть связанный список из addTwoNumbers.

Подробности раздела об ошибках

Вот мой полный код:

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

struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {
    int valueL1 = 0, valueL2 = 0, valueTotal;
    
    struct ListNode* temp = l1;
    int loopNo = 0;
    do {
        valueL1 += (temp->val) * (10^loopNo);
        temp = temp->next;
        loopNo++;
    } while (temp != NULL);

    temp = l2;
    loopNo = 0;
    do {
        valueL2 += (temp->val) * (10^loopNo);
        temp = temp->next;
        loopNo++;
    } while (temp != NULL);

    valueTotal = valueL1 + valueL2;
    int order = findOOM(valueTotal);

    struct ListNode* result = malloc(sizeof(struct ListNode));

    temp = result;
    int valTemp;
    for (int i = 0; i < order; i++) {
        valTemp = valueTotal - ((valueTotal /= 10) * 10);
        temp->val = valTemp;
        if (i != order) {
            temp->next = malloc(sizeof(struct ListNode));
            temp = temp->next;
        }
    }

    return result;
}

int findOOM(int num) {
    int OOM = 0;
    while(num > 0) {
        OOM++;
        num /= 10;
    }

    return OOM;
}

и сообщение об ошибке гласит: Строка 70: ​​Символ 15: ошибка времени выполнения: доступ к элементу по смещенному адресу 0xbebebebebebebebe для типа «struct ListNode», который требует выравнивания по 8 байтам [ListNode.c] 0xbebebebebebebebe: примечание: здесь указывает указатель

Мой код доходит только до строки 56, однако в сообщениях об ошибках упоминается ошибка в строке 70.

Код, как видно на скриншоте, не компилируется.

Я попытался вернуть функцию с предоставленными связанными списками в качестве входных данных (т. е. l1 и l2), и код компилируется (хотя ответ неверен, разумеется).

Возможно, у кого-нибудь есть идеи, что я сделал не так? Это то, как я неправильно определил свой «результат»?

Может быть связано, а может и нет, но 10^loopNo — это не возведение в степень в C, это xor. Встроенного оператора для целочисленных степеней нет, поэтому вам придется делать это вручную с повторным умножением. (pow предназначен для чисел с плавающей запятой и не подходит для целых чисел.)

Nate Eldredge 15.06.2024 19:40

Вместо того чтобы полагаться на загадочные сообщения об ошибках от онлайн-компиляторов, попробуйте запустить компилятор и отладчик на своем локальном компьютере. Такие инструменты, как valgrind, предоставят вам гораздо более полезную диагностику.

Nate Eldredge 15.06.2024 19:41

Кроме того, чтобы получить хорошую помощь на этом сайте, вам следует включить минимально воспроизводимый пример, который можно компилировать и запускать как есть. В опубликованном вами фрагменте нет определений типов, заголовков, функций main и т. д.; кто-то, желающий протестировать это, должен будет добавить все эти вещи и, вероятно, просто не станет беспокоиться и перейдет к чужому посту.

Nate Eldredge 15.06.2024 19:43

Очень дикая догадка: возможно, где-то у вас есть указатель next, который не инициализирован, или вы не установили последний узел, указывающий на NULL. Поскольку вы не предоставили нам часть своего кода, которая инициализирует списки или как вызывается addTwoNumbers, я не могу знать наверняка. Еще одна причина для минимально воспроизводимого примера; люди часто пытаются опубликовать только ту часть кода, которую они считают «релевантной», но очень часто они ошибаются, и ошибка находится в какой-то части кода, которую они не включили. Это просто трата времени всех.

Nate Eldredge 15.06.2024 19:45

@NateEldredge, возможно, у меня нет основной функции, поскольку это проблема Leetcode, и я предполагаю, что она вызывается для тестовых случаев, предусмотренных проблемой? Вот ссылка на проблему: leetcode.com/problems/add-two-numbers/description

Scyllase 15.06.2024 19:59

Я не использую Leetcode, но если бы я это делал, у меня был бы свой main() и несколько дополнительных тестовых примеров, чтобы я мог проверить его локально.

Weather Vane 15.06.2024 20:03
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
6
74
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
  • У вашего алгоритма есть несколько проблем.
  • Нам не обязательно использовать pow(), а ^ зарезервировано для побитового исключающего ИЛИ в C.
  • Ваш алгоритм вычисления valueL1 и valueL2 может вызвать переполнение для больших чисел.
  • Неверный цикл создания результирующего связанного списка.

Алгоритм

  • Мы создаем дозорный узел и указатель текущего узла, равный дозорному узлу. Это необходимо для создания связанного списка для окончательного результата, чтобы у нас был доступ к заголовку связанного списка.

  • Мы присваиваем carry ноль и проверяем, являются ли list1 или list2NULL или у нас есть ненулевое значение carry:

    • Мы устанавливаем текущий sum на carry. Если list1 не NULL, мы добавляем его текущее значение узла к sum и перемещаем указатель на следующий узел. Мы делаем то же самое для list2.
    • Новый керри - sum / 10.
    • Мы создаем указатель узла (p). Мы устанавливаем значение sum % 10, а следующий узел — NULL.
    • В конце мы устанавливаем текущий узел на p.

Код

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

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

struct ListNode *addTwoNumbers(struct ListNode *l1, struct ListNode *l2) {
  struct ListNode sentinel;
  struct ListNode *curr = &sentinel;
  sentinel.next = NULL;

  int carry = 0;
  while (l1 != NULL || l2 != NULL || carry != 0) {
    int sum = carry;
    if (l1 != NULL) {
      sum += l1->val;
      l1 = l1->next;
    }
    if (l2 != NULL) {
      sum += l2->val;
      l2 = l2->next;
    }
    carry = sum / 10;
    struct ListNode *p = (struct ListNode *)malloc(sizeof(struct ListNode));
    p->val = sum % 10;
    p->next = NULL;
    curr->next = p;
    curr = p;
  }

  return sentinel.next;
}

struct ListNode *p(int val) {
  struct ListNode *node = (struct ListNode *)malloc(sizeof(struct ListNode));
  node->val = val;
  node->next = NULL;
  return node;
}

void print_linked_list(struct ListNode *head) {
  while (head != NULL) {
    printf("%d -> ", head->val);
    head = head->next;
  }
  printf("NULL\n");
}

int main() {

  struct ListNode *l1 = p(2);
  l1->next = p(4);
  l1->next->next = p(3);

  struct ListNode *l2 = p(5);
  l2->next = p(6);
  l2->next->next = p(4);

  struct ListNode *res = addTwoNumbers(l1, l2);

  print_linked_list(res);

  return 0;
}

Принты

7 -> 0 -> 8 -> NULL

Другие вопросы по теме