Diferencias
Muestra las diferencias entre dos versiones de la página.
| Próxima revisión | Revisión previa | ||
| el_lenguaje_de_programacion_c_-_capitulo_4 [2024/09/27 22:44] – creado peron | el_lenguaje_de_programacion_c_-_capitulo_4 [2026/04/21 16:06] (actual) – editor externo 127.0.0.1 | ||
|---|---|---|---|
| Línea 253: | Línea 253: | ||
| ==== 4.3 Variables Externas ==== | ==== 4.3 Variables Externas ==== | ||
| - | ==== 4.4 Reglas | + | Un programa en C consta de un conjunto de objetos externos, que son variables o funciones. El adjetivo “externo” se emplea en contraste con “interno”, |
| + | Debido a que las variables externas son accesibles globalmente, | ||
| + | |||
| + | Si un gran número de variables se debe compartir entre funciones, las variables externas son más convenientes y eficientes que las largas listas de argumentos. Sin embargo, como se señaló en el capítulo 1, este razonamiento se deberá aplicar con precaución, | ||
| + | |||
| + | Las variables externas son también útiles debido a su mayor alcance y tiempo de vida. Las variables automáticas son internas a una función y su existencia se inicia cuando se entra a la función y desaparecen cuando ésta se abandona. Por otro lado, las variables externas son permanentes, | ||
| + | |||
| + | Examinemos más a fondo este tema con un ejemplo más amplio. El problema es escribir el programa de una calculadora que provea los operadores '' | ||
| + | |||
| + | En notación polaca inversa, cada operador sigue a sus operandos; por lo tanto, lo que en una expresión infija se exoresa como | ||
| + | |||
| + | < | ||
| + | |||
| + | en notación polaca inversa se introduce como | ||
| + | |||
| + | <code c>1 2 - 4 5 + *</ | ||
| + | |||
| + | Las paréntesis son innecesarias; | ||
| + | |||
| + | La implantación es simple. Cada operando se introduce en una pila o " | ||
| + | |||
| + | De esta forma, La estructura del programa que opere de esta manera será un ciclo que realice las operaciones adecuadas sobre cada operador y operando en la medida que aparecen; | ||
| + | |||
| + | <code c> | ||
| + | while (siguiente operador u operando que no es fin de archivó) | ||
| + | if (número) | ||
| + | introducirlo | ||
| + | else if (operador) | ||
| + | extraer operandos | ||
| + | hacer operaciones | ||
| + | introducir el resultado | ||
| + | else if (nueva línea) | ||
| + | extrae e imprime el tope de la pila | ||
| + | else | ||
| + | error | ||
| + | </ | ||
| + | |||
| + | Las operaciones de introducir en pila {//push//, o " | ||
| + | |||
| + | La principal decisión de diseño que aún no se ha explicado es dónde está la pila, esto es, cuáles rutinas tienen acceso a ella directamente. Una posibilidad es mantenerla en '' | ||
| + | |||
| + | Traducir este bosquejo a código es sumamente fácil. Si por ahora pensamos que el programa existe en un archivo fuente, se verá así | ||
| + | |||
| + | <code c> | ||
| + | #includeS | ||
| + | #defineS | ||
| + | |||
| + | declaración de funciones para main | ||
| + | |||
| + | main() { ... } | ||
| + | |||
| + | variables externas para push y pop | ||
| + | |||
| + | void push(double f) { ... } | ||
| + | double pop(void) { ... } | ||
| + | |||
| + | int getop(char s[ ]) { ... } | ||
| + | rutinas llamadas por getop | ||
| + | </ | ||
| + | |||
| + | Más adelante se verá cómo se puede dividir todo esto entre dos o más archivos de código fuente. | ||
| + | |||
| + | La función '' | ||
| + | |||
| + | <code c> | ||
| + | #include < | ||
| + | #include < | ||
| + | |||
| + | #define MAXOP 100 /* máx tamaño de operando u operador */ | ||
| + | #define NUMBER ' | ||
| + | |||
| + | int getop(char []); | ||
| + | void push(double); | ||
| + | double pop(void); | ||
| + | |||
| + | /* Calculadora polaca inversa */ | ||
| + | main() | ||
| + | { | ||
| + | int type; | ||
| + | double op2; | ||
| + | char s[MAXOP]; | ||
| + | | ||
| + | while ((type = getop(s)) != EOF) { | ||
| + | switch (type) { | ||
| + | case NUMBER: | ||
| + | push(atof(s)); | ||
| + | break; | ||
| + | case ' | ||
| + | push(pop() + pop()); | ||
| + | break; | ||
| + | case ' | ||
| + | push(pop() * pop()); | ||
| + | break; | ||
| + | case ' | ||
| + | op2 = pop(); | ||
| + | push(pop() - op2); | ||
| + | break; | ||
| + | case '/': | ||
| + | op2 = pop(); | ||
| + | if (op2 != 0.0) | ||
| + | push(pop() / op2); | ||
| + | else | ||
| + | printf(" | ||
| + | break; | ||
| + | case ' | ||
| + | printf(" | ||
| + | break; | ||
| + | default: | ||
| + | printf(" | ||
| + | break; | ||
| + | } | ||
| + | } | ||
| + | return 0; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Puesto que '' | ||
| + | |||
| + | <code c> | ||
| + | push(pop() - pop()); | ||
| + | </ | ||
| + | |||
| + | no se ha definido el orden en el que se evalúan las dos llamadas de '' | ||
| + | |||
| + | <code c> | ||
| + | #define MAXVAL 100 /* máxima profundidad de la pila val •/ | ||
| + | int sp = 0 ; /* siguiente posición libre en la pila */ | ||
| + | double val[MAXVAL]; | ||
| + | |||
| + | /* push: introduce f a la pila */ | ||
| + | void push(double f) | ||
| + | { | ||
| + | if (sp < MAXVAL) | ||
| + | val[sp++] = f; | ||
| + | else | ||
| + | printf(" | ||
| + | } | ||
| + | |||
| + | /* pop: extrae y regresa el valor superior de la pila */ | ||
| + | double pop(void) | ||
| + | { | ||
| + | if (sp > 0) | ||
| + | return val[--sp]; | ||
| + | else { | ||
| + | printf(" | ||
| + | return 0.0; | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | |||
| + | Una variable es externa si se encuentra definida fuera de cualquier función. Por tanto, la pila y el índice de la pila que deben ser compartidos por '' | ||
| + | |||
| + | Pasemos ahora a la implantación de '' | ||
| + | |||
| + | <code c> | ||
| + | #include < | ||
| + | |||
| + | int getch(void); | ||
| + | void ungetch(int); | ||
| + | |||
| + | /* getop: obtiene siguiente caracter u operando numérico */ | ||
| + | int getop(char s[]) | ||
| + | { | ||
| + | int i, c; | ||
| + | |||
| + | while ((s[0] = c = getch()) == ' ' || c == ' | ||
| + | ; | ||
| + | s[1] = ' | ||
| + | if (!isdigit(c) && c != ' | ||
| + | return c; /* no-número */ | ||
| + | i = 0; | ||
| + | if (isdigit(c)) | ||
| + | while (isdigit(s[++i] = c = getch())) | ||
| + | ; | ||
| + | if (c == ' | ||
| + | while (isdigit(s[++i] = c = getch())) | ||
| + | ; | ||
| + | s[i] = ' | ||
| + | if (c != EOF) | ||
| + | ungetch(c); | ||
| + | return NUMBER; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | ¿Qué son '' | ||
| + | |||
| + | El problema podría ser resuelto si fuera posible “desleer” el carácter indeseado. De esta manera, toda vez que el programa lea un carácter de más, podría devolverlo a la entrada, provisión con la cual el resto del código se comportará como la lectura de más jamás hubiese sucedido. Afortunadamente, | ||
| + | |||
| + | Cómo trabajan juntas es sencillo, '' | ||
| + | |||
| + | <code c> | ||
| + | #define BUFSIZE 100 | ||
| + | |||
| + | char buf[BUFSIZE]; | ||
| + | int bufp = 0; /* siguiente posición libre en el buffer */ | ||
| + | |||
| + | int getch(void) | ||
| + | { | ||
| + | return (bufp > 0) ? buf[--bufp] : getchar(); | ||
| + | } | ||
| + | |||
| + | void ungetch(int c) /* devuelve caracter a la entrada */ | ||
| + | { | ||
| + | if (bufp >= BUFSIZE) | ||
| + | printf(" | ||
| + | else | ||
| + | buf[bufp++] = c; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | La biblioteca estándar incluye una función '' | ||
| + | |||
| + | * **Ejercicio 4-3**. Dada la estructura básica, es fácil extender la calculadora. Agregue el operador módulo ('' | ||
| + | * **Ejercicio 4-4**. Agregue órdenes para imprimir el elemento al tope de la pila sin sacarlo de ella, para duplicarlo y para intercambiar los dos elementos del tope. Agregue una orden para limpiar la pila. □ | ||
| + | * **Ejercicio 4-5**. Agregue acceso a funciones de biblioteca como '' | ||
| + | Consulte ''< | ||
| + | * **Ejercicio 4-6**. Agregue órdenes para manipular variables. (Es fácil proporcionar veintiséis variables con nombres de una letra.) Añada una variable para el valor impreso más reciente. □ | ||
| + | * **Ejercicio 4-7**. Escriba un a rutina '' | ||
| + | * **Ejercicio 4-8**. Suponga que nunca existirá más de un carácter de regreso. Modifique '' | ||
| + | * **Ejercicio 4-9**, Nuestros '' | ||
| + | * **Ejercicio 4-10**. Una organización alternativa emplea '' | ||
| + | |||
| + | ==== 4.4 Reglas y Alcance ==== | ||
| ==== 4.5 Archivo de encabezamiento header ==== | ==== 4.5 Archivo de encabezamiento header ==== | ||
| Línea 275: | Línea 498: | ||
| === 4.1.3 Inclusión condicional === | === 4.1.3 Inclusión condicional === | ||
| + | |||
| + | __**Continuar**__: | ||
