2009-03-05 12 views
5

Tengo problemas para compilar el programa de ejemplo presentado en la sección 5.11 del libro. He eliminado la mayor parte del código y solo dejé las cosas relevantes.Compilación de problemas Ejemplo K & R

#define MAXLINES 5000 
char *lineptr[MAXLINES]; 

void qsort1(void *lineptr[], int left, int right, int (*comp)(void *, void *)); 
int numcmp(char *, char *); 

main(int argc, char *argv[]) { 
    int numeric = 1; 
    /* ... */ 
    qsort1((void**) lineptr, 0, 100, (int (*)(void*, void*))(numeric ? numcmp : strcmp)); 
} 

void qsort1(void *v[], int left, int right, int (*comp)(void *, void *)) { 
    /* ... */ 
} 

int numcmp(char *s1, char *s2) { 
    /* ... */ 
} 

El problema es que el código no se compila (estoy usando el compilador Digital Mars). El error que consigo es la siguiente:

 qsort1((void**) lineptr, 0, nlines - 1, (int (*)(void*, void*))(numeric 
? numcmp : strcmp)); 

       ^
go.c(19) : Error: need explicit cast to convert 
from: int (*C func)(char const *,char const *) 
to : int (*C func)(char *,char *) 
--- errorlevel 1 

Debe haber algo mal con las declaraciones aunque me pega el código del libro correctamente. No sé lo suficiente como para hacer los cambios correctos (la sección sobre los punteros a las funciones podría haber sido escrita de forma más extensa).

EDIT: Debería haber mencionado que estoy leyendo la versión ANSI del libro.

+0

son que compilar como un programa C o C++ programa –

+0

que podía imaginar que el viejo código de K & R no sabía const. intente definir su función como int numcmp (char const * s1, char const * s2) {} –

+0

@litb: esto parece haber funcionado. – Ree

Respuesta

8

Creo que el error proviene del hecho de que la C antigua no sabía const aún: strcmp tomó dos punteros a los caracteres no const (char *), creo (que podría ser la razón por la que se compiló en ese momento, pero no con tu compilador). Sin embargo, actualmente strcmp toma char const* (const char* es lo mismo). Cambiar su prototipo de función a esto:

int numcmp(char const*, char const*); 
+0

qsort1() firma necesita cambiar también;) – dirkgently

+0

de hecho, hay muchas cosas de qué preocuparse. debería dar los parámetros de numcmp void *, void * en lugar de puntero a char. pero quería obtener el ejemplo del libro para compilar. No quería cambiar todo el código del ejemplo del libro –

0

Ha pasado un tiempo desde que realicé cualquier programación en C pura, no estoy seguro del nuevo estándar.

Sin embargo, la conversión a vacío ** crea un puntero a un puntero donde la función requiere un puntero a una matriz. Claro, son lo mismo internamente, pero una fuerte comprobación de tipo lo detectará como un error.

reescribe qsort para aceptar ** en lugar de * [] y deberías estar bien.

+0

bueno, él ya acepta **. * foo [] en un prototipo de función le dará el mismo tipo que ** foo :) que no es el error, pero a menudo es confundido por los programadores –

2

El puntero de función estándar esperado por qsort() o bsearch() tiene el prototipo:

int comparator(const void *v1, const void *v2); 

El qsort1() definido en el código de espera:

int comparator(void *v1, void *v2); 

Las funciones de comparación definidos en el código no tienen que prototipo, y no hay conversión automática entre diferentes tipos de punteros de función.

Así, fija para qsort1() son o bien:

  1. introducir un reparto: (int (*)(void *, void *)) o
  2. reescribir la comparadores:

    int numcmp(void *v1, void *v2) 
    { 
        char *s1 = v1; 
        char *s2 = v2; 
        ... 
    } 
    
    int str_cmp(void *v1, void *v2) // Note new function name! 
    { 
        return(strcmp(v1, v2)); 
    } 
    

Obviamente, la llamada a qsort1() haría referencia str_cmp en lugar de strcmp. Los autores trataron de evitar una función intermedia, pero fallaron los compiladores (legítimamente) más complicados en uso hoy en día.

La versión estándar de qsort() requeriría un grupo de calificadores const, como en la primera versión de esta respuesta.

+0

Está usando una función personalizada llamada qsort(). – dirkgently

+0

Bueno, sí: qsort1() para ser pedante pedante. Y ese qsort1() tiene expectativas diferentes; Voy a editar –

2

Eso es un problema común :)

La siguiente línea dice qsort esperar un puntero a una función con dos parámetros void *.Por desgracia, strcmp toma dos cadenas no modificables por lo tanto, es la firma es

int (*comp)(const char*, const char*) 

en lugar de lo que tiene:

int (*comp)(void *, void *) 

cambiar la firma de ambos qsort1 y numeric:

qsort1(void *v[], int left, int right, int (*comp)(const void *, const void *)) 

y :

int numcmp(const char*, const char*) 
+0

La firma de qsort1() que escribió ya es idéntica a la de mi ejemplo. – Ree

+0

Me di cuenta de que aproximadamente un minuto y medio antes que usted;) – dirkgently

1

Tenga en cuenta que strcmp toma dos argumentos const, mientras que su numcmp no. Por lo tanto, los dos tipos de funciones no coinciden, y el operador ? : se quejará.

realice una de:

  1. cambio numcmp para que coincida con el prototipo strcmp en términos de constness
  2. empuje del (int (*)(void*, void*)) fundido en el interior del ? :, por ejemplo,

    numeric ? (int (*)(void*, void*))numcmp : (int (*)(void*, void*))strcmp 
    
Cuestiones relacionadas