Vous êtes sur la page 1sur 74

Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C.

Medina

LENGUAJE C
Ken Thompson desarrolló un mini sistema UNIX con el lenguaje B. Dennis Ritchie revisa
el lenguaje B y crea el lenguaje C en los Laboratorios Bell de la AT&T , en 1972.
En 1978 Brian Kernighan y D. Ritchie publican el lenguaje C y lo hacen popular

ESTRUCTURA DE UN PROGRAMA EN C

#include < stdio.h > Inclusión de archivos cabeceras y definición


#include <otros...> de símbolos manejados por el preprocesador
#define K 100
#define otros....
.....
void función1(int, char), función2(double, int); Prototipos de funciones otras
declaraciones de prototipo de funciones
........
int y; Variables globales
double x,z;
........
void main(int argc, char *argv[]) Función principal siempre debe ir declarada
{ inicio de bloque
int w;
char c[10];
float a,b;
.........
/* cuerpo del programa principal */ comentario
............
} fin de bloque

void funcion1(int a, char x[])


{
int j;
..........
/*cuerpo de la función*/
.......
}
double funcion4(double x, int n)
{
int i,j;
.......
/* cuerpo de la función */
......
return(z);
}
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

Un programa básico

#include <stdio.h>

int main()
{
/* Aquí va el cuerpo del programa */
printf( "Hola mundo\n" );/* Esto imprime hola mundo en pantalla
*/
return 0;
}

Este programa lo único que hace es mostrar por pantalla el mensaje:


Hola mundo

Comentario del programa línea por línea.

#include <stdio.h>

#include se llama una directiva. Sirve para indicar al compilador que incluya otro
archivo. Cuando en compilador se encuentra con esta directiva la sustituye por el
archivo indicado. En este caso es el archivo stdio.h que es donde está definida la
función printf, que se verá más adelante.

int main()

Es la función principal del programa. Todo programa de C debe tener una función
llamada main. Es la que primero se ejecuta. El int (entero) que la precede, significa
que cuando la función main termina devolverá un valor entero. Normalmente este
valor será 0 si todo ha ido bien, o un valor distinto si se ha producido algún error. De
esta forma si el programa se ejecuta desde otro el programa 'padre' sabe como ha
finalizado, si ha habido errores o no.
Se puede usar la definición 'void main()', que no necesita devolver ningún valor. A lo
largo del curso veremos muchos ejemplos con el uso 'void main' y falta el return 0.

Son llaves que indican el comienzo de bloque de sentencias o de una función, en este
caso la función main.

/* Aquí va el cuerpo del programa */

Esto es un comentario, que no se ejecuta. Sirve para comentario del programa. Un


comentario puede ocupar más de una línea. Por ejemplo el comentario:

/* Este es un comentario
que ocupa dos líneas */
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

printf( "Hola mundo\n" );

printf es una función de salida, muestra un mensaje por la pantalla. Al final del
mensaje "Hola mundo" aparece el símbolo '\n'; este hace que después de imprimir el
mensaje se pase a la línea siguiente.
El ";" del final de cada sentencia es la forma que se usa en C para separar una
sentencia de otra. Se pueden poner varias en la misma línea siempre que estén
separadas por ; .

return 0;

Como se ha indicado antes, el programa al finalizar devuelve un valor entero.

Cierre de llave, indica el término del bloque de sentencias o término de una función,
en este caso el término de la función principal. Todos los programas finalizan cuando
se llega al final de la función main.

Conceptos Básicos
En la escritura de un programa se pueden utilizar letras mayúsculas, minúsculas, dígitos y
símbolos especiales. Las funciones propias del C, como main y printf del programa
anterior, deben ser escritas en minúscula al igual que las palabras reservadas del lenguaje.

Identificadores
Es un nombre que se da a un elemento del programa (variable, función, arreglo, etc.).
Está formado por letras y dígitos donde el primero de ellos es una letra o el símbolo
carácter _. El lenguaje C diferencia entre las letras mayúsculas y minúsculas.
No se pueden poner más que letras de la 'a' a la 'z' (la ñ no vale), números y el
símbolo '_'. No se puede poner acentos, signos de exclamación, interrogación,
operadores aritméticos, u otros.

Ejemplo : x2, Suma_total, _VariableEspecial

No son equivalentes los identificadores NombreEmpleado con nombreEmpleado.


El largo de un identificador aceptado por ANSI C es 31 caracteres

Palabra reservada
Es un identificador que tiene un significado en el lenguaje y sólo sirve para ser
utilizado para su propósito.
Las palabras reservadas en C++ son :

_asm int static char class


_cdecl _near signed _es huge
_fastcall _far _pascal virtual _huge
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

_seg short
_seg _cs cdelc near _interrupt
continue void far unsigned return
default private asm for do
firend _loadds _esport _ss _ds
float register goto sizeof double
inline typedef delete volatile exterm
operator struct protected enum case
template const float break if
union long this public else
while switch new auto interrupt

Tipos de datos

Para un programa es muy importante manejar datos. En C se almacenan los datos en


variables. El contenido de las variables se pueden “ver” o cambiar en cualquier momento.
Variable
Una variable es un identificador que representa un tipo de información en una parte o
en todo el programa. Esta debe ser declarada antes de ser utilizada por una sentencia
ejecutable.

TipoDato variable[,lista_var];

Ejemplo:
double a,b;
char respuesta ;
unsigned int x4 ;

Las variables pueden ser de distintos tipos dependiendo del tipo de dato que se quiera
ingresar. No es lo mismo almacenar un nombre que un número. Hay que recordar
también que la memoria de la computadora es limitada, así que cuando se almacena
un dato, se debe usar sólo la memoria necesaria.

Tipos de datos simples en C.

Tipo dato bits Rango Aplicaciones o usos


unsigned char 8 0 a 255 Números pequeños y conjunto de caracteres
char 8 -128 a 128 Pequeños números y caracteres ASCII
enum 16 -32768 a 32767 Valores de conjuntos numerables
unsigned int 16 0 a 65535 Números enteros y ciclos
short int 16 -32768 a 32767 Contadores, ciclos y números pequeños
int 16 -32768 a 32767 Contadores, ciclos y números pequeños
unsigned long 32 0 a 4294967295 “
long 32 -2147483648 a “
2147483647
float 32 3.4e-38 a 3.4e38 científico 7 dígitos de precisión
fouble 64 1.7e-308 a 1.7e308 científico 15 dígitos de precisión
long double 80 3.4e-4932 a Financieros 19 dígitos de precisión
1.1e4932
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

Tipo char
Las variables de tipo char sirven para almacenar caracteres. Los caracteres se
almacenan en realidad como números del 0 al 255. Los 128 primeros (0 a 127) son el
ASCII estándar. El resto es el ASCII extendido y depende del idioma y de la CPU.
Declaración de una variable de tipo char :

char letra;
o
char respuesta, ch;

En una variable char sólo se puede almacenar solo una letra, no se puede almacenar
ni frases ni palabras. Las frases se verán más adelante (cadenas). Para almacenar un
dato en una variable char se tienen dos posibilidades:
letra = 'A';
o
letra = 65; /*significa el número del la Tabla ASCII del carácter ‘A’*/

unsigned char significa sin signo modifica el rango de valores que puede contener
una variable. Sólo admite valores positivos.

unsigned char variable;

Esta variable en vez de tener un rango de -128 a 128 pasa a tener un rango de 0 a
255.
Para declarar una cadena de caracteres, se debe indicar la cantidad de caracteres que
se quiere almacenar, de la siguiente forma:

char nombre[30]; o
char linea[]=”esto es una línea de caracteres”;

Tipo int
En una variable de este tipo almacena números enteros (sin decimales). El rango de
valores que admite es -32767 a 32768. Cuando se define una variable int, lo que se
está haciendo es decirle al compilador que reserve una zona de la memoria para
almacenar datos de tipo int. Para almacenar el valor se necesita 16 bits de la memoria
del ordenador (215=32768). Para poder usar una variable primero hay que declararla
como:

int numero;

y se asigna un valor
numero=24;

Tipo float
En este tipo de variable se almacenan números decimales, no sólo enteros como en
los anteriores. El rango de posibles valores es del 3,4E-38 al 3,4E38.
Declaración de una variable de tipo float:
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

float numero;
asignación:
numero=3.141516;

Tipo double
En las variables tipo double se almacenan números reales del 1,7E-307 al 1,7E308.
Se declaran como:
double numero;

Constante
Una constante tiene un valor que no se puede cambiar durante la ejecución del
programa.
Definición de Constante Simbólica
Una constante simbólica es un nombre que el pre-procesador sustituye por una
secuencia de caracteres

#define nombre_de_la_constante valor_de_la_constante

Por ejemplo:
#define PI 3.1416
#define LARGO_M AX 100

Las constantes se suelen escribir en mayúsculas y sólo se puede definir una


constante por línea de código. No se pone ";" al final de la definición.
Las constantes proporcionan una mejor comprensión del código fuente.

Ejemplo:

#include <stdio.h>
#define PI 3.1416
int main()
{
int radio ;
float perimetro;
radio = 20;
perimetro = 2 * PI * radio;
printf( "El perímetro es: %f", perimetro );
}

De esta forma cada vez que el compilador encuentre el nombre PI lo sustituirá


por la secuencia de caracteres 3.1416.

Tipos de constantes

• Constante Entera :
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

Es un número con un valor entero. Puede ser escrita en los tres sistemas numéricos:
Decimal : Combinación de dígitos 0,1,2,.....9
Octal : Digitos 0,1,2,...y 7, el primero debe ser 0
Hexadecimal : Dígitos 0,1,2....,7, A, B, C, D, E, y F, el primero debe ser 0X

Ejemplo
#define MAYOR_DE 18
#define TRUE 1
#define MASCARA 0XA3D

• Constante Entero largo y sin signo


Sin signo: valor numérico no negativo. A las cifras se le agrega U
Largos : Toma valores mayores al máximo especificado. A las cifras se
agrega L.

Ejemplo :
#define K 07777U
#define VALOR_CLAVE 0X500000L
#define CONSTANTE 123456789UL

• Constante de Punto Flotante


Son números que contienen cifras decimales en base 10.

Ejemplo :
#define X 1.0
#define Pi 3.14156
#define COTA 4.1e-12

• Constante Carácter
Son constantes que contienen un carácter.

Ejemplo :
#define RESPUESTA_AFIRMATIVA ‘S’
#define ESPACIO_BLANCO ‘‘

• Constante Cadena (String)


Consta de un número de caracteres encerrados entre comilla.

Ejemplo :
#define TITULO “Programación de Computadoras”

• Secuencias de Escape
Son secuencias de caracteres que siempre comienzan con \ y seguido de uno
o más caracteres especiales.
\a sonido \b retroceso
\f fromfeed \n nueva línea
\r retorno de carro \t tabulador hor.
\v tab vertical \\ backslash
\’ apóstrofe \” comillas
\? interrogación \0 nulo
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

Ejemplo:
#define RETORNO ‘\n’
Asignación
*0 Simple
Con una asignación se puede dar un valor inicial a una variable.

Identificador = expresión

Donde expresión puede ser constante, variable, expresión compleja o sentencia.

Ej. : #define PI 3.14


int x = 3 ; /* declaración y definición de la variable*/
char respuesta=’S’ ;
double a ;
a= PI*x*x;
x= a-b/c*d ;

Obs :
El valor del resultado de la expresión del lado derecho se convierte al tipo de
dato del identificador del lado izquierdo.
- Punto flotante (float) se trunca al ser asignado a un entero (int)
- Doble precisión (double) se redondea a punto flotante (float).
- Entero (int) es alterado a un entero corto (short int) o a carácter (char).

*1 Múltiple

Identificador1 =Identificador2 = ..........= expresión

Ej. : int x,y ;


x=y=4;
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

OPERADORES
Un operador permite manipular datos. Los hay de varios tipos; aritméticos, de asignación,
de relación, lógicos, y de manipulación de bits.

Operadores Unarios -,+


Su sintaxis es:

<variable><operador> o, <operador><variable>.

Signo (-)
Se utiliza para cambiar de signo. Anteponiéndolo delante de una variable o
constante equivale a multiplicarla por -1.

Ejemplo:
#include <stdio.h>

int main()
{
int a, b;
a = 5;
b = -a;
printf( "a = %d, b = %d\n", a, b );
return 0;
}

Operadores Incremento y Decremento (++ / - - )


Los operadores de incremento ++ y decremento -- permiten incrementar o
decrementar respectivamente el valor de una variable en 1. Estos operadores pueden
ser en prefijo o sufijo.

Sufijo i++ ; el valor del operando i se incrementa en 1 después de utilizarlo.


Prefijo ++i ; el valor del operando i se incrementa en 1 antes de utilizarlo.

Ejemplo : Si b=5 para las siguientes expresiones


(2 * ++b) + 3 ; /* se obtiene el valor 15 */
(2 * b++) + 3 ; /* se obtiene el valor 13 */

Operadores Aritméticos
Los operadores aritméticos son:

+, -, *, /, %
Su sintaxis es:
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

binarios:

<variable1><operador><variable2>

Suma (+)
Este operador permite sumar variables o constantes numéricas.
Ejemplo:
#include <stdio.h>
void main() {
int a , b, c;
a=2;
b=3;
c = a + b;
printf ( "Resultado = %i\n", c );
}

Resta(-)
Este operador permite sumar variables o constantes numéricas.
Ejemplo:

#include <stdio.h>
#define K 10
void main() {
int a , b;
a=2;
c = a - K;
printf ( "Resultado = %i\n", c );
}

Multiplicación (*)
Este operador permite multiplicar variables o constantes numéricas.
Ejemplo:

#include <stdio.h>
#define PI 3.14
void main() {
int radio,altura;
float volumen;
radio=20;
altura = 10;
volumen= PI*radio*radio*altura;
printf ( "Resultado = %f\n", volumen );
}
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

División (/)
Este operador funciona al igual que los anteriores pero se debe tener cuidado. Si se
dividen dos números en punto flotante (tipo float) se tiene la división con sus
correspondientes decimales. Pero si se dividen dos enteros se obtiene un número
entero. Es decir 4/3 se tiene como resultado 1. El redondeo se hace por
truncamiento, simplemente se eliminan los decimales y se deja la parte entera.
Si se dividen dos enteros el resultado es un número entero, aunque se saque por
pantalla usando %f o %d no se obtiene la parte decimal.
Ejemplo:

Modulo o resto de la división entera(%)


Cuando se divide dos enteros, si se quiere saber cual es el resto (o módulo) se usa
el operador %.
Este operador tiene sentido sólo con variables o valores enteros.
Ejemplo:
#include <stdio.h>
void main() {
int a, b;
a = 18;
b = 5;
printf( "Resto de la división: %d \n", a % b );
}

Observaciones:
• Si dos operando son de punto flotante de distinta precisión el resultado se
expresa en la notación más alta.
• Si un operando es de punto flotante y el otro entero o carácter el resultado se
convierte al mayor
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

• Conversión de tipo
Se puede convertir el resultado de una expresión a un tipo de dato
diferente.

(tipoDato)expresión

Ejemplo :

#include <stdio.h>
#define PI 3.14
void main() {
int x,r;
double d;
x = 20;
d = 10.5;
r = ((int)(x+d)%4);
printf ( "Resultado = %d\n", r );
}

• Prioridad
* / % mayor
+ - menor

En una línea la prioridad de operación es de izquierda a derecha.

Ejemplo :
Si a=1.0, b=2.0, c=3.0 y d=4.0 entonces a-b/c*d es -1.66666.... Esto
se calcula de la siguiente manera : a-((b/c)*d)=1-((2/3)*4).

Se puede utilizar también los paréntesis para dar otra prioridad que la
establecida.

Operador de asignación
La mayoría de los operadores aritméticos binarios explicados anteriormente
tienen su correspondiente operador de asignación:

+= Suma
-= Resta
*= Multiplicación
/= División
%= Módulo (resto)
sintáxis

expresión1 operador = expresión2


Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

es equivalente a expresión_1 = expresión_1 operador expresión_2

Ejemplo :
i+ = 5 ; /*es equivalente a escribir i= i+5; */
j * = (i-2) ; /* es equivalente a escribir j = j*(i-2); */

Operadores relacionales
Estos operadores se utilizan para comparar y formar expresiones lógicas que pueden
tener los valores verdadero (valor no 0) o falso ( valor 0).
En C existen seis operadores relacionales básicos:

< menor
<= menor o igual
> mayor
>= mayor o igual
== igual
!= distinto

Ejemplo:
Se desea escribir la expresión
Si la edad de una persona es mayor de 18 años.

int edad;
…….
if ( edad >18) ……. /* la sentencia if se estudiará más adelante */
…….
No sólo se pueden comparar variables, también se pueden comparar constantes.
Ejemplo:
Si el usuario ingresó una respuesta afirmativa
if( respuesta==SI) …..hacer algo

Operadores Lógicos
Estos operadores son conectivos lógicos. Permiten combinar expresiones lógicas
individuales para formar otras más complejas.

&& and
|| or
! not
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

Tabla de verdad

p !p q p&&q p||q
1 0 1 1 1
1 0 0 0 1
0 1 1 0 1
0 1 0 0 0
Ejemplo :
Se desea escribir la expresión
Si la edad de una persona está comprendida entre 20 y 30 años.

int edad;
…….
if ( edad >=20 && edad<=30) …hacer algo….
…….

Operador condicional

expr1 ? expr2 : expr3

Ej. : (x>=0) ? x : -x

Prioridad de los operadores

Categoría Operador Prioridad lineal


Unario -, ++, -- derizq
Aritmético *, /, % izqder
Aritmético +, - izqder
Relacional <, <=, >, >= izqder
Comparación ==, != izqder
Lógico (and) && izqder
Lógico (or) || izqder
Lógico (not) ! izqder
Condicional ?: derizq
Asignación =, operador= derizq

Ej. :Determine el valor de las variables x e y después de la sentencia, para


x=9 e y= 5
y+ = !(x>=-10 && x<10) ? ++x : ++x/4 ;
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

Entrada y Salida de Datos - E/S


Algo muy usual de un programa es esperar que el usuario introduzca datos por el teclado.
Para ello se cuenta con varias posibilidades: Usar las funciones de la biblioteca estándar,
crear nuestras propias interrupciones de teclado (MS-DOS) o usar funciones de alguna
biblioteca diferente.
Funciones de entrada y salida de datos
El lenguaje C cuenta con una biblioteca de funciones estándar para la entrada y salida de
datos. Como se utilizo en el programa hola mundo debe incluir la directiva #include
<stdio.h>,es un archivo cabecera en el cual se encuentran funciones de entrada y salida de
datos.

Función printf()
La función printf, que sirve para mostrar información por pantalla, tanto de valores
numéricos, caracteres y cadena de caracteres.

printf(FormatoControl, listaVariables);

FormatoControl: Es una tira de caracteres entre comillas. Con modificadores que


indican la forma en que se mostrarán los argumentos posteriores. También se puede
introducir una cadena de texto ( sin necesidad de argumentos), o combinar ambas
posibilidades, así como también secuencias de escape
El modificador está compuesto por el caracter % seguido por un caracter de
conversión, que indica de que tipo de dato se trata. Estos son:
%c Un único carácter
%d Un entero con signo, en base decimal
%u Un entero sin signo, en base decimal
%o Un entero en base octal
%x Un entero en base hexadecimal
%e Un número real en coma flotante, con exponente
%f Un número real en coma flotante, sin exponente
%s Una cadena de caracteres
%p Un puntero o dirección de memoria

Formato de modificador % [signo] [longitud] [.precisión] [l/L] conversión

Signo: se indica si el valor se ajustará a la izquierda, en cuyo caso se utiliza el signo


menos, o a la derecha ( por defecto ).

Longitud: especifica la longitud máxima del valor que aparece por pantalla. Si la
longitud es menor que el número de dígitos del valor, éste aparecerá ajustado a la
izquierda.

Precisión: indica el número máximo de decimales que tendrá el valor.


Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

l/L: se utiliza l cuando se trata de una variable de tipo long y L cuando es de tipo
double.

En el caso que se utilicen argumentos se debe indicar en la cadena de control tantos


modificadores como argumentos se van a presentar.
Ejemplo.
#include <stdio.h>
void main(){ /* Modificadores 2 */
char cad[ ]="El valor de";
int a=25986;
long int b=1976524;
float c=9.57645;
printf("%s a es %9d\n", cad, a);
printf("%s b es %ld\n", cad, b);
printf("%s c es %.3f", cad, c);
}

Función scanf()

scanf(FormatoControl, listaVariables);

La función scanf() permite el ingreso de datos desde el teclado y asigna el valor a una
variable.
En la cadena de control se indican los modificadores que harán referencia al tipo de
dato de los argumentos. Al igual que en la función printf los modificadores estarán
formados por el caracter % seguido de un caracter de conversión.

Si se desea leer un valor numérico se debe anteponer el símbolo ampersand ( & )


a la variable de tipo numérico.
Ejemplo:
#include <stdio.h>
void main(){
int edad; float sueldo; char nombre[20];
printf(“Ingrese nombre .\n”);
scanf(“%s”,nombre);
printf(“Ingrese edad y sueldo\n”);
scanf(“%d,%f”, &edad,&sueldo);
printf(“Sr(a)(ta) %s : \n por tener %d años se debe
descontar %f \% de su sueldo \n“, nombre, edad, );
}
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

Función getchar()
la función getchar() retorna el carácter leído desde la entrada estandar.
La referencia de la función es:

ch=getchar();

Función putchar()
Esta escribe un solo carácter en la salida estándar.
putchar(ch);

Ejemplos:

#include <stdio.h>

int main(){
char letra;

printf( "Introduce una letra: " );


letra = getchar();
printf("\n ha introducido la letra :");
putchar(letra);
}

Función gets()
Permite leer una cadena de caracteres desde teclado. El último carácter es la secuencia de
escape ‘\n’.
La función gets() ofrece una alternativa sencilla que la función scanf(), con la diferencia
que acepta un argumento.

gets(linea);

Donde línea debe ser declarado como una cadena de caracteres; char linea[80];

Función puts()
Permite escribir en pantalla una cadena de caracteres hasta encontrar la secuencia de escape
carácter nulo

puts(linea);

Función getch()
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

Si lo que se desea es que el usuario introduzca un caracter por el teclado se pueden


usar las funciones getch() y getche(). Estas esperan a que el usuario introduzca un
carácter por el teclado. La diferencia entre getche() y getch() es que la primera
muestra por pantalla el carácter de la tecla que se ha pulsado y la segunda no (la e del
final se refiere a echo=eco).

ch=getch();

Ejemplo

#include <stdio.h>
#define K 32
void main()
{
float grados_C, grados_F ;
printf(”Ingrese grados Fahrenheit \n” );
scanf(“%f”,&grados_F) ;
grados_C = (5. / 9. )*(grados_F - K) ;
printf(“La temperatura de %4.2f grados
Fahrenheit \n equivale a %3.1f grados Celsius \n”,
grados _F, grados_C “);

Otras funciones en C
El lenguaje C contiene un número de funciones de biblioteca que realizan operaciones o
cálculos de uso frecuente. Estas funciones no son parte del lenguaje. Algunas retornan un
tipo de dato, otras realizan una cierta tarea o bien permiten comparar datos.
Estas funciones se encuentran agrupadas en diferentes archivos dependiendo de su
propósito. Estos archivos son parte del compilador de C y no existe una normalización
respecto a todas las funciones, por lo tanto pueden existir algunas diferencias entre las
funciones entre las distintas versiones del lenguaje. Es necesario antes de usarlas, recurrir la
manual de referencia de su versión C que Ud. posee.
Algunas funciones más utilizadas son:
En math.h

• int abs(x): retorna el varlor entero positivo del entero x


• double cos(rad): retorna el coseno del ángulo en radianes
• double sin(rad): retorna el seno del ángulo en radianes
• double pow(base,exp): retorna el valor en punto flotante de la base elevado al
exponente.
• double sqrt(x): retorna la raíz cuadrada de x
• double log(x): retorna el logaritmo en base 10 de x
• double exp(x): retorna el valor de la función exponencial.
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

En conio.h
• void clrscr(void): limpia la pantalla en modo texto
• int getch(void): captura un carácter desde teclado
• void gotoxy(x,y): posiciona el cursor en la posición (x,y) de la pantalla
• int kbhit(void): chequea si una tecla fue pulsada
• void textcolor(color): selecciona el color de escritura en modo texto
• int cprintf(argumento): al igual que printf() pero escribe con el color selecionado en
modo texto.
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

Sentencias de control
Decisión
Este tipo de sentencias permiten variar el flujo del programa en base a determinadas
condiciones.

Sentencia IF
La sentencia de decisión simple if se utiliza para realizar un test lógico y a
continuación llevar acabo una acción dependiendo del resultado del test.

if ( expresión) sentencia

Obs : La sentencia será ejecutada si la expresión tiene un valor no nulo (es cierta).
Ejemplo:
#include <stdio.h>
void main() {
int num;
printf( "Introduce un número " );
scanf( "%i", &num );
if (num == 10) printf( "El número es correcto\n"
);
}

La sentencia puede ser compuesta, es decir, contiene varias sentencias.

if (expresión) {
sentencia1 ;
sentencia2 ;
.......
}

Ejemplos :
if (x >=0) printf(“ el valor es positivo \n”) ;
if (a>=’0’ && a<=’9’) printf (“La variable es un dígito \n”) ;
if ( ! x%2) printf(” Es un numero par \n” );
if (ch==‘\n’){
numlinea++;
printf( “Se contó una línea más\n”) ;
}

IF - ELSE
La sentencia de control de decisión, if-else, se utiliza para realizar un test lógico y a
continuación llevar acabo una de las acciones dependiendo del resultado del test.
if ( expresión)
sentencia_1
else
sentencia_2
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

Si la expresión tiene un valor no nulo se ejecuta la sentencia_1, de lo contrario se


ejecuta la sentencia_2.

Ejemplo:
#include <stdio.h>
void main() /* Simula una clave de acceso */{
int usuario,clave=18276;
printf("Introduce tu clave: ");
scanf("%d",&usuario);
if(usuario==clave)
printf("Acceso permitido");
else
printf("Acceso denegado");
}

Ejemplo:
int cantidadImpares,cantidadPares;
cantidadImpares=cantidadPares=0;
……..
if ( x%2 ) cantidadImpares++ ;
else cantidadPares++ ;

Ejemplo: la siguiente sentencia


if (a >b) z = a;
else z = b;
es equivalente al operador condicional
z = (a >b) ? a : b;

Decisiones anidadas

if ( expresión_1)
sentencia_1
else if ( expresión_2)
sentencia_2
else sentencia_3

Si la expresión_1 es cierta se ejecuta la sentencia_1. Si la expresión _1 es falsa, pero


la expresión_2 es cierta, se ejecuta la sentencia_2. Si ambas son falsas se ejecuta la
sentencia_3.

Ejemplo : No son equivalentes


Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

if (expresión1) sentencia1;
if(expresión2) sentencia2;
else sentencia3;
..............................................
if (expresión1)
{ sentencia1;
if(expresión2) sentencia2;
}
else sentencia3;

Obs : El esle va con el if más cercano, al menos que las {} ( inicio y fin de bloque )
indiquen lo contrario.

Ej. : Realizar un programa para determinar el mayor de tres números ingresados por
el usuario
#include <stdio.h>
main()
{
int x,y,z,Mayor ;
scanf(“%d,%d,%d”,& x,&y,&z) ;
if ( x > y)
if ( x > z) Mayor = x ;
else
Mayor = z ;
else if ( y > z) Mayor = y ;
else
Mayor = z ;
printf( “ El número mayor es %d \n “ , Mayor) ;
return 0 ;
}

Ejercicio: Expresar el programa anterior en función del operador condicional.


Ejercicio: Un buque de la ONU iba a dejar alimentos a Yugoslavia y cuando se
encontraba en la posición (x,y) recibió un misil Serbio, motivo por el cual se
comenzó a hundirse. Para acudir en su ayuda se encontraba en la zona dos buques
británicos con las siguientes características:

Características Buque A Buque B


Posición (A,B) (C,D)
Velocidad E F
Combustible disponible G H
Consumo de combustible I J
Desarrolle un programa que determine:
a) ¿Qué buque debe ir al rescate?
b) ¿Cuánto combustible consumirá ese buque?
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

SWITCH
En ocasiones se necesita elegir entre varias alternativas. Este tipo de selección se
puede realizar mediante una cadena de if...else if ....else if.... else.... pero esto es más
conveniente realizarlo mediante la sentencia switch

Selección múltiple

switch(expresión){
case constante1: sentencia_1;[break;]
case constante2: sentencia_2; [break;]
.........................
[default: sentencia_n;]
}

La constantes pueden tener un valor entero o de carácter. Cuando el resultado de la


expresión coincide con una constante se ejecuta la(s) sentencia(s) asociada(s) a
partir del case hasta encontrar un break o el default o el final del switch. El default
es optativo. La sentencia del default se ejecuta si el resultado de la expresión no
coincide con ninguna de las constantes.

Ejemplo :
......
printf(“Ingrese dos numeros \n” );
scanf(“%d, %d “,&x ,&y) ;
printf(“Pulse +, -,* o / para realizar la operación \n”) ;
ch=getch();
switch(ch){
case ‘+’: r = x+y ;break;
case ‘-’ : r = x-y ; break ;
case ‘*’: r =x*y ; break;
case ‘/’: if (y) r = x/y ;
else printf(“división por cero \n”) ;
break;
default: printf(“No conozco la operación %c \n”,ch);
};
......

Ejemplo:
............
ch=getch() ;
if((ch>=‘a’ &&ch<=‘z’)||( ch>=‘A’ &&ch<=‘Z’))
switch(ch){
case ‘I’:
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

case ‘i’: printf(“Aquí debe hacerse un llamado al código de ingreso


de datos\n”);break;
case ‘L’:
case ‘l’: printf(“Aquí debe hacerse un llamado al código de listado de
datos\n”);break;
case ‘O’:
case ‘o: printf(“Aquí debe hacerse un llamado al código de
ordenamiento de datos\n”);break;
default: printf(“Función no asignada \n”);
};
else printf(“ingrese sólo caracteres alfabéticos, no dígitos \n”);
...........

Repeticiones - Bucles

Permiten que una o más sentencias se ejecuten varias veces. El número de


ejecuciones depende de la verificación de una o varias condiciones.

WHILE

while (expresión)
sentencia

La sentencia while permite repetir una sentencia cierta cantidad de veces mientras la
expresión sea cierta ( no 0).

Ejemplo :desarrollar el código para calcular el factorial de un número


..........
printf(“ ingerse un número entero positivo\n”);
scanf(“%d”, &n);
fact=1 ;
i=0 ;
while(i<=n)
fact* = ++i ; /* cuerpo del ciclo*/
printf(“El factorial de %d es %d \n”,n,fact);
.........

Características
 Las expresiones se verifican antes de entrar al cuerpo del ciclo.
 Las variables deben estar definidas e inicializadas antes de ejecutar el ciclo
 El bucle WHILE se ejecuta mientras la condición sea verdadera (no nulo).
 Dentro del bucle debe existir una sentencia que modifique la expresión, pues
de lo contrario se crea un ciclo infinito
 Si la expresión es nula al comenzar el bucle, este no se realizará

Tipos de bucles
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

1. Controlado por contador


Es aquel que se ejecuta un número conocido de veces.
Ejemplo
printf(“indique el número de veces a realizar el buble\n”);
scanf(“%d”, &n) ;
contador=1; /*Inicialización de la variable que controla el bucle*/
while (contador <=n)
{
printf(“Se ha realizado %d veces\n”,contador);
contador++; /* modificación de la variable que controla el
ciclo*/
};
......

2. Controlado por suceso


Es aquel que termina cuando ocurre algo en el interior del cuerpo del bucle,
indicando que debe salir de él.

 Por centinela
Variable que permite ser leída y procesada cada vez que el cuerpo del bucle
se ejecuta. Esta debe ser del mismo tipo que los datos que se están leyendo o
procesando pero su valor no debe corresponder a uno de ellos.

Ejemplo
printf(“Ingrese caracteres, pulse * para terminar”);
ch=getche(); /* ch variable centinela*/
while (ch!='*')
{
putchar(ch);
ch=getch(); /* la variable es leída en el interior del ciclo*/
};
....…
Ejemplo: Aplicando el concepto de ciclo controlado por centinela, realizar
un programa lea números enteros positivos, y muestre en pantalla el promedio de los
valores pares ingresados.

 Por indicador
Una variable booleana que se utiliza para controlar el flujo lógico del bucle.
Esta variable permite registrar si se ha producido un suceso en el interior del
cuerpo del bucle.

Ejemplo
enum { FALSE,TRUE};
……
suma=0;
hayUnNegativo=FALSE; /*inicialización de variable indicador*/
while (! hayUnNegativo)
{
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

scanf(“%d”,&numero);
if (numero<0)
hayUnNegativo=TRUE; /* ocurrió suceso */
else
suma+=numero;
};
printf(“Total ingresado %d “,suma);

Analice los siguientes segmentos de código


Ejemplo :
scanf(“%d”, &n) ;
suma = 0 ;
i=1;
while (i<=n) suma+ = i++ ;
.....

Ejemplo :
int n;
.........
n=32;
while(n>0){
--n/ = 2 ;
printf(“%d”, n+1) ;
}

Realizar el ejemplo anterior con n=33

Ejemplo:
.........
n=3 ;
i=3 ;
while(n) i- = n ;
........

Cuidado con las variables de punto flotante que conforman la expresión. Las
variables de punto flotante dependen del número de dígitos de precisión.

Ejemplo:
float x ;
x=1. ;
while( x !=1.1 ) x+ = 0.1e-30 ;
.....

Ejemplo :
....
int i ;
float x ,y ;
int i=1 ;
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

while( i<10) {
y = sqrt(x) ;
if( x == y*y ) /* cambiar la expresión por x == sqrt(y)*sqrt(y) */
printf(“valor exacto \n”) ;
else printf(”No exacto \n” );
x/ = i ;
}
......

DO - WHILE
La sentencia do-while permite repetir una sentencia una o más veces mientras la
expresión sea cierta ( no 0).
do
sentencia
while (expresión);

Ejemplo.
…………..
int n, sonIguales;
scanf(“%d”,&n);
contador=0;
do{
contador++;
printf(“valor del contador %d\n”, contador);
sonIguales = (contador == n)? 1 : 0;
}while (!sonIguales);
........
Ejercicio: ¿qué pasa si la línea contador++ se encuentra al final del cuerpo del
ciclo?

Características
 Se garantiza que el cuerpo del bucle se ejecuta al menos una vez.
 El término del bucle se produce cuando la expresión o condición de salida es
falsa.
 do-while es un bucle con condición de salida. Esto significa que la sentencia
se realiza al menos una vez.

Analice los siguientes segmentos de código


Ejemplo :
.....
scanf(“%d”,&n) ;
i=1;
do{
if(n%i) printf(“No es divisor i:%d”, i) ;
i++;
}while(i<=n) ;
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

....

Obs : Las variables que componen la expresión pueden ser inicializada dentro del
bloque.

Ejemplo :
..........
scanf(“%d %d”,&x,&y) ;
z=0 ;
u=x ;
do{
z+=y ; u-- ;
}while (u)
.......
Estudie el ejemplo anterior si x=0.

Ejemplo:
N=10;
do while(++N<10);

Ejemplo : Código para control de menú.


#define FALSE 0
.....
Salir = FALSE ;
do{
printf(“ingrese opción \n“ );
ch=getch();
if((ch>=‘a’ &&ch<=‘z’)||( ch>=‘A’ &&ch<=‘Z’))
switch(ch){
case ‘I’:
case ‘i’: printf(“Aquí va el código de ingreso”\n);break;
case ‘L’:
case ‘l’: printf(“Aquí va el código de listado\n”);break;
case ‘O’:
case ‘o: printf(“Aquí va el código de ordenar\n”);break;
case ‘S’ :
case ‘s’ : Salir = TRUE ;
default: printf(“Opción no asignada \n”);
};
else printf(“Ingrese caracteres I, i, L, l, O, o, S y s, no otros \n”);
}while ( !Salir) ;

Traza
Es el procedimiento de repetir ordenadamente en el tiempo los valores que van
tomando la variables para una determinada entrada.
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

Ej. :
#include <stdio.h>
void main()
{
int w,x,y,z ;
/* ingresar valores para x=2 e y=3 */
scanf(“%d %d “,&x, &y) ; //1
z=0 ; //2
while (x != 0) { //3
w=0 ; //4
while(w != y){ //5
z++ ; w++ ; //6
}
x--- ; //7
}
printf(“valor de z :%d”,z) ; //8
}

Traza w X y Z Observaciones.
1 2 3 Se ingresan por teclado los valores
2 0
3 2!=0 es verdadero
4 0
5 0 !=3 es verdadero
6 1 1 1 !=3 es verdadero
6 2 2 2 !=3 es verdadero
6 3 3 3 !=3 es falso se sale del ciclo (5)
7 1
3 1 !=0 es verdadero
4 0
5 0 !=3 es verdadero
6 1 4 1 !=3 es verdadero
6 2 5 2 !=3 es verdadero
6 3 6 3 !=3 es falso se sale del ciclo (5)
7 0
3 0 !=0 es falso se sale del ciclo (3)
8 Se escribe en salida estándar 6

FOR

for (inicialización; test; actualización)


sentencia

La sentencia for reúne tres secciones separadas por “;” para controlar un bucle. La
inicialización se ejecuta una sola vez antes de entrar al ciclo y es utilizada
generalmente para dar un valor inicial a la variable de control del ciclo. Si el test es
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

cierto (no 0) se ejecuta la sentencia. A continuación se ejecuta la actualización y se


comprueba de nuevo el test antes de ejecutar la sentencia nuevamente.

El ciclo se repite mientras el test sea cierto. El ciclo for es un bucle con condición
de entrada. Es posible que no se ejecute ninguna vez la sentencia.
Ejemplos de ciclo for:
Ej. : pot = 1 ;
for(i=1; i <= exponente; i++) /*Forma progresiva */
pot*=base;

Ej. : pot = 1 ;
for(i=expomente; i >= 1; i--) /*Forma regresiva */
pot*=base;

Ej. : suma=0 ;
for( i=0 ; i <= n ;i+=2)
suma+=i ;

Ej. : for( ch=’a’ ; ch <=’z’ ; ch++) printf(“%c\n”, ch) ;

Ej. : mes=1 ;
for( deuda= 100000 ; mes<=12 ; deuda*=i)
{
mes++ ;
printf(“%f \n“,deuda );
}

La sección de “inicialización” puede inicializar más de una variable. Si es así se


debe separar por coma cada variable inicializada.
Ej. :.........
for(i=1,pot=1; i<=exponente; i++)
pot*=base;
Ejemplo :
.........
for(i=1, j=8 ; i<j ; i++, j--)
printf(“%d\n”, i*j );

Ejemplo. :
#include <stdio.h>
#define LIMITE 15
void main()
{
int contador ;
float suma, p ;
for( suma=0. , p=1. ; contador=1 ; contador <=LIMITE ; contador++,
p*=2)
{
suma+=1/p ;
printf(“Para %d el total es %f \n“, contador, suma) ;
}
}
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

Se puede dejar una sección vacía, pero debe separarse por punto y coma con
respecto de las demás secciones. El test vacío se considera cierto por lo tanto
for(;;) es una repetición infinita.

BREAK y CONTINUE
La sentencia break fuerza la salida inmediata de un bucle for, do-while o while y
de la sentencia switch.
Ej. :
for( ; ; )
{
......
printf(“Pulse S para salir”);
ch= getch() ;
if(ch == ’S’) break ;
......
}

La sentencia continue produce un salto a la siguiente iteración del ciclo for, do-
while+ o while.
Ej:.......
while((ch=gethc())!=EOF) {
if(ch==‘\n’) continue; // salta a la siguiente iteración
putchar(ch);
}
Ejemplo.
#include <stdio.h>
void main()
{
int nc,np,nl;
char ch;
enum{No,Si};
int palabra=No;
nc=np=nl=0;
while((ch=getch())!=’*’ ){
if(ch==EOF) break;
nc++;
if (ch=='\n')nl++;
if(ch!=' '&& ch!='\n'&& ch!='\t'&& palabra==No){
palabra =Si;
np++;
}
if((ch==' '|| ch=='\n'||ch=='\t')&& palabra==Si)
palabra=No;
printf(“%c”,ch);
}
printf("Líneas %d y Palabras %d\n",nl, np);
}
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

Ejercicios
1.- Sea N un número entero positivo, considere sus divisores sin incluir N. El número se
dice:
• abundante si la suma de sus divisores es mayor que el número
• Deficiente si la suma de sus divisores es menor que el número.
Perfecto si la suma es igual al número
Diseñar un programa que permita clasificar los números comprendidos entre a y b ,
imprimiendo la cantidad de cada tipo.

2.- Existe un algoritmo para generar números pseudo aleatorios, que consiste en:
• Se entrega una semilla que es un número de 4 cifras y además es par.
• Se eleva este número al cuadrado y del resultado se sacan la cuatro cifras
correspondientes a las centenas, unidad de mil, decenas de mil y centenas de mil.
El número obtenido se escribe y se repite el proceso, utilizando este número como semilla.
Construya un programa que permita generar 100 números aleatorios teniendo en cuenta lo
siguiente:
a) Debe verificar que la semilla inicial sea par y de cuatro cifras.
b) Debe comprobar el número aleatorio recién obtenido con el que se obtuvo
anteriormente, si son iguales se detiene el proceso y enviar un mensaje que no se puede
continuar.
3.- Un computador sufrió un grave desperfecto que dejó inutilizable las operaciones
aritméticas de multiplicación y división enteras. Se estima que la reparación tomará más de
un mes por la ineficiencia del técnico. A fin de que el computador pueda seguir
funcionando se pide a los estudiantes de programación que diseñen un programa que
permita implementar tales operaciones, utilizando solo adiciones y sustracciones, las cuales
funcionan correctamente, de tal modo que al ingresar dos números N y M enteros positivos
el programa escriba:
a) el producto P=N*M por suma
b) el cuociente C=M div N por restas

obs: El programa deberá detectar y enviar un mensaje si existe división por cero

4.- La famosa agencia espacial PAZA, está planificando su próxima misión que consiste
en los siguiente: en la tierra existe una estación de control que por medio de un computador
tele opera (maneja a distancia) un robot que se instaló en el planeta Miércoles. Cada orden
de tamaño M que se transmite desde la tierra viaja vía satélite. Se sabe que existen N
satélites posibles por donde transmitir, cada uno con velocidad de transmisión Vk y que el
tiempo que se tarda en transmitir una orden a través de un satélite es:
TiempoK = M/Vk
Para que la comunicación sea eficiente, el sistema debe elegir el satélite que tarde el
mínimo tiempo en la transmisión.
Además, se sabe que una vez que la orden i-ésima llegue al robot, el tiempo que le toma en
procesarla viene dada por:
(i −1)!
T (i ) =
2i
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

Dado las condiciones anteriores, realice un programa que calcule y escriba en pantalla el
tiempo total transcurrido desde que se envía la primera orden hasta cuando bel robot ha
procesado la última. Suponga que se envían R órdenes y que el tiempo total está dado por:
Tiempo total=(Tiempo de transmisión de R órdenes de tamañoM) + (Tiempo de procesamiento de R órdenes de tamaño M)
Obs:
• Los valores de cada una de las velocidades de los posibles satélites a emplear debe
leerse desde teclado.
• Las R órdenes que se transmiten tienen el mismo tamaño.
• Los valores de M,N y R son constantes.

5.- El sindicato de conductores de camiones de carga de TRANSMANIA esta siendo


afectado a través de sus afiliados por un gran problema de cálculo de combustible. Gran
cantidad de conductores ha quedado sin combustible a mitad del camino, causando un gran
retraso en la entrega de su carga.
Luego de varios estudios, se ha logrado determinar que la cantidad de combustible que los
camiones necesitan depende directamente del peso P de la carga. Es por ello que los
camiones cuyo peso de carga sea PAR, la cantidad de combustible a tener en el estanque
está dada por
(i +1) i
cantidad = ∑i =1
K

Si el peso es impar la cantidad de combustible a tener en el estanque está dada por


K
cantidad = ∏(i − 1)!
i =1
Donde K en el número de kilómetros de viaje a transportar la carga.
Se pide realizar un programa que dad el peso de la carga y la cantidad de kilómetros de
viaje, entregue la cantidad de combustible requerido para el trayecto.

6.- Para el programa


#include <stdio.h>
#include <math.h>
void main()
{
int x, y, f, r;
printf(“Ingrese dos números \n”);
scanf(“%d,%d”, &x, &y);
r=1; f=y;
while( x!=0)
if(x%2==0){
x/=2;
f=sqrt(f);
}
printf(“su resultado es %r \n”, r);
}
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

a) Efectuar el ruteo para x=5 e y=3.


b) Explicar que hace el programa.

7.- Dado el siguiente programa


#include <stdio.h>
void main()
{
int num, inv, aux, dig;
printf(“Ingrese un número”);
scanf(“%d”,&num);
aux=num;
inv=0;
while(aux>0){
dig=aux%10;
inv=10*inv+dig;
aux/=10;
}
if(num==inv) printf(“es algo\n”);
else printf(“No es algo\n”);
}

Rutee el programa para valores de entrada 271 y 323. Explique que realiza el programa

Funciones en C
Introducción
Se han utilizado algunas funciones de librería de C para realizar ciertas operaciones
de uso común, como son las funciones de entrada y salida (scanf(),
printf(),getchar(), putchar() y otras) y funciones matemáticas como son sqrt(),
pow(), sin(), cos(), etc. C como otros lenguajes, permite que el programador pueda
crear sus propias funciones.

El uso de funciones permite dividir el programa en componentes pequeñas donde


cada una persigue una tarea o un propósito determinado. Como por ejemplo
ingresar, ordenar, listar, buscar, modificar datos. Esta técnica se llama
programación modular que facilita el diseño descendiente como método de
resolución de problemas y permite encapsular la estructura de información asociada
al subproblema.

Las ventajas del uso de funciones son:


• Poder acceder varias veces desde otras partes del programa, a un grupo
determinado de sentencias que constituyen la función. El código es escrito una
vez en el programa y se accede a él varias veces desde distintas partes del
programa.
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

• Facilidad de depurar un programa. La depuración sólo se limita a la función


o funciones que realizan una tarea específica.
• Construir librerías propias ( a medida) para uso frecuente. Si se utilizan
algunas funciones de uso frecuentes lo mejor es tenerlas grabadas. Esto ahorra
tiempo de codificación y de depuración (la funciones ya están comprobadas y
no tienen errores).

Una función es un segmento de programa (subprograma) que realiza una tarea


específica. Por ejemplo ingresar datos a una matriz, ordenar los elementos de un
arreglo, etc.

Definición de una función


La definición de una función consta de tres componentes: Identificación de la
función, declaración de sus argumentos y el cuerpo de la función.
El formato es el siguiente:

TipoDato IdentificadorFuncion( [ Lista_de_parámetros_formales ] )


{
/*declaración de variables locales */

/* Cuerpo de la función */

[ return expresión ] /* optativo */


}

El IdentificadorFunción es el nombre que se le da a la función.


Todo programa en C tiene una función principal cuyo nombre es main(), este
nombre no puede ser usado por otra función. Esta función indica donde se comienza
a ejecutar el programa y esta puede llamar a otras funciones. En este caso se habla
de función conductora, y su misión es transferir el control del programa a los
distintos módulos o funciones. Cuando estas funciones o módulos terminen su tarea,
entregan el control a la función que los llamó.
El TipoDato representa el tipo de dato que la función puede retornar. Por ejemplo,
si se quiere desarrollar una función que calcule la raíz cúbica de un número, el valor
que retornará será un valor tipo punto flotante que podría ser float o double.
Si la función retorna un valor, en el cuerpo de la función, debe estar la sentencia
return. Sentencia que devuelve el valor al lugar donde se hizo la llamada a la
función.
Si la función no retorna ningún valor entonces el tipo de dato definido para la
función es void y en el cuerpo de la función no debe contener la sentencia return.
El C toma por defecto que toda función es del tipo int. Es decir si la función retorna
un valor entero no es necesario anteponer la palabra int al nombre de la función.

La Lista_de_parámetros_formales son los argumentos de la función, los cuales


permiten que la función se comunique con el resto del programa. Con ellos puede
recibir cero o más valores y también “modificar” el contenido de cero o más
variables del lugar de donde se realizó la llamada.
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

El formato de la Lista_de_parámetros_formales es la siguiente:

TipoDato IdentificadorParametro1[,TipoDato IdentificadorParametro1,....]

Si la función no recibe valores entonces no tiene parámetros, por lo tanto se escribe


el paréntesis vacío o bien se escribe la palabra void.

Ejemplo.
/* factorial()es el identificador de la función */
long int factorial( int n) /* se recibe un valor entero y retorna un entero largo
*/
{
/* declaración de variables locales */
int i;
long int producto=1.0;

/* cuerpo de la función */
for(i=1; i<=n ;i++)
producto*=i;
/* valor que la función retorna al lugar de donde se invocó */
return producto;
}

Ejemplo.
void linea(void ) /* la función línea no recibe ni retorna valores */
{ /* sólo escribe una línea de asteriscos */
int i;
for(i=1; i<=LARGOLINEA;i++) putchar('*');
putchar('\n');
}

Ejemplo
/* retorna la cantidad de dígitos de un número entero*/
numeroDigitos(long int n)
{
int c=0;
do{
n=n/10;
c++;
}while( n>=0);
return c;
}

Llamada a función
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

Se pueden realizar varias llamadas a una función desde diferentes partes del
programa.
No se puede llamar a la función principal main() desde otra función.
La llamada puede ser parte de una expresión o una sentencia, dependiendo si la
función retorna o no un valor. Por ejemplo la función factorial() puede ser parte de
una expresión ( o fórmula matemática) en la llamada.

El formato de llamada es la siguiente:


IdentificadorFuncion([Lista_de_parámetros_actuales])

La lista_de_parámetros_actuales pueden ser constantes, variables o expresiones los


cuales permiten entregar valores en el momento de la llamada a la función. Debe
existir una correspondencia uno a uno con el tipo de dato, el número de parámetros
y en su posición con la Lista_de_parámetros_formales.

Ejemplo:
void main()
{
.......
printf(“ Ingrese un valor entero \n”);
scanf( “%d”, &x);
y=0.5*factorial(x); /* se realiza una llamada a la función factorial() */
........ /* pasando x como valor actual */
}

Ejemplo:
void main()
{
.......
printf(“ Ingrese un valor entero \n”);
scanf( “%d”, &n);
/* se realiza una llamada a la función numeroDigitos () */
printf(“ la cantidad de dígitos de %d es %d ”,n, numeroDigitos(n));
........ /* notase que la llamada se realizó desde el argumento de otra
función*/
}

¿Dónde se define y se declara una función?


Una función debe ser definida fuera de otra función y en cualquier parte del
programa antes o después del main(), pero teniendo en cuenta la siguiente regla;

Si una función A realiza una llamada a otra función B, entonces la función B debe
ser declarada o definida antes que A. En caso contrario se debe declarar, dentro
del cuerpo de la función A, indicando que se utilizará la función B, la cual se
encuentra definida después de A. Esta declaración se llama declaración forward o
declaración por adelantado.
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

Ejemplo 1. Se define la función factorial antes de ser llamada


#include <stdio.h>

long int factorial( int n) /* definida antes de ser utilizada*/


{
/* declaración de variables locales */
long int producto=1.0;
int i;

/* cuerpo de la función */
for(i=0; i<=n ;i++)
producto*=i;

return producto; /* valor que la función retorna al lugar donde se hizo la


llamada */
}
void main()
{
.......
printf(“ Ingrese un valor entero \n”);
scanf( “%d”, &x);
y=0.5*factorial(x); /* llamado a la función factorial */
........
}

Ejemplo 2.
#include<stdio.h>
long int factorial(int); /*declaración por prototipo */
void main()
{
int n;
.......
printf(“ Ingrese un valor entero \n”);
scanf( “%d”, &n);
y=0.5*factorial(n);
........
}

long int factorial( int n) /* definición de la función*/


{
/* declaración de variables locales */
long int producto=1.0;
int i;

/* cuerpo de la función */
for(i=0; i<=n ;i++)
producto*=i;
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

/* valor que la función retorna al lugar de donde se invocó */


return producto;
}

El formato de declaración por adelantado es:


Tipodato IdentificadorFuncion(tipoDato);

Ejemplo. En la función main() se declarar por adelantado la función factorial,


indicando así que se utilizará una función que se encuentra definida después.
#include<stdio.h>
void main()
{
long int factorial(int); /*declaración por adelantado */
.......
printf(“ Ingrese un valor entero \n”);
scanf( “%d”, &x);
y=0.5*factorial(x);
........
}

long int factorial( int n)


{
/* declaración de variables locales */
long int producto=1.0;
int i;

/* cuerpo de la función */
for(i=0; i<=n ;i++)
producto*=i;
/* valor que la función retorna al lugar de donde se invocó */
return producto;
}

Obs: La declaración por prototipo indica que la función será reconocida desde el
punto de su declaración hasta el resto del programa por las demás funciones. En
cambio la declaración por adelantado permite que la función sea reconocida solo
por la función que la declaró.

Tipo de almacenamiento de variables


Existen dos formas de caracterizar una variables, por su tipo de dato y por su tipo de
almacenamiento. El tipo de dato es el rango de valores que la variable puede tomar.
Por ejemplo una variable de tipo int pueden tomar valores enteros comprendidos
entre –32768 a 32767.
El tipo de almacenamiento se refiere a la permanencia en memoria que la variable
pueda tener y al ámbito que esta tiene dentro del programa ( ámbito se refiere al
bloque de programa en el cual la variable es reconocida).
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

Existen cuatro especificaciones de tipo de almacenamiento en C; auto, extern, static


y register.

• Automática (auto)
Son variables que se declaran siempre dentro de la función y estas son locales a
la función. En este caso su ámbito es sólo el cuerpo de la función. Por ejemplo
la variable i o producto de la función factorial().
Cualquier variable declarada dentro de la función es interpretado como variable
automática y no es necesario anteponerle la palabra auto.
Las variables automáticas definidas en funciones diferentes son independientes
entre sí incluso si tienen el mismo nombre. Por ejemplo la variable n en el
ejemplo 2.
Las variables automáticas se crean en el momento que se hizo la llamada y son
destruidas cuando la ejecución del programa hace abandono de la función, por
lo tanto su contenido se pierde y no puede ser usado posteriormente.

• Externas (extern)
Estas no están confinadas a una función y se reconocen como variables globales.
Son declaradas fuera de las funciones y su ámbito se extiende desde el punto de
su declaración hasta el resto del programa.
La declaración de una variable externa es idéntica que una variable normal con la
diferencia que se encuentra fuera de una función.
Se puede acceder a una variable externa desde cualquier función, siempre que la
función esté dentro de su ámbito. Si se asigna un valor a una variable externa
dentro de una función, su valor permanece al termino de la ejecución de esta, y
su valor puede ser utilizado por otras funciones.
Si en la definición de la función, que utiliza una variable externa, precede a la
declaración de esta, en la función se debe incluir la declaración de la variable
externa anteponiendo la palabra extern seguido por su tipo y su identificador.

Formato
extern TipoDato IdentificadorVarExterna;

Una variable externa pierde preferencia frente a una variable automática si


tienen el mismo nombre dentro de la función.

Ej. Realizar la traza del siguiente programa.


#include <stdio.h >
funcionB(in x, int y)
{
int a;
a=3; x=y+x; a=x++;
printf(“%d, %d, %d \n”, x,y,a);
return a;
}
int a=1;
void funcionA(int z)
{
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

int y;
y=t++;
a=funcionB(y,1);
printf(“%d ,%d, %d \n”,a,y,z);
}
void main()
{
int x,y z;
x=a;
y=x++;
z=funcionB(y,x);
funcionA(x);
printf(“%d,%d,%d,%d\n”,x,y,z,a);
}

• Estáticas (static)
En un programa con un archivo simple las variables estáticas se define dentro de
las funciones y tiene el mismo ámbito que las variables automáticas.
Las variables estáticas se diferencian de la variables automáticas porque estas
retienen su valor durante el tiempo de ejecución del programa.

El formato de declaración de variable estática es:


static TipoDato IdentificadorVariable;

Las variables externas mantienen su independencia frente a las variables


automáticas y estáticas.

Traspaso por referencia ( o por dirección)

• Operador &

El operador & permite obtener la dirección de memoria de una variable.

Formato
&IdentificadorVariable

Ejemplo.

#include <stdio.h>
void main()
{
int x,y;
x=45;
y=25;
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

printf(“ el nombre de la variable es x,\n su valor es %d y se encuentra en la


dirección %d \n“, x, &x);
printf(“ el nombre de la variable es y,\n su valor es %d y se encuentra en la
dirección %d \n“, y, &y);
}

• Operador *

Existe un tipo de variable que permite almacenar la dirección de memoria de


otra variable. Este tipo de variables se llaman punteros.

Formato
Tipodato *identificadorVariablePuntero;

Es posible acceder al contenido de una dirección de memoria para ello basta


anteponer * a un identificador de variable puntero.

Ejemplo.
#include <stdio.h>
void main()
{
int x; /* declaración de variable */
int *p; /* declaración de puntero */
x=45; /* definición de variable */
p=&x; /* obtención de la dirección de memoria de x*/
printf(“ la dirección de x es %d “, p);
printf(“\n y su contenido en esa dirección es %d “, *p);
*p= 25;
printf(“ \nSu contenido fue modificado y es %d “, *p);
*p= *p+3;
printf(“ \nSu contenido fue de nuevo modificado y es %d “, *p);
}

Es posible traspasar la dirección de una variables a una función, de manera que


dentro de la función se pueda alterar su contenido. De este modo una función
puede modificar los contenidos de variables que son pasadas a la función.

Para poder realizar el traspaso por referencia en necesario entregar a la función


la dirección de la variable que se quiere alterar. Para esto, se antepone el
operador de dirección & al identificador de la variable en la lista de parámetros
actuales. En la lista de parámetro formales debe ser recibida por un puntero del
mismo tipo de dato que la variable traspasada.
Esquema:
void identificadorFunción1(tipoDato1 *varPuntero1, [ otros parámetros])
{
/* cuerpo de la función */
…….
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

*varPuntero=……. // se modifica el contenido a cual hace referencia


…..
}
void identificadorFunción2( [ Lista_de_parámetros formales ])
{
/* cuerpo de la función */
tipoDato1 nombreVar;
…….
nombreVar=valor; // la variable se inicializa
…….
IdentificadorFunción1(&nombreVar, [otros parámtros]); // llamada a función
pasando la dirección de la variable
…….
}

Ejemplo. Realice la traza del siguiente programa.


#include <stdio.h>
void swap1( int x, int y)
{
int aux;
aux=x; x=y; y=aux;
}

void swap2( int *x, int *y)


{
int aux;
aux=*x; *x= *y; *y=aux;
}

void main()
{
int a,b;
printf( “ingrese dos valores enteros \n”);
scanf (“ %d %d “, &a,&b);
printf(( “ Antes de llamar a swap1() a=%d y b=%d\n”,a,b );
swap1(a,b);
printf(( “ Después de llamar a swap1() a=%d y b=%d\n”,a,b );
swap2(&a,&b);
printf(( “ Después de llamar a swap2() a=%d y b=%d\n”,a,b );
}
Ejercicios: Realizar la traza de los siguientes programas.
1.-
# include <stdio.h>
int d=3;
int p;
void algo(int *j)
{
int y,i,k;
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

y=10;
* j=(*j+y)%3; p=0; k=*j;
for(i=0; i<k; i++){
*j=d-p;
printf(“%d, %d”, y,*j);
}
}
void que_hace(int *x, int *y, int z)
{
int t;
t=*x+2; *x=t+1; z=*x+3; * y= t;
printf(“%d, %d, %d,%d “, t,*y, *x,z);
}
void main()
{
int x,y,z;
x=2; y=1; z=0;
printf(“%d, %d, %d”,x,y,z);
que_hace(&x,&y,z);
printf(“%d, %d, %d”,x,y,z);
algo(z);
printf(“%d”,z);
}
2.-
#include <stdio.h>
int b,c;
void r( int x, int y, int *z)
{
*z= x+y+*z; x=y;
printf(“%d, %d, %d”,x,y,*z);
}

void t(int *b, int h)


{
extern int a;
int c;
a=6;
c=*b+h; *b=h-1; h++;
printf(“%d,%d,%d,%d”,a,*b,c,h);
}
int a;
void main()
{
int c;
a=5; b=8; c=0;
r(a,b,&c);
printf(“%d, %d, %d”, a,b,c);
t(&a,b);
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

printf(“%d,%d,%d”,a,b,c)
}
Ejercicio: Escribir una función digito(n,k) que entregue el valor del dígito que está k
posiciones desde la derecha del número n.
Ejercicio: Escriba una función simetrico(n) que entregue verdadero si las cifras del número
tienen simetría respecto de su centro, en caso contrario retorne falso. Por ejemplo:
simetrico(12345)  falso simetrico(123321)  verdadero simetrico(2) verdadero
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

Arreglos

Arreglo Unidimensional o Vector


A veces es conveniente colocar varios datos del mismo tipo compartiendo el mismo
nombre. Por ejemplo las notas de los alumnos de un curso. Donde la nota0
corresponde a la del primer alumno, nota1 corresponde a la del segundo alumno y
así sucesivamente. En este caso todas las notas de los alumnos se podrían almacenar
bajo un mismo nombre de variable llamado Nota, identificando cada una de ellas
mediante un subíndice.
Este tipo de variable donde se pueden almacenar varios datos de un mismo tipo y en
el cual se puede identificar cada uno de los datos mediante un subíndice se llama
arreglo unidimensional.

Elemento del arreglo

Nota

Nota[0] Nota[1] Nota[n-1]

Obs : El número de subíndices determina la dimensión del arreglo.

Un arreglo es un tipo estructurado de datos que permite agrupar elementos


primitivos del mismo tipo y asociar un número de orden a cada elemento.

Declaración de un arreglo unidimensional


TipoDato IdentificadorArrreglo[tamaño]

tamaño : constante de tipo entero positivo.

Ej. :
int x[10] ; /* Contiene 10 elementos c/u de tipo entero */
float y[300] ; /* Contiene 300 elementos c/u de tipo float */
char ch[40]; /* Contiene 40 elementos c/u de tipo char */

Cabe destacar que el arreglo es una estructura estática, es decir, el número de


elementos queda determinada en el momento que su compilación. No es posible
volver a modificar el tamaño del arreglo cuando se esté ejecutando el programa.

A veces es conveniente definir el tamaño de un arreglo mediante una constante


simbólica.

Ej. :
#define MAX 400
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

.........
int X[MAX] ;

Para asignar valores a los elementos de un arreglo se debe calcular el valor del
índice y luego accesar a la estructura y asignar el valor del elemento
correspondiente.

NombreArreglo[índice] = valor ;
Ej. :
X[3]=6 ; // En la cuarta posición del arreglo se asigna el valor 6

Para ingresar valores a un arreglo se puede utilizar un ciclo for, do-while o while
donde la variable índice comience desde 0.
Ej. :
#define MAX 20
.......
int x[MAX] , i ;
for(i=0 ; i<MAX ; i++)
scanf(“%d”,x[i ]); // se lee el valor de la entrada estándar y se asigna en el
arreglo x
.........

Inicialización del arreglo x con ceros.


..........
i=0 ;
while( i<MAX) {
x[i ]=0 ;
i++ ;
}
..........
A un arreglo se le pueden definir valores iniciales. Estos valores deben estar en el
orden en que serán asignados a los elementos del arreglo.

TipoDato IdentificadorArreglo[tamaño] ={valor_1, valor_2,......., valor_n};

donde valor_1 será asignado al primer elemento del arreglo, valor_2 será asignado
al segundo elemento del arreglo y así sucesivamente.

Ej. :
int digitos[10] ={0,1,2,3,4,5,6,7,8,9} ;
float x[8] ={-0.34, 1.54, 2., 3.15} ; /* Al resto de los elementos se le asigna 0*/
char digito[10] = {‘0’,’1’,’2’,’3’,’4’,’5’,’6’,’7’,’8’,’9’};

En el lenguaje C no se permiten operaciones que impliquen arreglos completos. Por


ejemplo
Si float A[8],B[8],C[8] ;
........
B=A ; // es ilegal. Otros lenguajes lo permiten.
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

C=A+B ; // ilegal

En este caso la asignación debe realizarse elemento a elemento.

for(i=0 ; i<8 ; i++) B[i ]=A[i ]; // copia de arreglo


o
for(i=0 ;i<8 ;i++) C[i]=A[i]+B[i] ; // operaciones con los elementos

Determinación del promedio de los elementos leídos en un arreglo


......
suma=0 ;
for(i=0 ; i< MAX ;i++) suma+=A[i] ;
promedio = suma/MAX ;

Determinar el máximo valor en un arreglo


Algoritmo:
Almacenar en una variable temporal el primer elemento del arreglo. Luego
comparar cada uno de los elementos del arreglo con la variable temporal, si el
elemento es mayor que la variable temporal cambiar su contenido por el del
elemento
.........
Maximo=A[0] ;
i=1 ;
while(i<MAX) {
if(A[i] >Maximo)Maximo=A[i] ;
i++ ;
}
otra forma
……..
Maximo=A[0];
for(i=1; i<MAX; i++)
if(A[i]>Maximo) Maximo=A[i];
…..
Ejercicio: Determinar el mínimo valor de un arreglo

Determinar la posición del primer mayor valor en un arreglo


........
Mayor=A[0] ;
posicion =0 ;
for(i=0 ; i<MAX ; i++)
if( A[i]>Mayor) {
Mayor=A[i] ;
posicion =i ;
}
Ejercicio: Determinar la posición del último mayor valor de un arreglo.

Ejercicio: Se tienen dos arreglos llamados palabraClave y Combinación de tamaños


N y M. Estos contiene números enteros y se encuentran llenos. En el arreglo palabraClave
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

se encuentran almacenados los números ASCII de caracteres. En el arreglo Combinación se


encuentran las posiciones de los números ASCII que están en el arreglo

Ordenamiento de los elementos de un arreglo


El ordenar los elementos en un arreglo es una tarea que se realiza con frecuencia. A
pesar que existen numerosos algoritmos de ordenamiento veremos uno de los más
simples llamado Ordenamiento Burbuja o BubleSort.
Dado un arreglo A de enteros es posible ordenarlo en forma ascendente comparando
dos elementos adyacentes (A[j] y A[j+1]), si no se encuentran en el orden
establecido sus elementos se intercambian. Los elementos más livianos (menores)
ascienden y los pesados bajan. En la primera revisión del arreglo se realizan N-1
comparaciones, quedando el elemento mayor en la última posición. En la segunda
revisión se realizan N-2 comparaciones. Y así sucesivamente hasta comparar las dos
primeras posiciones.

for(i=MAX-1 ; i>0 ; i--)


for( j=0 ; j<i ; j++)
if( A[j]>A[j+1]) {
auxiliar = A[j] ;
A[j]=A[j+1] ;
A[j+1]= auxiliar ;
}

Búsqueda de un elemento en un arreglo


Otra de las tareas frecuente que se realizan en arreglos es buscar un elemento ya sea
para modificarlo, eliminarlo o insertar otro en la posición encontrada.

Búsqueda secuencial o lineal

Consiste en revisar cada elemento del arreglo con un valor a buscar partiendo desde
un extremo. Si el elemento i del arreglo coincide con el valor a buscar se detiene la
búsqueda en caso contrario se continua hasta llegar al final del arreglo. Es necesario
utilizar una variable que indique cuando detener la búsqueda.

enum{ FALSE,TRUE} ;
int i , SeEncontro ;
......
i=0 ;
SeEncontro=FALSE ;
while( (! SeEncontro) && (i<MAX) )
if( A[i]==DatoBuscar) SeEncontro=TRUE ;
else i++ ;
if( SeEncontro) printf(“El dato se encuentra en la posición %d“, i) ;
else printf(“El dato no se encontró \n”) ;
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

Otra forma de escribir lo anterior es :

i=0 ;
while ( (DatoBuscar != A[i]) && (i<MAX) )i++ ;
if (i<MAX) printf(”El dato se encuentra en la posición %d“,i) ;
else printf(“El dato no se encuentra \n” );

Una pequeña variante sería


.....
i=0 ;
while( DatoBuscar !=A[i] && i<MAX-1) i++ ;
SeEncontro= DatoBuscar ==A[i] ? TRUE : FALSE ;
....
Nótese que en el ciclo no se realiza la comparación con el último elemento. La
comparación del último elemento se realiza si no se encontró en los MAX-1
elementos anteriores.

Búsqueda binaria

En el caso anterior los elementos se encontraba en el orden en que fueron


ingresados. Por lo tanto en el peor de los casos deben realizarse N comparaciones.
A veces es necesario realizar búsquedas en arreglos donde sus elementos no
cambian en el tiempo. Por ejemplo, en un diccionario. En estos casos conviene que
sus elementos se encuentren previamente ordenados. Si comparamos el tiempo que
tardaríamos en realizar una búsqueda en un diccionario donde sus palabras estén
desordenas con uno en el cual están ordenadas, nos damos cuenta que es mucho
menor el tiempo de búsqueda en aquel que sus palabras están ordenadas. Se puede
comprobar que el número de comparaciones se reduce a log2n.
Supongamos que tenemos una lista de nombres ordenada ascendente, y nos piden
buscar un nombre. Lo primero que realizamos es ubicar el nombre por la mitad de
la lista. Si lo ubicamos detenemos nuestra búsqueda. Si no lo tratamos de ubicar en
la mitad superior o en la mitad inferior de la lista dependiendo si nombre en orden
alfabético es menor o mayor que del centro de la lista respectivamente. Este proceso
se repite hasta que lo ubiquemos o bien hasta que no hay submitades para seguir
buscando.
Suponiendo que el arreglo A está ordenado en forma ascendente.
........
primero=0 ;
ultimo=MAX-1 ;
SeEncontro=FALSE ;
while( (!SeEncontro) && (primero<=ultimo)){
medio=(primero+ultimo)/2 ;
if( A[medio]==DatoBuscar) SeEncontro=TRUE ;
else
if( A[medio]>DatoBuscar) ultimo=medio-1 ;
else primero=medio+1 ;
}
if (SeEncontro) printf(“El dato se encuentra en la posición %d“, medio) ;
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

else printf(“El dato no se encuentra \n” );

Arreglos Bidimensionales o Matrices


Cada elemento del arreglo unidimensional es un tipo de arreglo unidimensional.
Se define como :

TipoDato IdentificadorMatriz[Dimensión_1][Dimensión_2] ;

La constante Dimensión_1 indica el número de filas y Dimensión_2 el número de


columnas del arreglo bidimensional o matriz.

Ej.
float A[50][50] ; // arreglo de 50 fila por 50 columnas
int B[10][5] ; // arreglo de 10 filas por 5 columnas

Para tener acceso a un elemento de la matriz se debe indicar la fila y columna


(recuerde que los subíndices comienzan desde 0). Por ejemplo, para almacenar el
valor 8 en la sexta fila y tercera columna del arreglo B definido previamente, sería
B[5][2]=8. Escribir B[2][5]=8 sería incorrecto.

Para recorrer una matriz se puede realizar por filas o por columnas. Si se realiza por
filas se debe tener una variable i que indique la fila en que se encuentra y una
variable j para recorrer todos los elementos de la fila. Por lo tanto para cada fila i se
recorre cada elemento j de la fila, donde 0≤ i<Número_de_Filas y
0≤ j<Número_de_Columnas, es decir:

for(i=0,i<MAX_FILAS ;i++)
for(j=0 ; j<MAX_COLUMNAS ; j++)
printf(“%f”,A[i][j] );

Para el recorrido de la matriz por columnas. En cada columna j se recorre todos los
elemento i de la columna, es decir :

for(j=0 ; j<MAX_COLUMNAS ; j++)


for(i=0,i<MAX_FILAS ;i++)
printf(“%f”,A[i][j] );

A una matriz se le pueden definir valores iniciales. Estos valores deben estar en el
orden en que serán asignados a los elementos de la matriz.

Ej. :
int A[3][4]={1,2,3,4,5,6,7,8,9,10,11,12} ; // matriz de tres filas por 4 columnas
es equivalente de haber asignado
A[0][0]=1 ; A[0][1]=2 ; A[0][2]=3 ; A[0][3]=4 ;
A[1][0]=5 ; A[1][1]=6 ; A[1][2]=7 ; A[1][3]=8 ;
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

A[2][0]=9 ; A[2][1]=10 ; A[2][2]=11 ; A[2][3]=12 ;

Se pueden utilizar “{}” para separar las filas de la matriz.

Ej. :
int A[3][4]={ {1, 2, 3, 4},
{5, 6, 7, 8},
{9,10,11,12} } ;

Si existen menos elementos en un par de llaves, al resto de los elementos de la fila


se asignan 0.

Ej. :
int A[3][4]={ {1, 2, 3},
{4, 5, 6},
{7, 8, 9} } ;
1 2 3 0 es equivalente a
4 5 6 0
7 8 9 0
Nótese que no es lo mismo
int A[3][4]={1,2,3,4,5,6,7,8,9 } ;
ya que genera la matriz
1 2 3 4
5 6 7 8
9 0 0 0
Si existen más valores que la dimensión de la matriz se produce un error.

Los arreglos bidimensionales o matrices se procesan del mismo modo que los
arreglos unidimensionales o vectores sobre la base de elemento a elemento.

Ej. : Suma de dos matrices


int A[5][5],B[5][5],C[5][5] ;
......
for(i=0,i<MAX_FILAS ;i++)
for(j=0 ; j<MAX_COLUMNAS ; j++)
C[i][j]=A[i][j]+B[i][j] ;

Arreglos Muldidimencionales

TipoDato IdentificadorArreglo[Dimensión_1][Dimensión_2][Dimensión _3].... ;

Ej. :
int A[10][20][30]={ { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} },
{ {13, 14, 15}, {16, 17, 18}, {19, 20, 21} } }
Los valores son asignados al arreglo de la siguiente forma :
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

A[0][0][0]=1 ; A[0][1][0]=5 ; A[0][2][0]=9 ;


A[0][0][1]=2 ; A[0][1][1]=6 ; A[0][1][1]=10 ;
A[0][0][2]=3 ; A[0][1][2]=7 ; A[0][1][2]=11 ;
A[0][0][3]=4 ; A[0][1][3]=8 ; A[0][1][3]=12 ;
A[1][0][0]=13 ; A[1][1][0]=16 ; A[1][2][0]=19 ;
A[1][0][1]=14 ; A[1][1][1]=17 ; A[1][2][1]=20 ;
A[1][0][2]=15 ; A[1][1][2]=18 ; A[1][2][2]=21 ;

Todos los demás elementos son 0.

Traspaso de arreglos a funciones


Los arreglos en C son traspasados por referencia por lo tanto su contenido es
alterado por las funciones. Para que ello no ocurra es necesario pasarle una copia
del arreglo a la función.
En la llamada a la función, en la lista de parámetros actuales, basta escribir le
nombre del arreglo. No debe ir precedido de &, ya que el nombre de un arreglo es
un puntero, a no ser que se desea pasarle la dirección de un elemento del arreglo
( &A[i]).
En los parámetro formales se debe declarar como puntero o de la forma TipoDato
IdentificadorArreglo[], que es otra forma de escribir un puntero a arreglo.

Ej.
#include <stdio.h>
void promedio( int X[], int c)
{
int i, suma=0;

for(i=0; i< c ;i++)


suma+=X[i];
printf(“El promedio es %f \n”, suma/i);
}

void main()
{
int A[10]={ 3,5,6,7,8,4,5,6,3,4};
int n;
printf(“Ingrese la cantidad de elemento que quiere calcular el promedio);
scanf(“%d”,&n);
promedio(A,n);
}

Ej.
#include <stdio.h>
#include <conio.h>
#define N 100

void listar(int A[],int l)


Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

{
int i;
printf("\n");
for(i=0;i<l ;i++)
printf("%d ",A[i]);
}

void intercambia(int *x, int *y)


{
int aux;
aux=*x; *x=*y; *y=aux;
}

void ordenar(int X[], int l)


{
int i,j;
for(i=l-1;i>0;i--)
for(j=0 ; j<i; j++)
if(X[j]>X[j+1]) intercambia(&X[j],&X[j+1]);
listar(X,l);
}

void ingreso(int A[], int *largo)


{
char resp='s';
int i=*largo;
while (i<N && resp!='n'){
printf("\n Ingrese valor para posición %d\n",i+1);
scanf("%d\n",&A[i]);
i++;
printf("Ingresa otro (s/n)\n");
resp=getchar();
}
*largo=i;
}

float calculoPromedio(int X[],int n)


{
int i;
float prom,suma;
suma=0.0;
for(i=0; i< n; i++)
suma+=X[i];
prom=suma/i;
return prom;
}

void menu()
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

{
printf("\n\n Opciones\n\n");
printf("Imgreso\n");
printf("Promedio\n");
printf("Ordenar\n");
printf("Listar\n");
printf("Salir\n\n");
}
enum boolean {falso, verdadero};

void main()
{
char ch;
int i,n,A[N],COPIA[N];
int cantidad=0;
boolean salir=falso;
do{
menu();
printf("ingrese una alternativa");
switch(ch=getche()){
case 'I':case 'i':ingreso(A,&cantidad);break;
case 'P':case 'p': printf("Ingrese número de elementos \n");
scanf("%d",&n);
if(n>cantidad) printf("No hay tantos elementos \n");
else
printf("\nEl promedio de los %d primeros es %f \n ", n, calculoPromedio(A,n));
break;
case 'O':case 'o': for(i=0;i<cantidad;i++)
COPIA[i]=A[i];
ordenar(COPIA,cantidad);
break;
case 'L':case 'l': listar(A,cantidad);break;
case 'S':case 's': salir=verdadero;break;
default : printf("pulse sólo I,O,P,L o S\n");
}
}while( !salir);
}

Para el caso de una matriz se puede pasar una fila o columna o la matriz completa a
una función.
En los parámetros formales de la función se debe declarar la matriz como:

TipoDato IdentificadorMatriz[][Tamaño]

#include <stdio.h>
#define N 3

void main()
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

{
void mayorFila(int []),listar(int [][N]);
static int A[N][N]={ {2,4,5},{7,2,4},{3,5,6}};
int i;

for(i=0; i<N; i++){


printf("Para fila %d \n",i+1);
mayorFila(A[i]);
}
listar(A);

void mayorFila( int X[] )


{
int i,mayor,posicion;
mayor=X[0];
posicion=0;
for(i=1;i<N;i++)
if(X[i]>mayor){
mayor=X[i];
posicion=i;
}
printf("el mayor es %d en posición %d \n", mayor, posicion+1);
}

void listar( int X[][N] )


{
int i,j;
for(i=0;i<N;i++){
for(j=0;j<N;j++)
printf("%d ",X[i][j]);
printf("\n");
}
}

Cadena de Caracteres
Es un arreglo unidimensional donde cada componente es de tipo carácter (char).
Toda cadena en C debe terminar con el carácter NULL (‘\0’) que indicará el
término de la cadena. Por lo tanto es necesario reservar el espacio de memoria
suficiente para almacenar el carácter NULL.

La mayoría de los compiladores C tienen funciones de bibliotecas que permiten


comparar cadenas de caracteres, copiar, concatenar, insertar, etc. Estas funciones se
encuentran en la biblioteca string.h . Algunas de las funciones más comunes son:
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

strcmp(s1,s2): Permite comparar dos cadenas de caracteres y retorna un valor entero


positivo si la cadena s2 precede alfabéticamente a la cadena s1. Si el valor es cero
significa que las cadenas son idénticas. En cambio si el valor en negativo significa
que la cadena s1 precede alfabéticamente a la cadena s2. Ver el ejemplo para su
utilización.
strcpy(s1,s2) : Permite copiar la cadena s2 en s1. Ver el ejemplo para su utilización.

#include <stdio.h>
#include <stdlib.h>
/* ordena alfabéticamente una lista de cadenas este programa usa un array
bidimensional de caracteres */
void main()
{
int i, n = 0;
char x[10][12] , temp[12];
printf(“Ingresar cada cadena en una línea separada\n\n”);
printf(“Escribir FIN para terminar el ingreso\n\n”);

/* leer la lista de cadenas*/


do {
printf(“cadena %d:”, n + l);
scanf(“%s", x[n]);
}while (strcmp(x[n++], “FIN")); /* recordar que 0 es falso. No hay control
de cantidad de nombres ingresados */

/* reordenar la lista de cadenas*/


for (i= n-1; i >0; i--)
for(j=0; j<i ; j++)
if (strcmp(x[j], x[j+1]) > 0) {
/* intercambiar las dos cadenas */
strcpy(temp, x[j]);
strcpy(x[j], x[j+1]);
strcpy(x[j+1], temp);
}

/*mostrar la lista ordenada de cadenas */


printf(“\n\tLista reordenada de cadenas:\n");
for (i = 0; i < n; ++i)
printf(“\ncadena %d: %s”, i + 1, x[i]);
}
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

Estructuras
El arreglo es un tipo básico de estructura de datos cuyos elementos son todos del
mismo tipo. Un registro es un tipo de estructura donde los elementos individuales
pueden ser de distinto tipo de dato. Así un registro puede contener elementos
enteros, de carácter, de punto flotante, arreglos, incluso otras estructuras.
Definición de una estructura
Es necesario primeramente definir el patrón que tendrá la estructura a utilizar.

struct identificadorRegistro {
miembro1;
miembro 2;
.......
};

Los miembros individuales pueden ser variables simples de C, arreglos u otras


estructuras. Estos identificadores deben ser todos diferentes y estos no se pueden
inicializar dentro de la definición del tipo de la estructura.

Ej.
struct FichaAlumno{
longint ROL;
char nombre[30];
int notaCat;
int notaLab;
};
Obs: Esta definición no es una variable donde se almacenarán los datos. Solamente
indicará el tipo de estructura ( forma) que tendrá la variable.

Declaración de variables del tipo estructura


Para almacenar los datos se necesitan declarar las variable que los contendrán.

struct IdentificadorEstructura listaVariables;

Ej.
struct FichaAlumno X,Y;

En este caso X e Y son variables que tienen la estructura de almacenaje del tipo
FichaAlumno. Es decir en X se puede almacenar el rol del alumno, su nombre y sus
notas.

Otra forma de declarar variables del tipo de una estructura es:


Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

struct identificadorEstructura{
miembro 1;
miembro 2;
........
} listaVariables;

Ej.
struct FichaAlumno{
longint ROL;
char nombre[30];
int notaCat;
int notaLab;
} X,Y;

En este caso puede ser optativo el identificador de la estructura.

También se pueden inicializar las variables del tipo struct al igual que se hace con
las variables simple y los arreglos.
Por ejemplo se puede inicializar la variable X de la siguiente forma

struc FichaAlumno X ={ 9921021, “Juana de Arco”, 70,70};

O bien
struct {
longint ROL;
char nombre[30];
int notaCat;
int notaLab;
} X={ 9921021, “Juana de Arco”, 70,70};
Notase que en este caso se omitió el identificador de la estructura

Para el caso de un arreglo donde los elementos del arreglo son de un tipo de
estructura, se declaran de la misma forma teniendo en cuenta que la variable es un
arreglo. Por ejemplo, para el caso de un curso.

#define N 45
struct FichaAlumno Alumno[N];

O bien

struct {
longint ROL;
char nombre[30];
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

int notaCat;
int notaLab;
} Alumno[N];
También puede ser inicializado el arreglo como:

struct FichaAlumno Alumno[]={ {9912045,”Juana de Arco”,70,70},


{9902154,”Albert Einstein”,20,30},
{9923253,”Carmelo Carvallo
Carvallo”,60,50},
................
};

Obs.: Se pueden omitir las llaves internas

Acceso a los miembros de una estructura


Los miembros de una estructura se procesan generalmente de modo individual,
como entidades separadas, por lo tanto se deben acceder a los miembros
individuales de la estructura.

IdentificadorVariable.miembro

Notase que el punto separa el nombre de la variable del nombre del miembro. De
esta manera se debe indicar en que variable y en que miembro se almacena el valor.

Ej.
X.notaCat=60;
Alumno[2].notaLab=50;

Los miembros de una estructura se pueden procesar al igual que las variables
simples. Por ejemplo
Printf( “ Alumno %s tiene %f“ , Alumno[i].nombre, Alumno[i].notaCat*0.9
+Alumno[i].notaLab*0.1);

En algunas versiones de C es posible realizar asignaciones con variables del mismo


tipo de estructura. Por ejemplo
Dadas las variables definidas anteriormente, es posible realizar la asignación:
Y=X;

De esta manera todos los datos de la variable Y son asignadas a la variable X.

En versiones antiguas de C es necesario realizarla la asignación miembro a


miembro.
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

X.ROL=Y.ROL;
strcpy(X.nombre,Y.nombre);
X.notaCat=Y.notaCat;
X.notaLab=Y.noatLab;

Ejercicio: Desarrolle un programa en C que permita ingresar el rol, nombre y notas de los
alumnos de un curso. El programa debe permitir mostrar en pantalla el nombre y su
promedio sabiendo que el promedio de cátedra tiene una ponderación de 80% y de
laboratorio 20%.

Traspaso de estructuras a funciones

Se puede traspasar a una función una estructura completa o un miembro de ella ya sea por
valor o por referencia.

i) Traspaso por valor

En la llamada a la función se escribe el nombre de la variable estructura o del campo a


traspasar.
En la definición de la función es recibido por otra variable que debe ser del mismo tipo de
dato.
En el ejemplo la función mostrar() recibe un registro y se declara como tal. Pero en el caso
de la función largoCadena() recibe un miembro del registro que en este caso es un arreglo
de caracteres que se encuentra definido en struct.
Ej.
#include <stdio.h>
#define N 4
#define LARGOLINEA 79

struct tipoRegistro {
char nombre[20];
int N_cuenta;
float saldo;
};

void espaciosblancos(int n)
{
int i;
for(i=1; i<=n ; i++)
putchar(' ');
}

void linea()
{
int i;
for(i=1; i<=LARGOLINEA;i++) putchar('*');
putchar('\n');
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

int largoCadena(char cadena[])


/* permite calcular en número de caracteres de la cadena. No es necesario escribir el tipo de
la función ya que por defecto es de tipo int */
{
int i=0;
while(*(cadena +i) !='\0') /* se puede usar cadema[i]!=’\0’ */
i++;
return i;
}

void mostrar(struct tipoRegistro X)


/* recibe un elemento que es de tipo registro */
{
int largo;
largo=largoCadena(X.nombre); /* se traspasa un miembro del registro */
espaciosblancos((LARGOLINEA-largo)/2);
printf("%s\n", X.nombre);
printf(" cuenta %d \n", X.N_cuenta);
printf(" saldo %f \n", X.saldo);
}

void main()
{
static struct tipoRegistro cliente[N]={
{"Pérez Juan", 111,300000},
{"Alfaro María",231,500000},
{"Fernández Pedro",432,100000},
{"Carvallo Carmelo",131,1000000}
};
int i;
float sumaSaldos=0.0;
for(i=0; i<N; i++){
mostrar(cliente[i]); /* se traspasa todo el registro i */
sumaSaldos+=cliente[i].saldo;
linea();
}
printf("Total saldo %f \n", sumaSaldos);
}

ii) Traspaso por referencia

En este caso se le pasa a la función la dirección de la estructura a modificar.


En la llamada a la función el registro va precedido del operador de dirección &. Y en la
definición de la función es recibido por un puntero. Ver en el ejemplo la función
modificar().
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

Nótese que la función listar() recibe un arreglo de registro que es traspasado por referencia,
pero en este caso no son modificados sus elementos, por lo tanto no es necesario pasar una
copia de él.
Ej.
#include <stdio.h>
#define N 4

struct tipoRegistro {
char nombre[20];
int N_cuenta;
float saldo;
};

void modificar(struct tipoRegistro *p)


/* recibe un la dirección de un registro para ser modificado */
{
float saldoNuevo;
printf("Ingrese nuevo saldo\n");
scanf("%f",&saldoNuevo);
p->saldo=saldoNuevo;
}

void listar(struct tipoRegistro X[])


{
int i;
for(i=0;i<N ;i++){
printf("\n%s\n", X[i].nombre);
printf(" cuenta %d \n", X[i].N_cuenta);
printf(" saldo %f \n", X[i].saldo);
}
}

void main()
{
static struct tipoRegistro cliente[N]={
{"Pérez Juan", 111,300000},
{"Alfaro María",231,500000},
{"Fernández Pedro",432,100000},
{"Carvallo Carmelo",131,1000000}
};

int n;
float sumaSaldos=0.0;

printf("Antes de modificar \n");


listar( cliente); /* traspaso todo el arreglo ( por referencia )*/
printf("Ingrese número de cliente a modificar saldo \n");
scanf("%d",&n);
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

modificar(&cliente[n-1]); /* traspaso por referencia */


printf("Después de modificar \n");
listar(cliente);
}

Una función también puede retornar la dirección de un registro.


En el caso de la función buscar() retorna un puntero a registro. Se declara el tipo de dato
que retorna.
Ej.
#include <stdio.h>
#define N 4

struct tipoRegistro {
char nombre[20];
int N_cuenta;
float saldo;
};

struct tipoRegistro * buscar(struct tipoRegistro X[],int buscaCuenta)


/* la función retorna la dirección del registro encontrado */
{
int i=0;
while(i<N && X[i].N_cuenta!=buscaCuenta) i++;
if( i<N ) return(&X[i]);
else return(NULL);
}

void listar(struct tipoRegistro X[])


{
int i;
for(i=0;i<N ;i++){
printf("\n%s\n", X[i].nombre);
printf(" cuenta %d \n", X[i].N_cuenta);
printf(" saldo %f \n", X[i].saldo);
}
}

void main()
{
static struct tipoRegistro cliente[N]={
{"Pérez Juan", 111,300000},
{"Alfaro María",231,500000},
{"Fernández Pedro",432,100000},
{"Carvallo Carmelo",131,1000000}
};

int n;
float sumaSaldos=0.0;
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

struct tipoRegistro *p;


printf("Listado de clientes \n");
listar( cliente);
printf("Ingrese número de cuenta del cliente \n");
scanf("%d",&n);
p=buscar(cliente, n);
if( p==NULL ) printf("Número de cuenta no existe \n");
else
printf("El cliente es %s \n", p->nombre);
}

Una función también puede retornar un registro.


La función ingresar() retorna un registro que es asignado a un elemento del arreglo de
registros.
Ej.
#include <stdio.h>
#define N 6

struct tipoRegistro {
char nombre[20];
int N_cuenta;
float saldo;
};

buscar(struct tipoRegistro X[],int buscaCuenta, int largo)


/* busca en número de cuenta y retorna la posición si no lo encuentra retorna el largo */
{
int i=0;
while(i<largo && X[i].N_cuenta!=buscaCuenta) i++;

return(i);
}

struct tipoRegistro ingresar() /* La función retorna un registro al lugar donde se hizo la


llamada */
{
struct tipoRegistro A; /* declaración de la variable */
printf("Ingrese nombre \n");
gets(A.nombre); /* función de C que captura una cadena de caracteres */
printf("Cuenta Nº\n");
scanf("%d", &A.N_cuenta);
A.saldo=0.0;
return(A);
}

void listar(struct tipoRegistro X[])


{
int i;
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

for(i=0;i<N ;i++){
printf("\n%s\n",X[i].nombre);
printf(" cuenta %d \n", X[i].N_cuenta);
printf(" saldo %f \n", X[i].saldo);
}
}

void main()
{
static struct tipoRegistro cliente[N]={
{"Pérez Juan", 111,300000},
{"Alfaro María",231,500000},
{"Fernández Pedro",432,100000},
{"Carvallo Carmelo",131,1000000}
};

int p,cantidad=4;

printf("Antes de modificar \n");


listar( cliente);
while(cantidad<N ){
cliente[cantidad]=ingresar();
p=buscar(cliente,cliente[cantidad].N_cuenta,cantidad );
if( p<cantidad ) printf("Número de cuenta ya existe\n");
else{
printf("Cliente nuevo ingresado %s \n", cliente[cantidad].nombre);
cantidad++;
}
}
listar( cliente);
}

Tipos de datos definidos por el usuario


Es posible definir nuevos tipos de datos que sean equivalentes en nombre a los ya
existentes. Una vez definido el tipo de dato este permitirá declarar nuevas variables,
arreglos, estructuras, etc. en términos del nuevo nombre del tipo dato.

typedef tipoDato tipoDatoNuevo;

TipoDato es uno ya existente y se redefine con un nuevo nombre.


typedef permite otorgar nombres simbólicos a tipos de datos ya existentes.
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

Ej.
typedef int posicion;

En este caso posicion e int tienen el mismo significado para el compilador, es decir,
permiten declarar variables de tipo entero.
Ej.
posicion i; /* es equivalente a escribir int i*/
printf(“ingrese la posición del alumno en el listado”);
scanf(“%d”,&i);
printf/”%s”,Alumno[i].nombre);

Ej.
typedef float altura[100];
......
altura hombres, mujeres;

en este caso se define altura como arreglo de 100 elementos de punto flotante.
hombres y mujeres son arreglos de 100 elementos de punto flotante cada uno.

Ej.
typedef struc FichaAlumno Curso;
....
Curso Alumno[N];

Otra forma
typedef struct FichaAlumno RegistroAlumno[N];
.....
RegistroAlumno Alumno;

En estos dos últimos casos Curso y RegistroAlumno define declaraciones como


tipos de datos definidos por el usuario.
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

Archivos en C

Un archivo es una estructura de datos consistente en una secuencia de elementos o


componentes llamados registros. Todos son del mismo tipo, ya sea simple o compuesto.
Los datos son almacenados en un almacenamiento externo cinta o diskette, de manera que
la información sea almacenada en forma permanente para su posterior utilización.
En C los archivos pueden ser de datos o de sistema. Los archivos de datos son una
secuencia de bytes que pueden ser interpretados como dato individual o como cadenas de
caracteres o números. También se pueden representar como una organización de datos en
bloques contiguos que mediante estructuras.
Existen archivos que no tienen un formato preestablecido, estos contienen bloques
contiguos de información representando estructuras de datos.

Apertura y cierre de un archivo

Es necesario establecer un área de buffer (memoria intermedia) donde la información sea


almacenada mientras los datos son transferidos desde el dispositivo externo (cinta o
diskette) y la memoria principal de la computadora. El buffer permite leer o escribir
información al archivo más rápidamente. El sistema no lee o escribe byte a byte desde el
dispositivo externo, si no que lo realiza por bloques de datos.
Para establecer una comunicación entre el archivo y el sistema se debe declarar un
descriptor de archivo
FILE *PtroArchivo;

FILE es un tipo especial de estructura (registro) que se encuentra definido en stdio.h. Esta
estructura es de la forma:

En ella se encuentra declarado un puntero al buffer, la dirección base del buffer de entrada
y salida, un número del archivo, etc.

*PtroArchivo es un descriptor de archivo el cual permitirá comunicarse el programa con el


archivo.

Función fopen()

Una vez declarado el descriptor de archivo es necesario abrir el archivo e indicar cómo será
utulizado el archivo, si es sólo lectura, escritura o ambos. Para esto se utiliza la función
fopen()
Formato de uso:
PtroArchivo= fopen(nombreArchivo,modo)

NombreArchivo es una cadena de caracteres que representa el nombre del archivo que se
encuentra en el disco.
Modo representa la forma de cómo se trabajará con el archivo. Este modo puede ser:
• “r” permite leer desde un archivo existente.
• “w” crea un archivo de escritura. Si este existe el contenido será borrado.
• “a” permite agregar información al final del archivo de uno que existe
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

• “r+” permite leer y escribir en uno que existe.


• “w+” permite crear un archivo para lectura y escritura.
• “a+” permite leer y agregar información en un archivo que existe. Si no existe se crea.

fopen() retorna NULL si hay un error en la apertura. Por ejemplo si el nombre es erróneo,
o si no existe el disco, o no existe el camino o path donde se encuentra el archivo, si se va
escribir y el disco está protegido, u otro error con el disco.

Función fclose()

Una vez utilizado el archivo este se debe cerrar. La función fclose() permite realizar esta
operación.
Forma de uso:
fclose(PtroArchivo).

Ejemplo. Estructura de programa en C de manejo de archivos


#include <stdio.h>
#include <stdlib.h >
void main()
{
FILE *fp;
fp=fopen(“A:datos.dat”,”r+”);
if(fp==NULL) { printf(“ERROR en la apertura del archivo \n”);
exit(0);
}
/* resto del programa */
........
fclose(fp);
}

Escritura en un archivo
Se puede escribir en un archivo secuencial al igual que la salida obtenida por las funciones
que permiten mostrar datos en pantalla.

Función putc()

Escribe un caracter en un archivo de texto.


formato
putc(VarCaracter, descriptorArchivo)

Ej.
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
void main()
{
FILE *fp;
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

char ch;
fp=fopen(“A:datos.dat”,”w”);
if(fp==NULL) { printf(“ERROR en la apertura del archivo\n”);
exit(0);
}
do{
ch=getche() /* se puede usar getchar() o getch() */
putc(ch,fp);
}while( ch!=’\n’);
fclose(fp);
}

Función fputc()
Es una función macro de putc(). Funciona forma análoga que la anterior.
Ejemplo:

Función fprintf()
Escribe una secuencia de caracteres, bajo un formato especificado de salida en un archivo
de texto, al igual de la función printf().
Formato
fprintf( descriptorArchivo,FormatoControl,listadeVariables);

Ejemplo.
#include <stdio.h>
#include <conio.h>
#include <ctype.h>
struct tipoRegistro{
char nombre[20];
int creditoUF;
float tasaInteres;
};
void main()
{
FILE *fp;
struct tipoRegistro cliente;
char ch;
fp=fopen("datos.dat","w");
if(fp!=NULL){
do{

printf("Ingrese nombre del cliente\n");


gets(cliente.nombre);
printf("ingrese credito en UF\n");
scanf("%d",&cliente.creditoUF);
printf("Ingrese la tasa de interés\n");
scanf("%f",&cliente.tasaInteres);
printf("Ingresa otro cliente (S/N)\n");
fprintf(fp,"%20s %8d %5.2f\n",cliente.nombre,cliente.creditoUF,cliente.tasaInteres);
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

ch=getche();
fflush(stdin);
}while( toupper(ch)=='S');
fclose(fp);
}
else printf("Error en abrir archivo\n");
getch();
}
Observaciones:
Se debe tener en cuenta los espacios que están en el formato de control ya que estos serán
escritos en el archivo.

Función puts()
Escribe una cadena de caracteres en un archivo de texto.

Lectura de un archivo
Función getc()
Retorna el carácter leído desde un archivo de texto e incrementa el puntero al siguiente
carácter. Si llegó al final del archivo o detecto un error en la lectura del carácter retorna
EOF (End Of File).
Formato
int ch;
ch=getc(descriptorArchivo)
Ejemplo.
#include <stdio.h>
#include <conio.h>

void main()
{
FILE *fp;
int ch;
fp=fopen("datos.dat","r");
if(fp!=NULL){
ch=getc(fp);
while(ch!=EOF){
putchar(ch);
ch=getc(fp);
}
fclose(fp);
}
else printf("Error en abrir archivo\n");
getch();
}
Ej.
#include <stdio.h>
#define EOF -1
void main()
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

{
FILE *fp;
int ch;
if(( fp=fopen(“A:datos.dat”,”r”))!=NULL ) {
while( (ch=getc(fp))!=EOF )putchar(ch);
fclose(fp);
}
else printf(“ERROR en la apertura del archivo\n”);

Ejemplo: Copiar un archivo

#include <stdio.h>
#define EOF –1

void main()
{
FILE *in,*out;
char archLectura[30], archEscritura[30];
int ch;
printf(“ingrese nombre del archivo a leer\n”);
scanf(“%s”,archLectura);
printf(“Ingrese nombre del archivo a escribir \n”);
scanf(“%s”,archEcritura);
if(( in=fopen(archLectura,”r”))==NULL ) {
printf(“ERROR en la apertura del archivo\n”);
exit();
}
out=fopen(archEscritura,”w”);
while((ch=getc(in))!=EOF) putc(ch,out);
fclose(in);
fclose(out);
}

Ej.
#include <stdio.h>
//#define EOF -1
void main()
{
FILE *fp;
char s[50];
int ch;
if(( fp=fopen("A:datos.dat","r"))!=NULL ) {
while( (fgets(s,20,fp))!=NULL )puts(s);
fclose(fp);
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

}
else printf("ERROR en la apertura del archivo\n");

En los archivos de carácter también se pueden usar otras funcione tales como;
fprintf() y fscanf() que escriben y leen datos en forma análoga que printf() y scanf(), sólo
se requiere agregar como primer argumento el descriptor de archivo.
Función fscanf()
Lee datos con formato especificado desde un archivo de texto. Retorna EOF si llegó al final
del archivo o detecto un error de lectura
Ej.
#include <stdio.h>
//#define EOF -1
void main()
{
FILE *fp;
char s[50];
int n, suma=0;
if(( fp=fopen("E:\\basura\\datos.txt","r"))!=NULL ) {
while( fscanf(fp,"%d",&n)!=EOF ){
suma+=n;
printf("%d ",suma);
}
fclose(fp);
}
else printf("ERROR en la apertura del archivo\n");
}
Ejemplo
#include <stdio.h>
#include <conio.h>
#include <string.h>
struct tipoRegistro{
char nombre[22];
int creditoUF;
float tasaInteres;
};
void main()
{
FILE *fp;
struct tipoRegistro cliente;
char c,cadena[25];
int uf,j=0;
float i;
fp=fopen("datos.dat","r");
if(fp!=NULL){
while(fgets(cadena,21,fp)){
fscanf(fp,"%d %f",&uf,&i);
Lenguaje C (Apuntes Versión Beta) Prof. H. Hoffmann y J. C. Medina

printf("%4d ",++j);
strcpy(cliente.nombre,cadena);
cliente.creditoUF=uf;
cliente.tasaInteres=i;
printf("%20s %10d %5.2f\n",cliente.nombre,cliente.creditoUF,cliente.tasaInteres);
getch();
};
fclose(fp);
}
else printf("Error en abrir archivo\n");
getch();
}
Operaciones con archivos

Vous aimerez peut-être aussi