循环在没有明显原因的情况下在第一次迭代后暂停

时间:2019-07-16 07:17:01

标签: c++ linked-list shared-ptr do-while

以下是使用shared_ptr的链表的实现。从main()调用的所有例程均按预期工作,这将验证code.hpp中的关联模板类方法定义,除了reverse_menu()reverse()方法的接口list中的code.hpp类模板。

下面已复制了源代码,供您参考。

    //code.hpp

#ifndef CODE_HPP
#define CODE_HPP
#include <memory>
#include <iostream>

using std::shared_ptr;
using std::make_shared;

using std::cout;
using std::endl;

#define DBG_TRACE (cout << "At line " << __LINE__ << endl);

template<typename T>
class node{
    private:
        T& data;
        shared_ptr<node<T>> next;
    private:
        void set_data(T&);
    public:
        node(T&);
        ~node();
    public:
        T& get_data(void);
        shared_ptr<node<T>> get_next (void);
        void set_next(shared_ptr<node<T>>);
};

template<typename X>
class list{
    private:
        shared_ptr<X> head;
        list(shared_ptr<X>);
    public:
        shared_ptr<X> get_head(void);
        void set_head(shared_ptr<X>);
    public:
        list();
        ~list();
    public:
        size_t size (void)const;
        shared_ptr<X> operator[] (size_t) const;
        size_t remove (size_t);
        void reverse (void);
};

template<typename T>
node<T>::node(T& _data):data(_data){
    this->next = NULL;
}
template<typename T>
node<T>::~node(){
}

template<typename T>
void node<T>::set_next(shared_ptr<node<T>> next){
    DBG_TRACE
    this->next = next;

    DBG_TRACE
    return;
}
template<typename T>
shared_ptr<node<T>> node<T>::get_next(void){
    return(this->next);
}
template<typename T>
T& node<T>::get_data(void){
    return(this->data);
}

template<typename X>
list<X>::list(){
    this->head = NULL;
}

template<typename X>
list<X>::~list(){
}

template<typename X>
shared_ptr<X> list<X>::get_head(void){
    return(this->head);
}

template<typename X>
void list<X>::set_head(shared_ptr<X> head){
    this->head = head;

    return;
}

template<typename X>
size_t list<X>::size (void)const{
    auto h = this->head;
    auto count = 0;

    while(h->get_next()){
        ++count;
        h = h->get_next();
    }
    if(h && !h->get_next()){
        ++count;
    }

    return count;
}

template<typename X>
shared_ptr<X> list<X>::operator[] (size_t idx) const{

    if(idx >= this->size()){
        return NULL;
    }

    auto h = this->head;
    size_t count = 0;

    while(h && count < idx){
        ++count;
        h = h->get_next();
    }

    return h;
}

template<typename X>
size_t list<X>::remove(size_t idx){

    if(idx >= this->size()){
        //a workaround; need to 
        //replace with exception
        return (this->size());
    }
    else{

         if(0 == idx){
         auto h = (*this)[idx];
         auto nxt = h->get_next();
         this->set_head(nxt);
         h.reset();
        }
        else{
         auto h = (*this)[idx - 1];
         auto nxt = h->get_next()->get_next();
         h->get_next().reset();
         h->set_next(nxt);
        }

        return (this->size());
   }
}

template<typename X>
void list<X>::reverse(void){
    size_t i = 0;
    size_t j = 0;
    size_t sz = size();
    i = sz - 1;
    j = i - 1;

    DBG_TRACE
    cout << "i:" << i << endl;
    cout << "j:" << j << endl;

    do{
        DBG_TRACE
        (*this)[i]->set_next((*this)[j]);
        i = j;
        j = i - 1;
        cout << "i:" << i << endl;
        cout << "j:" << j << endl;
        DBG_TRACE
     }while(j >= 0);

     DBG_TRACE

    set_head((*this)[sz - 1]);
    (*this)[i]->set_next(NULL);

    return;
}
#endif



//main.cpp

#include "code.hpp"
#include <string>
#include <iostream>
#include <vector>
#include <cassert>
using std::string;
using std::cout;
using std::endl;
using std::vector;

void load_menu(void);
void rectify_menu (void);
void reverse_menu (void);
void print_menu(void);

list<node<string>>menu;
vector<string>menu_items{"pasta", "cake", "pizza", "soup", "muffin", "chai", "pie", "croissant", "coffee"};

int main (void){
    load_menu();
    //print_menu();

    rectify_menu();
    //print_menu();

    reverse_menu();
    print_menu();

    return 0;
}

void load_menu (void){
    auto num_menu_items = menu_items.size();

for(size_t i = 0; i < num_menu_items; ++i){
    switch(i){
        case 0:
            {
                auto menu_item = make_shared<node<string>>(menu_items[i]);
                menu_item->set_next(NULL);
                menu.set_head(menu_item);
            }
            break;
        case 1:
        case 2:
        case 3:
        case 4:
        case 5:
        case 6:
        case 7:
        case 8:
            {
                auto menu_item = make_shared<node<string>>(menu_items[i]);
                menu_item->set_next(NULL);

                auto m = menu.get_head();

                while(m->get_next()){
                     m = m->get_next();
                }

                m->set_next(menu_item);
            }
            break;
        default:    
            break;
    }
}

    return;
}

void rectify_menu (void){

    size_t num_menu_items = menu.size(); 
    assert(num_menu_items == menu_items.size()); 
    size_t i = 0;

    do{
        auto item_i = menu[i]->get_data();
        //cout << i <<  " " << "item_i: " << item_i << endl;
        for(size_t j = i + 1; j < num_menu_items; ++ j){
            auto item_j = menu[j]->get_data();
            //cout << j << " " << "item_j: " << item_j << endl;
           if(item_i == item_j){
               num_menu_items = menu.remove(j);
           }
       }
    }while(++i <= num_menu_items - 1); 

    return;
}

void print_menu (void){
    auto h = menu.get_head();
    do{
        cout << h->get_data() << endl;
    }while(h = h->get_next());
    cout << endl;

    return;
}

void reverse_menu (void){
    menu.reverse();

    return;
}

link<X>::reverse()node<T>::set_next()中,我包括了调试打印语句,以弄清楚逻辑流程。以下是程序的输出,在从print_menu()调用reverse_menu()之前两次禁用了main()的调用之后(要查看完整的程序输出,请启用注释掉的{{1} } print_menu()的调用:

main()

从调试跟踪中可以明显看出,At line 58 At line 61 At line 58 At line 61 At line 58 At line 61 At line 58 At line 61 At line 58 At line 61 At line 58 At line 61 At line 58 At line 61 At line 58 At line 61 At line 58 At line 61 At line 58 At line 61 At line 58 At line 61 At line 58 At line 61 At line 58 At line 61 At line 58 At line 61 At line 58 At line 61 At line 58 At line 61 At line 58 At line 61 At line 163 i:8 j:7 At line 168 At line 58 At line 61 i:7 j:6 At line 174 At line 168 中的do-while循环在第一次迭代后就没有明显的原因挂起。该结论是基于这样的事实得出的:link<X>::reverse()i的值在循环执行停止之前在循环内打印一次。如果要编译和运行程序,则调试跟踪中包含的行号也将确认此观察。

以下是gdb的输出:

j

根据上面的调试信息,无法确定循环执行为何在执行时会暂停。任何想法都将不胜感激。

TIA

0 个答案:

没有答案