Programacion en C++
Programacion en C++
HISTORIA
- 31 -
1.1. IDENTIFICADORES ESTANDAR
1
ciones y etiquetas de un programa.
Por ejemplo:
Suma
Calculo_numeros_primos
ab123
_ordenar
i
- 32 -
1.3 ESTRUCTURA DE UN PROGRAMA Todo programa en C debe contener una función nombrada main(), donde el
programa comienza a ejecutarse. Las llaves ({}) que incluyen el cuerpo de
Como en todos los lenguajes siempre es bueno comenzar con un programa, esta función principal, definen el principio y el final del programa.
simple y sencillo.
Un programa C, además de la función principal main(), consta generalmente
/* Un primer programa en C*/ de otras funciones que definen rutinas con una función específica en el pro-
#include <stdio.h> grama.
void main(void)
{ • Estructura general de un programa en C:
printf(''Hola Puebla”); • Directrices para el preprocesador
return; • Definición de constantes
} • Definición de variables globales
• Declaración de funciones (función prototipo o declaración forward)
Explicación: • Función main
La primera línea dice que se debe de incluir un archivo de cabece-
ra, este archivo de cabecera contiene todas las funciones de entra- Los comentarios en C son cadenas arbitrarias de símbolos coloca-
da y salida (por ejemplo el printf, es una función que imprime da- dos entre los delimitadores /* y */ .
tos y/o letreros en pantalla), la segunda línea de código es el inicio
que todo programa en C debe de tener (función main), la tercera
línea imprime en pantalla el letrero hola Puebla, y después finaliza Ejemplos:
el programa, en las dos líneas finales se da por concluido el pro- /* Comentarios */
grama en C, la palabra return se utiliza para regresar un valor, en /* Este es un comentario
este caso es el término de la función main y no se regresa ningún muy largo ya que ocupa mas de un renglón */
valor.
Ejemplo de la estructura general de un programa en C:
Un programa en C está formado por una secuencia de caracteres que inclu-
yen: #include <stdio.h> /* Directrices del preprocesador */
Letras Minúsculas : a, b, ...., z #include <stdlib.h>
Letras Mayúsculas : A, B, ..., Z #define SU 100 /* Definición de constantes */
Dígitos : 0, 1, ..., 9 int x,y; /* Variables globales */
Caracteres Especiales : “, !, #, ”, $, %, &, /, (, etc. main() /* Programa principal */
{ /* Inicia el programa principal */
A partir de estos podemos generar cualquier programa en C, hay que tener float real; /* Variables locales */
cuidado por que algunos caracteres, tiene significados distintos, es decir, /* Acciones */
depende del contexto donde se utilizan. printf (“\n Dame dos numeros enteros: ”);
scanf(“%d%d”, &x,&y) ;
Un programa fuente C es una colección de cualquier número de directrices real=SU + x/y;
(inclusión de archivos), declaraciones, definiciones, expresiones, sentencias printf(“\n Resultado: %f”,real);
y funciones. } /* Fin del programa principal */
- 33 -
1.4. TIPOS DE DATOS ESTÁNDAR DEL LENGUAJE C
Combinaciones
Los tipos básicos del lenguaje son:
Carácter: Este tipo de dato se declara con la palabra reservada char y ocu-
pa un byte en memoria, con un byte se pueden representar 256 símbolos char 8 bits ASCII -128 a 127
posibles. unsigned char 8 bits ASCII 0 a 255
Real: Este tipo de datos se declara con la palabra reservada double o float, signed char 8 bits ASCII -128 a 127
si se utiliza la primera, entonces la variable que se declare ocupa 8 bytes de int 16 bits -32768 a 32767
memoria y si se utiliza la segunda entonces la variable que se declare utiliza
4 bytes de memoria. unsigned int 16 bits 0 a 65535
signed int 16 bits -32768 a 32767
Entero: Este tipo de datos se declara con la palabra reservada int y tiene
típicamente la misma longitud en bits que los registros del procesador de short int 16 bits -32768 a 32767
cada máquina. Por ejemplo, ocupa 2 bytes de memoria para equipos de 16
bis (8088, 80286) y 4 bytes en equipos de 32 bits (80486, Pentium, Celeron , unsigned short int 16 bits 0 a 65535
Xeon, Athlon, Duron). signed short int 16 bits -32768 a 32767
En la Tabla 1 se muestran todos los tipos de datos estándar en el lenguaje C.
long int 32 bits -2147483648 a 2147483647
1.4.1. Acerca de los tipos de datos reales ( flotantes ) signed long int 32 bits -2147483648 a 2147483647
unsigned long int 32 bits 0 a 4294967295
C proporciona los tipos flotantes float y double para manejar números de
la forma 1.7, 0.0001, 3.14159. También existe una forma exponencial para float 32 bits 6 dígitos de precisión 3.4E-38 a 3.4E+38
representar un número, por ejemplo, 1.092332e5. La correspondiente nota-
ción científica de este número es: double 64 bits 12 dígitos de precisión 1.7E-308 a 1.7E+308
long double 64 bits 12 dígitos de precisión 1.7E-308 a 1.7E+308
1.092332e5 = 1.092332*10*10*10*10*10
= 1.092332*100000 Tabla 1. Tipos de datos estándar
= 109233.2
1.4.2. Acerca del tipo de datos char
De forma similar se tiene el número 1.092332e-3, esto significa que el punto
decimal se desplaza 3 lugares a la izquierda y se tiene el siguiente valor Las constantes y las variables de tipo char se usan para representar caracte-
0.001092332. res y cada carácter se almacena en un byte.
El número 333.777e.22 se puede descomponer de la siguiente forma: Un byte esta compuesto de 8 bits, el cual es capaz de almacenar 2 a la 8 o
256 valores diferentes, pero solo un grupo pequeño de ellos es realidad
Parte entera = 333 representa a un conjunto de caracteres imprimibles.
Parte fraccionaría = 777
Parte exponencial = e-22
- 34 -
A continuación se muestran algunas constantes enteras y sus valores enteros Las variables y las constantes son los objetos que manipulan un pro-
correspondientes. grama. En general se deben declarar las variables antes de usarlas.
- 35 -
1.6.1 Operadores
2. Debido a que se especifican los tipos de datos asociados con las va-
riables, éstas permiten al compilador instruir a la máquina para que Un operador es un símbolo que indica al compilador que se lleven a cabo
desempeñe correctamente ciertas operaciones. específicas manipulaciones matemáticas o lógicas. El C tiene tres clases de
operadores: aritméticos, relacionales y lógicos y de bits. Además de otros
1.5.2. Declaración de CONSTANTES operadores especiales.
Números reales Números enteros Cadenas Carácter El signo de igualdad (=) es el operador básico de asignación en C. Un
3.10 1234 “hola C.U.” ‘a’ ejemplo de una “expresión” de asignación es: i = 7. A la variable i se le
0.987 -10 “” ‘#’ asigna el valor de 7 y la expresión como un todo toma ese valor.
Una constante (cualquier tipo de constante) en C se define de la siguiente Las proposiciones de asignación simples tiene la siguiente sintaxis:
manera:
variable = expresión;
#define identificador valor
donde,
identificador es el nombre de la constante
valor es el valor asociado a la constante 1.6.3 Proposiciones
Ejemplo:
Cuando la expresión va seguida de un punto y coma (;) se convierte en una
#define entero 10 proposición.
#define real 1.09982
#define cad “Estoy definiendo una constante que se llama cad “ Ejemplo de proposiciones:
#define car ‘a’
i=7;
x=3.1+sin(10.8);
1.6 EXPRESIONES, PROPOSICIONES Y ASIGNACIONES printf(“hola”);
Las expresiones son combinaciones de constantes, variables, operadores y Las siguiente proposiciones son válidas pero no tienen ningún significado
llamados a funciones. útil:
- 36 -
1.6.4. Operadores Aritméticos Operadores Asociatividad
-(unuario) derecha a izquierda
Los operadores aritméticos binarios se muestran en la siguiente tabla 2. *,/,% izquierda a derecha
+,- izquierda a derecha
Operador Operación = derecha a izquierda
Tabla3. Prioridad de los operadores aritméticos
+ Suma. Los operandos pueden ser enteros o reales
- Resta. Los operandos pueden ser enteros o reales Los operadores de una misma línea como *, /, %, tienen la misma prioridad
* Multiplicación. Los operandos pueden ser enteros o reales y ésta es mayor que la prioridad de las líneas inferiores. La regla de asocia-
/ División. Los operandos pueden ser enteros o reales. Si ambos tividad que rige a los operadores con la misma prioridad se muestra en la
operandos son enteros el resultado es entero. En el resto de los columna de la derecha
casos el resultado es real.
% Módulo o resto de la división entera. Los operandos tienen que Ejemplo:
ser enteros.
-(unario) Menos unario. Los operadores pueden ser enteros o reales. Encontrar la expresión equivalente y el valor de la expresión, utilizando las
Tabla 2. Principales operadores aritméticos siguientes declaraciones y asignaciones. También se debe de utilizar la tabla
de prioridad mencionada anteriormente.
Ejemplos:
int a=10, b=3, c; int a, b, c, d; /*Se declaran 3 variables de tipo entero*/
float x=2.0, y;
a=2; b=-3; c=7; d=-19;
y = x +a; /* El resultado es 12.0 de tipo float */
c = a / b; /* El resultado es 3 de tipo int */ Expresión Expresión Equivalente Valor
c = a % b; /* El resultado es 1 de tipo int */ a/b (a / b) 0
a = -b; /* El resultado es –3 */ b/b/a (b / b) / a -1
c%a (c%a) 1
1.6.4.1. Prioridad de los operadores aritméticos a%b (a%b) ?
d/b%a ((d/b)%a) 0
-a*d (-a)*d 38
Los operadores tiene reglas de prioridad y asociatividad, estas reglas deter- a%-b*c A%-(b*c) 14
minan la forma de evaluar las expresiones. Al evaluarse en primer lugar las 9/c+-20/d (9/c)+ ( (-20)/d) 2
expresiones que se encuentran entre paréntesis (), éstas pueden emplearse -d%c-b/a*5+5 (((-d)%c)-((b/a)*5))+5 15
para aclarar o cambiar el orden de ejecución de las operaciones que se de- 7-a%(3+b) 7-(a%(3+b) Error
sean realizar. ---a - (- (- a)) -2
A= b= c= -33 A= (b= (c= -33)) a=-33 y b=-33
La tabla 3. muestra las reglas de prioridad y asociatividad para los operado-
res aritméticos vistos hasta este momento.
- 37 -
1.6.5. Operadores de Relación y Lógicos Operador Operación Ejemplo
&& AND. Da como resultado el valor lógico 1 (z<x) && (y>w)
Al igual que los operadores anteriores, los operadores de relación y lógicos si ambos operandos son distintos de 0. Si
tienen reglas de prioridad y asociatividad que determinan de forma exacta la uno de ellos es cero el resultado es el valor
evaluación de las expresiones que los incluye. lógico 0. Si el primer operando es igual a
cero, el segundo operando no es evaluado.
Un operador relacional se refiere a la relación entre unos valores con otros, || OR. El resultado es cero si ambos operan- (x= =y) || (z!=p)
y un operador lógico se refiere a las formas en que estas relaciones pueden dos son 0. Si uno de los operandos tiene un
conectarse entre sí. valor distinto de 0, el resultado es 1. Si el
primer operando es distinto de 0, el segun-
Los Operadores de Relación son binarios (tabla 4). Cada uno de ellos toma do operando no es evaluado.
dos expresiones como operando y dan como resultado el valor int 0 o el ! NOT. El resultado es 0 si el operando tiene !a
valor int 1 (tómese en cuenta que en el lenguaje C cualquier valor distinto de un valor distinto de cero, y 1 en caso con-
0 es verdadero y el cero es falso). trario. El resultado es de tipo int. El ope-
rando puede ser entero, real o un apunta-
dor.
Operador Operación Ejemplos Tabla 5. Operadores lógicos
< Primer operando menor que el segundo a<3
Ejemplo:
> Primer operando mayor que el segundo b>w Operador de Negación
<= Primer operando menor o igual que el -7.7<=-99.335
segundo Expresión Valor
>= Primer operando mayor o igual que el -1.3>=(2.0*x+3.3) !5 0
segundo !a Depende del valor de a
== Primer operando igual que el segundo c= =’w’ !’z’ 0
!= Primer operando distinto del segundo x!=-2.77 !(x+7.7) Depende del valor de x
Tabla 4. Operadores de Relación Los operandos pueden ser de tipo entero, !!5 1
real o apuntador.
Los Operadores Lógicos (tabla 5) al igual que los operadores anteriores Ejemplo:
cuando se aplican a expresiones producen los valores int 0 o int 1. La nega-
ción lógica es aplicable a una expresión arbitraria. Los operadores lógicos Operadores Lógicos. Supóngase que se tienen las siguientes decla-
binarios && y || también actúan sobre expresiones. raciones y asignaciones:
char c;
int i,j,k;
double x,y;
- 38 -
Expresión Expresión Equivalente Valor Ejemplo:
i && j && k (i && j) && k 1 Multiplicación y división mediante operaciones de desplazamientos
X && i || j-3 (x && i) || j-3 0
X || i && j-3 (x|| i) && (j-3) 0 char X; X después de cada Valor de X
I<j && x<y (i<j) && (x<y) 0 ejecución
I<j || x<y (i<j) || (x<y) 1 X=7; 00000111 7 (Asignación)
I= =j && x<=y (i= =j) && (x<=y) 1 X << 1; 00001110 14 (X * 2)
I= = 2 || j= = 4 ||k= =6 (i= = 2) || (j= = 4) ||(k= =6) 0 X << 3; 01110000 112 (X * 8)
X << 2; 11000000 192 (X * 4, con pérdida del bit más signi-
ficativo)
X >> 1; 01100000 96 (X / 2)
1.6. 6 Operadores de manejo de bits X >> 2; 00011000 24 (X / 4)
Los operadores (tabla 6) para este tipo de operaciones tienen que ser de tipo
entero de uno o dos bytes o char, no pueden ser reales.
1.6.7. Operadores de asignación
Operador Operación
~ Complemento a 1. El operando tiene que ser entero Lista de operadores de asignación
& AND a nivel de bits
| OR a nivel de bits Operador Operación
^ XOR a nivel de bits ++ Incremento
<< Corrimiento (desplazamiento) a la izquierda -- Decremento
>> Corrimiento (desplazamiento) a la derecha
= Asignación simple
Tabla 6. Operadores para el manejo de bits
+= Suma más asignación
Ejemplo: -= Resta más asignación
|= Operación OR sobre bits más asignación
int a=0777, m=2;
a=a & 0177; /* Pone a cero todos los bits de a excepto los 7 bits de &= Operación AND sobre bits más asignación
menor peso */ >>= Corrimientos a la derecha más asignación
<<= Corrimientos a la izquierda más asignación
a=a | m; /* pone a uno todos los bits de a que están a 1 en m */
a = a & ~077; /* pone los 6 bits de menor peso de a, a 0 */ *= Multiplicación más asignación
/= División más asignación
%= Módulo más asignación
Tabla 7. Operadores de asignación
- 39 -
Los operadores de incremento ++ y decremento -- son unarios y tienen la 1.6.8. Tabla final de prioridad y orden de evaluación
misma prioridad que el operador unario - , éstos se asocian de derecha a
izquierda. Tanto ++ como -- se pueden aplicar a variables, pero no a cons- Una expresión entre paréntesis, siempre se evalúa primero. Los paréntesis
tantes o a expresiones. Además pueden estar en la posición de prefijos o tienen mayor prioridad y son evaluados de más internos a más externos.
sufijos, con diferentes significados posibles.
Incremento: ++ añade 1 a una variable El operador coma (,) hace que las expresiones se evalúen de izquierda a
Decremento: - - resta 1 a una variable derecha.
Ejemplo:
Operadores Asociatividad
A+=3 es equivalente a A=A+3
() Izquierda a derecha
k*=3+x es equivalente a k=k*(3+x)
-(unario), ++, --, ~, !, *, &(los últimos dos como Derecha a izquierda
x = x+1; equivalente a ++x; operadores apuntadores)
x = x-1; equivalente a - -x; *,/,% Izquierda a derecha
+,- Izquierda a derecha
Estos operadores pueden ir antes o después de la variable. <,<=,>,>= Izquierda a derecha
x = x+1; ++x; x = x-1; - -x; = =, != Izquierda a derecha
x++; x - -; & Izquierda a derecha
^ Izquierda a derecha
| Izquierda a derecha
• Antes de la variable: Si el operador ++ o - - aparece antes del ope- && Izquierda a derecha
rando, entonces el operando se incrementa o decrementa antes de || Izquierda a derecha
que se evalúe la expresión. =, +=, -=, *=, <<=, >>=, %= Derecha a izquierda
, (operador coma) Izquierda a derecha
Ejemplo: Tabla 8. Tabla final de todos los operadores en C, así como su prioridad y
x = 10; su asociatividad
y = ++x; ==> y = 11;
Los operadores que se encuentran en las líneas superiores tiene más priori-
• Después del operando: Si el operador ++ o -- aparece después del dad que los operadores de las líneas inferiores y los operadores que se en-
operando, entonces primero se evalúa la expresión con el valor ac- cuentran en la misma línea tiene la misma prioridad y si existen operadores
tual del operando y posteriormente se incrementa o decrementa el con la misma prioridad en una expresión, éstos se asocian según la columna
operando. de la derecha de la tabla anterior.
Ejemplo:
x = 10;
y = x++; ==> y =10;
en ambos casos x = 11;
- 40 -
1.6.8.1. Otros operadores formato bajo el cual se requiere la salida de la información
(datos) hacia pantalla
El operador de indirección (*) accede a un valor indirectamente a través de
un apuntador. El resultado es el valor direccionado por el operando. lista de argumentos
representa el valor o valores a escribir en la pantalla. Una
El operador de dirección-de (&) indica la dirección de su operando. Este especificación de formato está compuesta por:
operador no se puede aplicar a un campo de bits perteneciente a una estruc-
tura o a un identificador declarado con el especificador register. % [flags] [width] [.prec] [F|N|h|l|L] tipo_de_dato
- 41 -
Ejemplo: esta formada por códigos de formato de entrada, que están
n1=5; precedidas por un signo % y encerrados entre comillas “ “
n2=6.7; dobles. Ver tabla 10.
printf(“El dato 1 es: %d y El dato 2 es: %f \n”,n1,n2); Código Significado
c Lee un único carácter
d Lee un entero decimal base 10
Explicación: i Lee un entero en base 10, 16 u 8
En este ejemplo el primer formato %d corresponde a un número f Lee un número en punto flotante
entero (n1) y el %f corresponde a un número real (n2), insertándo- e Lee un número en punto flotante
se un cambio de línea al final (\n).
h Lee un número entero corto
Salida: El dato 1 es: 5 y El dato 2 es: 6.700000
s Lee una cadena de caracteres
o Lee un entero en octal
Secuencia Nombre
x Lee un número hexadecimal
\n Nueva línea
Tabla 10. Códigos de formato de scanf()
\t Tab horizontal
\v Tab vertical (solo para impresora)
lista de argumentos
\b Backspace (retroceso) representa el valor o valores a escribir en la pantalla.
\r Retorno de carro
\f Alineación de página (solo para impresora) Una especificación de formato esta compuesta por:
\a Bell (sonido) Símbolo Significado
\´ Comilla simple * Un asterisco a continuación de % suprime la
\” Comilla doble asignación del siguiente dato en la entrada.
\0 Nulo Ancho Máximo numero de caracteres a leer de la entra-
\\ Backslash (barra hacia atrás) da. Los caracteres en exceso no son tenidos en
\ ddd Carácter ASCII. Representación Octal cuenta.
\ xdd Carácter ASCII. Representación hexadecimal f Indica que se quiere leer un valor apuntado por
Tabla 9. Secuencias de escape en lenguaje C una dirección far(dirección segmentada).
N Indica que se quiere leer un valor apuntado por
1.7.2. Entrada de datos utilizando la función scanf( ) una dirección near (dirección dada por el valor
offset).
La función scanf( ) es una rutina de entrada de propósito general, que per- F y N no pertenecen al C estándar.
mite leer datos formateados y convertir automáticamente la información H Se utiliza como prefijo con los tipos d, i, n, o y x,
numérica a enteros o a flotantes por ejemplo. El formato general de esta para especificar en el argumento es short int, o
función es: con u para especificar un short unsigned int.
scanf (cadena de control, lista de argumentos); L Se utiliza como prefijo con los tipos d,i,n,o, y x,
cadena de control para especificar que el argumento es long int.
También se utiliza con los tipos e,f y g para
especificar un double.
- 42 -
Tipo El tipo determina si el dato de entrada es inter- Para leer datos de tipo cadena no lleva el operador de dirección &. Y tene-
pretado como un carácter, como una cadena de mos que cambiar el formato %s por %[^\n].
caracteres o como un número.
Cuando se especifica mas de un argumento, los valores correspon- Si en lugar de especificar el formato %[^\n] se hubiera especifica-
dientes en la entrada hay que separarlos por uno o mas espacios en do el formato %s , el resultado hubiera sido: Francisco.
blanco (’ ’),tabuladores(\t) y cambios de línea(\n).
La función scanf() devuelve un entero correspondiente al número 1.7.3. Entrada de caracteres getchar( )
da datos leidos de la entrada.
Lee un carácter de la entrada estándar y avanza la posición de lectura al
Ejemplo: siguiente carácter a leer
Main()
{ int getchar(void);
int a,r;
float b; Ejemplo:
char c; car = getchar();
printf(“Introducir un valor entero, un real y un carácter \n => “);
r=scanf(“ %d %f %c \n”,a,b,c); Resultado: Lee un caracter y lo almacena en la variable car.
printf(“Numero de datos leidos: %d \n”,r);
printf(“ Datos leídos: %d %f %c \n”,a,b,c); 1.7.4. Salida de caracteres putchar( )
}
Escribe un carácter en la salida estándar en la posición actual y avanza a la
Salida: siguiente posición de escritura.
Introducir un valor entero, un real y un carácter
=> 12 3.5 x int putchar(int ch);
Numero de datos leidos: 3 Ejemplo:
Datos leídos: 12 3.500000 x putchar(ch);
- 43 -
En el lenguaje C se incluyen las siguientes estructuras condicionales: if y
switch Y las sentencias de repetición : for, while y do/while.
2
para referirnos al mismo concepto.
2.1. PROPOSICIÓN if
Explicación:
Se evalúa la expresión (grado >=90) si es verdadera se muestra el
letrero FELICIDADES y escribe “Su grado es : x“. Si la expresión
es falsa entonces solo se muestra el letrero “Su grado es : x”.
- 44 -
2.2. PROPOSICIÓN if-else 2.2.1. Anidamiento de sentencias if
Una proposición if-else es una construcción de la forma: Las sentencias if-else pueden estar anidadas. Esto quiere decir que como
proposión1 o proposición2, de acuerdo al formato anterior, puede escribirse
if (expresión) otra sentencia if.
{
proposición_1 /* bloque 1*/ if (expresion1)
} Sentencias1;
else { else if(expresión2)
proposición_2 /* bloque 2*/ Sentencias2;
} else if(expresión3)
proposición_siguiente; sentencia3;
….
Se evalua la expresión si es verdadera entonces se ejecuta el bloque 1 que else
puede estar formado por una proposición (no usar llaves {}) o un conjunto sentenciasN;
de proposiciones (usar llaves {}).
Si se cumple la expresion1, se ejecuta las sentencias1, si no se cumple se
Si la expresión es falsa entonces se ejecuta la proposición 2 o el bloque 2. examinan secuenciales las expresiones siguientes hasta el else, ejecutándose
las sentencias correspondientes al primer else if, cuya expresión sea cierta.
Si todas las expresiones son falsas, se ejecutan las sentenciasN.
Ejemplo:
if (x<=y) El if se puede anidar indistintamente después del if o después del else y
min=x puede ser en cada una de estas una sentencia o un conjunto de sentencias.
else
min=y; Ejemplo
if (a>b)
Expliación: printf(“%d es mayor que %d”,a,b);
En este segmento del programa se asigna a la variable min el me- else if (a<b)
nor de x y y. printf(“%d es menor que %d”,a,b);
else
Ejemplos: printf(“%d es igual a %d”,a,b);
if (a>=0)
printf("\el numero es positivo"); Cuando en una línea de programa aparecen anidadas sentencias if-else, la
else regla para diferenciar cada una de estas sentencias, es que cada else se co-
printf("\el numero es negativo"); rresponde con el if más próximo que no haya sido emparejado.
- 45 -
2.3. LA PROPOSICIÓN switch Ejemplo:
Esta proposición permite ejecutar una de varias acciones, en función del char ch;
valor de una expresión. ch=getchar();
switch (ch)
El formato de esta proposición es: {
case ‘0’:
switch (expresión-test) case ‘1’:
{ case ‘2’:
case constante1: sentencia; case ‘3’:
case constante2: sentencia; case ‘4’:
case constante3: sentencia; case ‘5’:
... case ‘6’:
default : sentencia case ‘7’:
} case ‘8’:
case ‘9’: printf(“\n Es un digito “);
donde: break;
case ‘ ‘:
expr-test case’\n’:
es una constante entera, una constante de caracteres o una expre- case’\t’: printf(“\n Es un separador”);
sión constante. El valor es convertido a tipo int. break;
sentencia default: printf(“\n Otro”);
es una sentencia simple o compuesta (bloque). break;
}
La sentencia switch evalúa la expresión entre paréntesis y compara su valor
con las constantes de cada case, si se cumple la expresión-test con alguna Explicación:
constante entonces se ejecutaran todas las sentencias después de la igualdad. Se almacena un caracter en ch y se evalua en el switch si este ca-
Usualmente se utiliza la sentencia break para romper la sentencia switch. rácter esta entre ‘0’ ..’9’ entonces se dice que es un digito y termi-
na el switch con el break. Si el carácter es un separador se indica
En el caso de que ninguna de las constantes coincida con la expresión-test con un letrero, pero si no es ninguno de los anteriores, entonces se
entonces se ejecuta la opción default. La sentencia switch puede incluir dice que es “otro”.
cualquier número de cláusulas case y opcionalmente la cláusula default.
- 46 -
2.4. PROPOSICIÓN for Ejemplo: Imprimir los múltiplos de 7 que hay entre 7 y 112
for (k = 7 ; k <= 112 ; k = k+7)
Cuando se desea ejecutar una acción simple o propuesta, repetidamente un Printf(“%d”,k)
número de veces conocido, es recomendable utilizar la proposición for.
Ejemplo: codificación de la suma de 10 números (del 1 al 10).
for (inicialización ; condición ; incremento)
{ suma=0;
sentencia1; for(i=0; i<=10; i++)
sentencia2; suma+=i;
... Explicación:
sentencian; Se inicializa la variable suma en 0 para ir acumulando la suma de
} los valores de i que van desde 0 hasta 10.
- 47 -
Una proposición while se ejecuta mientras la expresión sea verdadera (cual- {
quier valor distinto de cero), en el momento en que se convierte en falsa la /* calcular la parte entera (z) de la raiz cuadrada */
expresión entonces se ejecuta la siguiente línea después del fin del while. z = sqrt(x *x + y * y);
while (y <= 50 && z <=50)
Ejemplo: {
char ca; /* comprobamos si z es suma de dos cuadrados perfectos*/
ca=0; if(z*z == x*x + y*y)
while (ca!=’A’) printf(“\n %10d %10d %10d”,z,x,y);
{ y++;
ca=getchar(); z = sqrt(x*x + y*y);
putchar(ca); }
} x++;
y = x;
Explicación: }
Se puede ver que ca se inicializo con cero, de esta forma podemos
iniciar el while, entonces se lee un carácter con la función get-
char() y se manda a escribir a la pantalla, a continuación se com- 2.6. PROPOSICIÓN do-while
para este valor de ca con ‘A’ si es distinta entonces vuelve a leer
otro carácter y a escribirlo en pantalla. Se estará entonces pidien- Ejecuta una sentencia o varias una o mas veces, dependiendo del valor de
do caracteres hasta que el carácter ca se igual a ‘A’ (haciéndose una expresión.
falsa la condición).
do
Ejemplo: Realizar un programa que nos imprima los números z, comprendi- {
dos entre 1 y 50, que cumplan la expresión: sentencia1;
sentencia2;
z2 = x2 +y2 sentencia3;
z,x e y son números enteros positivos. ...
sentencian;
/* Cuadrados que se pueden expresar como suma de otros dos cuadrados */ }while (expresión);
#include <stdio.h>
#include <math.h> donde:
main()
{ expresión
unsigned int x,y,z; es cualquier expresión numérica, relacional o lógica.
printf(“%10s %10s %10s \n”,”Z”,”X”,”Y”); Sentencia:
printf(“-----------------------------------------\n”); es una sentencia simple (sin usar llaves {}) o un bloque de senten-
x=1; cias
y=1;
while (x <= 50)
- 48 -
La sentencia do-while se ejecuta de la siguiente manera. Se ejecuta primero scanf(%lf”,&epsilon);
la sentencia o bloque de sentencias dentro del do. Se evalúa la expresión si do
es falsa (igual cero) termina la proposición do-while y si al evaluar la expre- {
sión el resultado es cualquier valor distinto de cero entonces se repite la antaprox = aprox;
sentencia o sentencias dentro del do {}. aprox = (n / antaprox + antaprox) / 2;
}while ( fabs (aprox – antaprox) >= epsilon);
Ejemplo: /* fabs calcula el valor absoluto de una expresión real */
int n; printf(“ \n \n La raíz cuadrada de %.2lf es %.2lf”,n, aprox);
do /* el .2 en el %.2lf nos toma solo dos cifras después del punto */
{ }
printf(“\n Da un número : “);
scanf(“%d”,&n); Entrada:
}while ( n>100); Número: 10
Raiz cuadrada aproximada: 1
Explicación: Coeficiente de error: 1e-6
se leeran números enteros de teclado hasta que se de un número
menor que 100. Salida:
La raiz cuadrada de 10.00 es 3.16
Ejemplo: Calcular la raíz cuadrada de un número n, por el método de New-
ton que dice:
2.7. CICLOS ANIDADOS
ri+1 = (n/ri + ri)/2
La proposición for al igual que el while y el do-while puede colocarse de-
La raíz calculada será válida, cuando se cumpla que: ntro de otro for (while o do-while) y entonces se dice que están anidados. En
abs(ri –ri+1) < = épsilon estos casos el ciclo de repetición más interno se ejecutara primero totalmen-
te, por cada valor del ciclo que lo contiene.
/* Raiz cuadrada de n por el metodo de Newton */
#include <stdio.h> Ejemplo: Escribir un programa que imprima un triangulo construido con
main() caracteres (#).
{
double n; /* número */ #
double aprox; /* aproximación a la raíz cuadrada */ # #
double antaprox; /* anterior aproximación a la raíz cuadrada */ # # #
double epsilon; /* coeficiente de error */ # # # #
printf(“Numero: “); # # # # #
scanf(“%lf”,&n);
printf(“Raiz cuadrada aproximada: “);
scanf(“lf”,&aprox);
printf(“Coeficiente de error: “);
- 49 -
/* construcción de un triangulo de n filas con # */ 2.9. LA FUNCIÓN exit()
#include <stdio.h>
main() Otra forma de terminar un ciclo de repetición desde dentro es utilizar la
{ función exit(). A diferencia con el break, la función exit terminará con la
unsigned int filas, columnas; ejecución del programa y regresara el control al sistema operativo.
unsigned int nfilas;
printf(“ Número de filas del triángulo : “); Ejemplo:
scanf(“%d”,&nfilas);
for (filas =1 ; filas <= nfilas ; filas++) for (i =0 ; i <= 1000 ; i++)
{ {
for ( columnas =1 ; columnas <= filas ; columnas++) printf(“ El valor de I es %d”,I);
printf(“# “); if (I>10) exit();
printf (“\n”); }
}
} Explicación: Aunque se ha elaborado una estructura para que la varable de
control I tome los valores de 0a 100 cuando llega al valor de 11 termina el
programa y solo escribirá de 0 a 10 para el valor de i.
2.8. LA SENTENCIA break
La sentencia break finaliza la ejecución de una proposición switch, for, 2.10. LA SENTENCIA continue
while y do-while en la cual aparece, saltándose la condición normal del
ciclo de repetición. La sentencia continue actúa al revés que la sentencia break: obliga a que
tenga lugar la siguiente iteración, saltándose cualquier código intermedio.
Ejemplo: Un break causará una salida sólo del ciclo más interno.
Ejemplo:
for (t=0;t<100; t++) do {
{ printf (“ Da un número : “);
contador=1; scanf(“%d”,&x);
do{ if (x<0) continue;
printf(“%d “,contador); printf(“ El número es %d”,x);
contador++; }while ( x != 100)
if (contador == 10) break;
}while(1) /* por siempre */ Explicación:
} aquí solo se imprimen los números positivos; introducir un número
negativo provocara que el control del programa se salte a evaluar
Explicación: la expresión x!=100.
se imprimirá 100 veces en la pantalla los números del 1 al 10. Ca-
da vez que se encuentre break, el control se devuelve al ciclo for,
terminando en do-while.
- 50 -
3
3.1. ARREGLOS
int X[6];
Posición
0 1 2 3 4 5
Muchas aplicaciones requieren el procesamiento X 78 12 8 -20 14 100
de múltiples datos que tienen características co-
munes y es conveniente colocarlos en estructuras Contenido del arreglo X en la posición 3
donde todos los elementos comparten el mismo
nombre. Para el caso de datos del mismo tipo se Explicación:
tienen los arreglos y para datos de tipos diferen- x es un arreglo de números enteros, para acceder a los datos en el
tes tenemos las estructuras. arreglo se hace mediante el nombre y la posición. Por ejemplo
para almacenar el –20 en la posición 3 del arreglo X se hace de la
forma: X[3]=-20; Para obtener algún valor del arreglo: C=X[2];
/* C=8 */
- 51 -
Los arreglo en C siempre inician en la posición 0. 3.1.1.1 Cadenas
- 52 -
nombre for (r=0 ; r<n;r++)
es un identificador que nombra el arreglo . for(c=0; c<m;c++)
renglones scanf(“%d”,&ma[r][c]);
indica el numero de renglones de la matriz
columnas printf(“Lectura de la Matriz 2: \n”)
indica el numero de columnas de la matriz for (r=0 ; r<n;r++)
for(c=0; c<m;c++)
Ejemplo: scanf(“%d”,&mb[r][c]);
- 53 -
tamaño1 nombre_estructura
indica el número de elementos de la primera dimensión es un identificador que nombra el nuevo tipo definido, la estructura
tamaño2 variables_estrutura
indica el número de elementos de la segunda dimensión son identificadores para acceder a los campos de la estructura
.
tamaño-n Después de definir un tipo estructura, podemos declarar una variable de este
indica el número de elementos de la n-ésima dimensión tipo de la forma:
Una estructura es una colección de datos elementales (básicos) de diferentes Para asignar datos en la estructura se hace mediante la variable_estructura
tipos, lógicamente relacionados. A una estructura se le da también el nombre y el campo donde se almacenara el valor separados por un punto (.). En el
de registro. Crear una estructura es definir un nuevo tipo de datos. En la ejemplo anterior para almacenar para poner edad en el cliente:
definición de la estructura se especifican los elementos que la componen así
como sus tipos. Cada elemento de una estructura se denomina miembro (o cliente.edad = 22;
campo). Declaración de una estrucura:
- 54 -
Ejemplo: De la declaración de la estructura ficha. /* Calcular resultados */
for (I=1ñi< n; i++)
struct ficha cliente[20] ; if (alumnus[i].nota >= 6)
aprobados++;
Ahora Para almacenar la edad en alguno de los clientes. else
cliente[3].edad = 25; reprobados++;
donde se esta asignando la edad 25 al cliente que se encuentra en la posición /* escribir resultados */
3 (recuerde que los arreglos inician desde 0, por lo que en realidad es la printf (“Aprobados %.4f \n”, aprobados/n*100);
posición 4 del mismo). printf (“Reprobados %.4f \n”, reprobados/n*100);
}
Ejemplo: El siguiente programa lee una lista de 10 alumnos y su correspon-
diente nota final de curso, dando como resultado el tanto por ciento de
alumnos aprobados y reprobados. 3.3. UNIONES
#include <stdio.h> La unión es una variable que puede contener, datos de diferentes tipos, de-
#define NA 10 /* número máximo de alumnos*/ nominados miembros o elementos, en una misma zona de memoria.
main()
{ union nombre_union
struct datos {
{ tipo nombre_variable;
char nombre[60]; tipo nombre_variable;
float nota; tipo nombre_variable;
} .....
struct datos alumnos[NA]; /* arreglo se estructuras */ }variables_union;
int n=0,i;
char fin; / apuntador al nombre leído */ nombre_union
float aprobados=0, reprobados=0; es un identificador que designa el nuevo tipo union
variables_union
/* Entrada de datos */ son identificadores para acceder a los campos de la union
printf(“Nombre: ”);
fin = gets(alumnos[n].nombre); La declaración de una unión tiene la misma forma que la de una estructura,
while ( n < NA) excepto que en lugar de la palabra reservada struct se pone la palabra
{ union. Todo lo expuesto para las estructuras es aplicable a las uniones,
printf(“Calificación : “); excepto la forma de almacenamiento de sus elementos. Cuando se define
/* %*c se utiliza para eliminar el retorno de carro */ una estructura cada uno de sus componentes ocupa una localidad de memo-
scanf(“%f%*c”,&alumnus[n++].nota); ria diferente, mientras en una union se utiliza el espacio de memoria igual a
printf(“Nombre: ”); la que ocupa el miembro mas largo de la union.
fin = gets(alumnos[n].nombre);
}
- 55 -
Después de definir un tipo union, podemos declarar una o más variables de
ese tipo de la forma:
variable_union.campo
Ejemplo:
union info
{
char var1;
int var2;
int var3;
}
union info var_union;
Explicación:
en este ejemplo, se declara una variable var_union que representa
a una union llamada info, con tres miembros o campos. La variable
var_union debe ser lo suficientemente grande como para contener
el mayor de los tres campos. Cualquiera de los tres campos puede
asignarse a var_union y utilizar en expresiones. Es responsabilidad
del programador recordar cual es el campo actual que esta en la
union.
var union
var1
var2
var3
- 56 -
4.1. FUNCIONES
4
FUNCIONES
Las funciones son bloques con los que se construyen programas C, y en
ellos se lleva a cabo toda actividad del programa. Una vez que una función
ha sido escrita y depurada, puede utilizarse una y otra vez. Este es uno de los
aspectos más importantes del C como lenguaje de programación.
main() func2()
{ func1() {
func1(); {
..... func2(); .....
func1() ..... return;
} return; }
El Lenguaje C utiliza funciones de biblioteca con }
el fin de realizar un cierto número de operaciones.
Sin embargo, C permite también al programador Flujo de control del llamdo de funciones
definir sus propias funciones que realicen deter-
minadas tareas. El uso de funciones (procedi- La definición de una función consiste en un encabezado y un cuerpo. De
mientos) definidas por el programador permite manera explicita, se puede decir que es un bloque o una proposición com-
dividir un programa grande en cierto número de puesta. La estructura básica de la definición de una función es:
componentes más pequeñas (modularización),
cada una de las cuales con un propósito único e tipo nombre([,argumentos])
identificable. {
[declaraciones]
proposiciones
[return(expresión);]
- 57 -
}
El siguiente ejemplo es más complicado:
• Encabezado de una función.
void letrero(int i)
tipo: {
indica el tipo del valor devuelto por la función. Puede ser cualquier if (i>0)
tipo básico, estructura o unión. Por defecto es int. Cuando no que- printf("\n i es positivo");
remos que devuelva ningún valor usaremos el tipo void. else
nombre: printf("\n i es negativo");
es un identificador que indica el nombre de la función. Si el nombre return;
va precedido por un *, el resultado devuelto por la función en el re- }
turn será un apuntador. Una función no puede retornar arrays o
funciones pero si puede retornar un apuntador a un array o a una Ejemplo: la siguiente función usa dos argumentos de tipo entero y regresa
función. un valor ( la suma de ambos argumentos) de tipo entero.
[argumentos]:
es una secuencia de declaraciones de parámetros separados por co- int suma(int a, int b)
mas, cada argumento(o parámetro) deberá ir con su tipo correspon- {
diente. Si no se pasan argumentos a la función podemos utilizar la int valor;
palabra reservada void. valor = a+b;
return(valor);
• Cuerpo de una función. }
El cuerpo de la función está formado por una sentencia compuesta que con-
tiene sentencias que definen lo que hace la función. También puede contener • LLamado a una función
declaraciones de variables utilizadas en dichas sentencias. Estas variables,
por defecto son locales a la función. Para llamar a una función se hace mediante su nombre con los argumentos
entre paréntesis. Generalmente se asigna el valor de la función a una varia-
[return(expresion)]: ble del mismo tipo de esta.
se utiliza para devolver el valor de la función el cual debe ser del
mismo tipo declarado en el encabezado de la función. Si la senten- Ejemplo:
cia return no se especifica o se especifica sin contener una expre-
sión, la función no devuelve un valor. #include <stdio.h>
main()
Ejemplos: {
void letrero(void) letrero(); /* llamado a la función letrero definida antes */
{ return;
printf("\n Esta es una función muy simple"); }
return;
}
- 58 -
Ejemplo: Ejemplo:
main()
{ main()
letrero(10); /* llamdo de la segunda funcion con {
un argumento*/ /* declaración de una función prototito */
getch(); double escribir(duble x, int y);
return;
} douible r,a=3.14;
int b= 5 ;
Ejemplo: llamado de la función suma, en el primer llamado se dan los ar- r = escribe(a,b) ; /* llamada a la función */
gumentos constantes y en el segundo llamado se pasan los valores en dos printf(“%.2lf \n”,r);
variables, en ambos casos el resultado de evaluar la función esta en la varia- }
ble res que es del mismo tipo que la función suma.
/* definición de la función */
main() duoble escribir(double x, int y)
{ {
int res; return( x + y * 13 );
int n1=23; }
int n2=55;
res = suma (5,10); Explicación:
printf(“La suma es : %d\n”,res); En este ejemplo. La declaración forward o funcion prototipo es ne-
res = suma(n1,n2); cesaria, ya que se esta llamando en el main() antes de haber sido
printf(“La suma de %d + %d = %d\n”,n1.n2,res); declarada.
}
Si la función se define antes del llamado de ésta en algún lugar del progra-
ma, entonces no es necesario hacer una declaración forward.
Una función prototipo (declaración forward) permite conocer el nombre, el 4.3. Paso de parámetros
tipo de resultado, los tipos y nombres de los argumentos, pero no se define
el cuerpo de la función. Esta información permite al compilador char los En C existen dos tipos de paso de parámetros en el llamado a una función:
tipos de los parámetros actuales por cada llamada a la función. Una función
prototipo tiene la misma sintaxis que la definición de una función, excepto Paso de parámetros por valor :
que esta, termina con un punto y coma (;). Es necesario hacer una declara- Pasar parámetros por valor, significa copiar los parámetros
ción forward cuando se hace el llamado de la función antes de haberla defi- actuales en sus correspondientes lista de argumentos, ope-
nido. ración que se hace automáticamente, con lo cual no se
modifican los argumentos actuales.
- 59 -
4.4. Reglas básicas de alcance (scope)
Paso de parámetros por referencia :
Pasar parámetros por referencia, significa que lo transferi- La regla básica de alcance consiste en que los identificadores son accesibles
do no son los valores, sino las direcciones de las variables sólo dentro del bloque en el que se declararon, fuera de éste son desconoci-
que contienen esos valores, con lo cual los argumentos ac- dos, por ejemplo:
tuales de la función pueden verse modificados.
{
Cuando se llama a una función, los argumentos especificados en la llamada int a=5;
son pasados por valor, excepto los arrays (arreglos) que se pasan por refe- printf("\n%d", a);
rencia. {
int a=7:
Ejemplo:
#include <stdio.h> printf("\n%d", a);
/* función sumar*/ }
int sumar(int a, int b, int c, int *s) printf("\n%d", ++a);
{ }
b += 2;
*s = a + b + c;
} Obsérvese que se ha declarado la misma variable dos veces, pero
aunque tenga el mismo nombre son variables distintas y por lo
main() tanto sus valores son distintos, en la segunda declaración de la
{ variable a, ésta se destruye cuando alcanza el fin de bloque de
int v = 5, res: proposiciones, primera llave cerrada (“}”).
sumar(4,v,v*2-1,&res) /* llamado a la función */
printf(“%d”,suma);
}
4.4.1 Variables Locales y Variables Globales
Explicación:
la llamada a la función sumar, pasa a esta función los parámetros La regla de alcance es utilizada comúnmente para utilizar variables globales
4, v y v*2-1 por valor y el parámetro res por referencia. Cualquier y locales. Las Variables Globales se declaran al inicio del programa fuera
cambio que sufra el argumento s, sucede también en su correspon- del main() y fuera de cualquier función, en cambio las Variables Locales se
diente parámetro actual res. En cambio, la variable v, no se ve declaran dentro e algún bloque. La diferencia sustancial entre estas dos tipos
modificada, a pesar de haber variado b, ya que ha sido pasada por de variables es el alcance: Las variables globales pueden modificar su valor
valor.
en cualquier parte del programa, mientras que las variables locales solo
pueden ser usadas en el bloque donde fueron definidas.
Nótese el uso del operador de referencia '&' u operador de direc-
ción para pasar un valor por referencia.
- 60 -
Ejemplo:
#include <stdio.h>
int x=20;
void escribe_x()
{
printf(“ El valor de x (Global) es = %d\n”,x); /* x=15 */
}
main()
{
int x=12;
escribe_x(); /* Escribe el Valor de x = 15 */
printf(“ El valor de x (Local) es = %d\n”,x); /* x=12 */
}
- 61 -
5.1. APUNTADORES
Una variable sencilla de un programa se almacena en un número de bytes
5
(p/e, un entero utiliza dos bytes). El apuntador se usa en programas que
acceden a la memoria y manipulan direcciones. Ya se han utilizado apunta-
dores (p/e, en la lista de argumentos del scanf...)), aunque de una manera
sencilla y sin saber exactamente como funcionan.
Para definir un apuntador lo primero que se debe tener en cuenta es que todo
apuntador tiene asociado un tipo de dato. Un apuntador se define igual que
una variable normal, salvo que delante del identificador se coloca el opera-
dor apuntador. Por ejemplo:
char *p = &p1;
- 62 -
• Asignarle el contenido de otro apuntador que ya está‚ iniciali- dice que p es de tipo apuntador a un entero. Ejemplos de apuntadores utili-
zado: zando asignaciones (bajo la declaración anterior):
Los lvalue más frecuentes son una cadena de caracteres, el iden- Supongamos la siguiente declaración:
tificador de un arreglo, el identificador de una función, entre
otros. Este es un detalle importante: los identificadores de fun- double x, y, *p; /* aquí se declaran dos variables simples de tipo double y
ciones y de arreglos son en sí mismos valores por la izquierda una variable que es de tipo apuntador a un double (real) */
(lvalue), por lo que se pueden usar directamente para inicializar
apuntadores. p=&x; /* a p se le pasa la dirección de x */
y=*p; /* a y se le pasa el contenido de p */
Una forma adicional de inicializar apuntadores es darle directamente una y=x; /* a y se le pasa el contenido de x */
posición de memoria. Este método no es portable, ya que depende del siste- y=*&x; /* son operadores unarios *y &y se asocian de de-
ma, pero suele ser muy útil en programación de sistemas, que es uno de los recha a izquierda y dice el contenido de la dirección de x
usos fundamentales del C. asignalo a y */
El operador & sólo se puede aplicar a variables y a elementos de arreglos, Construcciones a las que no se deben de apuntar son las siguientes:
de tal forma que si se tiene la siguiente construcciones: &(x+1) y &3 no son
permitidas dentro de C. &4 /* no se deben de apuntar a constantes */
Por otra parte, un error muy frecuente consiste en no inicializar el apuntador int a[10]; /*se declara un arreglo */
antes de usarlo. Este error frecuentemente lo localiza el compilador y avisa &a /* como a es un arreglo no se debe de hacer referencia a la
de ello. dirección de arreglo ya que por si sola la variable a signifi-
ca una dirección */
Las direcciones que se manejan con los apuntadores son un conjunto de
valores que pueden manipularse. Las variables de apuntadores pueden de- Para ver el uso de los apuntadores dentro de las funciones y como paso de
clararse en los programas y después utilizarse para tomar las direcciones parámetros, a continuación se muestran dos funciones que hacen lo mismo,
como valores. es decir intercambian sus valores, si es que el primer parámetro es mayor
que el segundo.
La declaración:
int *p;
- 63 -
Ordena (int p, int q) La forma de llamar a Ordena desde una función es: Ordena(i,j) y la forma
{ de llamar a Odena1 desde un función es: Ordena(&i, &,j)
int tmp;
if (p>q){ Por último, es importante hacer notar que los apuntadores no son enteros,
tmp=p; puesto que generalmente al hacer una asignación de un apuntador a una
p=q; variable de tipo entero no hay pérdida de información, ni escalado o conver-
q=tmp; sión, pero esto puede ser una práctica peligrosa.
} Una aplicación también muy extendida de los apuntadores corresponde a
return; definir una parte de la memoria para trabajar en ella y manejarla mediante
} un solo objeto, el apuntador a ella. Ésta metodología se llama manejo de
Memoria Dinámica.
Ordena1(int *p, int *q) Ésta técnica permite hacer manipulaciones muy eficientes y flexibles de la
{ memoria, las instrucciones de C que permiten lograr esto son malloc y free,
int tmp; la primera reserva una cantidad de memoria definida por el usuario y la
if (*p>*q){ segunda la libera. Éstas funciones pertenecen a la librería estándar de C.
tmp=*p;
*p=*q; La sintaxis para asignar la memoria es muy simple, en la zona de declara-
*q=tmp; ción de variables se define un apuntador a objetos de cierto tipo (p.e. char
} *p, define un apuntador a caracteres), luego se reserva la memoria requerida
return; mediante malloc(N), donde N indica el número de localidades (definida en
} bytes) deseadas. Para liberar la memoria luego de haber sido utilizada se
utiliza la función free(p).
La diferencia entre la función Ordena y la función Ordena1 es que en la En el caso que la memoria no se pueda asignar malloc regresa típicamente
primer al regresar de la función, los valores que se enviaron en las variables cero. La función sizeof regresa el tamaño en bytes de un tipo de variable.
p y q, no son modificadas puesto que se crearon copias de éstas variables, y
los cambios realizados dentro de la función no se ve reflejada en quien la Ejemplo. El siguiente código reserva 75 localidades de memoria de tipo
llamó. Por otra parte, la segunda función al tener como paso de parámetros entero, observe el uso de la función sizeof, luego se almacenan los primeros
las direcciones de las variables que se envían, en el momento que se regresa 75 números naturales en ella y se enlistan finalmente.
de la función, el cambio se refleja, puesto que se esta trabajando sobre el
mismo espacio en la memoria. main(){
int *p, t;
La forma en que pasa sus valores la función Ordena se le conoce como p = malloc(75*sizeof(int));
paso de parámetros por valor; puesto que se envía a la función los valores de if (p==0){
las variables y a su vez ésta recibe los valores en “nuevas” variables, y a printf(“Memoria insuficiente \n”);exit(0);
Ordena1se le conoce como paso de parámetros por referencia; debido a que }
los que se envía son las direcciones de las variables y se trabaja sobre el for(t=0;t<75;t++) *(p+t) = t+1;
mismo espacio, aunque las variables se “llamen” de manera distinta. for(t=0;t<75;t++) printf(“%d “, *(p+t));
free(p);
}
- 64 -
6.1. ARCHIVOS
6
Un archivo o fichero es una colección de información que almacenamos en
un soporte magnético para poder manipularla en cualquier momento. Esta
información se puede almacenar y leer de las siguientes maneras:
Función Descripción
fputc, fgetc Los datos pueden ser escritos y leídos carácter a carácter
ARCHIVOS putw, getw Los datos pueden ser escritos y leídos palabra a palabra
fputs, fgets Los datos pueden ser escritos y leídos como cadenas de
caracteres
fprintf, fscanf Los datos pueden ser escritos y leídos con formato
fwrite, fread Los datos pueden ser escritos y leídos como registros o
bloques, es decir como un conjunto de longitud fija, tales
como estructuras o elementos de un arreglo
Tabla 11. Formas de acceder a los datos de un archivo
- 65 -
acceso Descripción 6.1.2 Entrada carácter a carácter: fputc y fgetc
“r” Abrir un archivo para leer. Si el archivo no existe o no se encuen-
tra, se obtiene un error. fputc(car,fp);
“w” Abrir un fichero para escribir. Si el archivo no existe se crea y si int car ;
existe su contenido se destruye para ser creado de nuevo. FILE *fp ;
“a” Abrir un archivo para añadir información al final del mismo. Si el
archivo no existe se crea. Esta función escribe un carácter car, en el archivo apuntado por fp, en la
“r+” Abrir un archivo para leer y escribir. El archivo debe existir. posición indicada por el apuntador de lectura/escritura.
“w+” Abrir un archivo para leer y escribir. Si el fichero no existe se crea
y si existe su contenido se destruye para ser creado de nuevo. Ejemplo:
“a+” Abrir un archivo para leer y añadir. Si el archivo no existe se crea. #incluide <stdio.h>
Tabla 12.Tipo de acceso a un archivo. #include <string.h> /* biblioteca de cadenas */
- 66 -
fgetc(fp);
FILE *fp; Esta función escribe la lista_de_argumentos, con el formato especificado
en la cadena_de_control, en el archivo apuntado por fp.
La función fgetc devuelve el carácter leido o un EOF si se ocurre un error o
se detecta el final del archivo. Se utiliza la función feof para distinguir si se Ejemplo: suma de dos números escribiendo los resultados en un archivo de
ha detectado el final del archivo. tipo añadir.
Las funciones fprintf y fscanf sirven para hacer escritura y lectura con for- Ejemplo: Lectura de un archivo de números reales (tabla)
mato de un archivo. Las descripción del formato es el mismo que se especi-
fican para printf() y scanf(); #include <stdio.h>
main()
fprintf(fp, cadena_de_control, lista_de_arcgumentos); {
FILE *fp; / declaración de apuntador a archivo */
- 67 -
float a,b,c,d,s; Ejemplo: Ejecución de un programa desde la línea de comandos
/* se verifica si se puede abrir el archivo para lectura */
if((fp=fopen("texto.txt","r")) == NULL) $prog Juan Perez /* El programa fue salvado con el nombre "prog"
{ printf("No se puede abrir el archivo \n"); y los argumentos son "Juan" y "Perez" */
exit(0);
} La siguiente figura describe exactamente a las variables argc y a
argv.
/* Lectura del archivo */
while(!feof(fp))
{
/* lectura de un renglon del archivo de la tabla de 4 columnas*/
fscanf(fp,”%f %f %f %f”,&a,&b,&c,&d);
s = (a+b+c+d)/4.0;
printf(“ El promedio es %f\n”,s);
}
fclose(fp);
} void main(int argc,char *argv[])
{
if (argc!=3) {
6.1.4. Argumentos argc y argv de líneas de comando printf("Número de argumentos no valido \n");
exit(0);
}
Los parámetros argc y argv sirven para trasmitir argumentos al programa else {
desde la línea de comandos cuando se inicia la ejecución de un programa. printf("El nombre es %s\n",argv[1]);
printf("El apellido es %s\n",argv[2]);
argc: }
Es de tipo int, y guarda el número de argumentos que se dieron exit(0);
desde la línea de comandos, y se declara de la siguiente manera: }
int argc;
argv:
Es un arreglo de apuntadores a una cadena de caracteres, donde la
posición 0 apunta a la cadena que tiene el nombre del programa en
ejecución, y las siguientes posiciones apuntan a cada uno de los ar-
gumentos, y se declara de la siguiente manera:
char *argv[]; /* No tiene dimensión */
- 68 -