【问题标题】:Lists of lists losing data after pointer arithmetics指针运算后丢失数据的列表列表
【发布时间】:2018-01-25 09:24:00
【问题描述】:

我一直在编写一组包含指向列表的指针的列表,并且想要创建一个方便的界面来浏览它们并将选定的数据从文件保存到列表。这个想法是有一个具有唯一 ID 的“API 列表”,每当我找到一个唯一 ID 时,我都会创建一个新的 API 列表。现在,我正在将数据保存到一个“API 列表”相关列表中。

结构看起来很简单:

enum day { mon, tue, wed, thu, fri, sat, sun };
static const string enumValues[] = { "mon", "tue", "wed", "thu", "fri", "sat", "sun" };

struct _ListSub {
  string h;
  day d;
  string gr;
  string sub;
  _ListSub *next = nullptr;
};

struct ListAPI {
  string id;
  ListAPI *next = nullptr;
  _ListSub *head = nullptr;
};

我从文件读取值并将其保存到列表的函数如下所示:

ListAPI *createLists(string arg) {
  ifstream f_in;
  ListAPI *listGrip;

  f_in.open(arg);

  if (!f_in.is_open()) {
    cout << "\"" << arg << "\": file does not exist!" << endl;
    exit(EXIT_FAILURE);
  }

  listGrip = new ListAPI;
  listGrip->head = new _ListSub;

  while (true) {
    // dummy data
    string h;
    string week = "";
    string gr;
    string id;
    string sub;

    if (!(f_in >> h >> week >> gr >> id >> sub)) {
      break;
    }

    cout << "ID check: " << checkListID(id, listGrip) << endl;

    listGrip->id = id;
    listGrip->head->h = h;
    listGrip->head->d = (day)enumerateDay(week);
    listGrip->head->gr = gr;
    listGrip->head->sub = sub;

    listGrip->head ++;
    listGrip->head = new _ListSub;
  }

  f_in.close();

  return listGrip;
}

无论如何,数据是正确的,它工作正常,所以很久没有添加这部分(移动_listSub的头指针并创建这个对象的新实例):

listGrip->head ++;
listGrip->head = new _ListSub;

我从中得到的所有数据都是 id 女巫,我保存到 listGrip(我的列表 API),但是嵌套列表列表中的所有数据都消失了。

有人能告诉我我在这里用指针做错了什么吗?

主要:

int main( int argc, char **argv ) {

  /* Directly parse options in order to avoid accepting abbrevations. */
  string ARGUMENT;
  validate_arguments;

  cout << "File path: " << ARGUMENT << endl;
  ListAPI *listGrip;

  listGrip = createLists( ARGUMENT );

  //listGrip->head;

  cout << "List has been created." << endl;
  cout << "ID: " << listGrip->id << endl;
  cout << "Subject: " << listGrip->head->sub << endl;
  cout << "Time: " << listGrip->head->h << endl;
  cout << "Day: " << getTextFromEnum((short)listGrip->head->d) << endl;

  delete listGrip;
  return EXIT_SUCCESS;
}

【问题讨论】:

  • main() 在哪里?请发布minimal reproducible example。不要描述你的代码,而是展示它。
  • "有人能告诉我我在这里用指针做错了什么吗?"一切。您只能使用指向数组的指针进行指针运算,head 不能。此外,head = new ... 丢弃了您辛辛苦苦构建的旧 head
  • 我建议你在一张纸上画一个3个元素的链表,然后在头指针上放置一个marker,通过移动marker并根据需要绘制一个新节点来模拟添加一个新元素。
  • _ListSub 标识符被保留。选择另一个名字。

标签: c++ list pointers


【解决方案1】:
listGrip->head ++;

没有意义。 head 指向单个 _ListSub。当您增加它时,它将指向您分配的 _ListSub 之后的一些随机内存。这个随机内存不是你的,可能会导致内存损坏,或者如果你幸运地遇到了 SegFault。

你可能想要的是在头部插入:

auto new_head = new _ListSub;
new_head->next = listGrip->head;
listGrip->head = new_head;

或者甚至更好地使用标准库。那里已经有一个std::list,它已经过很好的测试并且可以正常工作。

【讨论】:

  • 谢谢,那条评论目前帮助了我。我很漂亮,这不是我的程序,所以我无法真正理解这个概念。我认为这种结构本身就是愚蠢的。最后,我使用nextprev 指针和插入函数创建了一个指向它自身的头部结构(node)。很简单。
【解决方案2】:

Linked-List 是一种连接松散节点的抽象结构。由于节点没有彼此相邻放置,我们无法执行指针算术以到达下一个节点。相反,我们可以创建一个插入函数来为我们重定向指针。

重定向节点:

经典链表在其结构中包含next 指针,指向相同类型的下一个节点。为了说服我们可以添加previous 指针和一个大小变量来跟踪列表大小。

void insertSub(string h, day d, string gr, string sub) {
  auto newNode = new _ListSub;

  //initialize
  newNode->h = h;
  newNode->d = d;
  newNode->gr = gr;
  newNode->sub = sub;

  // point new node to the currently previous and next node
  newNode->next = node->next;
  newNode->prev = node;

  // point currently next and previous node to the new node
  node->next->prev = newNode;
  node->next = newNode;

  // increment size
  ++ node->size;
}

这适用于我的结构,但可能您想使用构造函数进行对象初始化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多