38:10: ошибка: базовый тип ссылки на элемент «Узел *» не является структурой или объединением * prev-> next = temp; - PullRequest
0 голосов
/ 01 мая 2020

Код для вставки элемента в конечную позицию списка ссылок. Я передаю указатель на указатель узла для вставки метода, при этом я получаю ошибку member reference base type 'Node *' is not a structure or union в строке номер 38, которая равна *prev->next = temp;. Пожалуйста, объясните проблему, и если вы предоставите решение по тому же логу c, это будет лучше.

#include "iostream"

using namespace std;

struct Node {
  int data;
  Node* next;
};

void insertElement(Node**, Node**, int);
void printLinkList(Node** head);

int main(int argc, char const *argv[]) {
  Node *head = NULL, *prev = NULL;
  int num, pos;
  char controller;
  cout << "To add element to link list press y, to quit press any other key: ";
  cin >> controller;
  while(controller == 'y') {
    cout << "Enter element: ";
    cin >> num;
    insertElement(&head, &prev, num);
    cout << "To add next element to link list press y, to quit press any other key: ";
    cin >> controller;
  }
  printLinkList(&head);
  return 0;
}

void insertElement(Node **head, Node **prev, int num) {
  Node *temp = new Node();
  temp->data = num;
  temp->next = NULL;
  if(*head == NULL) {
    *head = temp;
  }
  if(*prev != NULL) {
    *prev->next = temp;
  }
  *prev = temp;
}

void printLinkList(Node** head) {
  Node* temp = *head;
  while(temp != NULL) {
    cout << temp->data << ", ";
    temp = temp->next;
  }
  cout << endl;
}

1 Ответ

1 голос
/ 01 мая 2020

Сообщение об ошибке будет самоочевидным, если ваше выражение будет менее сложным. Тем не менее, это довольно просто, когда вырвано из контекста.

member reference base type 'Node *' is not a structure or union

Это говорит о том, что в какой-то момент вы пытались получить доступ к элементу указателя до Node, что недопустимо, поскольку членами являются только структуры и союзы (Компилятор использует «структуру» для охвата struct и class.) В частности, указатели не имеют членов.

Надеюсь, это звучит правдоподобно. Если temp является Node*, то выражение temp.data не имеет смысла; сначала вам нужно отменить ссылку на указатель, как в (*temp).data или эквивалентном temp->data. Итак, что происходит в вашем коде?

В проблемной точке c в вашем коде у вас есть указатель на указатель, который часто не самый лучший подход. Указатель на указатель prev появляется в подвыражении prev->next, что эквивалентно (*prev).next. Посмотрите на это последнее выражение. Поскольку prev равно Node**, одна разыменование дает Node*, что является ситуацией сверху: попытка получить доступ к полю next не имеет смысла, если вы сначала не отмените ссылку на указатель, как в (**prev).next. Это близко к тому, что вы написали, но не совсем.

Правильное выражение, (**prev).next эквивалентно (*prev)->next. Ваше выражение *prev->next эквивалентно *(prev->next) или *((*prev).next). Существует разница в порядке оценки. Это различие является одной из причин, по которым указателям на указатели сложно правильно управлять. (Язык не предназначен для краткого размещения указателей на указатель на структуру. Вместо этого он предполагает более вероятный сценарий для двух уровней косвенности - указатель на структуру-с-указателем-членом.)


Поскольку вы кодируете на C ++ вместо C, есть отличная языковая функция, которая помогает избежать этой проблемы. Пусть insertElement принимает Node указатели по ссылке, а не по адресу. Это уменьшает сложность ваших выражений, устраняет текущую проблему и решает будущую проблему, когда вы никогда не проверяли, являются ли параметры функции нулевыми. (У вас есть проверка на то, что *head равно нулю, но эта проверка взрывается, если само значение head равно нулю.)

void insertElement(Node *&head, Node *&prev, int num);

С этим изменением вхождения внутри тела функции head* становятся head, из prev* становятся prev, а вызов функции становится insertElement(head, prev, num); (без адреса оператора). Вы получаете более простой синтаксис, так что вы можете сосредоточиться на логике c вставки элемента.

См. Также Значение * & и ** & в C ++ .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...