funciones2
Diferencias
Muestra las diferencias entre dos versiones de la página.
Ambos lados, revisión anteriorRevisión previaPróxima revisión | Revisión previa | ||
funciones2 [2013/04/12 21:08] – [Ordenar un arreglo de enteros] lmateu | funciones2 [2014/09/24 21:36] (actual) – [Ejercicios] lmateu | ||
---|---|---|---|
Línea 48: | Línea 48: | ||
=== Primer ejemplo de uso === | === Primer ejemplo de uso === | ||
- | El siguiente programa utiliza la función anterior para ordenar líneas lexicográficamente: | + | El siguiente programa utiliza la función anterior para ordenar líneas lexicográficamente |
< | < | ||
- | #include < | + | % ordenar juan pedro diego |
- | # | + | diego |
+ | juan | ||
+ | pedro | ||
+ | </code> | ||
- | void qsort(void *a[], int left, int right, | + | Esta es la solución usando |
- | int (*compare)(void *, void *)); | + | |
- | | + | < |
+ | int mistrcmp(void *p1, void *p2) { | ||
+ | char *s1= (char*)p1; | ||
+ | char *s2= (char*)p2; | ||
+ | return strcmp(s1, s2); | ||
+ | } | ||
+ | |||
int main(int argc, char **argv) { | int main(int argc, char **argv) { | ||
int j; | int j; | ||
- | int (*compare)(void *, void *)= (int (*)(void *, void*)) strcmp; /* Ver nota */ | ||
- | qsort((void**)argv, | + | qsort((void**)argv, |
for (j= 1; j<argc; ++j) | for (j= 1; j<argc; ++j) | ||
printf(" | printf(" | ||
} | } | ||
+ | </ | ||
+ | |||
+ | === Segundo ejemplo de uso === | ||
+ | |||
+ | Esto no es elegante pero permite usar directamente la función strcmp, sin tener que definir mistrcmp. | ||
+ | |||
+ | < | ||
+ | int (*compare)(void *, void *)= (int (*)(void *, void*)) strcmp; /* Ver nota */ | ||
+ | qsort((void**)argv, | ||
</ | </ | ||
Línea 71: | Línea 88: | ||
para compatibilizar strcmp con el tipo de la variable asignada. | para compatibilizar strcmp con el tipo de la variable asignada. | ||
Si se pasa directamente strcmp a qsort, el compilador podría reclamar conflicto | Si se pasa directamente strcmp a qsort, el compilador podría reclamar conflicto | ||
- | de tipos. | + | de tipos. Este cast es correcto en este caso porque todos los parámetros |
+ | de la función son punteros y sabemos que un cast entre punteros no realiza | ||
+ | ninguna conversión. | ||
+ | no son punteros. | ||
+ | impredescibles: | ||
+ | |||
+ | < | ||
+ | int h(int x, double y); | ||
+ | int (*f)(double x, int k)= (int (*)(double x, int k)) h; | ||
+ | </ | ||
+ | |||
+ | Si no se coloca el cast, el compilador reclama porque no hay concordancia de tipos. | ||
+ | Con el cast, el compilador no reclama, pero al invocar f mediante: | ||
+ | |||
+ | < | ||
+ | int n= (*f)(3.14, 1); | ||
+ | int m= (*f)(3, 1.5); | ||
+ | </ | ||
+ | |||
+ | En ningún caso la función h recibirá algo parecido a los argumentos usados en estas invocaciones. | ||
+ | El error ocurre porque en este caso los argumentos de la función sí requieren conversión de tipo | ||
+ | (entero a real o viceversa), pero debido al cast de funciones el compilador no realizará | ||
+ | ninguna conversión. | ||
- | Otra forma de hacer esto mismo: | + | Otra forma de lograr lo mismo, aunque no es más o menos eficiente, es: |
< | < | ||
Línea 89: | Línea 128: | ||
</ | </ | ||
- | Lo cual es mucho más legible. | + | Lo cual es más legible. |
- | Por último también se puede usar una función de comparación de strings propia que | + | === Tercer |
- | reciba como parámetros punteros a void: | + | |
- | + | ||
- | < | + | |
- | int mistrcmp(void *p1, void *p2) { | + | |
- | char *s1= (char*)p1; | + | |
- | char *s2= (char*)p2; | + | |
- | return strcmp(s1, s2); | + | |
- | } | + | |
- | </ | + | |
- | + | ||
- | Ahora se puede llamar a qsort especificando como comparador mistrcmp sin tener | + | |
- | que aplicar un complicado cast: | + | |
- | + | ||
- | < | + | |
- | qsort((void**)argv, | + | |
- | </ | + | |
- | + | ||
- | === Segundo | + | |
Este ejemplo ordena los strings por valor numérico: | Este ejemplo ordena los strings por valor numérico: | ||
< | < | ||
- | int numcmp(void *s1, void *s2) /* compara | + | int numcmp(void *s1, void *s2) /* compara |
int i1, i2; | int i1, i2; | ||
Línea 183: | Línea 204: | ||
< | < | ||
+ | /* Este programa solo funciona en plataformas de 32 bits, no cuando son de 64 bits */ | ||
int a[6]= {3, 7, 8, 10, 1, 2}; | int a[6]= {3, 7, 8, 10, 1, 2}; | ||
| | ||
Línea 209: | Línea 231: | ||
correctamente en x86, al compilarlos en una arquitectura de 64 bits, ya no funcionan. | correctamente en x86, al compilarlos en una arquitectura de 64 bits, ya no funcionan. | ||
- | Pero en Linux/amd64 se puede hacer que funcione declarando '' | + | === Forma portable === |
+ | |||
+ | La siguiente solución debería funcionar | ||
+ | los enteros | ||
< | < | ||
- | | + | |
| | ||
int longcmp(void *p1, void *p2) { | int longcmp(void *p1, void *p2) { | ||
Línea 227: | Línea 252: | ||
int main() { | int main() { | ||
int i; | int i; | ||
- | qsort((void**)a, 0, 5, longcmp); | + | qsort(a, 0, 5, longcmp); |
for (i= 0; i<6; i++) | for (i= 0; i<6; i++) | ||
- | printf(" | + | printf(" |
return 0; | return 0; | ||
} | } | ||
</ | </ | ||
- | Pero esto no funcionará en Windows de 64 bits, porque en esta plataforma | + | En Windows de 64 bits el tipo long es de 32 bits como |
- | se explica [[http:// | + | se explica [[http:// |
+ | y por lo tanto no coincide con el tamaño de un puntero. | ||
+ | entregue algún warning. | ||
+ | |||
+ | Enfín, el autor de este documento no recomienda escribir este tipo de código, pero sí entenderlo | ||
+ | porque hay abundante código del legado que recurre a este tipo de trucos y por lo tanto es importante | ||
+ | ser capaz de modificarlo si se requieren cambios. | ||
+ | |||
+ | ==== Ejercicios ==== | ||
+ | |||
+ | * Resuelva la pregunta 3 parte i.- del [[http:// | ||
+ | * Resuelva la pregunta 1 del [[http:// | ||
- | |
funciones2.1365800914.txt.gz · Última modificación: 2013/04/12 21:08 por lmateu