Tengo una estructura:

struct pkt_
{
  double x;
  double y;
  double alfa;
  double r_kw;
};

typedef struct pkt_ pkt;

Una tabla de estas estructuras:

pkt *tab_pkt;

tab_pkt = malloc(ilosc_pkt * sizeof(pkt));

Lo que quiero hacer es ordenar tab_pkt por tab_pkt.alfa y tab_pkt.r:

qsort(tab_pkt, ilosc_pkt, sizeof(pkt), porownaj);

Donde porownaj es una función de comparación, pero ¿cómo escribir? Aquí está mi «boceto» de la misma:

int porownaj(const void *pkt_a, const void *pkt_b)
{
  if (pkt_a.alfa > pkt_b.alfa && pkt_a.r_kw > pkt_b.r_kw) return 1;
  if (pkt_a.alfa == pkt_b.alfa && pkt_a.r_kw == pkt_b.r_kw) return 0;
  if (pkt_a.alfa < pkt_b.alfa && pkt_a.r_kw < pkt_b.r_kw) return -1;
}
he añadido el qsort etiqueta, ya que este problema es acerca de la qsort función de predicado. creo que otros ppl utilizando qsort tendrá problemas con él ahora y, a continuación, demasiado.
Por la misma razón, la misma función se puede utilizar con bbusca(); de hecho, generalmente es un error si no se usa la misma función de comparación para ambos qsort() de una matriz y bbusca() de la misma matriz – suponiendo que hacer uso de ambas funciones.

OriginalEl autor diminish | 2008-11-29

3 Comentarios

  1. 12

    Algo como esto debería funcionar:

    int porownaj(const void *p_a, const void *p_b)
    {
      /* Need to store arguments in appropriate type before using */
      const pkt *pkt_a = p_a;
      const pkt *pkt_b = p_b;
    
      /* Return 1 or -1 if alfa members are not equal */
      if (pkt_a->alfa > pkt_b->alfa) return 1;
      if (pkt_a->alfa < pkt_b->alfa) return -1;
    
      /* If alfa members are equal return 1 or -1 if r_kw members not equal */
      if (pkt_a->r_kw > pkt_b->r_kw) return 1;
      if (pkt_a->r_kw < pkt_b->r_kw) return -1;
    
      /* Return 0 if both members are equal in both structures */
      return 0;
    }

    Permanecer lejos de tontos trucos como:

    return pkt_a->r_kw - pkt_b->r_kw;

    que el retorno de la onu-valores normalizados, son confusos para leer, no funcionará correctamente para números de punto flotante, y a veces complicado casos de esquina que no funcionan correctamente, incluso para valores enteros.

    arg. yo sabía void* no necesita un yeso en C cuando se le asigne a algo T* . pero no estaba seguro de si también se aplica a const void* 😀 voy a memorizar que también es posible entonces 🙂
    Yo iba a comentar en favor de la «tonto truco» que usted menciona, pero luego me vino a mis sentidos :b +1
    Sí; he cometido varios errores en mi solución. Me olvidé por completo de que estamos tratando con dobles aquí, no enteros. Un entero resta es mucho más rápido que los tres extra si, que es la razón por la que he usado ese método.
    Yo comparativo de esto hace mucho tiempo y que se encuentran allí era muy poca, si alguna, a diferencia de rendimiento. El principal problema es que el método no manejar de desbordamiento de enteros, es decir, si a-b > INT_MAX el comportamiento no está definido, el método también da la respuesta equivocada en algunos casos extremos.
    Y el rincón de los casos’ no tienen que ser todos de que la extrema. si a > (INT_MAX/2 + 1) y b < -(INT_MAX/2 + 1), entonces (a – b) es una garantía de desbordamiento, y por lo tanto un comportamiento indefinido.

    OriginalEl autor Robert Gamble

  2. 1

    Hay dos partes en el problema – cómo escribir el código, y cómo comparar los tipos de paquetes. Usted debe asegurarse de que siempre devuelven un valor. El código debería ser tal que:

    porownaj(&pkt_a, &pkt_b) == -porownaj(&pkt_b, &pkt_a)

    Su esquema de comparación no se ocupa de casos tales como:

    pkt_a->alfa >  pkt_b->alfa && pkt_a->r_kw <= pkt_b->r_kw
    pkt_a->alfa <  pkt_b->alfa && pkt_a->r_kw >= pkt_b->r_kw
    pkt_a->alfa == pkt_b->alfa && pkt_a->r_kw != pkt_b->r_kw

    Hay un problema más – es apropiado comparar los valores de punto flotante para la exacta igualdad? Eso dependerá de su aplicación.

    Mecánicamente, usted tiene que convertir la const void punteros a const estructura de punteros. Yo uso la conversión explícita – C++ requiere, y yo trato de hacer mi código aceptable para un compilador de C++, incluso cuando es muy C de código.

    int porownaj(const void *vp1, const void *vp2)
    {
         const pkt *pkt_a = (const pkt *)vp1;
         const pkt *pkt_b = (const pkt *)vp2;
    
         if (pkt_a->alfa >  pkt_b->alfa && pkt_a->r_kw >  pkt_b->r_kw) return 1;
         if (pkt_a->alfa == pkt_b->alfa && pkt_a->r_kw == pkt_b->r_kw) return 0;
         if (pkt_a->alfa <  pkt_b->alfa && pkt_a->r_kw <  pkt_b->r_kw) return -1;
         return 0;
     }

    No se trata de los bits que no puedo resolver, ya que no soy parte de la información necesaria. Tenga en cuenta que, en general, multi-dimensional de los objetos (tales como los números complejos, o (x,y) o (x,y,z) coordenadas) simplemente no pueden ser comparados para la mayor o menor que o igual a.

    OriginalEl autor Jonathan Leffler

  3. 0

    Sí, yo soy la clasificación por alfa y r_kw decide si pkt es primero (el primer valor que tendrán un mayor (o menor) alfa y r_kw creo). Que es como yo entiendo el problema, no estoy 100% seguro.

    OriginalEl autor diminish

Dejar respuesta

Please enter your comment!
Please enter your name here