你能对数组的一部分进行排序吗?

Can you qsort part of an array?

提问人:Connor 提问时间:4/3/2023 最后编辑:Vlad from MoscowConnor 更新时间:4/4/2023 访问量:159

问:

我想将整数数组中的前 100 个元素保持不变,其余元素保持不变。qsort

我目前正在尝试通过以下调用来执行此操作:

int cmpfunc(const void *a, const void *b)
{
  int xi = *(const int *) a;
  int yi = *(const int *) b;
  
  return (xi - yi);
}

int my_array[100+some_size];
memset(my_array, 0, sizeof(my_array));
qsort(my_array, 100, sizeof(int), cmpfunc);

但是,我遇到了分段错误。是否可以在 C 语言中对数组的第一个值进行排序?x

数组 C 排序 比较 qsort

评论

6赞 Jabberwocky 4/3/2023
请展示一个最小的可重复示例
1赞 motto 4/3/2023
对阵列进行某种连续部分处理是可以的,但是根据大小,您可能会耗尽可用的堆栈大小,从而导致...堆栈溢出 (!),因此出现段错误。之前有很多关于这个问题的讨论some_size
2赞 Jabberwocky 4/3/2023
是的,你可以,你的代码在我看来或多或少没问题,问题出在你没有显示的代码的其他地方。回到第一条评论。
3赞 Jabberwocky 4/3/2023
全部删除并检查是否遇到相同的问题。你的平台到底是什么?qsort
4赞 John Bollinger 4/3/2023
你似乎问了一个XY问题。是的,当然,您可以对较大数组的元素的连续子集进行排序,并且无需为此执行任何特殊操作。但我认为你的主要兴趣是为什么你会得到段错误,这是一个完全不同的问题,我们无法从给出的信息中回答。在这一点上,如果你想让我们解决这个问题,那么你将需要提出一个新的问题,它提供了一个最小的可重现的例子来证明段错误。qsort()

答:

5赞 mkrieger1 4/3/2023 #1

从函数的角度来看,如果在前 100 个之后还有更多数组元素,则没有区别,因为它只获得指向数组开头的指针,以及起始指针之后的元素数。qsort

所以,是的,假设可以对一个有 100 个元素的数组进行排序,也可以对一个较大数组的前 100 个元素进行排序。

评论

0赞 Agent_L 4/3/2023
它更像是 C 数组对指针衰减的属性,而不是 .qsort
3赞 Vlad from Moscow 4/4/2023 #2

您可以对数组的任何部分进行排序,并正确提供指向元素排序范围的初始元素的指针以及该范围中的元素数。

至于您的问题,那么其原因可能是整数溢出,导致您的比较函数产生未定义的行为

int cmpfunc(const void *a, const void *b)
{
  int xi = *(const int *) a;
  int yi = *(const int *) b;
  
  return (xi - yi);
}

在 return 语句中。

这是一个简单的例子。Let's 等于 和 等于 。然后表达式导致整数溢出,例如,它的值可能是负值,而实际上函数将返回一个正数,因为大于 。xiINT_MAXyi-1xi - yixiyi

也就是说,无论如何,比较函数都是错误的。

您应该按以下方式重写比较函数

int cmpfunc(const void *a, const void *b)
{
  int xi = *(const int *) a;
  int yi = *(const int *) b;
  
  return ( yi < xi ) - ( xi < yi );;
}

这是一个演示程序。

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

int cmpfunc(const void *a, const void *b)
{
  int xi = *(const int *) a;
  int yi = *(const int *) b;
  
  return ( yi < xi ) - ( xi < yi );;
}

int main( void ) 
{
    int a[] = { INT_MAX, INT_MAX - 1, INT_MAX - 2, -1, -2, 10, 9, 8, 7, 6 };
    const size_t N = sizeof( a ) / sizeof( *a );

    for ( size_t i = 0; i < N; i++ )
    {
        printf( "%d ", a[i] );
    }
    putchar( '\n' );

    size_t n = N / 2;
    qsort( a, n, sizeof( int ), cmpfunc );

    for ( size_t i = 0; i < n; i++ )
    {
        printf( "%d ", a[i] );
    }
    putchar( '\n' );

    qsort( a + n, N - n, sizeof( int ), cmpfunc );

    for ( size_t i = n; i < N; i++ )
    {
        printf( "%d ", a[i] );
    }
    putchar( '\n' );

    for ( size_t i = 0; i < N; i++ )
    {
        printf( "%d ", a[i] );
    }
    putchar( '\n' );
}

程序输出为

2147483647 2147483646 2147483645 -1 -2 10 9 8 7 6 
-2 -1 2147483645 2147483646 2147483647 
6 7 8 9 10 
-2 -1 2147483645 2147483646 2147483647 6 7 8 9 10 

如果您尝试将比较功能与演示程序一起使用,那么至少您会得到不正确的结果。

例如,使用内联编译器,我得到了以下输出

2147483647 2147483646 2147483645 -1 -2 10 9 8 7 6 
2147483646 2147483647 -2 -1 2147483645 
6 7 8 9 10 
2147483646 2147483647 -2 -1 2147483645 6 7 8 9 10 

如您所见,数组的第一部分排序不正确。