【问题标题】:Printing A linked List - Access Violation C++打印链接列表 - 访问冲突 C++
【发布时间】:2015-10-24 09:59:18
【问题描述】:

我有一个链表,它接受多个输入文件,然后将它们放入链表中以便稍后打印。

我实现了一个打印功能,但它不能很好地工作并给出访问冲突错误。我尝试调试,不幸的是我找不到问题的根源。

函数中的错误行:

cout << ptr2->command + " ";

运行时错误:

file.exe 中 0x00DAC616 处的第一次机会异常:0xC0000005:访问冲突读取位置 0xCDCCDCDE1。

代码如下:

#include <iostream>
#include <fstream>
#include <string>
#include "strutils.h" 
using namespace std;

struct Commands;

struct Functions
{
    string fname;
    Functions *right;
    Commands  *down;
};
struct Commands
{
    string command;
    Commands *next;
};

Functions *head;
Functions *temp;
Commands *temp2;

void StreamToLinkedList(ifstream &inputfile)
{
    string s;
    getline(inputfile, s);
    temp = new Functions();
    temp->fname = s.substr(0, s.length());
    temp2 = temp->down;
    while (!inputfile.eof())
    {
        getline(inputfile, s);
        temp2 = new Commands();
        temp2->command = s.substr(0, s.length()-1) + ",";
        temp2 = temp2->next;
    }
    inputfile.clear();
    inputfile.seekg(0);
}
void printLinkedList()
{
    Functions *ptr = head;
    Commands *ptr2;
    while (ptr != nullptr)
    {
        cout << ptr->fname << endl;
        ptr2 = ptr->down;
        while (ptr2 != nullptr)
        {
            cout << ptr2->command + " ";
            ptr2 = ptr2->next;
        }
        cout << endl;
        ptr = ptr->right;
    }   
}
int main()
{
    string file, key, s;
    ifstream input;
    cout <<"If you want to open a service (function) defining the file," << endl
         <<"then press (Y/y) for 'yes', otherwise press any single key" << endl;
    cin >> key;
    ToLower(key);
    if (key == "y")
    {
        cout << "Enter file the input file name: ";
        cin >> file;
        input.open(file.c_str());
        if (input.fail())
        {   
            cout << "Cannot open the file." << endl
                 << "Program terminated."   << endl;
            cin.get();
            cin.ignore();
            return 0;
        }
        else 
        {
            StreamToLinkedList(input);
            head = temp;
            temp = temp->right;
        }   
    }
    else 
    {
        cout << "Cannot found any input file to process" <<endl
             << "Program terminated."<< endl;
        cin.get();
        cin.ignore();
        return 0;
    }
    do
    {
        cout<<  "Do you want to open another service defining file?"<<endl
            << "Press (Y/y) for 'yes', otherwise press any key" <<endl;
        cin >> key;
        ToLower(key);
        if (key == "y")
        {
            cout << "Enter file the input file name: ";
            cin >> file;
            input.open(file.c_str());
            if (input.fail())
            {   
                cout << "Cannot open the file." << endl
                     << "Program terminated."   << endl;
                cin.get();
                cin.ignore();
                return 0;
            }
            else
            {
                StreamToLinkedList(input);
                temp = temp->right;
            }
        }
    } while ( key == "y");
    cout << "-------------------------------------------------------------------" << endl
        << "PRINTING AVAILABLE SERVICES (FUNCTIONS) TO BE CHOSEN FROM THE USERS"   << endl
        << "-------------------------------------------------------------------" << endl << endl;
    printLinkedList();
    cin.get();
    cin.ignore();
    return 0;
}

错误代码可能是什么?

【问题讨论】:

  • 你忘了问问题。您尝试调试什么?
  • 真的要实现自己的链表吗? vs std::list
  • 对于第一个问题,我调试了它,因为我必须确保它确实有效;第二,我必须实现我自己的链表。
  • 0xCDCDCD ... 是 Microsoft VC 调试版本填充未初始化数据的典型。这是扩展,在正常的“非调试”C++ 中,此类区域将具有随机值。
  • 我应该将这些指针初始化为 nullptr 吗?

标签: c++ linked-list


【解决方案1】:

回答

您的打印功能正常。您创建和管理列表的方式有问题,可能是由于您从未初始化您的Functions.rightFunctions.down 字段,因此您的链接列表链接到无效内存。好吧,您实际上并没有链接您的列表。

您的某些分配(例如 temp2 = temp-&gt;downtemp = temp-&gt;right)没有任何意义,因为这些字段未初始化,并且您随后会用新对象覆盖这些变量(temptemp2)。

另外,您有重复的代码。您正在以完全相同的方式在两个不同的地方读取文件。问题是您的代码是错误的,因此您需要修复双倍的错误。此处代码重复的唯一明显原因是您希望在用户第一次输入和第 n 次时显示不同的消息。

我建议将此代码放在它自己的函数中。否则,请找到一种更有效的方式来使用条件/循环,这样您就不会有太多重复的代码。


注意事项

我对您的代码有“一些”需要注意的地方。 LinkedList 在两个名为FunctionsCommands 的类中实现。我知道你想要一个函数列表并且每个函数都有一个命令列表,但是你必须学会​​将你的程序域与其他功能区分开来。 p>

IE:LinkedList 是对象(任何类型)的容器。 FunctionCommand 是您为程序制作的特定内容,与链表本身无关。从概念的角度来看,Function 包含Commands,但不一定通过LinkedListmaparray 等。

您的代码需要概念分离,看看它有多清晰

// Linked list of functions
Functions list;

// No need to comment this one
LinkedList functions;

(我们不要争论缺少模板类型)

此外,除非使用复数来命名一个类有意义,否则您几乎应该始终使用单数(FunctionsFunction)。这是因为当您实例化一个类时,您将拥有 一个 对象/实例,因此使用复数作为类型可能会产生误导。考虑以下声明,

Function someFunction; // This is a single function
Functions someFunction; // Is this one function or multiple functions??

List< Function > functions; // This is a list of functions
List< Functions > functions; // Is this a list of lists of functions???

您应该创建一个名为 LinkedList 的类(提示:尽可能使用模板以使其更可重用)。然后,如果你要将函数和命令的实现从链表中分离出来,你可以做这样的事情,

template <class T>
struct LinkedList {
    T* obj;
    LinkedList<T>* next;

    LinkedList() : obj( nullptr ), next( nullptr ) {}
};

struct Command {
    string cname;
};

struct Function {
    string fname;
    LinkedList<Command> commands;
};

现在你可以像这样声明你的函数列表,

LinkedList<Function> functions;

由于每个Function 都有自己的Commands 列表,因此您有一个列表列表,您不必像在当前实现中那样独立管理每个列表。当然,您的列表仍然需要一个接口(和内存管理),但这不在这个问题的范围内。

编辑:

当指针不指向任何东西时,初始化指向 nullptr 的指针。

temp = new Functions;
temp->right = nullptr;
temp->down = nullptr;

或者使用默认构造函数,

struct Functions {
    ...
    Functions() : right( nullptr ), down( nullptr ){}
};

然后像这样初始化,

temp = new Functions();

【讨论】:

  • @Oguz 你在 SO。您可以到处搜索模板的使用情况。编辑了我的问题。
【解决方案2】:

您的访问冲突问题是 new 默认情况下不会将其分配的内存归零, 所以最后一个结构内的指针指向一个随机值。

temp2 = new Commands; // this memory is not initilized to zero
temp2 = new Commands(); // this memory is initialized to zero, (all elements is set to 0)

【讨论】:

    猜你喜欢
    • 2012-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-23
    • 1970-01-01
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    相关资源
    最近更新 更多