【问题标题】:C++ Read Access Violation in Singly Linked List单链表中的 C++ 读取访问冲突
【发布时间】:2020-04-05 16:26:22
【问题描述】:

我正在编写一个关于创建国家列表的程序,我的代码中似乎没有错误,但是在调试时,我收到错误:未处理的异常抛出:读取访问冲突 p 是 0xFFFFFFFFFFFFFFFF,在我输入一些值后。 谁能给我一个提示或找出我的错误?

#include <cstring>
#include <string>
using namespace std;

这是我的结构 Provice。

struct Province
{
    int Code;
    string Name;
    int Pop;
    float Area;
};
struct node
{
    struct Province data;
    node* next;
};
struct List
{
    node* head;
    node* tail;
};
void Init(List &l)
{
    l.head = NULL;
    l.tail = NULL;
}
void add_tail(List& l, node* p)
{
    if (l.head == NULL)
    {
        l.head = p;
        l.tail = p;
    }
    else
    {
        l.tail->next = p;
        l.tail = p;
    }
}

我想我在这里创建节点而不初始化值时遇到了一些问题,对吗?

void inputListProvinces(List& l)
{
    int n;
    cin >> n;
    int i = 0;
    while(i<n)
    {
        node* p = new node;
        cin >> p->data.Code;
        cin.ignore();
        getline(cin, p->data.Name);
        cin.ignore();
        cin >> p->data.Pop;
        cin >> p->data.Area;
        add_tail(l, p);
        i++;
    }
}

错误发生在这里,但我不知道如何解决。

void outputListProvinces(List& l)
{
    node* p = l.head;
    while (p != NULL)
    {
        cout << p->data.Code << '\t'; /*Unhandled exception thrown: read access violation.
p was 0xFFFFFFFFFFFFFFFF*/

        cout << p->data.Name << '\t';
        cout << p->data.Pop << '\t';
        cout << p->data.Area << '\t';
        cout << endl;
        p = p->next;
    }
}
void outputProvince(node* p)
{
    cout << p->data.Code << '\t';
    cout << p->data.Name << '\t';
    cout << p->data.Pop << '\t';
    cout << p->data.Area << '\t';
}
void outputProvincesMore1MillionPop(List& l)
{
    node* p = l.head;
    while (p != NULL)
    {
        if (p->data.Pop > 1000)
        {
            outputProvince(p);
            cout << endl;
        }
        p = p->next;
    }
}
node* findProMaxArea(List& l)
{
    node* n = l.head;
    node* p = l.head;
    while (p != NULL)
    {
        if (p->data.Area > n->data.Area)
        {
            n = p;
        }
        p = p->next;
    }
    return n;
}



int main()
{
    List L;
    Init(L);
    inputListProvinces(L);
    cout << "List of provinces:" << endl;
    cout << "ID\t|Province\t|Population\t|Area" << endl;
    outputListProvinces(L);

    cout << "Provinces with a population of more than 1 million:" << endl;
    outputProvincesMore1MillionPop(L);

    cout << "The largest province:" << endl;
    node* p = findProMaxArea(L);
    if (p) outputProvince(p);

    return 0;
}

【问题讨论】:

  • LNULL... 不确定您期望在这里发生什么。
  • 无关:std::getline 使用它找到的分隔符。后面很少需要ignore
  • 如果您想要单链表,请使用std::forward_list。但老实说,不要使用链表。他们的表现很糟糕。
  • 强烈考虑将Init 变成List 的构造函数。这样你就不会忘记调用它。

标签: c++ struct singly-linked-list


【解决方案1】:

错误是node 从未初始化其next 指针。如果将其设置为NULL,则只能指望它为NULL,并且列表中的最后一个node 必须是NULL,否则程序找不到List 的结尾并离开进入Undefined Behaviour的古怪世界。

最安全的修复:将构造函数添加到 node 以确保始终初始化 next

struct node
{
    struct Province data;
    node* next;
    node(node* n = NULL): next(n)
    {
    }
};

还有其他修复,例如确保 l.tail-&gt;next = NULL; 位于 inputListProvinces 的末尾,但鉴于控制台 IO 的缓慢性,我认为减少开销并不值得。

如果你这样做了,那么你还应该将Init 作为构造函数滚动到List

struct List
{
    node* head;
    node* tail;
    List(): head(NULL), tail(NULL)
    {
    }
};

这应该会给您留下一个问题,即放置不当的cin.ignore() 会消耗您不想消耗的角色。

旁注:如果您的编译器和目标 C++ 标准修订版可用,请将 NULL 替换为 nullptrnullptr 删除了可能由于 NULL 被美化的 0 而导致的错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-28
    • 1970-01-01
    • 2016-09-02
    • 2012-10-11
    • 1970-01-01
    • 2022-01-10
    • 1970-01-01
    相关资源
    最近更新 更多