Lógica de programación. Elementos del lenguaje. Estructura de un programa. Entrada y salida. Sentencias de control. Matr...
C/C++ Curso de Programación 4.ª edición Fco. Javier Ceballos Sierra Profesor titular de la Escuela Politécnica Superior Universidad de Alcalá
http://www.fjceballos.es/
C/C++: Curso de programación. 4.ª edición © Fco. Javier Ceballos Sierra © De la edición: RA-MA 2015 MARCAS COMERCIALES: las marcas de los productos citados en el contenido de este libro (sean o no marcas registradas) pertenecen a sus respectivos propietarios. RA-MA no está asociada a ningún producto o fabricante mencionado en la obra, los datos y los ejemplos utilizados son ficticios salvo que se indique lo contrario. RA-MA es una marca comercial registrada. Se ha puesto el máximo empeño en ofrecer al lector una información completa y precisa. Sin embargo, RA-MA Editorial no asume ninguna responsabilidad derivada de su uso, ni tampoco por cualquier violación de patentes ni otros derechos de terceras partes que pudieran ocurrir. Esta publicación tiene por objeto proporcionar unos conocimientos precisos y acreditados sobre el tema tratado. Su venta no supone para el editor ninguna forma de asistencia legal, administrativa ni de ningún otro tipo. En caso de precisarse asesoría legal u otra forma de ayuda experta, deben buscarse los servicios de un profesional competente. Reservados todos los derechos de publicación en cualquier idioma. Según lo dispuesto en el Código Penal vigente, ninguna parte de este libro puede ser reproducida, grabada en sistema de almacenamiento o transmitida en forma alguna ni por cualquier procedimiento, ya sea electrónico, mecánico, reprográfico, magnético o cualquier otro, sin autorización previa y por escrito de RA-MA; su contenido está protegido por la ley vigente, que establece penas de prisión y/o multas a quienes intencionadamente reprodujeren o plagiaren, en todo o en parte, una obra literaria, artística o científica. Editado por: RA-MA Editorial C/ Jarama, 3A, Polígono industrial Igarsa 28860 Paracuellos del Jarama, Madrid Teléfono: 91 658 42 80 Telefax: 91 662 81 39 Correo electrónico:
[email protected] Internet: www.ra-ma.es y www.ra-ma.com ISBN: 978-84-9964-527-8 Depósito Legal: M-2512-2015 Autoedición: Fco. Javier Ceballos Filmación e impresión: Copias Centro, S.L. Impreso en España Primera impresión: marzo 2015
La mente es como un paracaídas. Solo funciona si la tenemos abierta. Einstein Dedico esta obra a María del Carmen, mi esposa, y a mis hijos Francisco y Javier.
CONTENIDO PRÓLOGO.............................................................................................................. XIX CAPÍTULO 1. FASES EN EL DESARROLLO DE UN PROGRAMA ............
1
QUÉ ES UN PROGRAMA................................................................................. LENGUAJES DE PROGRAMACIÓN............................................................... Compiladores ................................................................................................. Intérpretes....................................................................................................... ¿QUÉ ES C? ........................................................................................................ HISTORIA DEL LENGUAJE C ........................................................................ Lenguaje C++................................................................................................. REALIZACIÓN DE UN PROGRAMA EN C ................................................... Edición de un programa ................................................................................. ¿Qué hace este programa?......................................................................... Guardar el programa escrito en el disco ......................................................... Compilar y ejecutar el programa .................................................................... Biblioteca de funciones ............................................................................. Guardar el programa ejecutable en el disco ................................................... Depurar un programa ..................................................................................... UN AVANCE SOBRE LA PROGRAMACIÓN CON C ................................... Entrada y salida .............................................................................................. Matrices .......................................................................................................... Sentencias de control ..................................................................................... Funciones ....................................................................................................... EJERCICIOS RESUELTOS ............................................................................... EJERCICIOS PROPUESTOS.............................................................................
1 2 4 4 4 5 6 7 8 9 10 10 11 12 13 13 14 15 16 18 19 21
VIII
C/C++: CURSO DE PROGRAMACIÓN
CAPÍTULO 2. ELEMENTOS DEL LENGUAJE C ...........................................
23
PRESENTACIÓN DE LA SINTAXIS DE C ..................................................... CARACTERES DE C ......................................................................................... Letras, dígitos y carácter de subrayado .......................................................... Espacios en blanco ......................................................................................... Caracteres especiales y signos de puntuación ................................................ Secuencias de escape...................................................................................... TIPOS DE DATOS ............................................................................................. Tipos primitivos ............................................................................................. char............................................................................................................ short .......................................................................................................... int .............................................................................................................. long ........................................................................................................... enum.......................................................................................................... Creación de una enumeración .............................................................. float ........................................................................................................... double........................................................................................................ Ejemplo: tipos de datos .................................................................................. Tipos derivados .............................................................................................. SINÓNIMOS DE UN TIPO ................................................................................ LITERALES ....................................................................................................... Literales enteros ............................................................................................. Literales reales ............................................................................................... Literales de un solo carácter ........................................................................... Literales de cadenas de caracteres .................................................................. IDENTIFICADORES ......................................................................................... PALABRAS CLAVE .......................................................................................... COMENTARIOS ................................................................................................ DECLARACIÓN DE CONSTANTES SIMBÓLICAS ...................................... Constantes C++ .............................................................................................. ¿Por qué utilizar constantes? .......................................................................... DECLARACIÓN DE UNA VARIABLE ........................................................... Iniciación de una variable .............................................................................. EXPRESIONES NUMÉRICAS .......................................................................... OPERADORES................................................................................................... Operadores aritméticos................................................................................... Operadores de relación................................................................................... Operadores lógicos ......................................................................................... Operadores unitarios ...................................................................................... Operadores a nivel de bits .............................................................................. Operadores de asignación .............................................................................. Operador condicional .....................................................................................
23 24 24 24 25 25 26 26 27 28 28 28 29 29 31 32 32 33 33 35 35 36 36 37 38 38 39 39 40 40 40 41 42 42 42 44 45 46 46 47 49
CONTENIDO
IX
Otros operadores ............................................................................................ Operador sizeof ......................................................................................... Operador coma .......................................................................................... Operador dirección-de .............................................................................. Operador de indirección ............................................................................ PRIORIDAD Y ORDEN DE EVALUACIÓN ................................................... CONVERSIÓN ENTRE TIPOS DE DATOS..................................................... EJERCICIOS RESUELTOS ............................................................................... EJERCICIOS PROPUESTOS.............................................................................
50 50 51 51 52 53 54 58 60
CAPÍTULO 3. ESTRUCTURA DE UN PROGRAMA...........................................
63
ESTRUCTURA DE UN PROGRAMA C .......................................................... Directrices para el preprocesador ................................................................... Directriz de inclusión ................................................................................ Directriz de sustitución ............................................................................. Definiciones y declaraciones.......................................................................... Sentencia simple ............................................................................................ Sentencia compuesta o bloque ....................................................................... Funciones ....................................................................................................... Declaración de una función ...................................................................... Definición de una función ......................................................................... Llamada a una función .............................................................................. Función main.................................................................................................. Un ejemplo ..................................................................................................... PASANDO ARGUMENTOS A LAS FUNCIONES.......................................... PROGRAMA C FORMADO POR MÚLTIPLES FICHEROS .......................... ÁMBITO DE UNA VARIABLE ........................................................................ Variables globales y locales ........................................................................... CLASES DE ALMACENAMIENTO DE UNA VARIABLE............................ Calificación de variables globales .................................................................. Calificación de variables locales .................................................................... Calificación de funciones ............................................................................... EJERCICIOS RESUELTOS ............................................................................... EJERCICIOS PROPUESTOS.............................................................................
63 67 68 68 69 69 70 70 71 73 75 75 76 77 81 83 84 86 86 88 90 90 93
CAPÍTULO 4. ENTRADA Y SALIDA ESTÁNDAR .........................................
99
DATOS NUMÉRICOS Y CADENAS DE CARACTERES .............................. FLUJOS DE E/S ESTÁNDAR ........................................................................... SALIDA CON FORMATO ................................................................................ ENTRADA CON FORMATO ............................................................................
100 101 102 108
X
C/C++: CURSO DE PROGRAMACIÓN
CARÁCTER FIN DE FICHERO ........................................................................ CARÁCTER \n ................................................................................................... Limpiar el buffer de la entrada estándar......................................................... LEER UN CARÁCTER DE LA ENTRADA ESTÁNDAR ............................... ESCRIBIR UN CARÁCTER EN LA SALIDA ESTÁNDAR ........................... FUNCIONES getch y getche .............................................................................. LEER UNA CADENA DE CARACTERES ...................................................... VALIDAR UN DATO DE ENTRADA .............................................................. REUTILIZAR CÓDIGO ..................................................................................... LIMPIAR LA PANTALLA ................................................................................ EJERCICIOS RESUELTOS ............................................................................... EJERCICIOS PROPUESTOS.............................................................................
114 115 117 118 119 120 121 124 126 128 128 133
CAPÍTULO 5. SENTENCIAS DE CONTROL ................................................... 139 SENTENCIA if ................................................................................................... ANIDAMIENTO DE SENTENCIAS if ............................................................. ESTRUCTURA else if ........................................................................................ SENTENCIA switch ........................................................................................... SENTENCIA while ............................................................................................. Bucles anidados.............................................................................................. SENTENCIA do ... while .................................................................................... SENTENCIA for ................................................................................................. SENTENCIA break ............................................................................................. SENTENCIA continue ........................................................................................ SENTENCIA goto .............................................................................................. EJERCICIOS RESUELTOS ............................................................................... EJERCICIOS PROPUESTOS.............................................................................
139 141 144 147 151 154 157 160 163 164 164 165 180
CAPÍTULO 6. TIPOS ESTRUCTURADOS DE DATOS .................................. 187 INTRODUCCIÓN A LAS MATRICES ............................................................. MATRICES NUMÉRICAS UNIDIMENSIONALES ........................................ Definir una matriz .......................................................................................... Acceder a los elementos de una matriz .......................................................... Trabajar con matrices unidimensionales ........................................................ Iniciar una matriz ........................................................................................... Matrices asociativas ....................................................................................... CADENAS DE CARACTERES ......................................................................... Leer y escribir una cadena de caracteres ........................................................ Funciones gets y fgets ............................................................................... Función puts ..............................................................................................
188 189 189 190 191 195 196 200 201 201 203
CONTENIDO
Trabajar con cadenas de caracteres ................................................................ Funciones de la biblioteca de C ..................................................................... TIPO Y TAMAÑO DE UNA MATRIZ ............................................................. MATRICES MULTIDIMENSIONALES ........................................................... Matrices numéricas multidimensionales ........................................................ Matrices de cadenas de caracteres .................................................................. COPIAR MATRICES ......................................................................................... TRABAJAR CON BLOQUES DE BYTES ....................................................... ESTRUCTURAS ................................................................................................ Crear una estructura ....................................................................................... Definir variables de un tipo de estructura ...................................................... Acceso a los miembros de una estructura ...................................................... Miembros que son estructuras ........................................................................ Operaciones con estructuras ........................................................................... Matrices de estructuras ................................................................................... UNIONES ........................................................................................................... Estructuras variables ...................................................................................... CAMPOS DE BITS ............................................................................................ EJERCICIOS RESUELTOS ............................................................................... EJERCICIOS PROPUESTOS.............................................................................
XI
206 207 208 209 209 214 218 220 221 221 222 224 225 226 231 234 237 242 246 259
CAPÍTULO 7. PUNTEROS .................................................................................. 267 CREACIÓN DE PUNTEROS ............................................................................ Operadores ..................................................................................................... Importancia del tipo del objeto al que se apunta ............................................ OPERACIONES CON PUNTEROS .................................................................. Operación de asignación ................................................................................ Operaciones aritméticas ................................................................................. Comparación de punteros............................................................................... Punteros genéricos ......................................................................................... Puntero nulo ................................................................................................... Punteros constantes ........................................................................................ PUNTEROS Y MATRICES ............................................................................... Punteros a cadenas de caracteres.................................................................... MATRICES DE PUNTEROS ............................................................................. Punteros a punteros ........................................................................................ Matriz de punteros a cadenas de caracteres ................................................... Ordenar matrices de cadenas de caracteres .................................................... ASIGNACIÓN DINÁMICA DE MEMORIA .................................................... Funciones para administrar dinámicamente la memoria .................................. malloc........................................................................................................
267 269 270 271 271 272 274 274 276 277 277 282 286 288 291 295 299 299 299
XII
C/C++: CURSO DE PROGRAMACIÓN
free ............................................................................................................ Reasignar un bloque de memoria ................................................................... MATRICES DINÁMICAS ................................................................................. Matrices dinámicas numéricas ....................................................................... Matrices dinámicas de una dimensión ...................................................... Matrices dinámicas de dos dimensiones ................................................... Matrices dinámicas de cadenas de caracteres................................................. PUNTEROS A ESTRUCTURAS ....................................................................... PUNTEROS COMO PARÁMETROS EN FUNCIONES .................................. DECLARACIONES COMPLEJAS .................................................................... EJERCICIOS RESUELTOS ............................................................................... EJERCICIOS PROPUESTOS.............................................................................
301 302 304 305 305 309 313 317 320 326 327 337
CAPÍTULO 8. MÁS SOBRE FUNCIONES ........................................................ 347 PASAR UNA MATRIZ COMO ARGUMENTO A UNA FUNCIÓN ..................... Matrices estáticas ........................................................................................... Matrices dinámicas......................................................................................... PASAR UN PUNTERO COMO ARGUMENTO A UNA FUNCIÓN ...................... PASAR UNA ESTRUCTURA A UNA FUNCIÓN ........................................... DATOS RETORNADOS POR UNA FUNCIÓN ............................................... Retornar una copia de los datos ..................................................................... Retornar un puntero al bloque de datos.......................................................... Retornar la dirección de una variable declarada static ................................... ARGUMENTOS EN LA LÍNEA DE ÓRDENES .............................................. REDIRECCIÓN DE LA ENTRADA Y DE LA SALIDA ................................. FUNCIONES RECURSIVAS............................................................................. PUNTEROS A FUNCIONES ............................................................................. EJERCICIOS RESUELTOS ............................................................................... EJERCICIOS PROPUESTOS.............................................................................
347 348 350 352 354 358 359 360 361 363 365 367 369 376 392
CAPÍTULO 9. TRABAJAR CON FICHEROS................................................... 401 VISIÓN GENERAL DE LOS FLUJOS DE E/S................................................. VISIÓN GENERAL DE UN FICHERO............................................................. ABRIR UN FICHERO ........................................................................................ fopen .............................................................................................................. freopen ........................................................................................................... CERRAR UN FICHERO .................................................................................... fclose .............................................................................................................. MANIPULACIÓN DE ERRORES ..................................................................... ferror ..............................................................................................................
403 405 409 409 411 412 412 413 413
CONTENIDO
XIII
clearerr ........................................................................................................... feof ................................................................................................................. perror .............................................................................................................. POSICIÓN DEL PUNTERO DE L/E ................................................................. ftell ................................................................................................................. fseek ............................................................................................................... rewind ............................................................................................................ E/S CARÁCTER A CARÁCTER....................................................................... fputc ............................................................................................................... fgetc................................................................................................................ E/S DE CADENAS DE CARACTERES ............................................................ fputs................................................................................................................ fgets ................................................................................................................ ENTRADA/SALIDA CON FORMATO ............................................................ fprintf ............................................................................................................. fscanf .............................................................................................................. E/S UTILIZANDO REGISTROS ....................................................................... fwrite .............................................................................................................. fread ............................................................................................................... ABRIENDO FICHEROS PARA ACCESO SECUENCIAL .............................. Un ejemplo de acceso secuencial ................................................................... ESCRIBIR DATOS EN UNA IMPRESORA ..................................................... Escribir en una impresora USB ...................................................................... CONTROL DEL BUFFER ASOCIADO CON UN FLUJO............................... setvbuf ............................................................................................................ fflush .............................................................................................................. FICHEROS TEMPORALES .............................................................................. tmpfile ............................................................................................................ ABRIENDO FICHEROS PARA ACCESO ALEATORIO ................................ EJERCICIOS RESUELTOS ............................................................................... EJERCICIOS PROPUESTOS.............................................................................
413 414 415 417 417 417 418 418 419 420 422 422 423 425 425 426 427 428 428 429 430 434 436 437 438 441 441 441 441 445 464
CAPÍTULO 10. EL PREPROCESADOR DE C ................................................. 471 DIRECTRIZ #define ........................................................................................... Macros predefinidas ....................................................................................... El operador # .................................................................................................. El operador ## ................................................................................................ DIRECTRIZ #undef ............................................................................................ DIRECTRIZ #include ......................................................................................... COMPILACIÓN CONDICIONAL .................................................................... Operador defined............................................................................................
472 475 476 476 476 477 477 479
XIV
C/C++: CURSO DE PROGRAMACIÓN
CONSTANTE DEFINIDA EN LA ORDEN DE COMPILACIÓN ................... DIRECTRICES #ifdef e #ifndef ......................................................................... DIRECTRIZ #line ............................................................................................... DIRECTRIZ #error ............................................................................................. UTILIZACIÓN DE FICHEROS DE CABECERA ............................................ EJERCICIOS RESUELTOS ............................................................................... EJERCICIOS PROPUESTOS.............................................................................
479 482 482 483 483 486 488
CAPÍTULO 11. ESTRUCTURAS DINÁMICAS ................................................ 495 LISTAS LINEALES ........................................................................................... Listas lineales simplemente enlazadas ........................................................... Operaciones básicas ....................................................................................... Inserción de un elemento al comienzo de la lista ...................................... Buscar en una lista un elemento con un valor x ........................................ Inserción de un elemento en general ......................................................... Borrar un elemento de la lista ................................................................... Recorrer una lista ...................................................................................... Borrar todos los elementos de una lista .................................................... UN EJEMPLO CON LISTAS LINEALES......................................................... Interfaz genérica para listas lineales............................................................... LISTAS CIRCULARES ..................................................................................... Interfaz para manipular una lcse .................................................................... PILAS.................................................................................................................. COLAS ................................................................................................................ Ejemplo .......................................................................................................... LISTA DOBLEMENTE ENLAZADA ............................................................... Lista circular doblemente enlazada ................................................................ Interfaz para manipular una lcde ............................................................... Ejemplo ..................................................................................................... ÁRBOLES........................................................................................................... Árboles binarios ............................................................................................. Formas de recorrer un árbol binario ............................................................... ÁRBOLES BINARIOS DE BÚSQUEDA .......................................................... Interfaz para manipular un árbol binario de búsqueda ................................... Buscar un nodo en el árbol ............................................................................. Insertar un nodo en el árbol............................................................................ Borrar un nodo del árbol ................................................................................ Utilización de la interfaz abb ......................................................................... ÁRBOLES BINARIOS PERFECTAMENTE EQUILIBRADOS ...................... Interfaz para manipular un árbol perfectamente equilibrado ......................... Utilización de la interfaz abe..........................................................................
496 496 500 501 502 502 503 504 504 505 509 520 522 527 528 530 533 533 534 540 542 543 544 546 547 550 550 552 554 558 559 564
CONTENIDO
XV
EJERCICIOS RESUELTOS ............................................................................... 567 EJERCICIOS PROPUESTOS............................................................................. 582 CAPÍTULO 12. ALGORITMOS DE USO COMÚN .......................................... 591 RECURSIVIDAD ............................................................................................... ORDENACIÓN DE DATOS .............................................................................. Método de la burbuja ..................................................................................... Método de inserción ....................................................................................... Método quicksort ........................................................................................... Comparación de los métodos expuestos......................................................... BÚSQUEDA DE DATOS .................................................................................. Búsqueda secuencial ...................................................................................... Búsqueda binaria ............................................................................................ Búsqueda de cadenas ..................................................................................... ORDENACIÓN DE FICHEROS EN DISCO..................................................... Ordenación de ficheros. Acceso secuencial ................................................... Ordenación de ficheros. Acceso aleatorio ...................................................... ALGORITMOS HASH ....................................................................................... Matrices hash ................................................................................................. Método hash abierto ....................................................................................... Método hash con desbordamiento .................................................................. Eliminación de elementos .............................................................................. Interfaz hash abierto ....................................................................................... Un ejemplo de una matriz hash ...................................................................... EJERCICIOS RESUELTOS ............................................................................... EJERCICIOS PROPUESTOS.............................................................................
591 597 598 600 602 605 605 606 606 607 610 611 616 619 619 621 622 623 623 627 629 633
A. ALGUNAS FUNCIONES DE LA BIBLIOTECA DE C................................ 639 FUNCIONES DE CADENAS Y DE CARACTERES ....................................... strcat ............................................................................................................... strcpy .............................................................................................................. strchr .............................................................................................................. strrchr ............................................................................................................. strcmp ............................................................................................................. strcspn ............................................................................................................ strlen ............................................................................................................... strncat ............................................................................................................. strncpy ............................................................................................................ strncmp ........................................................................................................... strspn ..............................................................................................................
639 639 640 640 640 642 643 644 644 645 645 645
XVI
C/C++: CURSO DE PROGRAMACIÓN
strstr................................................................................................................ strtok .............................................................................................................. strlwr .............................................................................................................. strupr .............................................................................................................. Funciones para conversión de datos ............................................................... atof ................................................................................................................. atoi.................................................................................................................. atol.................................................................................................................. sprintf ............................................................................................................. Funciones de caracteres.................................................................................. toascii ............................................................................................................. tolower ........................................................................................................... toupper ........................................................................................................... FUNCIONES MATEMÁTICAS ........................................................................ acos ................................................................................................................ asin ................................................................................................................. atan ................................................................................................................. atan2 ............................................................................................................... cos .................................................................................................................. sin ................................................................................................................... tan ................................................................................................................... cosh ................................................................................................................ sinh ................................................................................................................. tanh ................................................................................................................. exp .................................................................................................................. log .................................................................................................................. log10 .............................................................................................................. ceil .................................................................................................................. fabs ................................................................................................................. floor ................................................................................................................ pow ................................................................................................................. sqrt.................................................................................................................. NÚMEROS SEUDOALEATORIOS .................................................................. rand ................................................................................................................ srand ............................................................................................................... FUNCIONES DE FECHA Y HORA .................................................................. clock ............................................................................................................... time................................................................................................................. ctime ............................................................................................................... localtime ......................................................................................................... FUNCIONES PARA MANIPULAR BLOQUES DE MEMORIA .................... memset ........................................................................................................... memcpy ..........................................................................................................
645 646 647 647 647 648 648 648 649 650 650 650 650 651 652 652 652 652 653 653 653 653 653 654 654 654 654 654 655 655 655 655 656 656 656 656 656 657 657 658 659 659 659
CONTENIDO
XVII
memcmp ......................................................................................................... 660 B. ENTORNOS DE DESARROLLO.................................................................... 661 MICROSOFT VISUAL STUDIO ....................................................................... Añadir ficheros existentes a un proyecto ....................................................... Depurar la aplicación ..................................................................................... INTERFAZ DE LÍNEA DE ÓRDENES EN WINDOWS.................................. CREAR UNA BIBLIOTECA DE FUNCIONES................................................ NETBEANS ........................................................................................................ Depurar una aplicación con NetBeans ........................................................... INTERFAZ DE LÍNEA DE ÓRDENES EN UNIX/LINUX .............................. El depurador gdb de Unix/Linux ................................................................... CODE::BLOCKS ................................................................................................
661 666 666 668 669 672 676 678 679 680
C. CÓDIGOS DE CARACTERES ....................................................................... 685 UTILIZACIÓN DE CARACTERES ANSI CON WINDOWS .......................... JUEGO DE CARACTERES ANSI ..................................................................... UTILIZACIÓN DE CARACTERES ASCII ....................................................... JUEGO DE CARACTERES ASCII.................................................................... JUEGO DE CARACTERES UNICODE ............................................................
685 686 687 688 689
ÍNDICE ................................................................................................................... 691
PRÓLOGO Aprender C nunca ha sido fácil. Por eso el autor, apoyándose en su experiencia docente, ha puesto todo su empeño en escribir un libro fácil de leer, progresivo en el aprendizaje y con muchos ejemplos que aclaren lo expuesto.
Para quién es este libro Este libro está pensado para aquellas personas que quieran aprender a escribir programas, utilizando el lenguaje C, siguiendo una metodología fundamentada en técnicas de desarrollo que conducen a realizar una programación estructurada. Para ello, ¿qué debe hacer el lector? Pues simplemente leer ordenadamente los capítulos del libro, resolviendo cada uno de los ejemplos que en ellos se detallan. Es evidente que el lenguaje C ha ido evolucionando a lo largo de su historia. Producto de esta evolución fue el lenguaje C++ y, finalmente, el diseño de una amplia biblioteca de funciones para el desarrollo de aplicaciones con interfaz gráfica (programación visual). De ahí que este libro sea el primero de una colección de tres libros orientados al desarrollo de aplicaciones con C/C++. Entre los tres, y en el orden comentado a continuación, cubren los siguientes aspectos: programación estructurada con C y programación orientada a objetos con C++. Este es el primero, C/C++: Curso de programación. Abarca todo lo relativo a la programación estructurada con C. También incluye diversos algoritmos de uso común así como desarrollos con estructuras dinámicas de datos. ¿Por qué el título C/C++? Porque C++ fue desarrollado a partir del lenguaje de programación C y con pocas excepciones incluye a C. Esta parte de C incluida en C++ es conocida como C–, y podría compilarse bajo C++ sin problemas. No obstante, cuando C++ se utiliza para lo que fue pensado, para realizar una programación orientada a objetos, los conocimientos nuevos que hay que adquirir son cuantiosos.
XX
C/C++: CURSO DE PROGRAMACIÓN
El segundo, Programación orientada a objetos con C++, estudia, como su nombre indica, el desarrollo de aplicaciones orientadas a objetos. Esta tecnología es imprescindible conocerla si su propósito es llegar a desarrollar aplicaciones vistosas como lo son las aplicaciones a base de ventanas, más bien conocidas como aplicaciones para Windows. Y el tercero, Enciclopedia de C++, incluye a los dos anteriores, pero con un nuevo enfoque, ya que a lo largo de todos los capítulos del libro solo se utiliza la biblioteca de C++. Por el contrario, si lo que usted persigue es profundizar en aplicaciones C incluyendo llamadas al sistema UNIX, entonces le recomiendo el libro de Francisco Manuel Márquez titulado UNIX, Programación Avanzada, publicado también por la editorial RA-MA.
Cómo está organizado el libro El libro se ha dividido en doce capítulos que van presentando el lenguaje poco a poco, empezando por lo más sencillo, viendo cada tema a su tiempo, hasta llegar al final donde se habrá visto todo lo referente a la programación con el lenguaje C, sin apenas encontrar dificultades. Se completa el estudio de C con un capítulo referente a estructuras dinámicas y otro de algoritmos de uso común. El lector podrá comprobar al final de esta obra que el nivel de conocimientos que ha adquirido es elevado. El primer capítulo introduce al lector en el mundo de la programación C. El segundo capítulo presenta de una sola vez todos los elementos del lenguaje que el lector utilizará constantemente en el resto de los capítulos; por eso, debe simplemente leerse fijándose en los ejemplos y, por el momento, no preocuparse de más; posteriormente se podrá retornar a él todas las veces que sean necesarias. El tercer capítulo presenta la estructura general de un programa C con un ejemplo; el lector debe también leerlo con un objetivo: asimilar cómo es la estructura de un programa C y cuál es su secuencia de ejecución, sin tratar de aprender en este instante todos los conceptos que ahí se exponen. Leídos estos tres capítulos, el lector tendrá claro el escenario donde se va a mover. A partir del capítulo 4 empezará a aprender a programar; por lo tanto, el lector debe tener un poco de paciencia hasta que se inicie en este capítulo. Este libro posee varias características dignas de resaltar. Es breve en teoría y abundante en ejemplos (más de 250 ejercicios resueltos), lo que le hará aún más fácil el aprendizaje.
PRÓLOGO XXI
Estos capítulos y apéndices que componen la materia total de C/C++: Curso de programación se resumen así: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. A. B. C.
Fases en el desarrollo de un programa. Elementos del lenguaje C. Estructura de un programa. Entrada y salida estándar. Sentencias de control. Tipos estructurados de datos. Punteros. Más sobre funciones. Trabajar con ficheros. El preprocesador de C. Estructuras dinámicas. Algoritmos de uso común. Algunas funciones de la biblioteca de C. Entornos de desarrollo. Códigos de caracteres.
Todo esto se ha documentado con abundantes ejemplos, ejercicios resueltos y ejercicios propuestos, de los cuales también se da su solución en un ZIP, muchos de ellos válidos como parte integrante en el desarrollo de aplicaciones.
Agradecimientos He recibido ideas y sugerencias de algunas personas durante la preparación de este libro, entre las que se encuentran, cómo no, mis alumnos, que con su interés por aprender me hacen reflexionar sobre objetivos que a primera vista parecen inalcanzables, pero que una vez logrados sirven para que todos aprendamos; a todos ellos les estoy francamente agradecido. En especial, quiero expresar mi agradecimiento a Martín Knoblauch Revuelta, por sus buenas recomendaciones y aportaciones para esta nueva edición, y a Inmaculada Rodríguez Santiago, por sus consejos en las versiones anteriores, así como a Alfredo Gallego Gandarillas y a Francisco Manuel Márquez García, por su participación en la corrección de las versiones anteriores, y a David Jurado González, porque aportó una solución para la mayoría de los ejercicios propuestos. Francisco Javier Ceballos Sierra http://www.fjceballos.es/
APÉNDICE A F.J.Ceballos/RAMA
ALGUNAS FUNCIONES DE LA BIBLIOTECA DE C Además de las funciones expuestas a lo largo de esta obra, hay otras muchas. Este apéndice muestra algunas de las funciones más útiles de la biblioteca de C que aún no han sido expuestas. Todas estas funciones se pueden agrupar en las siguientes categorías:
Funciones de E/S. Funciones de cadenas y de caracteres. Funciones matemáticas. Funciones de fecha y hora. Funciones de asignación dinámica. Otras funciones.
FUNCIONES DE CADENAS Y DE CARACTERES La biblioteca de C proporciona un amplio número de funciones que permiten realizar diversas operaciones con cadenas de caracteres, como copiar una cadena en otra, añadir una cadena a otra, etc. A continuación se describen las más utilizadas.
strcat #include char *strcat( char *cadena1, const char *cadena2 ); Compatibilidad: ANSI, UNIX y Windows
640
C/C++: CURSO DE PROGRAMACIÓN
La función strcat añade la cadena2 a la cadena1, finaliza la cadena resultante con el carácter nulo y devuelve un puntero a cadena1.
strcpy #include char *strcpy( char *cadena1, const char *cadena2 ); Compatibilidad: ANSI, UNIX y Windows
La función strcpy copia la cadena2, incluyendo el carácter de terminación nulo, en la cadena1 y devuelve un puntero a cadena1. /* Este programa utiliza strcpy y strcat * strcpy.c */ #include #include main(void) { char cadena[81]; strcpy( cadena, "Hola, " ); strcat( cadena, "strcpy " ); strcat( cadena, "y " ); strcat( cadena, "strcat te saludan!" ); printf( "cadena = %s\n", cadena ); } Ejecución del programa: cadena = Hola, strcpy y strcat te saludan!
strchr #include char *strchr( const char *cadena, int c ); Compatibilidad: ANSI, UNIX y Windows
La función strchr devuelve un puntero a la primera ocurrencia de c en cadena o un valor NULL si el carácter no es encontrado. El carácter c puede ser el carácter nulo (‘\0’).
strrchr #include char *strrchr( const char *cadena, int c ); Compatibilidad: ANSI, UNIX y Windows
APÉNDICE A: ALGUNAS FUNCIONES DE LA BIBLIOTECA DE C
641
La función strrchr devuelve un puntero a la última ocurrencia de c en cadena o un valor NULL si el carácter no se encuentra. El carácter c puede ser un carácter nulo (‘\0’). /* Este programa ilustra cómo buscar un carácter con strchr * (hacia delante) o con strrchr (hacia atrás). /* strchr.c */ #include #include main( void ) { int car = 'i'; char cadena[] = "La biblioteca de C proporciona muchas funciones"; char dec1[] = " 1 2 3 4 5"; char uni2[] = "12345678901234567890123456789012345678901234567890"; char *pdest; int resu; printf( "Cadena en la que se busca: \n%s\n", cadena ); printf( "%s\n%s\n\n", dec1, uni2 ); printf( "Buscar el carácter: %c\n\n", car ); // Buscar de adelante hacia atrás pdest = strchr( cadena, car ); resu = pdest - cadena; if ( pdest != NULL ) printf( "La %c primera está en la posición %d\n", car, resu ); else printf( "%c no se encuentra en la cadena\n" ); // Buscar desde atrás hacia delante pdest = strrchr( cadena, car ); resu = pdest - cadena; if ( pdest != NULL ) printf( "La última %c está en la posición %d\n\n", car, resu ); else printf( "%c no se encuentra en la cadena\n" ); } Ejecución del programa: Cadena en la que se busca: La biblioteca de C proporciona muchas funciones 1 2 3 4 01234567890123456789012345678901234567890123456789 Buscar el carácter: i La i primera está en la posición 4 La última i está en la posición 42
642
C/C++: CURSO DE PROGRAMACIÓN
Sabemos que los elementos de una matriz de caracteres, igual que los de cualquier otra matriz, ocupan posiciones sucesivas en memoria. También sabemos que el nombre de una matriz es la dirección de comienzo de la matriz y coincide con la dirección del primer carácter. Así mismo, observe que el valor retornado por strchr y strrchr está definido como un puntero a un char; esto es, una dirección que hace referencia al lugar donde está almacenado el carácter que se busca. cadena
pdest L
a
b
i
b
...
u
n
c
i
o
n
e
s
\0
Por lo tanto, una sentencia como: resu = pdest - cadena;
da como resultado la posición 0, 1, 2,... del carácter buscado dentro de la cadena, que es lo que hace el programa planteado.
strcmp #include int strcmp( const char *cadena1, const char *cadena2 ); Compatibilidad: ANSI, UNIX y Windows
La función strcmp compara la cadena1 con la cadena2 lexicográficamente y devuelve un valor: 0 si la cadena1 es mayor que la cadena2. En otras palabras, la función strcmp nos permite saber si una cadena está en orden alfabético antes (es menor) o después (es mayor) que otra y el proceso que sigue es el mismo que nosotros ejercitamos cuando lo hacemos mentalmente: comparar las cadenas carácter a carácter. La función strcmp diferencia las letras mayúsculas de las minúsculas. Las mayúsculas están antes por orden alfabético. Esto es así porque en la tabla ASCII las mayúsculas tienen asociado un valor entero menor que las minúsculas. /* strcmp.c */ #include #include
APÉNDICE A: ALGUNAS FUNCIONES DE LA BIBLIOTECA DE C
643
main(void) { char cadena1[] = "La Comunidad de Cantabria es muy bonita"; char cadena2[] = "La Comunidad de CANTABRIA es muy bonita"; char temp[20]; int resu; // Se diferencian mayúsculas de minúsculas printf( "Comparar las cadenas:\n\n%s\n%s\n\n", cadena1, cadena2 ); resu = strcmp( cadena1, cadena2 ); if ( resu > 0 ) strcpy( temp, "mayor que" ); else if ( resu < 0 ) strcpy( temp, "menor que" ); else strcpy( temp, "igual a" ); printf( "strcmp: cadena 1 es %s cadena 2\n", temp ); } Ejecución del programa: Comparar las cadenas: La Comunidad de Cantabria es muy bonita La Comunidad de CANTABRIA es muy bonita strcmp: cadena 1 es mayor que cadena 2
La solución de este problema es que la cadena1 es mayor que la cadena2 porque alfabéticamente Cantabria está después de CANTABRIA.
strcspn #include size_t strcspn( const char *cadena1, const char *cadena2 ); Compatibilidad: ANSI, UNIX y Windows
La función strcspn da como resultado la posición (subíndice) del primer carácter de cadena1, que pertenece al conjunto de caracteres contenidos en cadena2. Este valor corresponde a la longitud de la subcadena de cadena1 formada por caracteres no pertenecientes a cadena2. Si ningún carácter de cadena1 pertenece a cadena2, el resultado es la posición del carácter de terminación (\0) de cadena1; esto es, la longitud de cadena1. /* strcspn.c */ #include #include main(void)
644
C/C++: CURSO DE PROGRAMACIÓN
{ char cadena[] = "xyzabc"; int pos; pos = strcspn( cadena, "abc" ); printf( "Primer a, b o c en %s es el carácter %d\n", cadena, pos ); } Ejecución del programa: Primer a, b o c en xyzabc es el carácter 3
strlen #include size_t strlen( char *cadena ); Compatibilidad: ANSI, UNIX y Windows
La función strlen devuelve la longitud en bytes de cadena, no incluyendo el carácter de terminación nulo. El tipo size_t es sinónimo de unsigned int. /* strlen.c */ #include #include main(void) { char cadena[80] = "Hola"; printf("El tamaño de cadena es %d\n", strlen(cadena)); } Ejecución del programa: El tamaño de cadena es 4
strncat #include char *strncat( char *cadena1, const char *cadena2, size_t n ); Compatibilidad: ANSI, UNIX y Windows
La función strncat añade los primeros n caracteres de cadena2 a la cadena1, termina la cadena resultante con el carácter nulo y devuelve un puntero a cadena1. Si n es mayor que la longitud de cadena2, se utiliza como valor de n la longitud de cadena2.
APÉNDICE A: ALGUNAS FUNCIONES DE LA BIBLIOTECA DE C
645
strncpy #include char *strncpy( char *cadena1, const char *cadena2, size_t n ); Compatibilidad: ANSI, UNIX y Windows
La función strncpy copia n caracteres de la cadena2 en la cadena1 (sobrescribiendo los caracteres de cadena1) y devuelve un puntero a cadena1. Si n es menor que la longitud de cadena2, no se añade automáticamente un carácter nulo a la cadena resultante. Si n es mayor que la longitud de cadena2, la cadena1 es rellenada con caracteres nulos (‘\0’) hasta la longitud n.
strncmp #include int strncmp( const char *cadena1, const char *cadena2, size_t n ); Compatibilidad: ANSI, UNIX y Windows
La función strncmp compara lexicográficamente los primeros n caracteres de cadena1 y de cadena2, distinguiendo mayúsculas y minúsculas, y devuelve un valor: 0 si la cadena1 es mayor que la cadena2. Si n es mayor que la longitud de la cadena1, se toma como valor la longitud de la cadena1.
strspn #include size_t strspn( const char *cadena1, const char *cadena2 ); Compatibilidad: ANSI, UNIX y Windows
La función strspn da como resultado la posición (subíndice) del primer carácter de cadena1, que no pertenece al conjunto de caracteres contenidos en cadena2. Esto es, el resultado es la longitud de la subcadena inicial de cadena1, formada por caracteres pertenecientes a cadena2.
strstr #include char *strstr( const char *cadena1, const char *cadena2 );
646
C/C++: CURSO DE PROGRAMACIÓN
Compatibilidad: ANSI, UNIX y Windows
La función strstr devuelve un puntero a la primera ocurrencia de cadena2 en cadena1 o un valor NULL si la cadena2 no se encuentra en la cadena1.
strtok #include char *strtok( char *cadena1, const char *cadena2 ); Compatibilidad: ANSI, UNIX y Windows
La función strtok permite obtener de la cadena1 los elementos en los que se divide según los delimitadores especificados en cadena2. Para obtener el primer elemento, strtok debe tener cadena1 como primer argumento y para obtener los siguientes elementos, debe tener NULL. Cada llamada a strtok devuelve un puntero al siguiente elemento o NULL si no hay más elementos. Si un elemento finaliza con un delimitador, este es sustituido con un \0 y se guarda un puntero al siguiente carácter para la siguiente llamada a strtok. Puede ponerse más de un delimitador entre elemento y elemento, y también puede variarse el conjunto de caracteres que actúan como delimitadores, de una llamada a otra. Finalmente, tiene que saber que esta función modifica su primer argumento, por lo tanto, debe existir un espacio de memoria sobre el que la función pueda escribir. Por ejemplo, para cadena1 serían válidas cualesquiera de las dos definiciones siguientes: char cadena1[] = "Una cadena de caracteres"; char *cadena1 = (char *)malloc(nBytes); strcpy(cadena1, "Una cadena de caracteres");
En cambio, no sería válida la siguiente definición porque cadena1 apunta a una zona de memoria sobre la que no se puede escribir (se trata de una constante). char *cadena1 = "Una cadena de caracteres";
El ejemplo siguiente divide la cadena de caracteres especificada por cadena en los elementos definidos por los delimitadores espacio en blanco y coma. /* strtok.c */ #include #include
APÉNDICE A: ALGUNAS FUNCIONES DE LA BIBLIOTECA DE C
647
main(void) { char cadena[] = "Esta cadena, está formada por varias palabras"; char *elemento; elemento = strtok(cadena," ,"); while (elemento != NULL) { printf("%s\n", elemento); elemento = strtok(NULL," ,"); } } Ejecución del programa: Esta cadena está formada por varias palabras
strlwr #include char *strlwr(char *cadena ); Compatibilidad: Windows
La función strlwr convierte las letras mayúsculas de cadena en minúsculas. El resultado es la propia cadena en minúsculas.
strupr #include char *strupr(char *cadena ); Compatibilidad: Windows
La función strupr convierte las letras minúsculas de cadena en mayúsculas. El resultado es la propia cadena en mayúsculas.
Funciones para conversión de datos Las funciones de la biblioteca de C que se muestran a continuación permiten convertir cadenas de caracteres a números y viceversa, suponiendo que la conversión sea posible.
648
C/C++: CURSO DE PROGRAMACIÓN
atof #include double atof( const char *cadena ); Compatibilidad: ANSI, UNIX y Windows
La función atof convierte una cadena de caracteres a un valor de tipo double.
atoi #include int atoi( const char *cadena ); Compatibilidad: ANSI, UNIX y Windows
La función atoi convierte una cadena de caracteres a un valor de tipo int.
atol #include long atol( const char *cadena ); Compatibilidad: ANSI, UNIX y Windows
La función atol convierte una cadena de caracteres a un valor de tipo long. Cuando las funciones atof, atoi y atol toman de la variable cadena un carácter que no es reconocido como parte de un número, interrumpen la conversión. /* Este programa muestra como los números almacenados como * cadenas de caracteres pueden ser convertidos a valores * numéricos utilizando las funciones atof, atoi y atol. * * atof.c */ #include #include main(void) { char *s = NULL; double x = 0; int i = 0; long l = 0; s = " -3208.15E-13"; // para ver cómo trabaja atof x = atof( s ); printf( "atof: cadena ASCII: %-17s float: %e\n", s, x ); s = "8.7195642337X120"; // para ver cómo trabaja atof x = atof( s ); printf( "atof: cadena ASCII: %-17s float: %e\n", s, x ); s = " -8995 libros"; // para ver cómo trabaja atoi i = atoi( s ); printf( "atoi: cadena ASCII: %-17s int : %d\n", s, i );
APÉNDICE A: ALGUNAS FUNCIONES DE LA BIBLIOTECA DE C
649
s = "89954 euros"; // para ver cómo trabaja atol l = atol( s ); printf( "atol: cadena ASCII: %-17s long : %ld\n", s, l ); } Ejecución del programa: atof: atof: atoi: atol:
cadena cadena cadena cadena
ASCII: -3208.15E-13 ASCII: 8.7195642337X120 ASCII: -8995 libros ASCII: 89954 euros
double: -3.208150e-010 double: 8.719564e+000 int : -8995 long : 89954
sprintf #include int sprintf( char *buffer, const char *formato [, argumento] ... ); Compatibilidad: ANSI, UNIX y Windows
La función sprintf convierte los valores de los argumentos especificados a una cadena de caracteres que almacena en buffer. La cadena de caracteres finaliza con el carácter nulo. Cada argumento es convertido y almacenado de acuerdo con el formato correspondiente que se haya especificado. La descripción de formato es la misma que la que se especificó para printf. La función sprintf devuelve como resultado un entero correspondiente al número de caracteres almacenados en buffer sin contar el carácter nulo de terminación. Por ejemplo: /* sprintf.c. Este programa utiliza sprintf para almacenar * en buffer la cadena de caracteres formada por: * * Cadena: ordenador * Carácter: / * Entero: 40 * Real: 1.414214 */ #include main(void) { char buffer[200], s[] = "ordenador", c = '/'; int i = 40, j; float f = 1.414214F; j = sprintf( buffer, "\tCadena: %s\n", s ); j += sprintf( buffer + j, "\tCarácter: %c\n", c ); j += sprintf( buffer + j, "\tEntero: %d\n", i ); j += sprintf( buffer + j, "\tReal: %f\n", f ); printf( "Salida:\n%s\nNúmero de caracteres = %d\n", buffer, j ); }
650
C/C++: CURSO DE PROGRAMACIÓN
Ejecución del programa: Salida: Cadena: Carácter: Entero: Real:
ordenador / 40 1.414214
Número de caracteres = 72
Funciones de caracteres Las funciones de la biblioteca de C que se exponen a continuación actúan sobre un entero para dar como resultado un carácter.
toascii #include int toascii( int c ); Compatibilidad: UNIX y Windows
La función toascii pone a 0 todos los bits de c, excepto los siete bits de menor orden. Dicho de otra forma, convierte c a un carácter ASCII.
tolower #include int tolower( int c ); Compatibilidad: ANSI, UNIX y Windows
La función tolower convierte c a una letra minúscula, si procede.
toupper #include int toupper( int c ); Compatibilidad: ANSI, UNIX y Windows
La función toupper convierte c a una letra mayúscula, si procede. /* tolower.c */ #include #include main()
APÉNDICE A: ALGUNAS FUNCIONES DE LA BIBLIOTECA DE C
651
{ char car; // ... do { printf("¿Desea continuar? s/n "); car = getchar(); fflush(stdin); } while (tolower(car) != 'n' && tolower(car) != 's'); // ... }
Este ejemplo admite una respuesta sí o no (s|S|n|N) en minúsculas o en mayúsculas, pero la comparación se hace en minúsculas.
FUNCIONES MATEMÁTICAS Las declaraciones para las funciones matemáticas que a continuación se describen están en el fichero de cabecera math.h. Quiere esto decir que, cuando se utilice una función matemática en un programa, debe especificarse la directriz: #include
Los argumentos para estas funciones son de tipo double y el resultado devuelto es también de tipo double. Por ello, en muchos casos utilizaremos una conversión explícita de tipo (conversión cast) para convertir explícitamente los argumentos al tipo deseado. Por ejemplo, suponiendo que valor es un int: a = acos((double)valor);
calcula el arco coseno de valor. Se puede observar que el argumento pasado a la función acos es convertido explícitamente a tipo double. Las funciones matemáticas las podemos clasificar en las siguientes categorías:
Funciones trigonométricas. Funciones hiperbólicas. Funciones exponencial y logarítmica. Otras varias.
652
C/C++: CURSO DE PROGRAMACIÓN
acos La función acos da como resultado el arco, en el rango 0 a , cuyo coseno es x. El valor de x debe estar entre 1 y 1; de lo contrario se obtiene un error (argumento fuera del dominio de la función). #include double acos( double x ); Compatibilidad: ANSI, UNIX y Windows
asin La función asin da como resultado el arco, en el rango /2 a /2, cuyo seno es x. El valor de x debe estar entre 1 y 1; si no se obtiene un error (argumento fuera del dominio de la función). #include double asin( double x ); Compatibilidad: ANSI, UNIX y Windows
atan La función atan da como resultado el arco, en el rango /2 a /2, cuya tangente es x. #include double atan( double x ); Compatibilidad: ANSI, UNIX y Windows
atan2 La función atan2 da como resultado el arco, en el rango a , cuya tangente es y/x. Si ambos argumentos son 0, se obtiene un error (argumento fuera del dominio de la función). #include double atan2( double y, double x); Compatibilidad: ANSI, UNIX y Windows /* acos.c */ #include #include main()
APÉNDICE A: ALGUNAS FUNCIONES DE LA BIBLIOTECA DE C
{ double valor = 0; do { printf("%lf %lf\n", acos(valor), atan2(valor, 1.0)); valor += 0.1; } while (valor tm_min); }
La función localtime utiliza una variable de tipo static struct tm para realizar la conversión y lo que devuelve es la dirección de esa variable.
FUNCIONES PARA MANIPULAR BLOQUES DE MEMORIA La biblioteca de C/C++ proporciona un conjunto de funciones para manipular bloques de bytes consecutivos en memoria. Comentamos a continuación las más utilizadas.
memset La función memset permite iniciar un bloque de memoria. #include void *memset( void *destino, int b, size_t nbytes ); Compatibilidad: ANSI, UNIX y Windows
El argumento destino es la dirección del bloque de memoria que se desea iniciar, b es el valor empleado para iniciar cada byte del bloque y nbytes es el número de bytes del bloque que se iniciarán. Por ejemplo, el siguiente código inicia a 0 la matriz a: double a[10][10]; // ... memset(a, 0, sizeof(a));
memcpy La función memcpy copia un bloque de memoria en otro. #include void *memcpy( void *destino, const void *origen, size_t nbytes );
660
C/C++: CURSO DE PROGRAMACIÓN
Compatibilidad: ANSI, UNIX y Windows
El argumento destino es la dirección del bloque de memoria destino de los datos, origen es la dirección del bloque de memoria origen de los datos y nbytes es el número de bytes que se copiarán desde el origen al destino. Por ejemplo, el siguiente código copia la matriz a en b: double a[10][10], b[10][10]; // ... memcpy(b, a, sizeof(a));
memcmp La función memcmp compara byte a byte dos bloques de memoria. #include int memcmp( void *bm1, const void *bm2, size_t nbytes ); Compatibilidad: ANSI, UNIX y Windows
Los argumentos bm1 y bm2 son las direcciones de los bloques de memoria a comparar y nbytes es el número de bytes que se compararán. El resultado devuelto por la función es el mismo que se expuso para strcmp. Por ejemplo, el siguiente código compara la matriz a con la b: double a[10][10], b[10][10]; // ... if ( memcmp(a, b, sizeof(a)) == 0 ) printf("Las matrices a y b contienen los mismos datos\n"); else printf("Las matrices a y b no contienen los mismos datos\n");
APÉNDICE B F.J.Ceballos/RA-MA
ENTORNOS DE DESARROLLO Un entorno de desarrollo integrado (EDI, en inglés IDE: Integrated Development Environment) es una aplicación que agrupa varias herramientas de programación, básicamente, las necesarias para escribir, compilar y depurar un programa. El EDI puede utilizar un solo lenguaje de programación, o bien puede ser compatible con varios, tales como C/C++, C#, Visual Basic, Java, PHP, Python, etc. Dicho EDI presentará al usuario una interfaz gráfica que le abstraerá del manejo individual, a nivel de línea de órdenes, de cada una de esas herramientas de programación. Para realizar los ejemplos de este libro, el autor propone utilizar alguno de los entornos indicados a continuación: Microsoft Visual Studio Express para Windows, NetBeans para Windows/Linux/Mac OS X o Code::Blocks para Windows/Linux/Mac OS X. Estos EDI pueden descargarse de Internet y utilizarlos sin coste alguno.
MICROSOFT VISUAL STUDIO Este entorno de desarrollo lo puede descargar gratuitamente desde Internet (www.fjceballos.es > Utilidades) en su edición Express. En la figura siguiente se puede observar la interfaz gráfica de este entorno de desarrollo integrado: Microsoft Visual Studio Express. Dicho entorno muestra una barra de menús y otra de herramientas, un panel de edición (en el ejemplo muestra un programa C), el explorador de soluciones (en el ejemplo muestra un proyecto progC correspondiente al programa que estamos realizando), el panel de propiedades y el panel de resultados (en el ejemplo muestra los resultados de la compilación).
662
C/C++: CURSO DE PROGRAMACIÓN
Para editar y ejecutar el programa avance.c expuesto en el capítulo 1 utilizando este entorno de desarrollo, los pasos a seguir son los siguientes: 1. Partiendo de la página de inicio de Microsoft Visual Studio Express, hacemos clic en Nuevo proyecto de la página principal para crear un proyecto nuevo o bien ejecutamos la orden Archivo > Nuevo proyecto. Esta acción hará que se visualice una ventana análoga a la siguiente:
APÉNDICE B: ENTORNOS DE DESARROLLO
663
Esta ventana muestra en su panel izquierdo los tipos de proyectos que se pueden crear y a la derecha de este, las plantillas que se pueden utilizar; la elección de una o de otra dependerá del tipo de aplicación que deseemos construir. Para nuestro ejemplo, elegimos el tipo de proyecto Visual C++ Win32 y la plantilla Aplicación de consola Win32. Después especificamos el nombre del proyecto y su ubicación (no hace falta que marque Crear directorio para la solución); observe que el proyecto será creado en una carpeta con el mismo nombre. A continuación pulsamos el botón Aceptar. Esta acción visualizará la ventana mostrada en la figura siguiente, que permitirá establecer la configuración de la aplicación; por ejemplo, aplicación de consola, proyecto vacío:
2. Una vez configurada la aplicación, pulsamos el botón Finalizar. El resultado será un proyecto vacío al que podremos añadir ficheros. Por ejemplo, para añadir el fichero avance.c, hacemos clic con el botón derecho del ratón sobre el nombre del proyecto y seleccionamos la orden Agregar > Nuevo elemento del menú contextual.
664
C/C++: CURSO DE PROGRAMACIÓN
3. La acción ejecutada en el punto anterior muestra la ventana que se expone a continuación, la cual nos permitirá elegir la plantilla para el fichero. En nuestro caso, al no haber una plantilla para archivos C, hemos añadido la extensión .c a continuación del nombre del fichero en la caja Nombre.
APÉNDICE B: ENTORNOS DE DESARROLLO
665
4. El siguiente paso es escribir el código que se almacenará en este fichero, según muestra la figura siguiente:
En esta figura observamos una ventana principal que contiene otras ventanas o paneles. La que está en la parte izquierda superior está mostrando la página de edición del fichero avance.c que estamos editando. La que está en la parte derecha superior está mostrando el explorador de soluciones; este lista el nombre de la solución (una solución puede contener uno o más proyectos), el nombre del proyecto o proyectos y el nombre de los ficheros que componen el proyecto; en nuestro caso solo tenemos el fichero avance.c donde escribiremos el código de las acciones que tiene que llevar a cabo nuestra aplicación. Al lado de la pestaña de la ventana del explorador puede haber otras pestañas como, por ejemplo, la Vista de clases. Y la ventana que hay debajo de la página de edición puede mostrar varios paneles, por ejemplo, el de resultados de la compilación. 5. Una vez editado el programa, para compilarlo ejecutamos la orden Compilar... del menú Compilar y para ejecutarlo, seleccionamos la orden Iniciar sin depurar del menú Depurar o bien pulsamos las teclas Ctrl+F5.
666
C/C++: CURSO DE PROGRAMACIÓN
Añadir ficheros existentes a un proyecto Supongamos que disponemos de un fichero .c que deseamos añadir a un proyecto vacío o no. ¿Cómo podemos hacerlo? Una vez abierto el proyecto, basta con ejecutar la orden Proyecto > Agregar elemento existente y seleccionar el fichero que deseamos añadir.
Depurar la aplicación ¿Por qué se depura una aplicación? Porque los resultados que estamos obteniendo con la misma no son correctos y no sabemos por qué. El proceso de depuración consiste en ejecutar la aplicación paso a paso, indistintamente por sentencias o por funciones, con el fin de observar el flujo seguido durante su ejecución, así como los resultados intermedios que se van sucediendo, con la finalidad de detectar dónde está la anomalía que produce un resultado final erróneo. Hay dos configuraciones, como se puede observar en la figura siguiente, bajo las que se puede compilar una aplicación: Release y Debug:
La primera permite obtener un programa ejecutable optimizado en código y en velocidad, y la segunda, un programa ejecutable con código extra necesario para depurar la aplicación. Por lo tanto, para depurar una aplicación utilizando el depurador del entorno de desarrollo de Visual Studio, debe activar la configuración Win32 Debug antes de iniciar su compilación. Para ello, ejecute la orden
APÉNDICE B: ENTORNOS DE DESARROLLO
667
Administrador de configuración... del menú Compilar y seleccione dicha configuración. Una vez construida la aplicación bajo la configuración Win32 Debug podrá, si lo necesita, depurar la misma. Para ello, ejecute la orden Depurar > Paso a paso por instrucciones y utilice las órdenes del menú Depurar o los botones correspondientes de la barra de herramientas (para saber el significado de cada botón, ponga el puntero del ratón sobre cada uno de ellos).
De forma resumida, las órdenes de que dispone para depurar una aplicación son las siguientes:
Iniciar o F5. Inicia la ejecución de la aplicación en modo depuración hasta encontrar un punto de parada o hasta el final si no hay puntos de parada.
Alternar puntos de interrupción o F9. Pone o quita un punto de parada en la línea sobre la que está el punto de inserción.
Detener depuración o Mayús+F5. Detiene el proceso de depuración.
Paso a paso por instrucciones o F11. Ejecuta la aplicación paso a paso. Si la línea a ejecutar coincide con una llamada a una función definida por el usuario, dicha función también se ejecutará paso a paso.
Paso a paso por procedimientos o F10. Ejecuta la aplicación paso a paso. Si la línea a ejecutar coincide con una llamada a una función definida por el usuario, dicha función no se ejecutará paso a paso, sino de una sola vez.
Paso a paso para salir o Mayús+F11. Cuando una función definida por el usuario ha sido invocada para ejecutarse paso a paso, utilizando esta orden se puede finalizar su ejecución en un solo paso.
Ejecutar hasta el cursor o Ctrl+F10. Ejecuta el código que hay entre la última línea ejecutada y la línea donde se encuentra el punto de inserción.
Inspección rápida o Ctrl+Alt+Q. Visualiza el valor de la variable que está bajo el punto de inserción o el valor de la expresión seleccionada (sombreada). El simple hecho de poner el punto de inserción sobre dicha variable ya visualiza su valor.
668
C/C++: CURSO DE PROGRAMACIÓN
Para ejecutar la aplicación en un solo paso, seleccione la orden Iniciar sin depurar (Ctrl+F5) del menú Depurar. Además de la barra de herramientas Depurar, dispone también de otras barras de herramientas que puede mostrar ejecutando la orden Barras de herramientas del menú Ver.
INTERFAZ DE LÍNEA DE ÓRDENES EN WINDOWS Los ficheros que componen una aplicación C pueden ser escritos utilizando cualquier editor de texto ASCII; por ejemplo, el Bloc de notas. Una vez editados y guardados todos los ficheros que componen la aplicación, el siguiente paso es compilarlos y enlazarlos para obtener el fichero ejecutable correspondiente a la misma. La orden para realizar estas operaciones es la siguiente: cl fichero01.c [fichero02 [fichero03] ...]
El nombre del fichero ejecutable resultante será el mismo que el nombre del primer fichero especificado, pero con extensión .exe. Previamente, para que el sistema operativo encuentre la utilidad cl, los ficheros de cabecera (directriz include) y las bibliotecas dinámicas y estáticas, cuando son invocados desde la línea de órdenes, hay que definir en el entorno de trabajo (en la consola sobre la que estemos trabajando) las siguientes variables: set path=%path%;ruta de los ficheros .exe y .dll set include=ruta de los ficheros .h set lib=ruta de los ficheros .lib
La expresión %path% representa el valor actual de la variable de entorno path. Una ruta va separada de la anterior por un punto y coma. Estas variables también pueden ser establecidas ejecutando el fichero vcvars32.bat que aporta Visual Studio en la ruta (no tiene porqué coincidir con la de su instalación): C:\Archivos de programa\Microsoft Visual Studio xx.x\VC\bin
Una vez establecidas estas variables, ya puede invocar al compilador C y al enlazador. En la figura siguiente se puede observar, como ejemplo, el proceso seguido para compilar avance.c:
APÉNDICE B: ENTORNOS DE DESARROLLO
669
Observe que primero hemos ejecutado vcvars32.bat para establecer las variables de entorno, después hemos cambiado al directorio de la aplicación (cd), a continuación hemos visualizado los ficheros .c de ese directorio (dir) y finalmente hemos invocado al compilador C (cl). El resultado es avance.exe. Para ejecutar este fichero, escriba avance en la línea de órdenes y pulse Entrar. El resultado será el mostrado en la figura.
CREAR UNA BIBLIOTECA DE FUNCIONES Visual Studio proporciona, entre otros, el tipo de proyecto Win32 Static Library que permite crear una biblioteca de funciones (ficheros con extensión .lib) análoga a las proporcionadas por C. Esto nos permitirá agrupar todas nuestras funciones de interés general en un solo fichero y utilizarlas en cualquier aplicación igual que utilizamos las funciones de la biblioteca C, printf, scanf, etc. Eso sí, antes de compilar una aplicación que utilice funciones de nuestra biblioteca, debemos es-
670
C/C++: CURSO DE PROGRAMACIÓN
pecificar en la lista de ficheros o en las opciones del enlazador (linker) el nombre de esa biblioteca. Para crear una de estas bibliotecas siga los pasos indicados a continuación. Como ejemplo, vamos a crear una biblioteca hash.lib con las funciones incluidas en el fichero cap12\hash\hash.c incluido en el ZIP que acompaña al libro. 1. Ejecute el entorno de desarrollo de Visual Studio. 2. Seleccione la orden Archivo > Nuevo > Proyecto. 3. Seleccione el tipo de proyecto Win32 y la plantilla Aplicación de consola Win32. Escriba el nombre del proyecto en la caja Nombre y en la caja Ubicación seleccione el directorio donde desea crear este proyecto. En nuestro caso vamos a dar al proyecto el nombre Hash. Pulse el botón Aceptar. Se visualiza la siguiente ventana:
4. En esta ventana seleccione Biblioteca estática, no seleccione Encabezado precompilado y haga clic en el botón Finalizar. 5. Ahora tenemos un proyecto vacío. Ejecute la orden Proyecto > Agregar elemento existente y añada el fichero o los ficheros que contengan las funciones que desea incluir en su biblioteca (hash.lib), así como los ficheros de cabecera necesarios para poder compilar el código escrito en cada una de las funciones. En nuestro caso, según muestra la figura siguiente, añadiremos el fichero
APÉNDICE B: ENTORNOS DE DESARROLLO
671
hash.c que contiene las funciones de nuestro interés y el fichero de cabecera hash.h que incluye las declaraciones de esas funciones.
6. Finalmente, ejecute la orden Compilar > Compilar... para compilar el proyecto y generar el fichero .lib. En nuestro caso se generará el fichero hash.lib con las funciones que incluía hash.c. Para utilizar esta biblioteca vamos a realizar otro ejemplo. Cree un nuevo proyecto ApHash formado por los ficheros: apHash.c, hash.h y hash.lib. El fichero apHash.c simplemente hará uso de las funciones de la biblioteca hash.lib lo que requerirá incluir el fichero hash.h. En la fase de enlace será necesario poder acceder a hash.lib, ya que apHash.c invoca a funciones de esta biblioteca. Por lo tanto, asegúrese de que ha añadido al proyecto la biblioteca hash.lib; después, compile y ejecute el proyecto.
672
C/C++: CURSO DE PROGRAMACIÓN
NETBEANS Evidentemente, para poder escribir programas C/C++ en una plataforma Linux se necesita un entorno de desarrollo válido para dicha plataforma. NetBeans, entre otros, puede ser este entorno de desarrollo. Se trata de un EDI libre, gratuito y sin restricciones de uso. Puede descargarlo de https://netbeans.org. Este EDI fue construido principalmente para el lenguaje Java, pero soporta otros lenguajes como C/C++. Está escrito en java, por lo que para ser ejecutado es necesario haber instalado previamente la máquina virtual de Java, que también puede descargar gratuitamente de http://java.com/es/. En la figura siguiente se puede observar la interfaz gráfica de este entorno de desarrollo integrado:
APÉNDICE B: ENTORNOS DE DESARROLLO
673
Para personalizar el EDI, ejecute la orden Options del menú Tools. Para editar y ejecutar el programa avance.c expuesto en el capítulo 1 utilizando este entorno de desarrollo, los pasos a seguir se indican a continuación: 1. Suponiendo que ya se está visualizando el entorno de desarrollo, ejecute la orden File > New Project (Archivo > Nuevo Proyecto). Se muestra la ventana New Project. 2. Seleccione C/C++ en la lista Categories (Categorías) y en la lista Projects (Proyectos) seleccione C/C++ Application (Aplicación C o C++). Después haga clic en el botón Next (siguiente). Se muestra la ventana New C/C++ Application. 3. Escriba el nombre del proyecto (Project Name); en nuestro caso será ProgC y, a continuación, seleccione la carpeta donde quiere guardarlo. 4. Asegúrese de que la casilla Create Main File (crear fichero/archivo principal) está marcada, establezca el nombre, en nuestro caso avance, y elija el lenguaje C (se añadirá la extensión correspondiente al fichero cuando se cree).
674
C/C++: CURSO DE PROGRAMACIÓN
5. Para finalizar haga clic en el botón Finish. El resultado será el siguiente:
El EDI crea la carpeta NetBeansProjects/ProgC en la que guardará el proyecto compuesto en este caso por un solo fichero de código fuente, avance.c, que almacenará el código correspondiente al programa.
APÉNDICE B: ENTORNOS DE DESARROLLO
675
En la ventana mostrada en la figura anterior distinguimos otras tres ventanas, algunas de ellas, con varios paneles. La que está en la parte superior derecha está mostrando el panel de edición para el código fuente de nuestra aplicación y tiene oculto el panel de inicio. La que está en la parte superior izquierda muestra el panel de proyectos; este lista el nombre del proyecto y el nombre de los ficheros que componen el proyecto. Observe el fichero avance.c; contiene el código de las acciones que tiene que llevar a cabo nuestra aplicación. También distinguimos otros nodos para otros tipos de ficheros, por ejemplo, para los ficheros de cabecera. Finalmente, la ventana que hay debajo de la de proyectos permite navegar por el código del proyecto. Puede visualizar otras ventanas desde el menú Window; por ejemplo, la ventana Output, que será utilizada para mostrar los resultados de la compilación y de la ejecución. Una vez creado el esqueleto de la aplicación, editamos el código de la misma. En nuestro caso, este código ya fue expuesto en el capítulo 1. El paso siguiente es construir el fichero ejecutable (fichero progc en la carpeta ProgC/dist/Debug/GNU-Linux-x86). Para ello, ejecute la orden Run > Build Project, o bien pulse la tecla F11. Si la compilación es correcta, puede pasar a ejecutar la aplicación ejecutando la orden Run > Run Project, o bien pulsando la tecla F6; observe el resultado en la ventana Output. En este caso, la ventana Output muestra un error: En la función ‘log’: avance.c:16: referencia a ‘log10’ sin definir. Para hacer uso de la biblioteca matemática en Linux tenemos que utilizar la opción –lm. Por ejemplo: cc avance.c -o avance.exe -lm
La opción –lm indica al compilador que utilice la biblioteca matemática libm.a como alternativa a la biblioteca estándar libc.a. Para especificar esta opción de compilación desde el entorno de desarrollo, haga clic con el botón secundario del ratón sobre el nombre del proyecto y seleccione Properties (propiedades del proyecto). Se muestra la ventana que se muestra a continuación; seleccione Build > C Compiler > Additional Options y escriba la opción –lm.
676
C/C++: CURSO DE PROGRAMACIÓN
Cuando la aplicación necesite más de un fichero, el proceso es igual de sencillo. Añadir otro fichero a una aplicación, por ejemplo un nuevo fichero que almacene una nueva clase, supone hacer clic con el botón derecho del ratón sobre el nombre del proyecto, elegir la orden New y seleccionar del menú contextual que se visualiza el tipo de elemento que se desea añadir.
Depurar una aplicación con NetBeans Anteriormente ya comentamos que una aplicación se depura porque los resultados que estamos obteniendo con la misma no son correctos y no sabemos por qué. Por ejemplo, para depurar una aplicación utilizando el depurador del entorno de desarrollo NetBeans, debe establecer un punto de parada inicial. Para ello, haga clic con el botón derecho del ratón sobre la sentencia a partir de la cual quiere ejecutar el código de su aplicación paso a paso y ejecute la orden Toggle Line Breakpoint (poner un punto de parada) del menú contextual que se visualiza, o haga clic en la zona sombreada a su izquierda:
APÉNDICE B: ENTORNOS DE DESARROLLO
677
Después, ejecute la orden Debug > Debug Project, o bien pulse las teclas Ctrl+F5 para iniciar la depuración. Continúe la ejecución paso a paso utilizando las órdenes del menú Debug o los botones correspondientes de la barra de herramientas Debug (para saber el significado de cada botón, ponga el puntero del ratón sobre cada uno de ellos).
De forma resumida, las órdenes disponibles para depurar una aplicación son las siguientes:
Debug Project o Ctrl+F5. Inicia la ejecución de la aplicación en modo depuración hasta encontrar un punto de parada o hasta el final si no hay puntos de parada.
Toggle Line Breakpoint o Ctrl+F8. Pone o quita un punto de parada en la línea sobre la que está el punto de inserción.
Finish Debugger Session o Mayús+F5. Detiene el proceso de depuración.
Step Into o F7. Ejecuta la aplicación paso a paso. Si la línea a ejecutar coincide con una llamada a un método definido por el usuario, dicho método también se ejecuta paso a paso.
Step Over o F8. Ejecuta la aplicación paso a paso. Si la línea a ejecutar coincide con una llamada a un método definido por el usuario, dicho método no se ejecuta paso a paso, sino de una sola vez.
Step Out o Ctrl+F7. Cuando un método definido por el usuario ha sido invocado para ejecutarse paso a paso, utilizando esta orden se puede finalizar su ejecución en un solo paso.
Run to Cursor o F4. Ejecuta el código que hay entre la última línea ejecutada y la línea donde se encuentra el punto de inserción.
Para ver los valores intermedios que van tomando las variables ponga el cursor sobre ellas, o bien utilice las ventanas Variable, etc., del fondo del EDI. Para añadir o quitar ventanas ejecute la orden Window > Debuggin.
678
C/C++: CURSO DE PROGRAMACIÓN
INTERFAZ DE LÍNEA DE ÓRDENES EN UNIX/LINUX Los ficheros que componen una aplicación C realizada bajo UNIX/LINUX pueden ser escritos utilizando cualquier editor de texto ASCII proporcionado por este. Una vez editados y guardados todos los ficheros .c que componen la aplicación, el siguiente paso es compilarlos y enlazarlos para obtener el fichero ejecutable correspondiente a la misma. La orden para realizar estas operaciones es la siguiente: cc fich01.c [fich02 [fich03] ...] –o fich_ejecutable opciones
En el caso de UNIX/LINUX las rutas de acceso para que el sistema operativo encuentre la utilidad cc, los ficheros de cabecera .h y las bibliotecas, cuando son invocados desde la línea de órdenes, ya están definidas en el entorno de trabajo. En la figura siguiente se puede observar, como ejemplo, el proceso seguido para compilar avance.c:
Observe que primero hemos cambiado al directorio de la aplicación (cd), después hemos visualizado el contenido de ese directorio (ls -l) y finalmente hemos invocado al compilador C (cc). El fichero ejecutable resultante es el especificado por la opción –o, en el ejemplo progc, o a.out por omisión. Para ejecutar la aplicación del ejemplo, escriba progc en la línea de órdenes y pulse Entrar. El resultado será el que muestra la figura anterior. Si al realizar esta operación se encuentra con que no puede hacerlo porque el sistema no encuentra
APÉNDICE B: ENTORNOS DE DESARROLLO
679
el fichero especificado, tiene que añadir la ruta del directorio actual de trabajo a la variable de entorno PATH. Esto se hace así: PATH=$PATH:.
o bien especificar explícitamente la ruta a partir del directorio actual: ./progc
La expresión $PATH representa el valor actual de la variable de entorno PATH. Una ruta va separada de la anterior por dos puntos. El directorio actual está representado por el carácter punto.
El depurador gdb de Unix/Linux Cuando se tiene la intención de depurar un programa C escrito bajo UNIX, en el momento de compilarlo se debe especificar la opción g. Esta opción indica al compilador que incluya información extra para el depurador en el fichero objeto. Por ejemplo: cc -g prog01.c -o prog01
La orden anterior compila y enlaza el fichero fuente prog01.c. El resultado es un fichero ejecutable prog01 con información para el depurador. Una vez compilado un programa con las opciones necesarias para depurarlo, invocaremos a gdb para proceder a su depuración. La sintaxis es la siguiente: gdb fichero-ejecutable El siguiente ejemplo invoca al depurador gdb de UNIX, que carga el fichero ejecutable prog01 en memoria para depurarlo. gdb prog01
Una vez que se ha invocado el depurador, desde la línea de órdenes se pueden ejecutar órdenes como las siguientes:
break [fichero:]función. Establece un punto de parada en la función indicada del fichero especificado. Por ejemplo, la siguiente orden pone un punto de parada en la función escribir. b escribir
680
C/C++: CURSO DE PROGRAMACIÓN
break [fichero:]línea. Establece un punto de parada en la línea indicada. Por ejemplo, la siguiente orden pone un punto de parada en la línea 10. b 10
delete punto-de-parada. Elimina el punto de parada especificado. Por ejemplo, la siguiente orden elimina el punto de parada 1 (primero). d 1
run [argumentos]. Inicia la ejecución de la aplicación que deseamos depurar. La ejecución se detiene al encontrar un punto de parada o al finalizar la aplicación. Por ejemplo: run
print expresión. Visualiza el valor de una variable o de una expresión. Por ejemplo, la siguiente orden visualiza el valor de la variable total. p total
next. Ejecuta la línea siguiente. Si la línea coincide con una llamada a una función definida por el usuario, no se entra a depurar la función. Por ejemplo: n
continue. Continúa con la ejecución de la aplicación. Por ejemplo: c
step. Ejecuta la línea siguiente. Si la línea coincide con una llamada a una función definida por el usuario, se entra a depurar la función. Por ejemplo: s
list. Visualiza el código fuente. Por ejemplo: l
bt. Visualiza el estado de la pila de llamadas en curso (las llamadas a funciones).
help [orden]. Solicita ayuda sobre la orden especificada.
quit. Finaliza el trabajo de depuración.
CODE::BLOCKS Otro entorno de desarrollo integrado para escribir programas C/C++ del que existen versiones para Windows, Linux y Mac OS X es Code::Blocks. Se trata de un EDI libre, gratuito y sin restricciones de uso que puede descargar de Internet desde la dirección http://www.codeblocks.org/. En la figura siguiente se puede observar el aspecto de este entorno de desarrollo integrado.
APÉNDICE B: ENTORNOS DE DESARROLLO
681
Para editar y ejecutar el programa avance.c visto en el capítulo 1, o cualquier otro programa, utilizando este entorno de desarrollo integrado, los pasos a seguir se indican a continuación: 1. Suponiendo que ya está visualizado el entorno de desarrollo, creamos un nuevo proyecto C++ (File, New, Project). Se muestra la ventana siguiente:
682
C/C++: CURSO DE PROGRAMACIÓN
2. Elegimos la categoría consola (Console), la plantilla Console application y pulsamos el botón Go. Se muestra la ventana siguiente:
3. Seleccionamos el lenguaje C y hacemos clic en el botón Next. Se muestra la ventana siguiente:
APÉNDICE B: ENTORNOS DE DESARROLLO
683
4. Especificamos el nombre del proyecto, la carpeta donde será guardado y hacemos clic en Next. Se muestra la ventana siguiente:
5. Si los datos presentados en la ventana anterior son correctos, hacemos clic en el botón Finish. El proyecto está creado; contiene un fichero main.c que incluye la función main por donde se iniciará y finalizará la ejecución del pro-
684
C/C++: CURSO DE PROGRAMACIÓN
grama. Si lo desea, puede cambiar el nombre main.c por avance.c. Después, edite este fichero igual que lo hizo en el capítulo 1.
6. A continuación, según se puede observar en la figura anterior, editamos el código que compone el programa y lo guardamos. 7. Después, para compilar el programa, ejecutamos la orden Build del menú Build y, una vez compilado (sin errores), lo podemos ejecutar seleccionando la orden Run del mismo menú (si no pudiéramos ver la ventana con los resultados porque desaparece ‒no es el caso‒, añadiríamos al final de la función main, antes de return, la sentencia “system("pause");” y al principio del fichero .c la directriz #include , si fuera necesario). En el caso de que la aplicación esté compuesta por varios ficheros fuente, simplemente tendremos que añadirlos al proyecto ejecutando la orden New del menú File.
APÉNDICE C
F.J.Ceballos/RA-MA
CÓDIGOS DE CARACTERES Una tabla de códigos es un juego de caracteres donde cada uno tiene asignado un número utilizado para su representación interna. Algunos lenguajes como Java utilizan UNICODE para almacenar y manipular cadenas, y otros como C utilizan ANSI o ASCII.
UTILIZACIÓN DE CARACTERES ANSI CON WINDOWS ANSI (American National Standards Institute) es el juego de caracteres estándar más utilizado por los equipos personales. Como el estándar ANSI solo utiliza un byte para representar un carácter, está limitado a un máximo de 256 caracteres. Aunque es adecuado para el inglés, no acepta totalmente muchos otros idiomas. Para escribir un carácter ANSI que no esté en el teclado: 1. Localice en la tabla que se muestra en la página siguiente el carácter ANSI que necesite y observe su código numérico. 2. Pulse la tecla Bloq Núm (Num Lock) para activar el teclado numérico. 3. Mantenga pulsada la tecla Alt y utilice el teclado numérico para pulsar el 0 y a continuación las teclas correspondientes al código del carácter. Por ejemplo, para escribir el carácter en el entorno Windows, mantenga pulsada la tecla Alt mientras escribe 0177 en el teclado numérico (ver la tabla de códigos en la página siguiente).
686
C/C++: CURSO DE PROGRAMACIÓN
JUEGO DE CARACTERES ANSI
APÉNDICE C: CÓDIGOS DE CARACTERES
687
UTILIZACIÓN DE CARACTERES ASCII En MS-DOS y fuera del entorno Windows se utiliza el juego de caracteres ASCII. Para escribir un carácter ASCII que no esté en el teclado: 1. Busque el carácter en la tabla de códigos que coincida con la tabla activa. Utilice la orden chcp para saber qué tabla de códigos está activa. 2. Mantenga pulsada la tecla Alt y utilice el teclado numérico para pulsar las teclas correspondientes al número del carácter que desee. Por ejemplo, si está utilizando la tabla de códigos 850, para escribir el carácter mantenga pulsada la tecla Alt mientras escribe 227 en el teclado numérico (ver la tabla de códigos en la página siguiente).
688
C/C++: CURSO DE PROGRAMACIÓN
JUEGO DE CARACTERES ASCII
APÉNDICE C: CÓDIGOS DE CARACTERES
689
JUEGO DE CARACTERES UNICODE UNICODE es un juego de caracteres en el que se emplean 2 bytes (16 bits) para representar cada carácter. Esto permite la representación de cualquier carácter en cualquier lenguaje escrito en el mundo, incluyendo los símbolos del chino, japonés o coreano. Códigos UNICODE de los dígitos utilizados en español: \u0030-\u0039
0-9 ISO-LATIN-1
Códigos UNICODE de las letras y otros caracteres utilizados en español: \u0024 \u0041-\u005a \u005f \u0061-\u007a \u00c0-\u00d6 \u00d8-\u00f6 \u00f8-\u00ff
$ signo dólar A-Z _ a-z ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö øùúûüýþÿ
Dos caracteres son idénticos solo si tienen el mismo código Unicode.
ÍNDICE # #, 476 ##, 476 #define, 39, 68, 472 #elif, 477 #else, 477 #endif, 477 #error, 483 #if, 477 #include, 68, 477, 483 #line, 482 #undef, 476
A abrir un fichero, 409 acceso aleatorio, 441 acceso secuencial, 429, 453 Ackerman, 592 acos, 652 algoritmo Boyer y Moore, 607 algoritmos hash, 619 ámbito de una variable, 83 ancho, 103 anidar if, 141 anidar while, do, o for, 154 ANSI, 72, 685 ANSI C, 475 árbol, 542 árbol binario, 543
árbol binario de búsqueda, 546 árbol binario perfectamente equilibrado, 558 árbol, recorrer, 544 archivo, 402 argumento, 71 argumentos en la línea de órdenes, 363 argumentos pasados por valor, 77 argumentos por referencia, 78 argumentos, pasar a una función, 77 aritmética de punteros, 272, 277, 278, 286 ASCII, 687 asignación, 100 asignación dinámica de memoria, 299 asignar bytes desde una dirección, 270 asin, 652 ASSERT, 486 atan, 652 atan2, 652 atof, 208, 648 atoi, 208, 648 atol, 208, 648 auto, 86
B biblioteca de funciones, 669 bit, 2 bits de error, 413 bloque, 70 borrar los elementos de una lista, 504 borrar nodo, 552 borrar un elemento de una lista, 503
692
C/C++: CURSO DE PROGRAMACIÓN
Boyer y Moore, 607 break, 149, 163 buffer, 404 flujo, 437 vaciar, 441 burbuja, 598 buscar nodo, 550 buscar un elemento en una lista, 502 búsqueda binaria, 606 búsqueda de cadenas, 607 búsqueda secuencial, 606 byte, 2
C cadenas de caracteres, 200 leer, 121 leer y escribir, 201 cadena, principio y final, 282 calificación de funciones, 90 calificadores, 86 calloc, 304 campo, 402 campo de bits, 242 carácter \n, 115 caracteres de C, 24 manipular, 198 cast, 55 ceil, 654 cerrar un fichero, 412 char, 27 clearerr, 413 clock, 656 cola, 528 comentario, 39 compilación condicional, 477 compilación, constante simbólica, 479 compilador, 4 const, 40 constante simbólica, 39, 472 contador, 199 continue, 164 conversión, 42 conversión entre tipos, 54 conversión forzada, 55 copiar matrices, 218 copiar un fichero en otro, 421 copiar una matriz, 280 cos, 653 cosh, 653
CR, 115 CR+LF, 410 ctime, 657
D decimal, 35 declaración, 69 declaración compleja, 326 declaración de una función, 71 define, 68 defined, 479 definición, 69 definición de una función, 73 depurar, 666, 676 dirección de, 51 dirección de memoria, 78, 267 directrices, 67 directrices #if, #elif, #else y #endif, 477 directrices para el preprocesador, 471 directriz, 471 #define, 472 #error, 483 #include, 477, 483 #line, 482 #undef, 476 de inclusión, 68 de sustitución, 68 dispositivos estándar, 434 do ... while, 157 double, 32
E E/S carácter a carácter, 418 E/S con formato, 425 E/S de cadenas de caracteres, 422 E/S utilizando registros, 427 EDI, 661 else if, 144 ensamblador, 2 enum, 29 EOF, 115 errno, 416 errores en operaciones de E/S, 413 escribir con formato, 102 escribir en un fichero, 430 escribir un carácter, 119 estática vs dinámica, 301 estructura como argumento, 354
ÍNDICE
estructura else if, 144 estructura FILE, 403 estructuras, 221 abstractas de datos, 496 acceso a sus miembros, 224 crear, 221 definir variables, 222 dinámicas, 495 miembros, 225 operaciones, 226 variables, 237 exit, 131, 302 exp, 654 expresión, 42 expresiones booleanas, 45 extern, 86
F fabs, 655 fclose, 412 feof, 415 ferror, 413 fflush, 117, 441 fgetc, 420 fgets, 423 fichero, 402 abrir, 409 cerrar, 412 de cabecera, 483 escribir, 430 indexado, crear, 637 leer, 433 temporal, 441 ficheros binarios, 406 ficheros de texto, 406 FILE, 403 fin de fichero, 115, 415 float, 31 floor, 655 flujo, 102, 403 buffer, 437 fopen, 410 for, 160 formato, especificaciones, 102 fprintf, 425 fputc, 419 fputs, 422 fread, 429 free, 301
freopen, 411 fscanf, 426 fseek, 417, 442 ftell, 417, 418, 442, 444, 461 fugas de memoria, 301 función, 63, 70 acos, 652 asin, 652 atan, 652 atan2, 652 atof, 648 atoi, 648 función atol, 648 calloc, 304 ceil, 654 clearerr, 413 clock, 656 cos, 653 cosh, 653 ctime, 657 es recursiva, 367 exit, 131, 302 exp, 654 fabs, 655 fclose, 412 feof, 415 ferror, 413 fflush, 117, 441 fgetc, 420 fgets, 423 floor, 655 fopen, 410 fprintf, 425 fputc, 419 fputs, 422 fread, 429 free, 301 frente a macro, 473 freopen, 411 fscanf, 426 fseek, 417 ftell, 417 fwrite, 428 getch, 120 getchar, 118 getche, 120 gets, 201, 423 localtime, 658 log, 654
693
694
C/C++: CURSO DE PROGRAMACIÓN
getchar, 118 getche, 120 gets, 122, 201, 423 getw, 422
log10, 654 malloc, 299 memcmp, 660 memcpy, 220, 659 memset, 220, 659 perror, 415 pow, 655 printf, 102 putchar, 119 puts, 203 rand, 656 realloc, 302 rewind, 418 scanf, 81, 108 setvbuf, 438 sin, 653 función sinh, 653 sprintf, 649 sqrt, 655 srand, 656 strcat, 640 strchr, 640 strcmp, 642 strcpy, 640 strcspn, 643 strlen, 644 strlwr, 647 strncat, 644 strncmp, 645 strncpy, 645 strrchr, 641 strspn, 645 strstr, 646 strtok, 646 strupr, 647 system, 128 tan, 653 tanh, 654 time, 657 tmpfile, 441 toascii, 650 tolower, 650 toupper, 650 fwrite, 428
H Hanoi, 595 hash, 619 hexadecimal, 36
I identificadores, 38 if anidados, 141 impresora, 434 include, 68 indirección, 52, 288 inorden, 544 inserción, 600 insertar nodo, 550 insertar un elemento en una lista, 501 int, 28 interfaz genérica, 509 intérprete, 4
L
G gdb, 679 getch, 120
lagunas de memoria, 301 leer con formato, 108 leer de un fichero, 433 leer un carácter, 118 lenguaje máquina, 3 lenguajes de alto nivel, 3 LF, 115 limpiar el buffer asociado con un flujo, 117 limpiar la pantalla, 128 línea de órdenes, 363, 668 LINUX, 678 lista circular, 520 lista circular doblemente enlazada, 533 lista doblemente enlazada, 533 lista lineal simplemente enlazada, 496 lista lineal, recorrer, 504 listas lineales, 496 literal, 35 literal de cadena de caracteres, 37 literal de un solo carácter, 36 literal entero, 35 literal real, 36
ÍNDICE
llamada a una función, 75 localtime, 658 log, 654 log10, 654 long, 28 long double, 32 LPT1, 435
M macro, 472 macro frente a función, 473 macros predefinidas, 475 main, 75 malloc, 299 matrices, 187, 188 matrices de punteros, 286 matrices dinámicas, 304 matrices dinámicas de cadenas de caracteres, 313 matrices dinámicas de dos dimensiones, 309 matrices dinámicas de una dimensión, 305 matriz, 15, 121 matriz asociativa, 196 matriz de cadenas de caracteres, 214 matriz de estructuras, 231 matriz de punteros a cadenas de caracteres, 291 matriz multidimensional, 209 matriz numérica multidimensional, 209 matriz sparse, 265 matriz static, 195 matriz, acceder a un elemento, 190 matriz, definir, 189 matriz, iniciar, 195 matriz, tipo y tamaño, 208 memcmp, 220, 660 memcpy, 220, 659 memoria intermedia, 404 memset, 220, 308, 659 mensajes de error, 415 método de inserción, 600 método de la burbuja, 598 método de quicksort, 602 mezcla natural, 611 milisegundos transcurridos desde el 1 de enero de 1970, 332
695
N nivel de indirección, 288 nodo de un árbol, 544 NULL, 276, 498 números aleatorios, 330
O octal, 35 operaciones con punteros, 271 operador #, 476 ##, 476 &, 51 *, 52 coma, 51 condicional, 49 defined, 479 sizeof, 50 ternario, 49 operadores, 42 a nivel de bits, 46 aritméticos, 42 de asignación, 47 de relación, 44 lógicos, 45 prioridad, 53 unitarios, 46 ordenación, 597 ordenar cadenas de caracteres, 295 ordenar un fichero, 610 ordenar un fichero utilizando acceso aleatorio, 616
P palabras clave, 38 pantalla, limpiar, 128 parámetros, 72, 74 path, 668 perror, 415 pila, 527 polinomios, 327 postorden, 545 pow, 655 precisión, 106 preorden, 544 preprocesador, 67, 471 printf, 102
696
C/C++: CURSO DE PROGRAMACIÓN
prioridad de los operadores, 53 programa, 2, 63 programa compuesto por varios ficheros, 81 prototipo de una función, 71 puntero, 79, 267 a un puntero, 288 a una cadena de caracteres, 282 a una función, 369 como argumento, 352 como parámetro, 320 de lectura/escritura, 417 definir, 267 genérico, 274 nulo, 276 punteros a estructuras, 317 asignación, 271 comparación, 274 const, 277 operaciones aritméticas, 272 operadores, 269 y matrices, 277 putchar, 119 puts, 203 putw, 422
Q quicksort, 602
R raíz de un árbol, 544 rand, 656 realloc, 302 reasignar un bloque de memoria, 302 recorrer un árbol, 544 recursión, 591 redireccionar la entrada o salida, 365 redireccionar stdin, stdout o stderr, 411 register, 86 registro, 402 registros, 427 retornar la dirección de una v. static, 361 retornar un puntero, 360 retornar una copia de los datos, 359 return, 74, 131 return vs exit, 302 rewind, 418
S scanf, 108, 123 secuencia de escape, 25 sentencia break, 163 compuesta, 70 continue, 164 de asignación, 100 do ... while, 157 for, 160 return, 74, 131 simple, 69 switch, 147 while, 151 set, 668 setvbuf, 438 short, 28 signed, 26 sin, 653 sinh, 653 sinónimos de otro tipo, 33 size_t, 300 sizeof, 50 sprintf, 208, 649 sqrt, 655 srand, 656 static, 86 stdaux, 405 stderr, 405 stdin, 102, 405 stdout, 102, 405 stdprn, 405 strcat, 640 strchr, 640 strcmp, 208, 642 strcpy, 208, 640 strcspn, 643 stream, 403 strlen, 208, 644 strlwr, 647 strncat, 644 strncmp, 645 strncpy, 645 strrchr, 641 strspn, 645 strstr, 646 strtok, 646 struct, 222 strupr, 647
ÍNDICE
tolower, 208, 650 torres de Hanoi, 595 toupper, 208, 650 typedef, 33, 208, 223
subíndice, 189 switch, 147 sys_errlist, 416 sys_nerr, 416 system, 128
T tan, 653 tanh, 654 temporal, fichero, 441 tiempo de ejecución, 479 time, 332, 657 tipo, 104 abstracto de datos, 227 char, 27 double, 32 enumerado, 29 float, 31 int, 28 long, 28 long double, 32 short, 28 tipos de datos, 26 tipos derivados, 33 tipos primitivos, 26 tmpfile, 441 toascii, 650
U UNICODE, 689 unión, 234 UNIX, 678 unsigned, 26
V validar un dato de entrada, 124 variable, 40 global, 84 iniciar, 41 local, 84 Visual C++, 661 void, 73 void , 274
W while, 151 while, do, o for anidados, 154
697
Del mismo autor ● Curso de programación con PASCAL ● Curso de programación GW BASIC/BASICA ● Manual para TURBO BASIC Guía del programador ● Manual para Quick C 2 Guía del programador ● Manual para Quick BASIC 4.5 Guía del programador ● Curso de programación Microsoft COBOL ● Enciclopedia del lenguaje C ● Curso de programación QBASIC y MS-DOS 5 ● Curso de programación RM/COBOL-85 ● El abecé de MS-DOS 6 ● Microsoft Visual C ++ (ver. 1.5x de 16 bits) Aplicaciones para Windows ● Microsoft Visual C ++ Aplicaciones para Win32 (2.ª edición) ● Microsoft Visual C ++ Programación avanzada en Win32 ● Visual Basic 6 Curso de programación (2.ª edición) ● Enciclopedia de Microsoft Visual Basic 6 ● El lenguaje de programación Java ● El lenguaje de programación C#
ISBN: 978-84-86381-36-3 224 págs. ISBN: 978-84-86381-87-5 320 págs. ISBN: 978-84-86381-43-1 444 págs. ISBN: 978-84-86381-65-3 540 págs. ISBN: 978-84-86381-74-5 496 págs. ISBN: 978-84-7897-001-8 480 págs. ISBN: 978-84-7897-053-7 888 págs. ISBN: 978-84-7897-059-9 384 págs. ISBN: 978-84-7897-070-4 396 págs. ISBN: 978-84-7897-114-5 224 págs. ISBN: 978-84-7897-180-0 846 págs. + 2 disquetes ISBN: 978-84-7897-561-7 792 págs. + disquete ISBN: 978-84-7897-344-6 888 págs. + CD-ROM ISBN: 978-84-7897-357-6 528 págs. + disquete ISBN: 978-84-7897-386-6 1.072 págs. + CD-ROM ISBN: 978-84-7897-485-6 320 págs. + CD-ROM ISBN: 978-84-7897-500-6 320 págs. + CD-ROM
Del mismo autor ● El lenguaje de programación Visual Basic.NET ● Java 2 Lenguaje y aplicaciones ● Programación orientada a objetos con C ++ (4.ª edición) ● C/C++ Curso de programación (3.ª edición) ● Microsoft C# Lenguaje y aplicaciones (2.ª edición) ● Aplicaciones .Net multiplataforma (Proyecto Mono) ● Enciclopedia del lenguaje C ++ (2.ª edición) ● Microsoft Visual Basic .NET Lenguaje y aplicaciones (3.ª edición) ● Java 2 Curso de programación (4.ª edición) ● Microsoft C# Curso de programación (2.ª edición) ● Visual C#. Interfaces gráficas y aplicaciones para Internet con WPF, WCF y Silverlight ● Visual Basic. Interfaces gráficas y aplicaciones para Internet con WPF, WCF y Silverlight ● Enciclopedia de Microsoft Visual C#. Interfaces gráficas y aplicaciones para Internet con Windows Forms y ASP.NET (4.ª edición) ● Enciclopedia de Microsoft Visual Basic. Interfaces gráficas y aplicaciones para Internet con Windows Forms y ASP.NET (3.ª edición) ● Java. Interfaces gráficas y aplicaciones para Internet (4.ª edición)
ISBN: 978-84-7897-525-9 464 págs. + CD-ROM ISBN: 978-84-7897-745-1 392 págs. + CD-ROM ISBN: 978-84-7897-761-1 648 págs. + CD-ROM ISBN: 978-84-7897-762-8 708 págs. + CD-ROM ISBN: 978-84-7897-813-7 520 págs. + CD-ROM ISBN: 978-84-7897-880-9 212 págs. + CD-ROM ISBN: 978-84-7897-915-8 902 págs. + CD-ROM ISBN: 978-84-9964-020-4 520 págs. + CD-ROM ISBN: 978-84-9964-032-7 820 págs. + CD-ROM ISBN: 978-84-9964-068-6 850 págs. + CD-ROM ISBN: 978-84-9964-203-1 956 págs. + CD-ROM ISBN: 978-84-9964-204-8 938 págs. + CD-ROM ISBN: 978-84-7897-986-8 1.145 págs. + CD-ROM ISBN: 978-84-7897-987-5 1.125 págs. + CD-ROM ISBN: 978-84-9964-522-3 1.000 págs. + ZIP
INSTALACIÓN Para instalar el kit de desarrollo de C/C++ y los ejemplos de este libro, descargue de Internet el paquete correspondiente al EDI preferido por usted (Microsoft Visual Studio, NetBeans, Code::Blocks, etc.) e instálelo. Después, proceda según se indica en el apéndice B.
SOBRE LOS EJEMPLOS DEL LIBRO El material adicional de este libro, con las aplicaciones desarrolladas y el software para reproducirlas, puede descargarlo desde http://www.fjceballos.es (sección Mis publicaciones > C/C++ > Material adicional) o desde http://www.ra-ma.com (en la página correspondiente al libro). La descarga consiste en un fichero ZIP con una contraseña que encontrará en el libro.
LICENCIA Los paquetes de software a los que se hace referencia en el material adicional del libro es propiedad de las firmas que los representan. La inclusión en este libro se debe a su gentileza y es totalmente gratuita y con la finalidad de apoyar el aprendizaje del software correspondiente. Para obtener más información y actualizaciones, visite las direcciones indicadas en dicho software. Al realizar el proceso de instalación, haga el favor de consultar el acuerdo de licencia para cada uno de los productos.
WEB DEL AUTOR: http://www.fjceballos.es En esta web podrá echar una ojeada a mis publicaciones más recientes y acceder a la descarga del software necesario para el estudio de esta obra, así como a otros recursos.