【问题标题】:Handling an error condition in the compare function of std::qsort在 std::qsort 的比较函数中处理错误情况
【发布时间】:2020-12-15 06:31:11
【问题描述】:

我正在尝试为qsort 找出一种方法,以便在比较函数发现元素由于某种原因对排序无效时抛出异常或指示错误情况。

例如,在这个比较函数中,如果some_function的返回值为5,我需要指出我的排序无效的错误条件。

我应该如何修改我的比较功能?

int compare (const void * a, const void * b)
{
  int ret1 = some_func(a);
  int ret2 = some_func(b):
  return ( ret1 - ret2 );
}

我正在处理遗留代码库,因此我无法使用 std::sort,并且由于实现的性质,事先调用 some_func 也可能涉及大量更改,所以我正在寻找了解是否有可能的解决方法。

【问题讨论】:

  • 为什么不预先检查并避免部分排序您的数据结构?
  • qsort 是一个 C 库函数,对 C++ 和异常一无所知。你为什么不使用std::sort,而是尽可能频繁地抛出异常?
  • 顺便说一句。自 C++11 以来,std::sort 必须使用比快速排序更好的算法(在大 O 表示法方面更好)。
  • @Yksisarvinen qsort() 不必使用快速排序
  • @Yksisarvinen N.B.符号就是:符号。你真正指的是最坏情况下的算法复杂性(无论是时间还是内存)。

标签: c++ sorting exception stl qsort


【解决方案1】:

抛出异常可能代价高昂,因此您可能希望返回错误条件。但是,在这种情况下,在 compare 函数中执行任何一种方法都是不必要的昂贵,因为您将对每个元素进行多次检查。相反,您可以调用qsort之前检查错误情况,这样效率更高:

auto ok = std::none_of(/* range */, /* predicate */);

if (ok)
  std::qsort(/* ... */)
else
  // report error

【讨论】:

    【解决方案2】:

    C++ 允许你抛出任何你需要的东西,不仅是异常,还包括其他类型,如果它适合你的目的,你可以做类似抛出 int 之类的事情,并使用 try-catch 块捕获你调用函数的位置。

    对于你需要的,我认为你可以使用 STL 异常库:

    Demostrative example:

    #include <iostream>
    #include <exception>
    
    int count = 0;
    
    int compare(const void *a, const void *b)
    {  
        int ret1 = *(int*)a > *(int*)b;
        
        if (++count == 5) //throws exception when count reaches 5
            throw std::invalid_argument("Argument is not sortable");
        //you could throw count by simply using throw count
    
        return ret1;
    }
    
    int main()
    {
        int x[]{2,1,3,5,6,1,7,2,5,3};
        try
        {
            //will sort until exception is thrown
            qsort(x, sizeof x / sizeof *x, sizeof(int), compare);
        }
        catch (const std::exception& e)
        {
            std::cout << e.what() << std::endl; //print exception in the console
            //handle the exception here
            //if you were to throw count you could cach it with
            //catch (int &e)
        }
    
        //note that the values were sorted until the exception was thrown
        for (int i = 0; i < sizeof x / sizeof *x; i++){
            std::cout << x[i] << " ";
        }
    }
    

    输出:

    Argument is not sortable
    1 2 3 5 6 1 7 2 5 3  
            ^
         sorting 
         stopped 
          here
    

    【讨论】:

    • 无条件地实例化 std::exception 然后像这样通过复制抛出它有点奇怪。为什么不是一个不错的throw std::runtime_error("explanation")
    • @AsteroidsWithWings 好吧,我不能通过引用抛出它,这是标准问题,按值抛出,按引用捕获,但你是对的,你的解决方案会更好,throw std::invalid_argument("explanation"); 会更合适不过。
    猜你喜欢
    • 2021-10-01
    • 1970-01-01
    • 2014-10-10
    • 1970-01-01
    • 2020-03-17
    • 2018-03-26
    • 2015-05-22
    • 1970-01-01
    相关资源
    最近更新 更多