函数只能在main中调用一次

时间:2011-05-10 02:28:27

标签: c++ function workflow freeze

由于某种原因,check_sort函数只能在main函数中调用一次,否则工作流在首次执行后会冻结。

例如。输出结束于:

How many elements for container? 5000
Check: list is sorted
Elapsed time: 0.32 seconds

而不是继续:

How many elements for next container? 5000
Check: list is sorted
Elapsed time: 0.30 seconds
Check: set is sorted
Elapsed time: 0.01 seconds
Check: vector is sorted
Elapsed time: 0.25 seconds

以下完整计划:

#include <cmath>
#include <iterator>
#include <iostream>
#include <iomanip>
#include <vector>
#include <ctime>
#include <list>
#include <set>
#include <algorithm>
#include <cstdlib>

using namespace std;

typedef void Inserter(vector<double>);

vector<double> gen_data(int num_elts);
void insert_list(vector<double> data);
void insert_set(vector<double> data);
void insert_vector(vector<double> data);

void time_insert( Inserter inserter, vector<double> data);

template <class Iter> bool is_sorted(Iter first, Iter last);
template <class Iter> void check_sort(Iter first, Iter last, string cont_kind);

list<double> l;
set<double> s;
vector<double> v;

int main() {
    srand(time(0));// initialize random number generator
    cout << "How many elements for container? ";
    int num_elts = 0;

    while (cin >> num_elts) {
    if (num_elts <= 0)
        cout << "Error, should be > 1";
    else {
        vector<double> data = gen_data(num_elts);

        check_sort(l.begin(), l.end(), "list");
        time_insert(insert_list, data);
        check_sort(s.begin(), s.end(), "set");
        time_insert(insert_set, data);
        check_sort(v.begin(), v.end(), "vector");
        time_insert(insert_vector, data);

    }
    cout << "\nHow many elements for next container? ";

    }
    return 0;

} 
void time_insert( Inserter inserter, vector<double> data) {
    clock_t t1 = clock();
    if (t1 == clock_t(-1)) { //if clock() doesn’t work
    cerr << "sorry, no clock\n";
    exit(1);
    }

    inserter(data);
    clock_t t2 = clock(); 
    if (t2 == clock_t(-1)) {
    cerr << "sorry, clock overflow\n";

    exit(2);
    }

    cout << "Elapsed time: " << fixed << setprecision(2)
     << double(t2-t1)/CLOCKS_PER_SEC << " seconds\n";

}

class Larger_than { 
    double v;
public: 
    Larger_than(double vv) : v(vv){}
    bool operator()(double x) const {return x>v;}
};

// Sorts and then inserts data into a list
void insert_list(vector<double> data)
{
    list<double> l;
    for(int i=0; i < data.size(); i++){
    list<double>::iterator p = find_if(l.begin(),l.end(), Larger_than(data[i]));
    l.insert(p, data[i]);
    }
} 
// Sorts and then inserts data into a list
void insert_set(vector<double> data)
{
    set<double> s; 
    for(int i=0; i < data.size(); i++){
    set<double>::iterator p = find_if(s.begin(),s.end(), Larger_than(data[i]
                          ));
    s.insert(p, data[i]);
    }
} 
// Sorts and then inserts data into a list 
void insert_vector(vector<double> data)
{
    vector<double> v; 
    for(int i=0; i < data.size(); i++){
    vector<double>::iterator p = find_if(v.begin(),v.end(), Larger_than(data
                                        [i]));
    v.insert(p, data[i]);
    }
} 

// generate num_elts random numbers in the range [0.0, 1.0), 
// which are returned in a vector

vector<double> gen_data (int num_elts) 
{
    vector<double> result; 
    for (int i = 0; i < num_elts; i++) {
    double datum = 1.0*rand()/RAND_MAX; 
    result.push_back(datum);
    }
    return result;
}

// is container spanned by [from, last) sorted?  
template <class Iter> bool is_sorted(Iter first, Iter last)  
{  
    Iter next = first;                   // next element  
    for (next++; next != last; next++, first++) {  
    if (*first > *next)  
        return false;  
    }  
    return true;  
}  

// prints a msg describing container kind, as well as whether container  
// spanned by [from, last) is sorted  
template <class Iter> void check_sort(Iter first, Iter last, string cont_kind)  
{  
    cout << "Check: " << cont_kind << " is ";  
    if (!is_sorted(first, last)) cout << "not ";  
    cout << "sorted\n";  
} 

3 个答案:

答案 0 :(得分:4)

我不知道这是否是您问题的一部分,但如果is_sorted是容器的末尾,则first无法正常工作。 next增加超过end并且遇到未定义的行为。

编辑:实际上这肯定是这样的:在调用它们的检查函数之前,不要填充vector / list / set容器。即使你在调用check函数之前调用了insert函数,它仍然无法工作,因为每个insert_*函数声明一个local填充哪个阴影你试图填充的全局变量。

EDIT2:在insert_set中,find_if实际上使您的代码的性能低于应有的水平。您应该使用std::set::insert并让它使用其内置排序,这将比find_if更有效,因为它知道底层set的实现。

答案 1 :(得分:2)

在递增is_sorted() first的副本之前,您的模板函数last未正确检查next是否等于first

template <class Iter> bool is_sorted(Iter first, Iter last)  
{  
    Iter next = first;                   // next element  
    for (next++; next != last; next++, first++) {  
        if (*first > *next)  
            return false;  
    }  
    return true;  
}

如果你想在一个空的范围内迭代,这可能会导致问题,我相信。

template <class Iter> bool is_sorted(Iter first, Iter last)  
{  
    if (first == last)
        return false;
    for (Iter next = first+1; next != last; next++, first++)
    {  
        if (*first > *next)  
            return false;  
    }  
    return true;  
}

我不确定你会得到空的范围......所以这可能是一个红色的鲱鱼。

由于在检查列表是否已排序之前没有设置列表(并且在插入数据后没有检查它是否已排序),因此会遇到空范围问题。您需要反转插入序列并检查操作:

    vector<double> data = gen_data(num_elts);
    time_insert(insert_list, data);
    check_sort(l.begin(), l.end(), "list");
    time_insert(insert_set, data);
    check_sort(s.begin(), s.end(), "set");
    time_insert(insert_vector, data);
    check_sort(v.begin(), v.end(), "vector");

您应该通过调用函数来获取要处理的元素数量来避免主循环中的重复代码。此外,通常会在cerr报告错误。

static int get_num_elts()
{
    int num_elts;
    cout << "How many elements for container? ";
    cin >> num_elts;
    if (num_elts < 1)
        cerr << "Error: number should be >= 1" << endl;
    return num_elts;
}


...
int num_elts;

while ((num_elts = get_num_elts()) > 0)
{
    vector<double> data = gen_data(num_elts);
    time_insert(insert_list, data);
    check_sort(l.begin(), l.end(), "list");
    time_insert(insert_set, data);
    check_sort(s.begin(), s.end(), "set");
    time_insert(insert_vector, data);
    check_sort(v.begin(), v.end(), "vector");
}

答案 2 :(得分:1)

您的代码未在is_sorted函数

中进入循环体

代替for (next++; next != last; next++, first++)执行for (next; next != last; next++, first++)。因为如果第一个==最后,那么这将是一个问题,这就是你所面临的问题。但是不增加下一个指针也不会造成任何伤害,因为第一个比较会将第一个元素与自身进行比较,而第一个元素将始终被评估为false,而不是与自身进行比较。