Singly Linked List & Destructor - C++ for C Programmers 3.4

/*  Update on Oct 7th
    Finally figured out the reason for the malfunction of str destructor.
    It is really about pass-by-reference, which means when I call "a.inputName_by_Seq(n2, 10);"(just as an instance)
    the str "n2" is actually partially passed by reference, and that part is "n2.element", which is a pointer itself.
   although the function "
inputName_by_Seq" generated another str "name" within its domain, the element of "name" is EXACTLY     pointing to the SAME content which the element of "n2" is pointing to. So when the generated "name" is destructed as      " inputName_by_Seq" ceases, the content of "n2.element" is freed as well. So when the main function ends, another freeing     operation of "n2.element" leads to an error.
    A way thereby to avoid this malfunction is to produce a switch(named "coin" here) to stop the freeing operation
    at the end of "inputName_by_Seq". The other things of the parameter "name", such as its coin, and its len, will be released,
    while the pointer "element" stays until the end of main function.
    well, maybe not so elegant... but it works..
    if you have any better solution, just reply please!
*/
 
/*Since school has begun, daily updating seems quite impratical, but I will try to keep it weekly..
  This time the content is much more complex and it took me quite a while to figure out all the mistakes
  the scope of destructor is determined by its initialization. here I initialized a in main func, BUT the destructor of a is called as soon as I 
  activate functions concerning str class,  thus the free() in destructor will be repeatively called, causing bugs. No idea at all...
  but apart from that everything of the first list I built worked fine. it is a singly linked list which contains nodes of students' sequence         number ,name and score
*/

#include<iostream>
#include<cstring> //for memcpy()
#include<cstddef> //for size_t 

using namespace std;
class str {          //str is a class of string which is enabled to automatically grow or decline in size
    friend ostream& operator<<(ostream& out, const str& s); //so that "<<" is compatible with native classes from left or from right

public:
    str();
    ~str() { if (coin) { free(element);  } }
    str(const char* ch);
    str& operator=(const char ch[]);    //overloading the heavily used operators to nativize the class
    str& operator=(const str&);
    bool operator==(const str&);
    bool operator==(const char ch[]);
    bool operator!=(const str&);
    bool operator!=(const char ch[]);
    void coinTurnFalse() { coin = false; }
    void coinTurnTrue() { coin = true; }
    bool getCoin() { return coin; }
private:
    char *element;
    bool coin;
    size_t len;
    str& Resize(size_t n);        //Resize() is used when the string size needs to be remodified
};

str::str()                //default constructor generates a void string
{
    element = (char*)malloc(sizeof(char));
    element[0] = 0;
    len = 0;
}

str::str(const char ch[])
{
    if (strlen(ch)>len)
        len = strlen(ch);
    *this = Resize(len + 1);
    for (size_t i = 0; i<len; i++)
        element[i] = ch[i];
    element[len] = 0;
}

str& str::Resize(size_t n)
{
    element = (char*)realloc(element, sizeof(char)*n);
    return *this;
}

str& str::operator=(const char ch[])
{
    len = strlen(ch);
    /*if (len>strlen(element))
    {
    if (element)
    *this = Resize(len + 1);
    else
    element = (char*)malloc(sizeof(char)*(len + 1));
    }*/
    if (len>strlen(element))
        *this = Resize(len + 1);
    for (size_t i = 0; i<len; i++)
        element[i] = ch[i];
    element[len] = 0;

    return *this;
}

str& str::operator=(const str& s)
{
    len = s.len;
    element = (char*)malloc(sizeof(char)*(len + 1));
    for (size_t i = 0; i<len; i++)
        element[i] = s.element[i];
    /*memcpy(element, s.element, sizeof(char)*len);*/
    element[len] = 0;

    return *this;
}

bool str::operator==(const str& s)
{
    int i = 0;
    while (element[i] == s.element[i] && element[i] != 0 && s.element[i] != 0)
        i++;
    if (i == len&&i == s.len)
        return true;
    else return false;
}

bool str::operator==(const char ch[])
{
    int i = 0;
    while (element[i] == ch[i] && element[i] != 0 && ch[i] != 0)
        i++;
    if (i == len&&i == strlen(ch))
        return true;
    else return false;
}

bool str::operator!=(const str& s)
{
    int i = 0;
    while (element[i] == s.element[i] && element[i] != 0 && s.element[i] != 0)
        i++;
    if (i == len&&i == s.len)
        return false;
    else return true;
}

bool str::operator!=(const char ch[])
{
    int i = 0;
    while (element[i] == ch[i] && element[i] != 0 && ch[i] != 0)
        i++;
    if (i == len&&i == strlen(ch))
        return false;
    else return true;
}

ostream& operator<<(ostream& out, const str& s)
{
    out << s.element;
    return out;
}
/*----------------------- Above is the str class for storing the name ------------------------------*/

/*--------------------Below is the singly linked list for storing student files---------------------*/

struct node {        //set the node in the singly linked list
    node *next;
    int score;
    str name;
    int sequence;
};

class slinkedlist {    //this is a list which contains the scores and names with sequence number in ascending order
public:
    slinkedlist() { head = (node*)new(node); head->next = NULL; }
    ~slinkedlist() { delete head; cout << "finished." << endl; } //destructor used to avoid memory leak
    node* getHead() { return head; }
    int inputScore_by_Name(int Score, str Name);
    int inputScore_by_Seq(int Score, int seq);
    int insertNode(int seq);
    int deleteNode(int seq);
    int inputName_by_Seq(str Name, int seq);
    void outputList();
    void displayNode_Name(int seq);
    void displayNode_Score(int seq);
private:
    node *head;
};

int slinkedlist::inputScore_by_Name(int score, str name)        // -1 for multiple names; 0 for search failure; 1 for success
{
    name.coinTurnFalse();
    node *prs;
    int seq;
    int dup = 0;
    if (head->next == NULL || head == NULL)
        return 0;
    else
    {
        prs = head->next;
        do {
            if (prs->name == name)
            {
                dup++;
                seq = prs->sequence;
            }
            if (prs->next != NULL)
                prs = prs->next;
        } while (prs->next != NULL);
    }
    if (dup == 0)
        return 0;
    else if (dup>1)
        return -1; //strengthen the immunity to duplications
    else
    {
        inputScore_by_Seq(score, seq);
        return 1;
    }
    return 0;
}

int slinkedlist::inputScore_by_Seq(int score, int seq)    // 0 for search failure; 1 for success
{
    if (head->next == NULL || head == NULL)
        return 0;
    else
    {
        node *pro = head->next;
        while (seq > pro->sequence&&pro->next != NULL)
            pro = pro->next;
        if (seq == pro->sequence)
        {
            pro->score = score;
            return 1;
        }
        else
            return 0;
    }
    return 0;
}

int slinkedlist::inputName_by_Seq(str name, int seq)    //-1 for ungeneration; 0 for search failure; 1 for success
{
    name.coinTurnFalse();
    if (head == NULL)
        return -1;
    else if (head->next == NULL)
        return 0;
    else
    {
        node *prs = head->next;
        while (seq > prs->sequence&&prs->next != NULL)
            prs = prs->next;
        if (seq == prs->sequence)
        {    
            prs->name = name;
            return 1;
        }
        else
            return 0;
    }
    return 0;
}

int slinkedlist::deleteNode(int seq)        //-1 for ungeneration; 0 for search failure; 1 for success
{
    if (head == NULL)
        return -1;
    else if (head->next == NULL)
        return 0;
    else
    {
        node *prs = head->next;
        node *temp = prs;
        while (seq > prs->sequence&&prs->next != NULL)
        {
            temp = prs;
            prs = prs->next;
        }
        if (seq == prs->sequence)
        {
            if (prs == head->next)
            {
                head->next = prs->next;
                delete prs;
                return 1;
            }
            else if (prs->next == NULL)
            {
                temp->next = NULL;
                delete prs;
                return 1;
            }
            else
            {
                temp->next = prs->next;
                delete prs;
                return 1;
            }
        }
        else
            return 0;
    }
    return 0;
}

int slinkedlist::insertNode(int seq)   // -1 for ungeneration; 0 for multiple existence failure; 1 for success
{
    node *ptr, *pro, *temp;
    ptr = (node *)new(node);
    if (head == NULL)
        return -1;
    else if (head->next == NULL)            // an empty list
    {
        head->next = ptr;
        ptr->sequence = seq;
        ptr->next = NULL;
        ptr->score = 0;
        return 1;
    }
    else
    {
        pro = temp = head->next;
        while (seq > pro->sequence && pro->next != NULL)
        {
            temp = pro;
            pro = pro->next;
        }
        if (head->next == pro)    // operating the first node
        {
            if (seq > pro->sequence)
            {
                pro->next = ptr;
                ptr->sequence = seq;
                ptr->next = NULL;
                ptr->score = 0;
                return 1;
            }
            else if (seq < pro->sequence)
            {
                ptr->next = pro;
                head->next = ptr;
                ptr->score = 0;
                ptr->sequence = seq;
                return 1;
            }
            else if (seq == pro->sequence)
                return 0;
        }
        else if (pro->next == NULL)        //operating the last node
        {
            if (seq != pro->sequence)
            {
                ptr->next = NULL;
                ptr->sequence = seq;
                ptr->score = 0;
                pro->next = ptr;
                return 1;
            }
            else if (seq == pro->sequence)
                return 0;
        }
        else                          //common cases
        {
            if (seq == pro->sequence)
                return 0;
            else
            {
                temp->next = ptr;
                ptr->next = pro;
                ptr->sequence = seq;
                ptr->score = 0;
                return 1;
            }
        }
    }
    return 0;
}

void slinkedlist::displayNode_Name(int seq)
{
    if (head == NULL)
        cout << "List ungenerated. Please check." << endl;
    else if (head->next == NULL)
        cout << "No such sequence number found. Please check." << endl;
    else
    {
        node *prs = head->next;
        while (seq > prs->sequence && prs->next != NULL)
            prs = prs->next;
        if (seq == prs->sequence)
            cout << "Name:" << prs->name << endl;
        else
            cout << "No such sequence number found. Please check." << endl;
    }
}

void slinkedlist::displayNode_Score(int seq)
{
    if (head == NULL)
        cout << "List ungenerated. Please check." << endl;
    else if (head->next == NULL)
        cout << "No such sequence number found. Please check." << endl;
    else
    {
        node *prs = head->next;
        while (seq > prs->sequence && prs->next != NULL)
            prs = prs->next;
        if (seq == prs->sequence)
            cout << "Score:" << prs->score << endl;
        else
            cout << "No such sequence number found. Please check." << endl;
    }
}

void slinkedlist::outputList()
{
    if (head == NULL)
        cout << "List ungenerated. Please check." << endl;
    else if (head->next == NULL)
        cout << "List is empty. Please check." << endl;
    else
    {
        node *prs = head->next;
        int seq;
        while (prs!=NULL)
        {
            cout << endl;
            seq = prs->sequence;
            displayNode_Name(seq);
            cout << "Sequence number:" << seq << endl;
            displayNode_Score(seq);
            prs = prs->next;
        }
    }
}

int main()
{
    slinkedlist a;
    a.insertNode(1);
    str n1, n2;
    n1 = "Jason";
    n2 = "Daisy";
    a.inputName_by_Seq(n1, 1);
    a.inputScore_by_Name(100, n1);
    a.displayNode_Name(1);
    a.displayNode_Score(1);
    a.inputScore_by_Seq(98, 1);
    a.displayNode_Score(1);

    a.insertNode(10);
    a.inputName_by_Seq(n2, 10);
    a.displayNode_Name(10);
    a.inputScore_by_Seq(98, 10);
    a.outputList();
    cout << a.deleteNode(1) << endl;
    a.outputList();
    system("pause");
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值