Diferencias
Muestra las diferencias entre dos versiones de la página.
| Ambos lados, revisión anteriorRevisión previaPróxima revisión | Revisión previa | ||
| el_lenguaje_de_programacion_c [2024/09/27 22:26] – peron | el_lenguaje_de_programacion_c [2026/04/21 16:06] (actual) – editor externo 127.0.0.1 | ||
|---|---|---|---|
| Línea 2: | Línea 2: | ||
| Este es un ejemplar amorosamente wikificado por ~peron de //El Lenguaje de Programación C//, 2da Edición, de B. Kerningham y D. Ritchie, adaptado para [[hacker|hackers]] del Tercer Mundo. | Este es un ejemplar amorosamente wikificado por ~peron de //El Lenguaje de Programación C//, 2da Edición, de B. Kerningham y D. Ritchie, adaptado para [[hacker|hackers]] del Tercer Mundo. | ||
| + | |||
| + | ==== Prefacios ==== | ||
| [[El lenguaje de programación C - Prefacios|Prefacios]] | [[El lenguaje de programación C - Prefacios|Prefacios]] | ||
| + | ==== Capítulos ==== | ||
| - | =====Introducción===== | + | [[El lenguaje de programación C - Introducción|Introducción]] |
| - | + | ||
| - | C es un lenguaje de programación de propósito general que ha sido estrechamente asociado con el sistema UNIX en donde fue desarrollado puesto que tanto el sistema como los programas que corren en él están escritos en lenguaje C. Sin embargo, este lenguaje no está ligado a ningún sistema operativo ni a ninguna máquina, y aunque se le llama “lenguaje de programación de sistemas” debido a su utilidad para escribir compiladores y sistemas operativos, se utiliza con igual eficacia para escribir importantes programas en diversas disciplinas. | + | |
| - | + | ||
| - | Muchas de las ideas importantes de C provienen del lenguaje BCPL, desarrollado por Martin Richards. La influencia de BCPL sobre C se continuó indirectamente a través del lenguaje B, el cual fue escrito por Ken Thompson en 1970 para el primer sistema UNIX de la DEC PDP-7. | + | |
| - | + | ||
| - | BCPL y B son lenguajes “carentes de tipos”. En contraste, C proporciona una variedad de tipos de datos. Los tipos fundamentales son caracteres, enteros y números de punto flotante de varios tamaños. Además, existe una jerarquía de tipos de datos derivados, creados con apuntadores, | + | |
| - | + | ||
| - | C proporciona las construcciones fundamentales de control de flujo que se requieren en programas bien estructurados: | + | |
| - | + | ||
| - | Las funciones pueden regresar valores de tipos básicos, estructuras, | + | |
| - | + | ||
| - | Un paso de preprocesamiento realiza substitución de macros en el texto del programa, inclusión de otros archivos fuente y compilación condicional. | + | |
| - | + | ||
| - | C es un lenguaje de relativo “bajo nivel”. Esta caracterización no es peyorativa, simplemente significa que C trata con el mismo tipo de objetos que la mayoría de las computadoras, | + | |
| - | + | ||
| - | C no proporciona operaciones para tratar directamente con objetos compuestos, tales como cadenas de caracteres, conjuntos, listas o arreglos. No existen operaciones que manipulen un arreglo o una cadena completa, aunque las estructuras pueden copiarse como una unidad. El lenguaje no define ninguna facilidad para asignación de almacenamiento que no sea la de definición estática y la disciplina de pilas provista por las variables locales de funciones; no emplea heap ni recolector de basura. Finalmente, C en sí mismo no proporciona capacidades de entrada/ | + | |
| - | + | ||
| - | De manera semejante, C solamente ofrece un control de flujo franco, y lineal: condiciones, | + | |
| - | + | ||
| - | Aunque la ausencia de alguna de esas capacidades puede parecer como una grave deficiencia (“¿significa que se tiene que llamar a una función para comparar dos cadenas de caracteres? | + | |
| - | + | ||
| - | Por muchos años, la definición de C fue el manual de referencia de la primera edición de El lenguaje de programación C. En 1983, el American National Standards Institute (ANSI) estableció un comité para proporcionar una moderna y comprensible definición de C. La definición resultante, el estándar ANSI o “ANSI C” , se esperaba fuera aprobada a fines de 1988. La mayoría de las características del estándar ya se encuentran soportadas por compiladores modernos. | + | |
| - | + | ||
| - | El estándar está basado en el manual de referencia original. El lenguaje ha cambiado relativamente poco; uno de los propósitos del estándar fue asegurar que la mayoría de los programas existentes pudiesen permanecer válidos o, al menos, que los compiladores pudieran producir mensajes de advertencia acerca del nuevo comportamiento. | + | |
| - | + | ||
| - | Para la mayoría de los programadores, | + | |
| - | + | ||
| - | Existen otros cambios de menor escala en el lenguaje. La asignación de estructuras y enumeraciones, | + | |
| - | + | ||
| - | Una segunda contribución significativa dei estándar es la definición de una biblioteca que acompañe a C. Esta especifica funciones para tener acceso al sistema operativo (por ejemplo, leer de archivos y escribir en ellos), entrada y salida con formato, asignación de memoria, manipulación de cadenas y otras actividades semejantes. Una colección de encabezadores (headers) estándar proporcionan un acceso uniforme a las declaraciones de funciones y tipos de datos. Los programas que utilizan esta biblioteca para interactuar con un sistema anfitrión están asegurados de un com portam iento com patible. La m ayor parte de la biblioteca está estrecham ente modelada con base en la “biblioteca E/S estándar" | + | |
| - | + | ||
| - | Debido a que los tipos de datos y estructuras de control provistas por C son manejadas directamente por la mayoría de las computadoras, | + | |
| - | + | ||
| - | Aunque C coincide con las capacidades de muchas com putadoras, es independiente de cualquier arquitectura. Con un poco de cuidado es fácil escribir programas portátiles, | + | |
| - | + | ||
| - | C no es un lenguaje fuertemente tipificado, sino que, al evolucionar, | + | |
| - | + | ||
| - | Sin embargo, C mantiene la filosofía básica de que los programadores saben lo Que están haciendo; sólo requiere que establezcan sus intenciones en forma explícita. | + | |
| - | + | ||
| - | Como cualquier otro lenguaje, C tiene sus defectos. Algunos de los operadores tienen la precedencia equivocada; algunos elementos de la sintaxis pueden ser mejores. A pesar de todo, C ha probado ser un lenguaje extremadamente efectivo y expresivo p ara una am plia variedad de program as de aplicación. | + | |
| - | + | ||
| - | El libro está organizado com o sigue. El capítulo 1 es una introducción orientada a la parte central de C. El propósito es hacer que el lector se inicie tan pronto como le sea posible, puesto que creemos firmemente que la forma de aprender un nuevo lenguaje es escribir program as en él. La introducción supone un conocimiento práctico de los elementos básicos de la programación; | + | |
| - | + | ||
| - | En los capítulos del 2 al 6 se discuten varios aspectos de C en mayor detalle y más formalmente de lo que se hace en el capítulo 1, aunque el énfasis está aún en los ejemplos de programas completos, más que en fragmentos aislados. El capítulo 2 trata de los tipos básicos de datos, operaciones y expresiones. El capítulo 3 trata sobre control de flujo: if-else, switch, while, for, etc. En el capítulo 4 se cubren funciones y la estructura de un programa —variables externas, reglas de alcance, archivos fuente múltiples y otros aspectos— y también abarca al preprocesador. El capítulo 5 discute sobre apuntadores y aritmética de direcciones. | + | |
| - | + | ||
| - | El capítulo 6 cubre estructuras y uniones. | + | |
| - | + | ||
| - | El capítulo 7 describe la biblioteca estándar, la cual proporciona una interfaz común con el sistema operativo. Esta biblioteca está definida por el estándar ANSI y se intenta que se tenga en todas las máquinas que manejan C; así, los programas que la usen para entrada, salida y otros accesos al sistema operativo se puedan transportar de un sistema a otro sin cambios. | + | |
| - | + | ||
| - | El capítulo 8 describe una interfaz entre los programas en C y el sistema operativo UNIX, concentrándose en entrada/ | + | |
| - | + | ||
| - | El apéndice A contiene un manual de consulta del lenguaje. El informe oficial de la sintaxis y la semántica de C es en sí el estándar ANSI. Ese documento, sin embargo, está principalmente pensado para quienes escriben compiladores. El manual de consulta de este libro transmite la definición del lenguaje en una forma más concisa y sin el mismo estilo legalista. El apéndice B es un resumen de la biblioteca estándar, de nuevo más para usuarios que para implantadores. El apéndice C es un breve resumen de los cambios del lenguaje original. A unque, en caso de duda, el estándar y el compilador en uso quedan como las autoridades finales sobre el lenguaje. | + | |
| - | + | ||
| - | [[El lenguaje | + | |
| - | + | ||
| - | + | ||
| - | =====Capitulo 2: Tipos, Operadores y Expresiones====== | + | |
| - | + | ||
| - | Las variables y las constantes son los objetos de datos básicos que se manipulan en un programa. Las declaraciones muestran las variables que se van a utilizar y establecen el tipo que tienen y algunas veces cuáles son sus valores iniciales. Los operadores especifican lo que se hará con las variables. Las expresiones combinan variables y constantes para producir nuevos valores. El tipo de un objeto determina el conjunto de valores que puede tener y qué operaciones se pueden realizar sobre él. Estos son los temas de este capítulo. | + | |
| - | + | ||
| - | El estándar ANSI ha hecho muchos pequeños cambios y agregados a los tipos básicos y a las expresiones. Ahora hay formas '' | + | |
| - | + | ||
| - | ====2.1 Nombres de variables==== | + | |
| - | + | ||
| - | Aunque no lo mencionamos en el capítulo 1, existen algunas restricciones en los nombre de las variables y de las constantes simbólicas. Los nombres se componen de letras y dígitos; el primer carácter debe ser una letra. El carácter de subrayado "'' | + | |
| - | de tal manera que '' | + | |
| - | + | ||
| - | Al menos los primeros 31 caracteres de un nombre interno son significativos, | + | |
| - | + | ||
| - | Es conveniente elegir nombres que estén relacionados con el propósito de la variable, que no sea probable confundirlos tipográficamente. Por estilo, nosotros tendemos a utilizar nombres cortos para variables locales (especialmente índices de iteraciones), | + | |
| - | + | ||
| - | ====2.2 Tipos y tamaños de datos==== | + | |
| - | + | ||
| - | Hay unos cuantos tipos de datos básicos en C: | + | |
| - | + | ||
| - | |'' | + | |
| - | |'' | + | |
| - | |'' | + | |
| - | |'' | + | |
| - | + | ||
| - | Además, existen algunos calificadores que se aplican a estos tipos básicos, '' | + | |
| - | + | ||
| - | short int sh; | + | |
| - | long int counter; | + | |
| - | + | ||
| - | La palabra '' | + | |
| - | + | ||
| - | La intención es que '' | + | |
| - | + | ||
| - | El calificador '' | + | |
| - | Los números // | + | |
| - | + | ||
| - | El tipo '' | + | |
| - | + | ||
| - | Los archivos de encabezado headers estándar ''< | + | |
| - | + | ||
| - | * **Ejercicio 2-1**. Escriba un programa para determinar los rangos de variables '' | + | |
| - | + | ||
| - | ====2.3 Constantes==== | + | |
| - | + | ||
| - | Una constante entera como '' | + | |
| - | + | ||
| - | Las constantes de punto flotante contienen un punto decimal ('' | + | |
| - | + | ||
| - | El valor de un entero puede especificarse en forma octal o hexadecimal en lugar de decimal. Un '' | + | |
| - | + | ||
| - | Una //constante de carácter// es un entero, escrito como un carácter dentro de apóstrofos, | + | |
| - | + | ||
| - | Ciertos caracteres pueden ser representados en constante de carácter y de cadena, Por medio de secuencias de escape como ''< | + | |
| - | + | ||
| - | <code c> | + | |
| - | ' | + | |
| - | </ | + | |
| - | + | ||
| - | en donde '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | ' | + | |
| - | </ | + | |
| - | + | ||
| - | en donde '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | #define VTAB ' | + | |
| - | #define BELL ' | + | |
| - | </ | + | |
| - | + | ||
| - | o, en hexadecimal, | + | |
| - | + | ||
| - | <code c> | + | |
| - | #define VTAB ' | + | |
| - | #define BELL ' | + | |
| - | </ | + | |
| - | + | ||
| - | + | ||
| - | La constante de carácter ''< | + | |
| - | + | ||
| - | El conjunto completo de secuencias de escape es | + | |
| - | + | ||
| - | ^Secuencia de Escape ^Caracter ASCII ^ | + | |
| - | |''< | + | |
| - | |''< | + | |
| - | |''< | + | |
| - | |''< | + | |
| - | |''< | + | |
| - | |''< | + | |
| - | |''< | + | |
| - | |''< | + | |
| - | |''< | + | |
| - | |''< | + | |
| - | |''< | + | |
| - | |''< | + | |
| - | |''< | + | |
| - | |''< | + | |
| - | + | ||
| - | Una // | + | |
| - | + | ||
| - | <code c> | + | |
| - | #define MAXLINE 1000 | + | |
| - | char line[MAXLINE+1]; | + | |
| - | </ | + | |
| - | + | ||
| - | o | + | |
| - | + | ||
| - | <code c> | + | |
| - | #define BISIESTO 1 /* en años bisiestos */ | + | |
| - | int days[31+28+BISIESTO+31+30+31+30+31+31+30+31+30+31]; | + | |
| - | </ | + | |
| - | + | ||
| - | Una //constante de cadena// o //cadena literal//, es una secuencia de cero o más caracteres encerrados entre comillas, como en | + | |
| - | + | ||
| - | <code c> | + | |
| - | "Soy una cadena" | + | |
| - | </ | + | |
| - | + | ||
| - | o | + | |
| - | + | ||
| - | <code c> | + | |
| - | ""/ | + | |
| - | </ | + | |
| - | + | ||
| - | Las comillas no son parte de la cadena, sólo sirven para delimitarla. Las mismas secuencias de escape utilizadas en constantes de carácter se aplican en cadenas; ''< | + | |
| - | + | ||
| - | <code c> | + | |
| - | "Viva " " | + | |
| - | </ | + | |
| - | + | ||
| - | es equivalente a | + | |
| - | + | ||
| - | <code c> | + | |
| - | "Viva Peron!" | + | |
| - | </ | + | |
| - | + | ||
| - | Esto es útil para separar cadenas largas entre varias líneas de código fuente. | + | |
| - | + | ||
| - | Técnicamente, | + | |
| - | + | ||
| - | <code c> | + | |
| - | /* strlen: | + | |
| - | int strlen(char s[]) | + | |
| - | { | + | |
| - | int i; | + | |
| - | while (s[i] != ' | + | |
| - | ++i; | + | |
| - | return i; | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | '' | + | |
| - | + | ||
| - | Se debe ser cuidadoso al distinguir entre una constante de carácter y una cadena que contiene un sólo carácter: ''< | + | |
| - | + | ||
| - | Existe otra clase de constante, la //constante de enumeración// | + | |
| - | + | ||
| - | <code c> | + | |
| - | enum boolean {NO, SI}; | + | |
| - | </ | + | |
| - | + | ||
| - | El primer nombre en un '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | enum escapes { BELL = ' | + | |
| - | | + | |
| - | + | ||
| - | enum months { ENE = 1, FEB, MAR, ABR, MAY, JUN, | + | |
| - | JUL, AGO, SEP, OCT, NOV, DIC}; | + | |
| - | /* FEB es 2, MAR es 3, etc. */ | + | |
| - | </ | + | |
| - | + | ||
| - | Los nombres que están en enumeraciones diferentes deben ser distintos. Los valores no necesitan ser distintos d entro de la misma enumeración. | + | |
| - | + | ||
| - | Las enumeraciones proporcionan una manera conveniente de asociar valores constantes con nombres, una alternativa a ''# | + | |
| - | + | ||
| - | ==== 2.4 Declaraciones ==== | + | |
| - | + | ||
| - | Todas las variables deben ser declaradas antes de su uso, aunque ciertas declaraciones pueden ser hechas en forma implícita por el contexto. Una declaración especifica un tipo, y contiene una lista de una o más variables de ese tipo, como en | + | |
| - | + | ||
| - | <code c> | + | |
| - | int inferior, superior, paso; | + | |
| - | char c, line [1000]; | + | |
| - | </ | + | |
| - | + | ||
| - | Las variables pueden ser distribuidas entre las declaraciones en cualquier forma; la lista de arriba podría igualmente ser escrita como | + | |
| - | + | ||
| - | <code c> | + | |
| - | int inferior; | + | |
| - | int superior; | + | |
| - | int paso; | + | |
| - | char c; | + | |
| - | char line [1000]; | + | |
| - | </ | + | |
| - | + | ||
| - | Esta última forma ocupa más espacio, pero resulta conveniente para agregar un comentario a cada declaración o para realizar subsecuentes modificaciones. | + | |
| - | + | ||
| - | Una variable también puede ser inicializada en su declaración. Si el nombre es seguido por un signo de igual y una expresión, la expresión sirve como un inicializador, | + | |
| - | + | ||
| - | <code c> | + | |
| - | char esc = ' | + | |
| - | int i = 0; | + | |
| - | int limit = MAXLINE + 1; | + | |
| - | float eps = l.0e—5; | + | |
| - | </ | + | |
| - | + | ||
| - | Si la variable en cuestión no es automática, | + | |
| - | + | ||
| - | El calificador '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | const double e = 2.71828182845905; | + | |
| - | const char msg[] = " | + | |
| - | </ | + | |
| - | + | ||
| - | La declaración '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | int strlen(const char[]); | + | |
| - | </ | + | |
| - | + | ||
| - | Si se efectúa un intento de cambiar un '' | + | |
| - | + | ||
| - | ====2.5 Operadores aritméticos==== | + | |
| - | + | ||
| - | Los operadores aritméticos binarios son '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | x % y | + | |
| - | </ | + | |
| - | + | ||
| - | produce el residuo cuando '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) | + | |
| - | printf(" | + | |
| - | else | + | |
| - | printf(" | + | |
| - | </ | + | |
| - | + | ||
| - | El operador '' | + | |
| - | + | ||
| - | Los operadores binarios '' | + | |
| - | + | ||
| - | La [[#tabla 2-1|tabla 2-1]] que se encuentra al final de este capítulo, resume la precedencia y asociatividad para todos los operadores. | + | |
| - | + | ||
| - | ==== 2.6 Operadores de relación y lógicos ==== | + | |
| - | + | ||
| - | Los // | + | |
| - | + | ||
| - | |''< | + | |
| - | |''< | + | |
| - | |''< | + | |
| - | |''< | + | |
| - | + | ||
| - | Todos ellos tienen la misma precedencia. Precisamente bajo ellos en precedencia están los // | + | |
| - | + | ||
| - | |''< | + | |
| - | |''< | + | |
| - | + | ||
| - | Los operadores de relación tienen precedencia inferior que los operadores aritméticos, | + | |
| - | + | ||
| - | Más interesantes son los // | + | |
| - | + | ||
| - | <code c> | + | |
| - | for (i=0; i < lim-1 && (c=getchar()) != ' | + | |
| - | s[i] = c; | + | |
| - | </ | + | |
| - | + | ||
| - | Antes de leer un nuevo carácter es necesario verificar que hay espacio para almacenarlo en el arreglo '' | + | |
| - | + | ||
| - | De manera semejante, seria desafortunado si '' | + | |
| - | + | ||
| - | La precedencia de ''&&'' | + | |
| - | + | ||
| - | <code c> | + | |
| - | i < lim-1 && (c=getchar()) != ' | + | |
| - | </ | + | |
| - | + | ||
| - | no requieren de paréntesis adicionales. Pero puesto que la precedencia de '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | (c=getchar()) != ' | + | |
| - | </ | + | |
| - | + | ||
| - | para obtener el resultado deseado de asignación a '' | + | |
| - | + | ||
| - | Por definición, | + | |
| - | + | ||
| - | El operador unario de negación '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | if (!nvalido) | + | |
| - | </ | + | |
| - | + | ||
| - | en lugar de | + | |
| - | + | ||
| - | <code c> | + | |
| - | if (valido == 0) | + | |
| - | </ | + | |
| - | + | ||
| - | Es difícil generalizar acerca de cuál es la mejor. Construcciones como '' | + | |
| - | + | ||
| - | * **Ejercicio 2-2**. Escriba un ciclo equivalente a la iteración '' | + | |
| - | + | ||
| - | ====2.7 Conversiones de tipo==== | + | |
| - | + | ||
| - | Cuando un operador tiene operandos de tipos diferentes, éstos se convierten a un tipo común de acuerdo con un reducido núm ero de reglas. En general, las únicas conversiones automáticas son aquellas que convierten un operando “angosto” en uno “amplio” sin pérdida de información, | + | |
| - | + | ||
| - | Un '' | + | |
| - | su equivalente numérico. | + | |
| - | + | ||
| - | <code c> | + | |
| - | /* atoi: convierte s en entero */ | + | |
| - | int atoi(char s[]) | + | |
| - | { | + | |
| - | int i, n; | + | |
| - | + | ||
| - | n = 0; | + | |
| - | for (i = 0; s[i] >= ' | + | |
| - | n = 10 * n + (s[i] - ' | + | |
| - | return n; | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | Tal com o se discutió en el [[#capitulo 1|capítulo 1]], la expresión | + | |
| - | + | ||
| - | <code c> | + | |
| - | s[i] - ' | + | |
| - | </ | + | |
| - | + | ||
| - | da el valor numérico del carácter almacenado en '' | + | |
| - | + | ||
| - | Otro ejemplo de conversión de '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | /* lower: convierte c a minúscula; solamente ASCII */ | + | |
| - | int lower(int c) | + | |
| - | { | + | |
| - | if (c >= ' | + | |
| - | return c + ' | + | |
| - | else | + | |
| - | return c; | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | Esto funciona en ASCII puesto que las correspondientes letras mayúsculas y minúsculas se encuentran a una distancia fija como valores numéricos y cada alfabeto es contiguo (no hay sino letras entre '' | + | |
| - | + | ||
| - | El header estándar ''< | + | |
| - | prueba | + | |
| - | + | ||
| - | <code c> | + | |
| - | c >= ' | + | |
| - | </ | + | |
| - | + | ||
| - | puede reemplazarse por | + | |
| - | + | ||
| - | <code c> | + | |
| - | isdigit(c) | + | |
| - | </ | + | |
| - | + | ||
| - | Nosotros utilizaremos las funciones de ''< | + | |
| - | + | ||
| - | La respuesta varía de una máquina a otra, reflejando diferencias en la arquitectura. En algunas máquinas un '' | + | |
| - | + | ||
| - | La definición de C garantiza que ningún carácter que esté en el conjunto estándar de caracteres de impresión de la máquina será negativo, de modo que esos caracteres siempre serán cantidades positivas en las expresiones. Pero hay patrones arbitrarios de bits almacenados en variables de tipo carácter que pueden aparecer como negativos en algunas máquinas, aunque sean positivos en otras - por razones de portabilidad - se debe especificar '' | + | |
| - | + | ||
| - | Las expresiones de relación como '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | d = c >= ' | + | |
| - | </ | + | |
| - | + | ||
| - | vuelve '' | + | |
| - | + | ||
| - | Las conversiones aritméticas implícitas trabajan como se espera. En general, si un operador como '' | + | |
| - | + | ||
| - | * Siendo cualquier operando '' | + | |
| - | * De otra manera, siendo cualquier operando '' | + | |
| - | * De otra manera, siendo cualquier operando '' | + | |
| - | * De otra manera, conviértase '' | + | |
| - | * Luego, siendo cualquier operando '' | + | |
| - | + | ||
| - | Nótese que los '' | + | |
| - | + | ||
| - | Cuando hay operandos '' | + | |
| - | + | ||
| - | Las conversiones también tienen lugar en las asignaciones; | + | |
| - | + | ||
| - | Un carácter es convertido a un entero, tenga o no extensión de signo, como se describió anteriormente. | + | |
| - | + | ||
| - | Los enteros más largos son convertidos a cortos o a '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | int i; | + | |
| - | char c; | + | |
| - | + | ||
| - | i = c; | + | |
| - | c = i; | + | |
| - | </ | + | |
| - | + | ||
| - | el valor de '' | + | |
| - | + | ||
| - | Si '' | + | |
| - | + | ||
| - | Puesto que un argumento de la llamada a una función es una expresión, también suceden conversiones de tipo cuando se pasan argumentos a funciones. En ausencia del prototipo de una función, '' | + | |
| - | + | ||
| - | Finalmente, la conversión explícita de tipo puede ser forzada (“coaccionada” ) en cualquier expresión, con un operador unario llamado //cast//. En la construcción | + | |
| - | + | ||
| - | < | + | |
| - | (nombre-de-tipo) expresión | + | |
| - | </ | + | |
| - | + | ||
| - | la // | + | |
| - | + | ||
| - | <code c> | + | |
| - | sqrt((double) n) | + | |
| - | </ | + | |
| - | + | ||
| - | para convertir el valor de '' | + | |
| - | + | ||
| - | Si un prototipo de función declara argumentos, como debe ser normalmente, | + | |
| - | + | ||
| - | <code c> | + | |
| - | double sqrt(double) | + | |
| - | </ | + | |
| - | + | ||
| - | la llamada | + | |
| - | + | ||
| - | <code c> | + | |
| - | root2 = sqrt(2) | + | |
| - | </ | + | |
| - | + | ||
| - | obliga al entero '' | + | |
| - | + | ||
| - | La biblioteca estándar incluye una implantación transportable de un generador de números pseudoalealorios, | + | |
| - | + | ||
| - | <code c> | + | |
| - | unsigned long int next = 1; | + | |
| - | + | ||
| - | /* rand: regresa un entero pseudoaleatorio en 0..32767 */ | + | |
| - | int rand(void) | + | |
| - | { | + | |
| - | next = next * 1103515245 + 12345; | + | |
| - | return (unsigned int)(next/ | + | |
| - | } | + | |
| - | /* srand: set seed for rand() */ | + | |
| - | void srand(unsigned int seed) | + | |
| - | { | + | |
| - | next = seed; | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | * **Ejercicio 2-3**. Escriba la función '' | + | |
| - | + | ||
| - | ==== 2.8 Operadores de incremento y decremento ==== | + | |
| - | + | ||
| - | El lenguaje C proporciona dos operadores poco comunes para incrementar y decrementar variables. El //operador de aumento// '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | if (c == ' | + | |
| - | | + | |
| - | </ | + | |
| - | + | ||
| - | El aspecto poco común es que '' | + | |
| - | '' | + | |
| - | + | ||
| - | Si '' | + | |
| - | + | ||
| - | x = n++; | + | |
| - | + | ||
| - | asigna '' | + | |
| - | + | ||
| - | x = ++n; | + | |
| - | + | ||
| - | hace que '' | + | |
| - | es ilegal. | + | |
| - | + | ||
| - | Dentro de un contexto en donde no se desea ningún valor, sino sólo el efecto de incremento, como en | + | |
| - | + | ||
| - | <code c> | + | |
| - | if (c == ' | + | |
| - | nl++; | + | |
| - | </ | + | |
| - | + | ||
| - | prefijos y postfijos son iguales. Pero existen situaciones en donde se requiere específicam ente unou otro. Por ejemplo, considérese la función '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | /* squeeze: borra todas las c de s */ | + | |
| - | void squeeze(char s[], int c) | + | |
| - | { | + | |
| - | int i, j; | + | |
| - | for (i = j = 0; s[i] != ' | + | |
| - | if (s[i] != c) | + | |
| - | | + | |
| - | s[j] = ' | + | |
| - | } | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | Cada vez que se encuentra un valor diferente de '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | if (s[i] != c) { | + | |
| - | s[j] = s[i]; | + | |
| - | j++; | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | Otro ejemplo de construcción semejante viene de la función '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | if (c == ' | + | |
| - | s[i] = c; | + | |
| - | ++i; | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | por algo más compacto como | + | |
| - | + | ||
| - | <code c> | + | |
| - | if (c == ' | + | |
| - | s[i++] = c; | + | |
| - | </ | + | |
| - | + | ||
| - | Como un tercer ejemplo, considérese que la función estándar '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | /* strcat: concatena t al final de s; s debe ser suficientemente grande *1 | + | |
| - | void strcat(char s[], char t[]) | + | |
| - | { | + | |
| - | int i, j; | + | |
| - | + | ||
| - | i = j = 0; | + | |
| - | while (s[i] != ' | + | |
| - | i++; | + | |
| - | while ((s[i++] = t[j++]) != ' | + | |
| - | ; | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | Como cada carácter es copiado de '' | + | |
| - | + | ||
| - | * **Ejercicio 2-4**. Escriba una versión alterna de '' | + | |
| - | * **Ejercicio 2-5**. Escriba la función '' | + | |
| - | + | ||
| - | ==== 2.9 Operadores para manejo de bits ==== | + | |
| - | + | ||
| - | El lenguaje C proporciona seis operadores para manejo de bits; sólo pueden ser aplicados a operandos integrales, esto es, '' | + | |
| - | + | ||
| - | |''&'' | + | |
| - | |'' | + | |
| - | |'' | + | |
| - | |''< | + | |
| - | |''< | + | |
| - | |'' | + | |
| - | + | ||
| - | El operador //AND// de bits ''&'' | + | |
| - | + | ||
| - | <code c> | + | |
| - | n = n & 0177; | + | |
| - | </ | + | |
| - | + | ||
| - | hace cero todos los bits de '' | + | |
| - | + | ||
| - | El operador //OR// de bits '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | x = x | SET_ON; | + | |
| - | </ | + | |
| - | + | ||
| - | fija en uno a todos los bits de '' | + | |
| - | + | ||
| - | El operador //OR// exclusivo '' | + | |
| - | + | ||
| - | Se deben distinguir los operadores de bits ''&'' | + | |
| - | + | ||
| - | Los operadores de corrimiento ''< | + | |
| - | + | ||
| - | El operador unario '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | x = x & ~077 | + | |
| - | </ | + | |
| - | + | ||
| - | fija los últimos seis bits de '' | + | |
| - | + | ||
| - | Como ilustración de algunos de los operadores de bits, considere la función '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | /* getbits: obtiene n bits desde la posición p */ | + | |
| - | unsigned getbits(unsigned x, int p, int n) | + | |
| - | { | + | |
| - | return (x >> (p+1-n)) & ~(~0 << n); | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | La expresión ''< | + | |
| - | + | ||
| - | + | ||
| - | * **Ejercicio 2-6**. Escriba una función '' | + | |
| - | * **Ejercicio 2-7**. Escriba una función '' | + | |
| - | principian en la posición '' | + | |
| - | * **Ejercicio 2-8**. Escriba una función '' | + | |
| - | + | ||
| - | ====2.10 Operadores de asignación y expresiones==== | + | |
| - | + | ||
| - | Las expresiones tales como | + | |
| - | + | ||
| - | <code c> | + | |
| - | i = i + 2 | + | |
| - | </ | + | |
| - | + | ||
| - | en las que la variable del lado izquierdo se repite inmediatamente en el derecho, pueden ser escritas en la forma compacta | + | |
| - | + | ||
| - | <code c> | + | |
| - | i += 2 | + | |
| - | </ | + | |
| - | + | ||
| - | El operador '' | + | |
| - | + | ||
| - | La mayoría de los operadores binarios (operadores como '' | + | |
| - | + | ||
| - | | '' | + | |
| - | + | ||
| - | Si //expr1// y //expr2// son expresiones, | + | |
| - | + | ||
| - | <code c> | + | |
| - | expr1 op— expr2 | + | |
| - | </ | + | |
| - | + | ||
| - | es equivalente a | + | |
| - | + | ||
| - | <code c> | + | |
| - | expr1 = (expr1) op (expr2) | + | |
| - | </ | + | |
| - | + | ||
| - | exceptuando que //expr1// se calcula sólo una vez. Nótense los paréntesis alrededor de // | + | |
| - | + | ||
| - | <code c> | + | |
| - | x *= y + 1 | + | |
| - | </ | + | |
| - | + | ||
| - | significa | + | |
| - | + | ||
| - | <code c> | + | |
| - | x = x * (y + 1) | + | |
| - | </ | + | |
| - | + | ||
| - | Y no | + | |
| - | + | ||
| - | <code c> | + | |
| - | x = x * y + 1 | + | |
| - | </ | + | |
| - | + | ||
| - | Como ejemplo, la función '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | /* bitcount: cuenta bits 1 en x */ | + | |
| - | int bitcount(unsigned x) | + | |
| - | { | + | |
| - | int b; | + | |
| - | + | ||
| - | for (b = 0; x != 0; x >>= 1) | + | |
| - | if (x & 01) | + | |
| - | b++; | + | |
| - | return b; | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | Declarar al argumento '' | + | |
| - | + | ||
| - | Muy aparte de su concisión, los operadores de asignación tienen la ventaja de que corresponden mejor con la forma en que la gente piensa. Decimos “suma 2 a i” o “incrementa i en 2” , no “toma i, agrégale 2, después pon el resultado de nuevo en i". Así la expresión '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | yyval[yypv[p3+p4] + yypv[p1]] += 2 | + | |
| - | </ | + | |
| - | el operador de asignación hace al código más fácil de entender, puesto que el lector no tiene que verificar arduamente que dos expresiones muy largas son en realidad iguales, o preguntarse por qué no lo son, y un operador de asignación puede incluso ayudar al compilador a producir código más eficiente. | + | |
| - | + | ||
| - | Ya hemos visto que la proposición de asignación tiene un valor y puede estar dentro de expresiones; | + | |
| - | + | ||
| - | <code c> | + | |
| - | while ((c = getchar()) != EOF) | + | |
| - | ... | + | |
| - | </ | + | |
| - | + | ||
| - | Los otros operadores de asignación ('' | + | |
| - | + | ||
| - | En todas esas expresiones, | + | |
| - | + | ||
| - | * **Ejercicio 2-9**. En un sistema de números de complemento a dos, '' | + | |
| - | + | ||
| - | ====2.11 Expresiones condicionales==== | + | |
| - | + | ||
| - | Las proposiciones | + | |
| - | + | ||
| - | <code c> | + | |
| - | if (a > b) | + | |
| - | z = a; | + | |
| - | else | + | |
| - | z = b; | + | |
| - | </ | + | |
| - | + | ||
| - | calculan en '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | expr1 ? expr2 : expr3 | + | |
| - | </ | + | |
| - | + | ||
| - | la expresión //expr1// es evaluada primero. Si es diferente de cero (verdadero), | + | |
| - | + | ||
| - | <code c> | + | |
| - | z = (a > b) ? a : b; /* z = max(a, b) */ | + | |
| - | </ | + | |
| - | + | ||
| - | Se debe notar que la expresión condicional es en sí una expresión, y se puede utilizar en cualquier lugar donde otra expresión pueda. Si //expr2// y //expr3// son de tipos diferentes, el tipo del resultado se determina por las reglas de conversión discutidas anteriormente en este capítulo. Por ejemplo, si '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | (n > 0) ? f : n | + | |
| - | </ | + | |
| - | + | ||
| - | es de tipo '' | + | |
| - | + | ||
| - | Los paréntesis no son necesarios alrededor de la primera expresión de una expresión condicional, | + | |
| - | + | ||
| - | La expresión condicional frecuentemente lleva a un código conciso. Por ejemplo, este ciclo imprimen elementos de un arreglo, 10 por línea, con cada columna separada por un //caracter en blanco//, y con cada línea (incluida la última) terminada por un caracter //nueva línea//. | + | |
| - | + | ||
| - | <code c> | + | |
| - | for (i = 0; i < n; i++) | + | |
| - | printf(" | + | |
| - | </ | + | |
| - | + | ||
| - | Se imprime un carácter nueva línea después de cada diez elementos, y después del n-ésimo. Todos los otros elementos son seguidos por un //espacio en blanco//. Esto podría parecer complicado, pero es más compacto que el '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | printf(" | + | |
| - | </ | + | |
| - | + | ||
| - | * **Ejercicio 2-10**. Reescriba la función '' | + | |
| - | + | ||
| - | ====2.12 Precedencia y orden de evaluación==== | + | |
| - | + | ||
| - | La //[[#tabla 2-1|tabla 2-1]]// resume las reglas de precedencia y asociatividad de todos los operadores, | + | |
| - | + | ||
| - | Los '' | + | |
| - | + | ||
| - | Nótese que la precedencia de los operadores de bits ''&'', | + | |
| - | + | ||
| - | <code c> | + | |
| - | if ((x & MASK) == 0) ... | + | |
| - | </ | + | |
| - | + | ||
| - | deben ser completamente colocadas entre paréntesis para dar los resultados apropiados. | + | |
| - | + | ||
| - | Como muchos lenguajes, C no especifica el orden en el cual los operandos de un operador serán evaluados. (Las excepciones son ''&&'', | + | |
| - | + | ||
| - | <code c> | + | |
| - | x = f() + g(); | + | |
| - | </ | + | |
| - | + | ||
| - | '' | + | |
| - | + | ||
| - | De manera semejante, el orden en el que se evalúan los argumentos de una función no está especificado, | + | |
| - | + | ||
| - | <code c> | + | |
| - | printf(" | + | |
| - | </ | + | |
| - | + | ||
| - | puede producir resultados diferentes con distintos compiladores, | + | |
| - | + | ||
| - | <code c> | + | |
| - | ++n; | + | |
| - | printf(" | + | |
| - | </ | + | |
| - | + | ||
| - | Las llamadas a funciones, proposiciones de asignación anidadas, y los operadores de incremento y decremento provocan “efectos colaterales” — alguna variable resulta modificada como producto de la evaluación de una expresión. En cualquier expresión que involucra efectos colaterales, | + | |
| - | + | ||
| - | <code c> | + | |
| - | a[i] = i++; | + | |
| - | </ | + | |
| - | + | ||
| - | La pregunta es si el subíndice es el viejo o el nuevo valor de '' | + | |
| - | + | ||
| - | La moraleja es que escribir un código dependiente del orden de evaluación es una mala práctica | + | |
| - | + | ||
| - | == Tabla 2-1: Precedencia y asociatividad de operadores == | + | |
| - | + | ||
| - | ^ Operadores ^Asociatividad ^ | + | |
| - | |'' | + | |
| - | |'' | + | |
| - | |'' | + | |
| - | |'' | + | |
| - | |''<<'' | + | |
| - | |''<'' | + | |
| - | |'' | + | |
| - | |''&'' | + | |
| - | |'' | + | |
| - | |'' | + | |
| - | |''&&'' | + | |
| - | |'' | + | |
| - | |''?:'' | + | |
| - | |'' | + | |
| - | + | ||
| - | + | ||
| - | ===== Capítulo 3: Control de Flujo ===== | + | |
| - | + | ||
| - | Las proposiciones de control de flujo de un lenguaje especifican el orden en que se realiza el procesamiento. Ya hemos visto la mayoría de las construcciones de control de flujo en ejemplos anteriores; aquí completaremos el conjunto, y seremos más precisos acerca de las discutidas con anterioridad. | + | |
| - | + | ||
| - | ==== 3.1 Proposiciones y bloques ==== | + | |
| - | + | ||
| - | Una expresión como '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | x = 0; | + | |
| - | i++; | + | |
| - | printf(...); | + | |
| - | </ | + | |
| - | + | ||
| - | En C, el punto y coma '';'' | + | |
| - | + | ||
| - | Las llaves '' | + | |
| - | + | ||
| - | ==== 3.2 If-Else ==== | + | |
| - | + | ||
| - | La proposición '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | if (expresión) | + | |
| - | proposición1 | + | |
| - | else | + | |
| - | | + | |
| - | </ | + | |
| - | + | ||
| - | donde la parte del '' | + | |
| - | + | ||
| - | Puesto que un '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | if (expresión) | + | |
| - | </ | + | |
| - | + | ||
| - | en lugar de | + | |
| - | + | ||
| - | <code c> | + | |
| - | if (expresión != 0) | + | |
| - | </ | + | |
| - | + | ||
| - | Algunas veces esto es claro y natural; otras puede ser misterioso. | + | |
| - | + | ||
| - | Debido a que la parte '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | if (n > 0) | + | |
| - | if (a > b) | + | |
| - | z = a; | + | |
| - | else | + | |
| - | z = b; | + | |
| - | </ | + | |
| - | + | ||
| - | el '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | if (n > 0) { | + | |
| - | if (a > b) | + | |
| - | z = a; | + | |
| - | } | + | |
| - | else | + | |
| - | z = b; | + | |
| - | </ | + | |
| - | + | ||
| - | La ambigüedad es especialmente perniciosa en situaciones como esta: | + | |
| - | + | ||
| - | <code c> | + | |
| - | if (n > 0) | + | |
| - | for (i = 0; i < n; i++) | + | |
| - | if (s[i] > 0) { | + | |
| - | printf(" | + | |
| - | return i; | + | |
| - | } | + | |
| - | else /* EQUIVOCADO */ | + | |
| - | printf(" | + | |
| - | </ | + | |
| - | + | ||
| - | El sangrado muestra en forma inequívoca lo que se desea, pero el compilador no entiende el mensaje y asocia el '' | + | |
| - | + | ||
| - | A propósito, nótese que hay un punto y coma '';'' | + | |
| - | + | ||
| - | <code c> | + | |
| - | if (a > b) | + | |
| - | z = a; | + | |
| - | else | + | |
| - | z = b; | + | |
| - | </ | + | |
| - | + | ||
| - | Esto se debe a que gramaticalmente al '' | + | |
| - | ==== 3.3 Else-if ==== | + | |
| - | + | ||
| - | + | ||
| - | La construcción | + | |
| - | + | ||
| - | <code c> | + | |
| - | if (expresión) | + | |
| - | proposición | + | |
| - | else if (expresión) | + | |
| - | proposición | + | |
| - | else if (expresión) | + | |
| - | proposición | + | |
| - | else if (expresión) | + | |
| - | proposición | + | |
| - | else | + | |
| - | proposición | + | |
| - | </ | + | |
| - | + | ||
| - | ocurre de modo tan frecuente que bien vale una pequeña discusión aparte. Esta secuencia de proposiciones '' | + | |
| - | + | ||
| - | La parte del último '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | else | + | |
| - | proposición | + | |
| - | </ | + | |
| - | + | ||
| - | puede omitirse, o puede utilizarse para detección de errores al atrapar una condición “imposible” . | + | |
| - | + | ||
| - | Para ilustrar una decisión de tres vías, se muestra a continuación una función de búsqueda binaria que decide si un valor particular de '' | + | |
| - | + | ||
| - | La búsqueda binaria primero compara el valor de entrada '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | /* binsearch: encuentra x en v[0] <= v[1] <= ... <= v[n-1] */ | + | |
| - | { | + | |
| - | int low, high, mid; | + | |
| - | + | ||
| - | low = 0; | + | |
| - | high = n - 1; | + | |
| - | while (low <= high) { | + | |
| - | mid = (low+high)/ | + | |
| - | if (x < v[mid]) | + | |
| - | high = mid + 1; | + | |
| - | else if (x > v[mid]) | + | |
| - | low = mid + 1; | + | |
| - | else /* el elemento fue encontrado */ | + | |
| - | return mid; | + | |
| - | } | + | |
| - | return -1; /* no fue encontrado */ | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | La decisión fundamental es si '' | + | |
| - | + | ||
| - | * **Ejercicio 3-1**. Nuestra búsqueda binaria realiza dos pruebas dentro del ciclo, cuando una podría ser suficiente (al precio de más pruebas en el exterior). Escriba una versión con sólo una prueba dentro del ciclo y mida la diferencia en tiempo de ejecución. □ | + | |
| - | ==== 3.4 Switch ==== | + | |
| - | + | ||
| - | La proposición '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | switch (expresión) { | + | |
| - | case exp-const: proposiciones | + | |
| - | case exp-const: proposiciones | + | |
| - | default: proposiciones | + | |
| - | ) | + | |
| - | </ | + | |
| - | + | ||
| - | Cada '' | + | |
| - | + | ||
| - | En el [[#capitulo 1|capítulo 1]] se escribió un programa para contar las ocurrencias de cada dígito, espacio en blanco y todos los demás caracteres, usando una secuencia de '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | #include < | + | |
| - | main() | + | |
| - | { | + | |
| - | int c, i, nwhite, nother, ndigit[10]; | + | |
| - | + | ||
| - | nwhite = nother = 0; | + | |
| - | for (i = 0; i < 10; i++) | + | |
| - | ndigit[i] = 0; | + | |
| - | while ((c = getchar()) != EOF) { | + | |
| - | switch (c) { | + | |
| - | case ' | + | |
| - | case ' | + | |
| - | ndigit[c-' | + | |
| - | break; | + | |
| - | case ' ': | + | |
| - | case ' | + | |
| - | case ' | + | |
| - | nwhite++; | + | |
| - | break; | + | |
| - | default: | + | |
| - | nother++; | + | |
| - | break; | + | |
| - | } | + | |
| - | } | + | |
| - | printf(" | + | |
| - | for (i = 0; i < 10; i++) | + | |
| - | printf(" | + | |
| - | printf(", | + | |
| - | nwhite, nother); | + | |
| - | return 0; | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | La proposición '' | + | |
| - | + | ||
| - | //Pasar a través// de los '' | + | |
| - | + | ||
| - | Como formalidad, coloque un '' | + | |
| - | + | ||
| - | * **Ejercicio 3-2**. Escriba una función '' | + | |
| - | ==== 3.5 Ciclos - While y For ==== | + | |
| - | + | ||
| - | Ya hemos encontrado los ciclos '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | while (expresión) | + | |
| - | proposición | + | |
| - | </ | + | |
| - | + | ||
| - | la expresión se evalúa. Si es diferente de cero, se ejecuta la // | + | |
| - | + | ||
| - | La proposición '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | for (expr1; expr2; expr3) | + | |
| - | proposición | + | |
| - | </ | + | |
| - | + | ||
| - | es equivalente a | + | |
| - | + | ||
| - | <code c> | + | |
| - | expr1; | + | |
| - | while (expr2) { | + | |
| - | proposición | + | |
| - | expr3; | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | excepto por el comportamiento de '' | + | |
| - | + | ||
| - | Gramaticalmente, | + | |
| - | + | ||
| - | <code c> | + | |
| - | for (;;) { | + | |
| - | ... | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | es una iteración “infinita”, | + | |
| - | + | ||
| - | El usar '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | while ((c = getchar()) == ' ' || c == ' | + | |
| - | ; /* ignora caracteres espaciadores */ | + | |
| - | </ | + | |
| - | + | ||
| - | no hay inicialización o reinicialización, | + | |
| - | + | ||
| - | El '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | for (i = 0; i < n; i++) | + | |
| - | ... | + | |
| - | </ | + | |
| - | + | ||
| - | que es la forma característica de procesar los primeros //n// elementos de un arreglo en C, lo análogo al ciclo '' | + | |
| - | + | ||
| - | Como un ejemplo más amplio, aquí está otra versión de '' | + | |
| - | + | ||
| - | La estructura del programa refleja la forma de la entrada: | + | |
| - | + | ||
| - | * ignora espacios en blanco, si los hay | + | |
| - | * toma el signo, si lo hay | + | |
| - | * toma la parte entera y conviértela | + | |
| - | + | ||
| - | Cada paso realiza su parte, y deja las cosas en forma clara para el siguiente. La totalidad del proceso termina con el primer carácter que no pueda ser parte de un número. | + | |
| - | + | ||
| - | <code c> | + | |
| - | #include < | + | |
| - | + | ||
| - | /* atoi: convierte s a entero; versión 2 */ | + | |
| - | int atoi(char s[]) | + | |
| - | { | + | |
| - | int i, n, sign; | + | |
| - | + | ||
| - | for (i = 0; isspace(s[i]); | + | |
| - | ; | + | |
| - | sign = (s[i] == ' | + | |
| - | if (s[i] == ' | + | |
| - | i++; | + | |
| - | for (n = 0; isdigit(s[i]); | + | |
| - | n = 10 * n + (s[i] - ' | + | |
| - | return sign * n; | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | La biblioteca estándar proporciona una función más elaborada, '' | + | |
| - | + | ||
| - | Las ventajas de mantener centralizado el control del ciclo son aún más obvias cuando existen ciclos anidados. La siguiente función es una clasificación Shell para ordenar un arreglo de enteros. La idea básica de este algoritmo de ordenamiento - inventado en 1959 por D.L. Shell - es que en las primeras etapas sean comparados elementos lejanos (en lugar de los adyacentes, como en los ordenamientos de intercambio más simples). Esto tiende a eliminar rápidamente gran cantidad de desorden, así que los estados posteriores tienen menos trabajo por hacer. El intervalo entre los elementos comparados disminuye en forma gradual hasta uno, punto en el que el ordenamiento viene a ser efectivamente un método adyacente de intercambio. | + | |
| - | + | ||
| - | <code c> | + | |
| - | /* shellsort: ordena v[0]...v[n-1] en orden ascendente */ | + | |
| - | void shellsort(int v[], int n) | + | |
| - | { | + | |
| - | int gap, i, j, temp; | + | |
| - | + | ||
| - | for (gap = n/2; gap > 0; gap /= 2) | + | |
| - | for (i = gap; i < n; i++) | + | |
| - | for (j=i-gap; j>=0 && v[j]> | + | |
| - | temp = v[j]; | + | |
| - | v[j] = v[j+gap]; | + | |
| - | v[j+gap] = temp; | + | |
| - | } | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | Existen tres ciclos anidados. El más externo controla el espacio entre los elementos comparados, reduciéndolo desde '' | + | |
| - | + | ||
| - | Un último operador de C es la coma '','' | + | |
| - | + | ||
| - | <code c> | + | |
| - | #include < | + | |
| - | + | ||
| - | /* reverse: invierte la cadena s en el mismo lugar */ | + | |
| - | void reverse(char s[]) | + | |
| - | { | + | |
| - | int c, i, j; | + | |
| - | + | ||
| - | for (i = 0, j = strlen(s)-1; | + | |
| - | c = s[i]; | + | |
| - | s[i] = s[j]; | + | |
| - | s[j] = c; | + | |
| - | } | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | Las comas que separan a los argumentos de una función, las variables en declaraciones, | + | |
| - | + | ||
| - | Los operadores coma deberán utilizarse poco. Los usos más adecuados son en construcciones fuertemente relacionadas una con la otra, como en el ciclo '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | for (i = 0, j = strlen(s)-1; | + | |
| - | c = s[i], s[i] = s[j], s[j] = c; | + | |
| - | </ | + | |
| - | + | ||
| - | * **Ejercicio 3-3**. Escriba la función '' | + | |
| - | + | ||
| - | ==== 3.6 Ciclos - do-while ==== | + | |
| - | + | ||
| - | Como ya se expuso en el [[#capitulo 1|capítulo 1]], los ciclos '' | + | |
| - | + | ||
| - | La sintaxis del do es | + | |
| - | + | ||
| - | <code c> | + | |
| - | do | + | |
| - | proposición | + | |
| - | while (expresión); | + | |
| - | </ | + | |
| - | + | ||
| - | La // | + | |
| - | + | ||
| - | La experiencia demuestra que el '' | + | |
| - | principio, debido a que los métodos fáciles para generar dígitos los generan en el orden incorrecto. Hemos elegido generar la cadena al revés y después invertirla. | + | |
| - | + | ||
| - | <code c> | + | |
| - | /* itoa: convierte n a caracteres en s */ | + | |
| - | void itoa(int n, char s[]) | + | |
| - | { | + | |
| - | int i, sign; | + | |
| - | + | ||
| - | if ((sign = n) < 0) /* registra el signo */ | + | |
| - | n = -n; /* hace a n positivo */ | + | |
| - | i = 0; | + | |
| - | do { /* genera digitos en orden inverso */ | + | |
| - | s[i++] = n % 10 + ' | + | |
| - | } while ((n /= 10) > 0); /* lo borra */ | + | |
| - | if (sign < 0) | + | |
| - | s[i++] = ' | + | |
| - | s[i] = ' | + | |
| - | reverse(s); | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | El '' | + | |
| - | + | ||
| - | * **Ejercicio 3-4**. En una representación de números en complemento a dos, nuestra versión de '' | + | |
| - | * **Ejercicio 3-5**. Escriba la función '' | + | |
| - | * **Ejercicio 3-6**. Escriba una versión de '' | + | |
| - | + | ||
| - | ==== 3.7 Break y Continue ==== | + | |
| - | + | ||
| - | Algunas veces es conveniente tener la posibilidad de abandonar un ciclo de otra manera que no sea probando al inicio o al final. La proposición '' | + | |
| - | + | ||
| - | Un '' | + | |
| - | + | ||
| - | La siguiente función, '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | /* trim: elimina blancos, tabuladores y nueva linea al final */ | + | |
| - | int trim(char s[]) | + | |
| - | { | + | |
| - | int n; | + | |
| - | + | ||
| - | for (n = strlen(s)-1; | + | |
| - | if (s[n] != ' ' && s[n] != ' | + | |
| - | break; | + | |
| - | s[n+1] = ' | + | |
| - | return n; | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | '' | + | |
| - | + | ||
| - | El ciclo se interrumpe cuando se encuentra alguno o cuando //n// se hace negativa (esto es, cuando se ha rastreado toda la cadena. Se deberá verificar que este comportamiento es correcto, aun cuando la cadena esté vacía o sólo contiene espacios en blanco. | + | |
| - | + | ||
| - | La proposición '' | + | |
| - | + | ||
| - | Como un ejemplo, el siguiente fragmento procesa sólo los elementos no negativos que están en el arreglo a; los valores negativos son ignorados. | + | |
| - | + | ||
| - | <code c> | + | |
| - | for (i = 0; i < n; i++) | + | |
| - | if (a[i] < 0) /* ignora elementos negativos */ | + | |
| - | continue; | + | |
| - | ... /* trabaja elementos positivos */ | + | |
| - | </ | + | |
| - | + | ||
| - | La proposición '' | + | |
| - | ==== 3.8 Goto y Etiquetas ==== | + | |
| - | + | ||
| - | + | ||
| - | C proporciona la infinitamente abusable proposición '' | + | |
| - | + | ||
| - | Sin embargo, hay algunas situaciones donde los '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | for ( ... ) | + | |
| - | for ( ... ) { | + | |
| - | ... | + | |
| - | if (desastre) | + | |
| - | goto error; | + | |
| - | } | + | |
| - | ... | + | |
| - | error: | + | |
| - | /* arregla el desorden /* | + | |
| - | </ | + | |
| - | + | ||
| - | Esta organización es útil si el código de manejo de error no es trivial y si los errores pueden ocurrir en varios lugares. | + | |
| - | + | ||
| - | Una etiqueta tiene la misma forma que un nombre de variable y es seguida por dos puntos '':'' | + | |
| - | + | ||
| - | Como otro ejemplo, considérese el problema de determinar si dos arreglos, '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | for (i = 0; i < n; i++) | + | |
| - | for (j = 0; j < m; j++) | + | |
| - | if (a[i] == b[j]) | + | |
| - | goto encontrado; | + | |
| - | /* no se encontró ningún elemento común */ | + | |
| - | ... | + | |
| - | encontrado: | + | |
| - | /* se encontró uno: a[i] == b[j] */ | + | |
| - | ... | + | |
| - | </ | + | |
| - | + | ||
| - | El código que involucra un '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | encontrado = 0; | + | |
| - | for (i = 0; i < n && !encontrado; | + | |
| - | for (j = 0; j < m && !encontrado; | + | |
| - | if (a[i] == b[j]) | + | |
| - | encontrado = 1; | + | |
| - | if (encontrado) | + | |
| - | /* Se encontró uno: a[i-1] == b[j-1] */ | + | |
| - | ... | + | |
| - | else | + | |
| - | /* no se encontró ningún elemento común */ | + | |
| - | ... | + | |
| - | </ | + | |
| - | + | ||
| - | Con pocas excepciones, | + | |
| - | ===== Capitulo 4: Funciones y la estructura del programa ===== | + | |
| - | + | ||
| - | Las funciones dividen tareas grandes de computación en varias más pequeñas, y permiten la posibilidad de construir sobre lo que otros ya han hecho, en lugar de comenzar desde cero. Las funciones apropiadas ocultan los detalles de operación de las partes del programa que no necesitan saber acerca de ellos, así que dan claridad a la totalidad y facilitan la penosa tarea de hacer cambios. | + | |
| - | + | ||
| - | El lenguaje C se diseñó para hacer que las funciones fueran eficientes y fáciles de usar; los programas escritos en C se componen de muchas funciones pequeñas en lugar de sólo algunas grandes. Un programa puede residir en uno o más archivos fuente, los cuales pueden compilarse por separado y cargarse junto con funciones de biblioteca previamente compiladas. No trataremos aquí tales procesos, puesto que los detalles varían de un sistema a otro. | + | |
| - | + | ||
| - | La declaración y definición de funciones es el área donde el estándar ANSI ha hecho los cambios más visibles a C. Tal como mencionam os en el [[#capitulo 1|capítulo 1]], ahora es posible declarar los tipos de los argumentos cuando se declara una función. La sintaxis de la definición de funciones también cambia, de modo que las | + | |
| - | declaraciones y las definiciones coincidan. Esto hace posible que el compilador pueda detectar muchos más errores de lo que podía anteriormente. Además, cuando los argumentos se declaran con propiedad, se realizan automáticamente las conversiones convenientes. | + | |
| - | + | ||
| - | El estándar clarifica las reglas sobre el alcance de los nombres; en particular, requiere que sólo haya una definición de cada objeto externo. La inicialización es más general: los arreglos y las estructuras automáticas ahora se pueden inicializar. | + | |
| - | + | ||
| - | El preprocesador de C también se ha mejorado. Las nuevas facilidades del Procesador incluyen un conjunto más completo de directivas para la compilación condicional, | + | |
| - | + | ||
| - | ==== 4.1 Conceptos básicos de funciones ==== | + | |
| - | + | ||
| - | Para comenzar, diseñemos y escribamos un programa que imprim a cada línea de su entrada que contenga un “patró n” o cadena de caracteres en particular. | + | |
| - | + | ||
| - | (Este es un caso especial del programa grep de UNIX.) Por ejem plo, al buscar el patrón de letras " | + | |
| - | + | ||
| - | < | + | |
| - | Ah Love! could you and I with Fate conspire | + | |
| - | To grasp this sorry Scheme of Things entire, | + | |
| - | Would not we shatter it to bits -- and then | + | |
| - | Re-mould it nearer to the Heart' | + | |
| - | </ | + | |
| - | + | ||
| - | producirá la salida | + | |
| - | + | ||
| - | < | + | |
| - | Ah Love! could you and I with Fate conspire | + | |
| - | Would not we shatter it to bits -- and then | + | |
| - | Re-mould it nearer to the Heart' | + | |
| - | </ | + | |
| - | + | ||
| - | El trabajo se ajusta ordenadamente en tres partes: | + | |
| - | + | ||
| - | <code c> | + | |
| - | while {hay otra línea) | + | |
| - | if {la línea contiene el patrón) | + | |
| - | imprímela | + | |
| - | </ | + | |
| - | + | ||
| - | Aunque ciertamente es posible poner el código de todo esto en '' | + | |
| - | + | ||
| - | “Mientras hay otra línea” es '' | + | |
| - | + | ||
| - | Podemos resolver ese problema escribiendo una función '' | + | |
| - | + | ||
| - | Una vez definido todo este diseño, llenar los detalles del programa es simple. Aquí está en su totalidad, de modo que se puede ver cómo las piezas quedan juntas. Por ahora, el patrón que se buscará es una cadena literal, lo cual no es el mecanismo más general. Regresaremos en breve a una discusión sobre cómo inicializar arreglos de caracteres, y en el [[#capitulo 5|capítulo 5]] mostraremos cómo hacer que el patrón de caracteres sea un parámetro fijado cuando se ejecuta el programa. | + | |
| - | + | ||
| - | También hay una versión ligeramente diferente de '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | # include < | + | |
| - | #define MAXILINE 1000 /* longitud máxima por línea de entrada */ | + | |
| - | + | ||
| - | int getline(char line[], int max) | + | |
| - | int strindex(char source[], char searchfor[]); | + | |
| - | + | ||
| - | char pattern[] = " | + | |
| - | + | ||
| - | /* encontrar todas las líneas que coincidan con el patrón */ | + | |
| - | main() | + | |
| - | { | + | |
| - | char line[MAXLINE]; | + | |
| - | int found = 0; | + | |
| - | + | ||
| - | while (getline(line, | + | |
| - | if (strindex(line, | + | |
| - | printf(" | + | |
| - | found++; | + | |
| - | } | + | |
| - | return found; | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | <code c> | + | |
| - | /* getline: pone linea en s, retorna longitud */ | + | |
| - | int getline(char s[], int lim) | + | |
| - | { | + | |
| - | int c, i; | + | |
| - | + | ||
| - | i = 0; | + | |
| - | while (--lim > 0 && (c=getchar()) != EOF && c != ' | + | |
| - | s[i++] = c; | + | |
| - | if (c == ' | + | |
| - | s[i++] = c; | + | |
| - | s[i] = ' | + | |
| - | return i; | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | <code c> | + | |
| - | /* strindex: retorna el índice de t en s, -1 si no hay */ | + | |
| - | int strindex(char s[], char t[]) | + | |
| - | { | + | |
| - | int i, j, k; | + | |
| - | + | ||
| - | for (i = 0; s[i] != ' | + | |
| - | for (j=i, k=0; t[k]!=' | + | |
| - | ; | + | |
| - | if (k > 0 && t[k] == ' | + | |
| - | return i; | + | |
| - | } | + | |
| - | return -1; | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | Cada definición de función tiene la forma | + | |
| - | + | ||
| - | <code c> | + | |
| - | tipo-regresado nombre-de-función(declaraciones de argumentos) | + | |
| - | { | + | |
| - | declaraciones y proposiciones | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | + | ||
| - | Varias partes pueden omitirse; una función mínima " | + | |
| - | + | ||
| - | <code c> | + | |
| - | nada() {} | + | |
| - | </ | + | |
| - | + | ||
| - | que no hace ni regresa nada. Una función '' | + | |
| - | + | ||
| - | Un programa es sólo un conjunto de definiciones de variables y funciones. La comunicación entre funciones es por argumentos y valores regresados por las funciones, | + | |
| - | varios archivos, mientras las funciones no se dividan. | + | |
| - | + | ||
| - | La proposición '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | return expresión | + | |
| - | </ | + | |
| - | + | ||
| - | La // | + | |
| - | + | ||
| - | La función que llama tiene la libertad de ignorar el valor regresado. Incluso, no hay necesidad de un a expresión después de '' | + | |
| - | aunque probablemente un signo de problemas, el que una función regrese un valor desde un lugar y ninguno desde otro. En cualquier caso, si una función no regresa explícitamente un valor, su “valor” es ciertamente basura. | + | |
| - | + | ||
| - | El programa de búsqueda del patrón regresa un estado desde '' | + | |
| - | + | ||
| - | El mecanismo de cómo compilar y cargar un programa en C que reside en varios archivos fuente varía de un sistema a otro. En el sistema UNIX, por ejemplo, la orden //cc// mencionada en el [[# | + | |
| - | + | ||
| - | <code bash> | + | |
| - | cc main.c getline.c strindex.c | + | |
| - | </ | + | |
| - | + | ||
| - | compila los tres archivos, sitúa el código objeto resultante en los archivos '' | + | |
| - | + | ||
| - | <code bash> | + | |
| - | cc main.c getline.o strindex.o | + | |
| - | </ | + | |
| - | + | ||
| - | //cc// emplea la convención "'' | + | |
| - | + | ||
| - | * **Ejercicio 4-1**. Escriba la función '' | + | |
| - | + | ||
| - | ==== 4.2 Funciones que regresan valores no enteros ==== | + | |
| - | + | ||
| - | Basta ahora los ejemplos de funciones han regresado o ningún valor (void) o un '' | + | |
| - | no es una rutina de conversión de alta calidad; tomaría más espacio del que podemos dedicarle. La biblioteca estándar incluye un '' | + | |
| - | + | ||
| - | Primero, '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | #include < | + | |
| - | + | ||
| - | /* atof: convierte la cadena s a double */ | + | |
| - | double atof(char s[]) | + | |
| - | { | + | |
| - | double val, power; | + | |
| - | int i, sign; | + | |
| - | + | ||
| - | for (i = 0; isspace(s[i]); | + | |
| - | ; | + | |
| - | sign = (s[i] == ' | + | |
| - | if (s[i] == ' | + | |
| - | i++; | + | |
| - | for (val = 0.0; isdigit(s[i]); | + | |
| - | val = 10.0 * val + (s[i] - ' | + | |
| - | if (s[i] == ' | + | |
| - | i++; | + | |
| - | for (power = 1.0; isdigit(s[i]); | + | |
| - | val = 10.0 * val + (s[i] - ' | + | |
| - | power *= 10; | + | |
| - | } | + | |
| - | return sign * val / power; | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | Segundo, e igualmente importante, la rutina que llama debe indicar que '' | + | |
| - | línea, precedido en forma optativa por un signo, y lo acumula, imprimiendo la suma actual después de cada entrada: | + | |
| - | + | ||
| - | <code c> | + | |
| - | #include < | + | |
| - | #define MAXLINE 100 /* calculadora rudimentaria * / | + | |
| - | main() | + | |
| - | { | + | |
| - | double sum, atof(char []); | + | |
| - | char line[MAXLINE]; | + | |
| - | int getline(char line[], int max); | + | |
| - | + | ||
| - | sum = 0; | + | |
| - | while (getline(line, | + | |
| - | printf(" | + | |
| - | return 0; | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | La declaración | + | |
| - | + | ||
| - | <code c> | + | |
| - | double sum, atof(char []); | + | |
| - | </ | + | |
| - | + | ||
| - | señala que '' | + | |
| - | + | ||
| - | La función '' | + | |
| - | + | ||
| - | A la luz de lo que hemos mencionado acerca de cómo deben coincidir las declaraciones con las definiciones, | + | |
| - | + | ||
| - | <code c> | + | |
| - | sum += atof(line) | + | |
| - | </ | + | |
| - | + | ||
| - | Si en una expresión se encuentra un nombre que no ha sido declarado previamente y está seguido por paréntesis izquierdo, se declara por contexto, de modo que se supone que es el nombre de una función que regresa un '' | + | |
| - | + | ||
| - | <code c>double atof();</ | + | |
| - | + | ||
| - | también es tomada de modo que no se supone nada acerca de los argumentos de '' | + | |
| - | + | ||
| - | Dado '' | + | |
| - | na a '' | + | |
| - | + | ||
| - | <code c> | + | |
| - | /* atoi: convierte la cadena s a entero usando atof */ | + | |
| - | int atoi(char s[]) | + | |
| - | { | + | |
| - | double atof(char s[]); | + | |
| - | return (int) atof(s); | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | Nótese la estructura de las declaraciones y la proposición '' | + | |
| - | + | ||
| - | <code c>return expresión;</ | + | |
| - | + | ||
| - | se convierte al tipo de la función antes de que se tome el '' | + | |
| - | + | ||
| - | * **Ejercicio 4-2**. Extienda '' | + | |
| - | + | ||
| - | ==== 4.3 Variables Externas ==== | + | |
| - | + | ||
| - | ==== 4.4 Reglas y Alcance ==== | + | |
| - | + | ||
| - | + | ||
| - | ==== 4.5 Archivo de encabezamiento header ==== | + | |
| - | + | ||
| - | ==== 4.6 Variables estáticas ==== | + | |
| - | + | ||
| - | ==== 4.7 Variables tipo registro ==== | + | |
| - | + | ||
| - | ==== 4.8 Estructura de bloques ==== | + | |
| - | + | ||
| - | ==== 4.9 Inicialización ==== | + | |
| - | + | ||
| - | ==== 4.10 Recursividad ==== | + | |
| - | + | ||
| - | ==== 4.11 El preprocesador de C ==== | + | |
| - | + | ||
| - | === 4.1.1 Inclusión de archivos === | + | |
| - | + | ||
| - | === 4.1.2 Substitución de macros === | + | |
| - | + | ||
| - | === 4.1.3 Inclusión condicional === | + | |
| - | + | ||
| - | ===== Capitulo 5: Apuntadores y arreglos ===== | + | |
| - | + | ||
| - | ==== 5.1 Apuntadores y Direcciones ==== | + | |
| - | + | ||
| - | ==== 5.2 Apuntadores y argumentos de funciones ==== | + | |
| - | + | ||
| - | ==== 5.3 Apuntadores y arreglos ==== | + | |
| - | + | ||
| - | ==== 5.4 Aritmética de direcciones ==== | + | |
| - | + | ||
| - | ==== 5.5 Apuntadores a caracteres, y funciones ==== | + | |
| - | + | ||
| - | ==== 5.6 Arreglos de apuntadores; | + | |
| - | + | ||
| - | ==== 5.7 Arreglos muitidimensionales ==== | + | |
| - | + | ||
| - | ==== 5.8 Inicialización de arreglos de apuntadores ==== | + | |
| - | + | ||
| - | ==== 5.9 Apuntadores vs. arreglos muitidimensionales ==== | + | |
| - | + | ||
| - | ==== 5.10 Argumentos en la línea de órdenes ==== | + | |
| - | + | ||
| - | ==== 5.11 Apuntadores a funciones ==== | + | |
| - | + | ||
| - | ==== 5.12 Declaraciones complicadas ==== | + | |
| - | + | ||
| - | ===== Capítulo 6: Estructuras ===== | + | |
| - | + | ||
| - | Una estructura es una colección de una o más variables, de tipos posiblemente diferentes, agrupadas bajo un solo nombre para manejo conveniente. (Las estructuras se conocen como “ records” en algunos otros lenguajes, principalm ente Pascal.) Las estructuras ayudan a organizar datos complicados, | + | |
| - | + | ||
| - | Un ejemplo tradicional de estructura es el registro de una nómina: un empleado está descrito por un conjunto de atributos, como nombre, domicilio, número del seguro social, salario, etc. Algunos de estos atributos pueden, a su vez, ser estructuras: | + | |
| - | + | ||
| - | El principal cambio realizado por el estándar ANSI es la definición de la asignación de estructuras: | + | |
| - | + | ||
| - | ==== 6.1 Conceptos básicos sobre estructuras ==== | + | |
| - | + | ||
| - | ==== 6.2 Estructuras y funciones ==== | + | |
| - | + | ||
| - | ==== 6.3 Arreglos de estructuras ==== | + | |
| - | + | ||
| - | ==== 6.4 Apuntadores a estructuras ==== | + | |
| - | + | ||
| - | ==== 6.5 Estructuras autorreferenciadas ==== | + | |
| - | + | ||
| - | ==== 6.6 Búsqueda en tablas ==== | + | |
| - | + | ||
| - | ==== 6.7 Typedef ==== | + | |
| - | + | ||
| - | ==== 6.8 Uniones ==== | + | |
| - | + | ||
| - | ==== 6.9 Campos de bits ==== | + | |
| - | + | ||
| - | ===== Capítulo 7: ===== | + | |
| - | + | ||
| - | Las operaciones de entrada y salida no son en si parle del lenguaje C, por lo que hasta ahora no las hemos destacado. Sin embargo, los programas interactúan con su medio ambiente en formas mucho más complicadas de las que hemos mostrado antes. En este capítulo describiremos la biblioteca estándar, un conjunto de funciones que proporcionan entrada y salida, manipulación de cadenas, manejo de memoria, rutinas matemáticas y una variedad de otros servicios para programas en C, aunque haremos hincapié en la entrada y salida. | + | |
| - | + | ||
| - | El estándar ANSI define de manera precisa estas funciones de biblioteca, de modo que pueden existir en forma compatible en cualquier sistema en donde exista C. Los programas que restringen su interacción con el sistema a las facilidades provistas por la biblioteca estándar pueden ser llevados de un sistema a otro sin cambios. | + | |
| - | + | ||
| - | Las propiedades de las funciones de biblioteca están especificadas en más de una docena de // | + | |
| - | + | ||
| - | ==== 7.1 Entrada y salida estándar ==== | + | |
| - | + | ||
| - | ==== 7.2 Salida con formato - printf ==== | + | |
| - | + | ||
| - | == Tabla 7-1. Conversiones básicas de Printf == | + | |
| - | + | ||
| - | ==== 7.3 Listas de argumentos de longitud variable ==== | + | |
| - | + | ||
| - | ==== 7.4 Entrada con formato — scanf ==== | + | |
| - | + | ||
| - | == Tabla 7-2 - Conversiones básicas de scanf == | + | |
| - | + | ||
| - | ^Caracter ^Dato de entrada: | + | |
| - | |'''' | + | |
| - | |'''' | + | |
| - | |'''' | + | |
| - | |'''' | + | |
| - | |'''' | + | |
| - | |'''' | + | |
| - | |'''' | + | |
| - | |'''' | + | |
| - | |'''' | + | |
| - | + | ||
| - | + | ||
| - | ==== 7.5 Acceso a archivos ==== | + | |
| - | + | ||
| - | ==== 7.6 Manejo de errores—stderr y exit ==== | + | |
| - | + | ||
| - | ==== 7.7 Entrada y salida de líneas ==== | + | |
| - | + | ||
| - | ==== 7.8 Otras funciones ==== | + | |
| - | + | ||
| - | La biblioteca estándar proporciona una amplia variedad de funciones. Esta sección es una breve sinopsis de las más útiles. En el [[#apendice b|apéndice B]] pueden encontrarse más detalles y muchas otras funciones. | + | |
| - | + | ||
| - | === 7.8.1 Operaciones sobre cadenas === | + | |
| - | + | ||
| - | === 7.8.2 Prueba y conversión de clases de caracteres === | + | |
| - | + | ||
| - | === 7.8.3 Ungete === | + | |
| - | + | ||
| - | === 7.8.4 Ejecución de órdenes === | + | |
| - | + | ||
| - | === 7.8.5 Administración del almacenamiento === | + | |
| - | + | ||
| - | === 7.8.6 Funciones matemáticas === | + | |
| - | + | ||
| - | + | ||
| - | === 7.8.7 Generación de números aleatorios === | + | |
| - | + | ||
| - | + | ||
| - | ===== Capítulo 8: La interfaz con el sistem a UNIX ===== | + | |
| - | + | ||
| - | El sistema operativo UNIX proporciona sus servicios a través de un conjunto de //llamadas al sistema//, que consisten en funciones que están dentro del sistema operativo y que pueden ser invocadas por programas del usuario. Este capitulo describe cómo emplear algunas de las más importantes llamadas al sistema desde programas en C. Si el lector usa UNIX, esto debe serle directamente útil, debido a que algunas veces es necesario emplear llamadas al sistema para tener máxima eficiencia, o para tener acceso a alguna facilidad que no esté en la biblioteca. | + | |
| - | + | ||
| - | Incluso, si se emplea C en un sistema operativo diferente el lector debería ser capaz de adentrarse en la programación estudiando estos ejemplos; aunque los detalles varían, se encontrará un código semejante en cualquier sistema. Puesto que la biblioteca de C ANSI está en muchos casos modelada con base en las facilidades de UNIX , este código puede ayudar también a su entendimiento. | + | |
| - | + | ||
| - | El capítulo está dividido en tres partes fundamentales: | + | |
| - | + | ||
| - | El capítulo 7 tuvo que ver con una interfaz de entrada/ | + | |
| - | ==== 8.1 Descriptores | + | [[El lenguaje |
| - | ==== 8.2 E/S de bajo nivel — read y write ==== | + | [[El lenguaje |
| - | ==== 8.3 Open, creat, close, unlink ==== | + | [[El lenguaje de Programación C - Capitulo |
| - | ==== 8.4 Acceso aleatorio — lseek ==== | + | [[El lenguaje de Programación C - Capitulo |
| - | ==== 8.5 Ejemplo - Una realización | + | [[El lenguaje |
| - | ==== 8.6 Ejemplo — listado | + | [[El lenguaje |
| - | ==== 8.7 Ejemplo - Asignador | + | [[El lenguaje |
| - | ===== Apéndice A: Manual | + | [[El lenguaje |
| - | === A1: Introducción | + | ==== Apéndices ==== |
| - | Este manual describe al lenguaje C tal como se especifica en Draft Proposed American National Standard for Information Systems — Programming Language C, documento número X3J11/88-001, con fecha 11 de enero de 1988. Este borrador no es el estándar final, y todavía es posible que ocurran algunos cambios en el lenguaje. Así pues, este manual no describe la definición final del lenguaje. Más aún es una interpretación del borrador propuesto del estándar, no el estándar en sí, aunque se ha tenido cuidado | + | [[El lenguaje |
| - | En su mayor parte, este manual sigue la línea amplia del borrador estándar, que a su vez sigue la de la primera edición de este libro, aunque la organización difiere en el detalle. Excepto por renombrar algunas producciones y porque no se formalizan las definiciones de los componentes léxicos o del preprocesador, | + | [[El lenguaje |
| - | >En este manual, el material comentado se encuentra sangrado y escrito en un tipo más pequeño, como este. A menudo estos comentarios resaltan las formas en las que el estándar ansí de C difiere del lenguaje | + | [[El lenguaje de Programación C - Apéndice C|Apéndice C: Resumen |
| - | ===== Apéndice B: Biblioteca Estándar ===== | ||
| - | ===== Apéndice C: Resúmen de Modificaciones ===== | ||
| - | Desde la publicación de la primera edición de este libro, la definición del lenguaje C ha sufrido modificaciones. Casi todas fueron extensiones al lenguaje original, y fueron diseñadas cuidadosamente para permanecer compatibles con la práctica existente; algunas repararon ambigüedades de la descripción original, y otras representan modificaciones de la práctica existente. Muchas de las nuevas características se anunciaron en los documentos que acompañan a los compiladores disponibles de AT&T, y posteriormente se han adoptado por otros proveedores de compiladores del lenguaje C. Recientemente, | ||
| - | Este apéndice resume las diferencias entre el lenguaje definido por la primera edición de este libro, y lo esperado como la definición del estándar final. Trata solamente al lenguaje en sí, no a su entorno ni a su biblioteca; aunque esas son partes importantes del estándar, hay poco con qué compararlas, | ||
| - | * El preprocesamiento está definido más cuidadosamente en el Estándar que en la primera edición, y está extendido: está explícitamete basado en tokens (símbolos); | ||
| - | * El significado mínimo el más pequeño de todos los identificadores internos se incrementó a 31 caracteres; permitido para identificadores con liga externo permanece en 6 letras, sin importar sin son mayúsculas o minúsculas (muchas implantaciones proporcionan más). | ||
| - | * Las secuencias trigráficas introducidas por ?? permiten la representación de caracteres que no se encuentran en algunos conjuntos. Están definidos los escapes para ''#'' | ||
| - | de cadenas que contengan la secuencia ''??'' | ||
| - | * Se introdujeron nuevas palabras reservadas (void, const, volatile, signed. enum). La palabra reservada entry, que nunca se puso en uso, fue retirada. | ||
| - | * Se definen nuevas secuencias de escape para uso dentro de constantes de carácter y cadenas literales. El efecto de seguir ''< | ||
