C ++课程&链表:添加&计算物品

时间:2010-05-16 09:34:46

标签: c++ linked-list

我需要用类创建一个链表。每个列表将存储两个值:URI和IP。完成所有添加后,我需要能够计算链表中的项目总数。我尝试了以下代码,但它没有编译。我们不允许使用std :: list。有什么建议吗?

#include <iostream>
#include <cstdlib>
#include <string>

using namespace std;

class ip_uri_store {
  protected:
    string ip;
    string uri;
    ip_uri_store *next;

  public:
     ip_uri_store(string huri, string hip);
    void additem(string auri, string aip);
    void deleteitem(string duri);
    void findbyuri(string furi);
    void findbyip(string fip);
    int totalitems();
};

ip_uri_store *head = NULL;
ip_uri_store *curr = NULL;

void ip_uri_store::additem(string auri, string aip)
{
    curr = head;
    while (curr->next != NULL) {
 curr = curr->next;
    }

    curr->uri = auri;
    curr->next = new ip_uri_store;
    curr->ip = aip;
    curr->next = new ip_uri_store;
    curr = curr->next;
    curr = head;
}

int ip_uri_store::totalitems()
{
    int i = 0;

    curr = head;

    while (curr->next != NULL) {
 i += 1;
 curr = curr->next;
    }

    return i;
}

int main(int argc, char *argv[])
{
    if (argc == 1) {
 cout << "123456, 123456@student.rmit.edu.au, Gordon Brown" << endl;
 return (0);
    }

    head = new ip_uri_store;
    curr = head;
    int i;


    for (i = 1; i < argc; i++) {

 if (argv[i][0] == 'A') //add item
 {
     ip_uri_store.additem(argv[i + 1], argv[i + 2]);
     i += 2;
 }

 else if (argv[i][0] == 'N') //print total tiems
 {
     cout << ip_uri_store.totalitems() << endl;
 }

 else {
     cout << "command error\n";
     return 0;
 }
    }
    return (0);
}

2 个答案:

答案 0 :(得分:1)

你的ip_uri_store::additem()非常混乱。在其中,您可以在为其指定新值之前更改curr对象:

curr->uri = auri;
curr->next = new ip_uri_store;

这样做可以更改列表中的最后一项,而不是将auri分配给稍后添加的新项目。 (有趣的是,您通过ip得到了正确的订单。)


我喜欢提供代码名称的想法,以便您可以阅读他们所做的事情。功能就是这样做的。例如,我将找出找到最后一个列表节点的代码

ip_uri_store *find_last_node(ip_uri_store *curr)
{
    while (curr->next != NULL) {
        curr = curr->next;
    }
    return curr;
}

并从ip_uri_store::additem()

调用它
void ip_uri_store::additem(string auri, string aip)
{
    ip_uri_store *curr = find_last_node(head);
    // ...

现在创建一个新对象并记住其在curr->next

中的地址
    // ...
    curr->next = new ip_uri_store(auri,aip);
}

您的ip_uri_store::totalitems()会返回int。为什么?你有没有期望对象的数量是负数?最好返回无符号类型。


您应该考虑删除列表节点时会发生什么。如果它仍指向next对象,则指针可能不存储在其他任何位置,因此对象(以及它指向的对象)正在泄漏。解决这个问题的一种方法是为ip_uri_store编写一个删除next的析构函数。 (如果要在不删除节点的情况下删除节点,可以先将NULL指定给其next指针。)

此外,根据Rule of Three,您需要考虑复制列表节点。在第一次尝试中做到这一点并不容易,所以你可能只想禁止它:

class ip_uri_store {
  private:
    ip_uri_store(const ip_uri_store&); // not implemented
    ip_uri_store& operator=(const ip_uri_store&); // not implemented
  // ...

您可以将它们放入类中,而不是使用全局变量。这样你就可以拥有多个列表。将ip_uri_store重命名为ip_uri_store_impl并将其重命名为新的ip_uri_store类:

class ip_uri_store {
  private:
    class ip_uri_store_impl { /* ... */ };
    ip_uri_store_impl* head;
};

由于此类管理动态分配的对象,因此您需要考虑销毁和复制此类对象。

包装器类应该有公共方法,可以调用ip_uri_store_impl的方法。像totalitems()这样在整个列表(而不是节点)上运行的函数应该可以在包装类中实现。

答案 1 :(得分:0)

您需要为ip_uri_store类的构造函数提供两个参数:

// The constructor call needs two arguments
curr->next = new ip_uri_store(huri, hip);

您无法在类本身上调用实例方法:

// Invalid, totalitems() is valid only on instances of ip_uri_store. 
cout << ip_uri_store.totalitems() << endl;

为什么变量headcurr是全局的?他们确实应该是班级的数据成员。

拉出ip的{​​{1}},urinext成员,并将它们放在自己的结构中,比如ip_uri_store。然后,ip_uri_store_node可以定义初始化它们的构造函数。然后让ip_ur_store_node按住ip_uri_storeheadcurr个实例。

这就是我的意思:

ip_uri_store_node

函数struct ip_uri_store_node { string ip; string uri; ip_uri_store_node* next; ip_uri_store_node(const char* u, const char* i) : ip(i), uri(u), next(0) {} }; class ip_uri_store { private: ip_uri_store_node* head; ip_uri_store_node* curr; public: // Initializes head and curr ip_uri_store(); // These functions woud act on head and curr. void additem(string auri, string aip); void deleteitem(string duri); void findbyuri(string furi); void findbyip(string fip); int totalitems(); }; int main() { ip_uri_store list; // Do things with the list... return 0; } 可以像这样创建additem的新实例:

ip_uri_store_node

其余由你决定。