lenguajes de programacin
Post on 23-Jun-2015
1.713 Views
Preview:
TRANSCRIPT
Lenguajes de programación
M. en C. Joel Omar Juárez Gambino
Introducción
• En una computadora un algoritmo se expresa a través de un programa
• Los lenguajes utilizados para escribir programas de computadora se denominan lenguajes de programación
• Los principales tipos de lenguajes utilizados son:– Lenguajes máquina (0’s y 1’s)– Lenguajes de bajo nivel (ensamblador)– Lenguajes de alto nivel
Lenguajes máquina
• El lenguaje que manejan es directamente entendible por la computadora
• Sus instrucciones son cadenas binarias que especifican operaciones y posiciones de memoria
• Las instrucciones en lenguaje máquina dependen del hardware de la computadora
Lenguajes máquina
• EjemploDirección Contenido
0100 0010 0000 0000 0100
0101 0100 0000 0000 0101
0111 0011 0000 0000 0110
... ... ... ... ...
Lenguajes máquina
• Ventajas– Cargar un programa sin necesidad de traducción
posterior– Velocidad superior a cualquier otro lenguaje de
programación
• Desventajas– Dificultad y lentitud en la programación– Dificultad para verificar y corregir errores– Los programas solo se pueden ejecutar en el
procesador en que se programó
Lenguajes de bajo nivel
• Son más fáciles de utilizar que los lenguajes máquina, pero igual son dependientes de la arquitectura
• Un lenguaje de bajo nivel muy conocido es el ensamblador
• El lenguaje ensamblador esta compuesto por un conjunto de instrucciones conocidas como nemotécnicos (ADD, SUB, DIV, etc.)
• Este lenguaje no es directamente ejecutable por la máquina y requiere una fase de traducción
Lenguajes de bajo nivel
• Ejemplo:
ADD M, N, P
0110 1001 1010 1011
Lenguajes de bajo nivel
• Ventajas– Mayor facilidad de codificación– Velocidad de cálculo
• Desventajas– Dependencia total de la máquina– El diseño de programas requiere no solo de
técnicas de programación, sino también el conocimiento interior de la máquina
Lenguajes de alto nivel
• Estos lenguajes ocultan los detalles del funcionamiento del procesador de las instrucciones que se desean programar
• La característica anterior hace posible que los programas hechos con estos lenguajes puedan ser portables (en cierta medida)
Lenguajes de alto nivel
• Ejemplos de lenguajes de alto nivel:– Cobol– Fortran– C– Pascal– Basic– C++– Visual Basic– JAVA– C#
Lenguajes de alto nivel
• Ventajas– El tiempo que se invierte en aprender el
lenguaje es relativamente corto– Escritura de programas basada en reglas
sintácticas parecidas al lenguaje humano– Proceso de verificación y corrección de
errores sencillo– Transportabilidad
Lenguajes de alto nivel
• Desventajas– Requieren un proceso de traducción más
complicado y tardado– No se explota al máximo los recursos internos
de la máquina– Requieren de más memoria– Tiempo de ejecución del programa mucho
más tardado
Traductores de lenguaje
• Los traductores de lenguaje son programas que traducen los programas fuente escritos en lenguajes de alto nivel a código máquina
• Los traductores se dividen en:– Compiladores– Intérpretes
Intérpretes
• Un interprete es un traductor que toma un programa fuente, lo traduce y a continuación lo ejecuta
Programa fuente
Intérprete
Traducción y ejecuciónlínea y línea
Compiladores
• Un compilador es un programa que traduce los lenguajes de alto nivel a lenguajes máquina
Programa fuente
Compilador
Programa objeto
Fases de compilación
Programa fuente
Compilador
Programa objeto
Montador (enlazador)
Programa ejecutableen lenguaje máquina
Orígenes de C
• Los orígenes de C datan de finales de los 60's y principios de los años 70's
• Se basó en el lenguaje BCPL desarrollado por Martin Richards, y el lenguaje B desarrollado por Ken Thompson
• En 1972 el sistema Unix se reescribo en un nuevo lenguaje llamado C desarrollado por Dennis Ritchie en los laboratorios Bell
Orígenes de C
• Brian Kernighan y Dennis Ritchie escriben en 1978 el primer estándar de facto para C
• En 1988 la ANSI (American National Standars Institute) publica el primer estándar oficial
Estructura de un programa en C
• Todo programa en C consta de uno o más módulos llamados funciones
• Una de las funciones se llama main• El programa siempre comenzará por la
ejecución de la función main• Las demás funciones se pueden acceder
desde la función main
Estructura de un programa en C
• Cada función debe contener:– Una cabecera de la función, que consta del
nombre de la función, seguido de una lista de argumentos encerrados entre paréntesis
– Una lista de declaración de argumentos, si se incluyen estos en la cabecera
– Una instrucción compuesta, que contiene el resto de la función
Ejemplo
#include <stdio.h>
int main(int argc, char *argv[]){ printf ("Hola mundo!\n");
return 0;}
Identificadores y palabras reservadas
• Un identificador es el nombre que se le da a los elementos de un programa (variables y funciones)
• Un identificador empieza por una letra seguido de letras y dígitos en cualquier orden. Se considera al guión bajo “_” como una letra más.
• Solo los primeros 31 caracteres son significativos
Ejemplos de identificadores
• Validos:– x, area, y12, suma_1, _temp, TABLA
• No validos– 4num, “x”, suma-1, mi variable
• Es importante recordar que C es un lenguaje sensible a mayúsculas y minúsculas
Palabras reservadas
• Existen algunas palabras que el lenguaje C ha reservado y que tienen un significado predefinido
• Estas no se pueden utilizar como identificadores, ni darle un uso distinto al que ya tienen asignado
Palabras reservadas
• auto• break• case• char• const• continue• default• do• double• else• enum
• extern• float• for• goto• if• int• long• register• return• short• signed
• sizeof• static• struct• switch• typedef• union• unsigned• void• volatile• while
Tipos de datosTipo de dato Descripción Requisito de
memoria
int Cantidad entera 2 bytes
char Carácter 1 byte
float Número en coma flotante
4 bytes
double Número en coma flotante de doble precisión
8 bytes
Modificadores de tipo
• short. Se utiliza cuando se desea una variable menor que un int. – Sintaxis: short int <identificador>;– Ejemplo: short int i;
• long. Cuando se utiliza sobre un int dobla el espacio utilizado para almacenar el entero. Algo similar sucede cuando se utiliza con los tipos float y double.– Sintaxis: long [int|float|double] <identificador>;
– Ejemplo: long double x;
Modificadores de tipo
• signed. Define que el valor de una variable numérica puede ser positivo o negativo. Este modificador se puede aplicar a los tipos int, char, long, short.– Sintaxis: signed <tipo> <identificador>;– Ejemplo: signed int i;
• unsigned. Se utiliza cuando se desea que la variable sea positiva. Este modificador se puede aplicar a los tipos int, char, long, short.– Sintaxis: unsigned <tipo> <identificador>;– Ejemplo: unsigned long int i;
Declaraciones
• Una declaración asocia un tipo de datos especificado a un grupo de variables. Se deben declarar todas las variables antes de que aparezcan en las instrucciones ejecutables
• Una declaración consta de un tipo de datos, seguido de uno o más nombres de variables, finalizando con un punto y coma
Declaraciones
• Ejemplos:
int a, b, c;
float raiz;
double num;
char letra1, letra2;
short int x;
Constantes simbólicas
• Una constante simbólica es un nombre que sustituye una secuencia de caracteres
• Los caracteres pueden representar una constante numérica, una constante de carácter o una constante de cadena de caracteres– Sintaxis: #define nombre texto– nombre: representa un nombre simbólico,
generalmente se escribe en mayúsculas– texto: representa la secuencia de caracteres
asociada al nombre simbólico– Ejemplo: #define PI 3.141592
Operadores
Operadores aritméticos
Operador Propósito
+ Suma
- Resta
* Multiplicación
/ División
% módulo
Precedencia
( )
* / %
+ -
a + b * c
(a + b) / c
Operadores
• Operadores unarios
Operador Propósito
- Signo negativo
++ Incremento
-- Decremento
int a = 1, b = 2;
printf(++a);
b--;
printf(b);
printf(a++)
Operadores
• Operadores relacionales y lógicos
Operador Propósito
< Menor que
<= Menor o igual que
> Mayor que
>= Mayor o igual que
== Igual que
!= Distinto de
&& Y
|| O
int a = 1, b = 2;
a < b
a > b
a != b
(a == 1) && (b > a)
(a != b) || (a > 2)
Funciones de biblioteca
• El lenguaje C se acompaña de un cierto número de funciones de biblioteca que realizan operaciones y cálculos de uso frecuente
• Estas funciones no son parte del lenguaje en si, pero se incluyen sus implementaciones
• Las funciones de biblioteca de propósitos relacionados suelen estar agrupadas archivos de bibliotecas
• Los archivos de biblioteca se proporcionan como parte del compilador de C
Funciones de biblioteca
• Algunas funciones de biblioteca de uso común son:
Función Tipo Propósito
abs(i) int Devuelve el valor absoluto de i
cos(d) int Devuelve el coseno de d
pow(d1,d2) double Devuelve d1 elevado a la potencia d2
getchar() char Permite leer un carácter desde el dispositivo de entrada estándar
tolower(c) char Convierte el carácter c a minúscula
Entrada y salida de datos
• El lenguaje C incluye una colección de funciones de biblioteca para trabajar con operaciones de entrada/salida
• Las de uso más común son: getchar, putchar, scanf, printf, gets, puts
• Cada una de estas funciones regresa un valor distinto y los parámetros que requiere son diferentes
Función getchar
• Devuelve un carácter leído del dispositivo de entrada estándar (teclado)
• No requiere argumentos• Sintaxis:
var_caracter = getchar();– Donde var_caracter es una variable de tipo carácter
donde se almacena lo leído por la función
• Ejemplo:char c;c = getchar;
Función putchar
• Transmite un carácter al dispositivo de salida estándar (monitor)
• Requiere como argumento una variable de tipo carácter
• Sintaxis:putchar(var_caracter);– Donde var_caracter es una variable de tipo carácter
que contiene el valor que se desea enviar de salida• Ejemplo:
char c = ‘a’;putchar (c);
Función scanf
• Permite introducir cualquier combinación de valores numéricos, caracteres sueltos y cadena de caracteres
• Esta función devuelve el número de datos que se han conseguido introducir correctamente
• Sintaxis:scanf (cadena_control, arg1, arg2, ..., argn)– Donde cadena_control hace referencia a una cadena que
contiene información sobre el formato de los datos y arg[n] son lo argumentos que representan los datos
Función scanf
• La cadena de control incluye grupos individuales de caracteres, con un grupo de caracteres por cada dato de entrada
• Cada grupo de caracteres debe iniciar con el símbolo de porcentaje (%)
Función scanfCarácter de conversión Significado
c El dato es un carácter
d El dato es un entero decimal
e El dato es un valor en coma flotante representado con exponente
f El dato es un valor en coma flotante representado sin exponente
h El dato es un entero corto
i El dato es un entero decimal, octal o hexadecimal
o El dato es un entero octal
s El dato es una cadena de caracteres de espaciado
u El dato es un entero decimal sin signo
x El datos es un entero hexadecimal
[...] El dato es una cadena de caracteres que puede incluir caracteres de espaciado
Función scanf
• Los argumentos pueden ser variables o arreglos, y sus tipos deben de coincidir con los indicados en la cadena de control
• Cada nombre de variable debe ser precedido por un ampersand (&)
• Los arreglos no deben ir precedidos por el ampersand
Función scanf
• Ejemplo:{ char nombre [20]; int num1; float costo; . . . . . scanf(“%s %d %f”, nombre, &num1, &costo); . . . . .}• Es importante notar que la conversión de tipo s se aplica a una
cadena de caracteres que acaba en un carácter de espaciado. Por tanto, una cadena que incluye espacios en blanco no se puede introducir de esta forma
Función scanf
• Ejemplo:#include <stdio.h>
int main()
{
char linea [80];
. . . . .
scanf (“%[ ABCDEFGHIJKLMNOPQRSTUVWXYZ]”, linea);
. . . . .
}• En este ejemplo el carácter de conversión utilizado especifica que
solo se reconocerán mayúsculas y el espacio en blanco
Función printf
• Permite escribir cualquier combinación de valores numéricos, caracteres y cadena de caracteres a la salida estándar
• Sintaxis:printf (cadena_control, arg1, arg2, ..., argn)
• Los argumentos de la función printf no representa direcciones de memoria y por lo tanto no son precedidos de ampersands
Función printf
• Ejemplo:#include <stdio.h>
int main(){ char nombre [20]; int num1; float costo; . . . . . printf (“%s %d %f”, nombre, num1, costo); . . . . . return 0;}
Funciones gets y puts
• La función gets permite leer de la entrada estándar un arreglo de caracteres
• Sintaxis gets (cadena);
– Donde cadena es un arreglo de caracteres
• La función puts permite escribir a la salida estándar una cadena de caracteres
• Sintaxis:puts (cadena);– Donde cadena es un arreglo de caracteres
Funciones gets y puts
• Ejemplo:#include <stdio.h>
int main(){
char linea[80];
//Lee del teclado una cadena de caracteres
gets(linea);
//Escribe a la pantalla una cadena de caracteres
puts(linea);
}
Control de flujo en C
Instrucción if-else
• Se utiliza para realizar una evaluación lógica y a continuación llevar a cabo una de dos posibles acciones
• Sintaxis if (expresión) instrucción if (expresión) instrucción1 else instrucción2
– Donde expresión es el valor a evaluar e instrucción son las sentencias a realizar
Instrucción if - else
• Ejemplo:
#include <stdio.h>
int main(){ int a=3, b=4; if (a > b){ a = a-b; printf(“%d”, a); }else if(a < b){ b = b-a; printf(“%d”, b); } return 0;}
Ciclo while
• Este ciclo ejecuta una serie de instrucciones de forma repetida, hasta que satisface alguna condición
• Sintaxis:
while (expresión) instrucción
Ciclo while
• Ejemplo:#include <stdio.h>
int main(){
int numero=0;
while (numero <= 9){
printf(“%d\n”, numero);
numero++;
}
return 0;
}
Ciclo do - while
• Este ciclo es utilizado cuando se desea que la condición de paro se realice después de la ejecución de las instrucciones
• Sintaxis do instrucción while (expresión)
Ciclo do - while
• Ejemplo:
#include <stdio.h>
int main(){ int numero=0; do{ printf(“%d\n”, numero++); }while (numero <= 9);
return 0;}
Ciclo for
• Este se compone de tres expresiones:– una que especifica el valor inicial de un índice– otra expresión que determina cuándo se continúa o
no el ciclo– una tercera que permite que el índice se modifique al
final de cada pasada
• Sintaxis:for (expresión1; expresión2; expresión3) instrucción
Ciclo for• Ejemplo:
#include <stdio.h>
int main(){ int numero; for (numero =0; numero <= 9; numero++){ printf(“%d\n”, numero); }
return 0;}
Estructuras de control anidadas
• Los ciclos descritos anteriormente, al igual que las instrucciones if – else, se pueden anidar, uno dentro de otro
• Ejemplo: Calcular el promedio de n alumnos para 4 calificaciones por alumno
La instrucción switch
• La instrucción switch hace que se seleccione un grupo de instrucciones entre varios grupos disponibles
• La selección se basa en el valor de una expresión que se incluye en la instrucción switch
• Sintaxis: switch (expresión) instrucción
La instrucción switch
• Las instrucciones incluidas en un switch son generalmente instrucciones compuestas que especifican opciones posibles a seguir
• Cada grupo de instrucciones se escribe en forma general:case expresión 1:
instrucción 1
instrucción 2
case expresión 2:
instrucción 3
instrucción 4
• Ejemplo:
#include <stdio.h>
int main(){ char color; switch(color){ case ‘r’: case ‘R’: printf(“ROJO”); break; case ‘a’: case ‘A’: printf(“AZUL”); break; }
return 0;}
La instrucción break
• La instrucción break se utiliza para terminar la ejecución de ciclos o salir de instrucciones switch
• Se puede utilizar dentro de una instrucción while, do – while, for o switch
• Sintaxis:break;
La instrucción continue
• La instrucción continue se utiliza para saltarse el resto de la pasada actual dentro de un ciclo
• El ciclo no termina cuando encuentra la instrucción continue, sino que no ejecuta las sentencias que están después de esta instrucción
• Sintaxis: continue;
La instrucción continue• Ejemplo:
#include <stdio.h>
int main(){ int n; for (n=0; n<=100; n++) { //si no es múltiplo de 5, siguiente iteración if (n % 5 != 0) continue; //imprime el siguiente múltiplo de 5 printf(“%d”,n); }
return 0;}
Funciones
• El lenguaje C se utilizan una serie de funciones de biblioteca para realizar operaciones de uso común
• Sin embargo, para algunas operaciones es necesario definir funciones propias
• El uso de funciones definidas por el usuario permite dividir un programa grande en una serie de subprogramas más pequeños (modularizar)
Funciones
• Existen varias ventajas al modular los programas:– Se evita la necesidad de repetir las mismas
instrucciones de forma redundante– Los programas son más fáciles de escribir y
depurar– Se puede construir una biblioteca de
funciones propias
Definición de una función
• La definición de una función tiene dos componentes principales: el encabezado de la función y el cuerpo de la función
• El encabezado contiene el tipo de valor devuelto por la función, seguido del nombre de la función y un conjunto opcional de parámetro
• En caso de que la función no requiera devolver ningún valor se utiliza como tipo de dato la palabra reservada void
Definición de una función
• Sintaxis:tipo-de-dato nombre(tipo 1 arg 1, ..., tipo n arg n)
• Donde:– tipo-de-dato: es el tipo devuelto por la función– nombre: es el identificador de la función– tipo n: es el tipo de dato del argumento– arg n: es el identificador del argumento
• El cuerpo de la función son las instrucciones que definen la acciones que se deben realizar
Ejemplo
• Determinar el máximo de dos númerosvoid maximo (int x, int y){ int mayor;
if ( x >= y) mayor = x; else mayor = y; printf(“El mayor es: %d”, mayor);}
Acceso a una función
• Para llamar a una función se utiliza su nombre, seguido de una lista de argumentos encerrados entre paréntesis y separados por coma
• Si la función no requiere ningún argumento, se debe escribir después del nombre de la función un par de paréntesis vacíos
• Si la función devuelve un valor, el acceso a la función se suele escribir como una instrucción de asignación
Acceso a una función
• Función que devuelve valor
z = suma (x, y)• Función que no devuelve valor
imprimir (nombre)
Arreglos en C
Arreglos en C
• Un arreglo es un conjunto finito y ordenado de elementos homogéneos
• Esta estructura de datos es estática, por lo que su tamaño no puede cambiar una vez que se ha definido
Arreglos en C
• La sintaxis para definir un arreglo es:tipo_dato identificador [tamaño]
• Donde– tipo_dato: es el tipo de dato que se almacenará en
el arreglo– identificador: es el nombre con el que se hace
referencia al arreglo– tamaño: especifica el número de elementos que
contendrá el arreglo.
• Es importante aclarar que el primer elemento en un arreglo esta en la posición cero
Arreglos en C
• Ejemplos:int x[100];
char texto[30];
float f[3];
Inicialización de arreglos
• El lenguaje C proporciona una forma de inicializar un arreglo desde su declaración
• Utilizando este método de inicialización, el tamaño del arreglo no necesita ser especificado
• Ejemplos:int numeros [] = {1,2,3,4,5};
char vocales [] = {‘a’, ‘e’, ‘i’, ‘o’, ‘u’}
Recorrido de arreglos
• Se puede recorrer cada uno de los elementos de una arreglo mediante un ciclo, utilizando el contador como índice del arreglo
• Ejemplo:int i, num[3];
for(i=0; i<3; i++)
num[i] = i+1;
Ejemplo
• Leer 3 cadenas de 10 caracteres e imprimirlas al revés
Arreglos multidimensionales
• La sintaxis para definir un arreglo multidimensional es muy parecida a los arreglos unidimensionales, excepto que se requiere un par separado de corchetes por cada dimensión
• Ejemplos:float tabla [50][50];
double registros [100][66][255];
Inicialización de arreglos multidimensionales
• Para asignar valores iniciales a un arreglo unidimensional se forman grupos de valores encerrados entre llaves
• Los valores dentro de cada par interno de llaves serán asignados a los elementos del arreglo cuyo índice este más a la derecha
Inicialización de arreglos multidimensionales
• Ejemplo:int valores [3][4]={
{1,2,3,4},
{5,6,7,8},
{9,10,11,12}
};
Inicialización de arreglos multidimensionales
• Ejemplo 2:int t [2] [3] [4] = {
{ {1,2,3,4}, {5,6,7,8}, {9,10,11,12}
}, { {13,14,15,16}, {17,18,18,20}, {21,22,23,24} }
}
Paso de arreglos como parámetros
• Un arreglo se puede pasar como parámetro a una función
• A diferencia de otros tipos de datos, un arreglo se envía por referencia, es decir se envía la dirección de memoria del arreglo
• Cualquier cambio hecho sobre un arreglo enviado a una función se verá reflejado cuando se retorne a la función principal
Paso de arreglos como parámetros
• Para pasar un arreglo a una función, el nombre del arreglo debe aparecer solo, sin corchetes ni índices
• La definición de la función requiere se que incluya después del nombre de la función un par de corchetes vacíos para indicar que se trata de un arreglo
Paso de arreglos como parámetros
• Ejemplo
float suma (int arr1[], int arr2[]); //Prototipo
int main(){ int arreglo1[3], arreglo2[3], res; ... res = suma(arreglo1, arreglo2);//llamada}
float suma (int arr1[], int arr2[]){//Definición ...}
Tipos de almacenamiento
Tipos de almacenamiento
• En C hay cuatro especificaciones diferentes de tipo de almacenamiento: auto, extern, static y register
• A veces se puede establecer el tipo de almacenamiento asociado a una variable simplemente por la posición de su declaración en el programa
• Ejemplos:auto int a,b,c;extern float raiz, cociente;static int cont = 0;
Variables automáticas
• Las variables automáticas se declaran siempre dentro de una función y son locales a ellas
• El ámbito de estas variables esta limitado a el cuerpo de la función contenedora
• Si se omite el tipo de almacenamiento dentro de la declaración de una variable esta toma el comportamiento de variable automática
Variables externas (globales)
• El ámbito de las variables externas se extiende desde el punto de su definición hasta el resto del programa
• Las variables externas se reconocen globalmente, por lo que pueden ser accedidas por cualquier función que caiga dentro de su ámbito
• Este tipo de variables son un mecanismo de transferencia de información entre funciones
Variables externas (globales)
• Es importante distinguir entre una declaración y una definición de variable externa
• Declaración: anuncia las propiedades de una variable (su tipo, principalmente). Esta debe empezar con el especificador extern
• Definición: reserva el espacio de memoria requerido por la variable
• La definición es única, pero la declaración es necesaria en todos los puntos donde se vaya a utilizar la variable
Variables externas (globales)
• Ejemplo://Archivo principal.c#include <stdio.h>#include “funciones.h”int cont = 0;
int main(){ printf(“%d”,++cont); fun(); ... return (0);}
Continuación ejemplo
//Archivo funciones.h#include <stdio.h>#include “principal.c”extern int cont;
void fun(){ printf(“%d”,++cont); ...}
Variables estáticas
• Una variable estática se define dentro de una función, por lo que tiene el mismo ámbito que una variable automática
• Las variables estáticas retienen sus valores durante toda la vida del programa
• Si se sale de una función y posteriormente se vuelve a entrar, las variables estáticas definidas dentro de ella retendrán sus valores previos
Variables estáticas#include <stdio.h>int fun (int x);
int main(){ int i, cont; for (i=1; i<=20; i++){ cont= fun(i); } printf (“total de pares %d:”, cont);}
int fun (int x){ static int cont=0; if ((i % 2) == 0){ printf(“El numero %d es par”, i); cont++ } return (cont);}
Manejo de cadenas en C
Cadenas en C
• Una cadena es un conjunto de caracteres tratados como una sola unidad
• Una cadena puede incluir letras, dígitos y varios caracteres especiales como +, -, * / y $
• En C las literales de cadena se escriben dentro de comillas dobles
Cadenas en C
• En C una cadena es un arreglo de caracteres los cuales terminan con el carácter nulo ‘\0’
• Se accede a una cadena mediante un apuntador a su primer carácter
• El valor de una cadena es la dirección del primer carácter
Inicialización de cadenas
Ejemplo: char medida[] = “chico”;• La inicialización de la cadena medida crea
un arreglo de 6 elementos, que contiene los valores ‘c’, ‘h’, ‘i’, ‘c’, ‘o’, ‘\0’
• Cuando se define un arreglo para que contenga una cadena, este debe ser lo suficientemente grande para almacenar la cadena y su carácter de terminación nulo
Funciones de manipulación de cadenas
• La biblioteca de manipulación de cadenas <string.h> proporciona muchas funciones útiles para trabajar datos de cadena
• Algunas manipulaciones disponibles son copiar, concatenar, comparar y buscar cadenas, entre otras.
Prototipo de la función Descripción de la función
char *strcpy(char *s1, const char *s2) Copia la cadena s2 dentro del arreglo s1.
Devuelve el valor de s1
char *strcat(char *s1, const char *s2) Agrega la cadena s2 al arreglo s1.
Devuelve el valor de s1
Int strcmp(char *s1, const char *s2) Compara la cadena s1 con la cadena s2
Devuelve 0, menor que 0 o mayor que 0, si s1 es igual, menor, o mayor que s2, respectivamente
int strlen(const char *s) Calcula la longitud de la cadena de caracteres
Biblioteca de manipulación de caracteres
• La biblioteca ctype.h incluye funciones que realizan evaluaciones y manipulaciones útiles en datos de tipo carácter
• Es importante recordar que en C los caracteres se manejan como enteros de un byte
Prototipo de la función Descripción de la función
int isdigit( int c) Devuelve un valor 1 si c es un dígito y 0 en caso contrario
int isalpha( int c) Devuelve un valor 1 si c es una letra y 0 en caso contrario
int isalnum( int c) Devuelve un valor 1 si c es un número o una letra y 0 en caso contrario
int tolower( int c) Devuelve c como una letra minúscula
int tolupper( int c) Devuelve c como una letra mayúscula
Apuntadores
Apuntadores
• El manejo de apuntadores es una de las características por las que el lenguaje C es muy poderoso
• Permite manejar estructuras de datos que pueden crecer y encogerse en tiempo de ejecución
• Los apuntadores son variables cuyos valores son direcciones de memoria
• Un apuntador contiene la dirección una variable que contiene un valor específico
Operador de dirección
• Cuando se declara una variable el compilador automáticamente asigna celdas de memoria y una dirección donde almacenará los datos
• La dirección de memoria de una variable puede ser determinada mediante la expresión &identificador
• El operador & es llamado operador de dirección, que proporciona la dirección del operando
Operador de indirección
• Para poder almacenar la dirección de una variable se requiere un tipo de dato especial, un apuntador
• Para declarar un apuntador se utiliza el operador * llamado operador de indirección
• Ejemplo:
int u = 3;
int *pu;
pu = &u;
F8E
3
Dirección EC7
Dirección F8E
pu
u
Operador de indirección
• El operador & sólo puede actuar sobre operandos con dirección única, como variables ordinarias o arreglos, por lo que no actúa sobre expresiones aritméticas (2 + a)
• El operador * solo puede actuar sobre operandos que sean punteros.
• Si se utiliza la expresión *identificador tendremos acceso al valor contenido dentro de la dirección de memoria que tiene almacenada la variable apuntador
Ejemplo
#include <stdio.h>int main(){ int u1, u2, v3 = 3; int *pv; u1 = 2 * (v3 + 5);
pv = &v3; u2 = 2 * (*pv + 5);
printf (“u1=%d u2= %d”, u1, u2) return (0);}
• Una referencia indirecta puede aparecer también en la parte izquierda de una instrucción de asignación
• Esto proporciona otro método para asignar un valor a una variable o a un elemento de arreglo
• Ejemplo: int v = 3; int *pv; pv = &v; *pv = 0;
Declaración de apuntadores
• Un apuntador al igual que cualquier otra variable requiere ser declarado antes de usarlo
• Sintaxis:tipo_dato *ptrvar
• Donde:– tipo_dato: es el tipo de dato al cual estará
direccionado el apuntador– ptrvar: es el nombre de la variable apuntador
• Se puede incializar el valor de un apuntador asignando un cero (0), o la constante NULL
Paso de parámetros por referencia
• Existen dos maneras de pasar argumentos a una función: por valor y por referencia
• Los argumentos en C se pasan por valor de manera automática, sin embargo a veces es necesario modificar este comportamiento
• Para pasar argumentos por valor se utiliza el operador de dirección y los apuntadores
Paso de parámetros por referencia
• Cuando un argumento se pasa por referencia la dirección de dicho argumento es enviada a la función
• El contenido de esta dirección puede ser accedido libremente dentro de la función y de la rutina de llamada
• Cualquier cambio que se realiza sobre el argumento será reconocido en ambas, la función y la rutina de llamada
Punteros y arreglos
• Cuando se utiliza el nombre de un arreglo en C, en realidad no estamos utilizando un apuntador al primer elemento del arreglo
• Si x es un arreglo unidimensional, entonces la dirección al primer elemento del arreglo se puede expresar tanto como &x[0] o simplemente como x
• Se tienen dos métodos para poder escribir la dirección de cualquier elemento del arreglo, &x[i] o (x + i)
Asignación dinámica de memoria
• Debido a que un arreglo es en realidad un apuntador al primer elemento de su estructura, se puede declarar una variable de arreglo como apuntador en vez de su forma convencional
• Una variable declarada como apuntador no tiene asignado un espacio de memoria inicialmente
Función malloc
• Se puede utilizar la función malloc para asignar memoria a una variable apuntador
• Sintaxis:void *malloc(size_t size)
• Esta función reserva el espacio size de bytes. Si se pudo asignar el espacio regresa un puntero al dicho espacio de memoria, en caso contrario regresa un apuntador nulo (NULL)
• Ejemplo:char* ptr = (char*)malloc(1000);
Función sizeof
• La función malloc requiere conocer cuantos bytes se desean reservar
• Si se quiere reservar una zona para diez enteros habrá que multiplicar diez por el tamaño de un entero
• La función sizeof retorna al tamaño en bytes de un elemento del tipo recibido como argumento
• Sintaxis:sizeof(tipo_dato);
• Ejemplo:int *x;x = (int *) malloc (10 * sizeof(int));
Punteros y arreglos multidimensionales
• Un arreglo unidimensional puede ser representado en términos de un apuntador y un desplazamiento
• Un arreglo multidimensional puede ser representado con una notación similar
Ejemplo
• Si se desea crear un arreglo bidimensional de enteros con 10 filas y 20 columnas se puede declarar como:int x[10][20];
O también:
int (*x) [20];
/*apuntador a un grupo de arreglos unidimensionales de 20 elementos cada uno*/
Ejemplo
0 1 2 3 4 5 6 7 8 9 10 ....................... 19
................
0 1 2 3 4 5 6 7 8 9 10 ....................... 19
................
0 1 2 3 4 5 6 7 8 9 10 ....................... 19
................
x
(x + 1)
(x + 9)
Primer arreglo unidimensional
Segundo arreglo unidimensional
Décimo arreglo unidimensional
Acceso a datos mediante apuntadores
• Si en el ejemplo anterior queremos tener acceso al elemento de la fila 2, columna 5, se puede especificar de la siguiente manera:x[2][5];
O también:
*(*(x+2)+5);
Apuntadores a apuntadores
• Un apuntador a un apuntador es una forma de direccionamiento indirecto múltiple, o una cadena de apuntadores
• En un apuntador a apuntador el direccionamiento es la siguiente forma:– El primer apuntador contiene la dirección del
segundo apuntador– El segundo apuntador apunta a la variable
que contiene el valor deseado
Apuntadores a apuntadoresint main(){ char ch; /* Un caracter */ char *pch; /* Un apuntador a caracter */ char **ppch; /* Un apuntador a un apuntador a
caracter */
ch = 'A'; pch = &ch; ppch = &pch; printf("%c\n",**ppch); /* muestra el valor de ch
*/
return (0);}
Apuntadores a funciones
• Anteriormente se especificó que un arreglo es en realidad la dirección de memoria al primer elemento del arreglo
• De igual manera, una función es en realidad la dirección inicial en memoria del código que realiza la tarea de la función
• Un apuntador a una función contiene la dirección de la función en memoria
Apuntadores a funciones
• Un apuntador a una función puede ser pasado como argumento a otra función
• Esto permite que una función sea transferida a otra, como si la primera función sea variable
• Sintaxis:tipo-dato (*nombre-funcion) (tipo1 arg1, ...)
Ejemplo
int procesar(int (*pf) (int a, int b));int func1(int a, int b);int func2(int a, int b);
int main (){ int i,j; i = procesar (func1); j = procesar (func2); ...}
Ejemploint procesar(int (*pf) (int a, int b)){ int a,b,c; a = 4; b= 6; c = (*pf)(a,b); return (c);}int func1(int a, int b){ int c; c = a + b; return (c);}int func2(int x, int y){ int z; z = x * y; return (z);}
ESTRUCTURAS
Estructuras
• Las estructuras son estructuras de datos cuyos elementos individuales pueden ser de tipo distinto
• Una estructura puede contener elementos enteros, flotantes y caracteres
• También puede contener apuntadores, arreglos y otras estructuras
• A los elementos individuales de una estructura se les denomina miembros
Definición de una estructura• Una estructura debe ser definida en términos de sus
miembros individuales• Sintaxis: struct marca{ miembro 1; miembro 2; ... miembro m; }Donde: struct: Es una palabra reservada miembro1,2,...,n: son declaraciones de miembros individuales
struct cuenta{ int num_cuenta; char tipo_cuenta; char nombre[80]; float saldo;}
struct cuenta cliente1, cliente2;
Acceso a miembros de una estructura
• Se utilizan dos operadores para acceder a una estructura
• El operador miembro de la estructura (.)
• El operador apuntador de la estructura (->)
Estructuras como miembro de otra estructura
• Una variable de estructura puede ser definida como miembro de otra estructura
• En tales situaciones la declaración de la estructura interna debe aparecer antes que la declaración de la estructura externa
• Para acceder a un miembro de una estructura definida dentro de otra se sigue el siguiente formatovariable.miembro.submiembro
Ejemplostruct fecha{ int mes; int dia; int anio;}
struct cuenta{ int num_cuenta; char tipo_cuenta; char nombre[80]; float saldo; struct fecha ultimopago;}
struct cuenta cliente;//cliente.ultimopago.mes
Inicialización de estructuras
• A los miembros de una variable de estructura se les pueden asignar valores iniciales
• Los valores iniciales deben aparecer en el orden en que serán asignados a sus correspondientes miembros de a estructura, encerrados entre llaves y separados por comas
struct cuenta cliente = {123, ‘R’, “Pedro Perez”, 500.50, 3, 11, 2009};
Arreglos de estructuras
• Es posible definir arreglos de estructuras
• En este tipo de arreglos cada elemento es un estructura
• Ejemplo:
struct cuenta clientes[10];• Para tener acceso a un elemento de este
arreglo:clientes[0].saldo = 130.5;
Operaciones sobre estructuras completas
• En algunas de las versiones más antiguas de C, las estructuras debían ser procesadas miembro por miembro
• Debido a esta restricción, la única operación permisible con la estructura completa es tomar su dirección
• La mayoría de las nuevas versiones (ANSI) permiten asignar una estructura completa a otra siempre que estas tengan la misma composicióncliente1 = cliente2;
Operaciones sobre estructuras completas
• Una estructura completa se puede pasar como parámetro a una función
• Las versiones antiguas de C solo permiten pasar estructuras como apuntadores
• El estándar ANSI pasar estructuras completas
Paso de estructuras a una función
• Se pueden transferir los miembros individuales o la estructura completa a una función
• Los miembros individuales de una estructura se pueden pasar a una función como argumento y ser devueltos mediante la instrucción return
Ejemplo
void asignafecha (int *m, int *d, int *a){ m = 11; d = 6; a = 2009;}
asignafecha(&cliente1.ultimopago.mes, &cliente1.ultimopago.dia, &cliente1.ultimopago.anio);
Paso de estructuras a una función
• Se puede pasar una estructura completa como argumento a una función de dos maneras
• Mediante un apuntador a la estructura
• O enviando la variable de tipo estructura directamente
Apuntadores a estructuras
• Cuando se envía un apuntador a estructura esta se pasa por referencia
• Para acceder a un miembro de la variable estructura enviada como apuntador se debe utilizar el operador flecha (->)
• Un apuntador a una estructura puede ser devuelto desde una función a la parte del programa que hizo la llamada
Ejemplo
void fun(struct cuenta *pc){ pc->nombre = “teresa”; pc->num_cuenta = 123;}
void main(){ struct cuenta cliente1; fun(&cliente1);}
• La mayoría de las versiones nuevas de C (ANSI) permiten que una estructura completa sea transferida directamente a una función y devuelta con return
• Cuando se pasa una estructura directamente a una función, la transferencia es por valor y no por referencia
Tipos de datos definidos por el usuario
• La instrucción typedef permite definir nuevos tipos de datos que sean equivalentes a los tipos de datos existentes
• Una vez definido el nuevo tipo de datos, las variables pueden ser declaradas en términos de este tipo de dato
• Sintaxis:typedef tipo nuevo-tipo;
Ejemplos
typedef int edad;edad hombre, mujer;
typedef float altura[100];altura hombres, mujeres;
typedef char nombre[50];nombre emp1, emp2;
Tipos de datos definidos por el usuario
• La instrucción typedef es útil cuando se definen estructuras ya que se elimina la necesidad de escribir repetidamente struct nombre_estructura cuando se referencia una estructura
• La instrucción typedef puede ser usada repetidamente para definir un tipo de dato en términos de otros tipos de datos definidos por el usuario
Ejemplo
typedef struct{ int no_cuenta; char tipo_cuenta; char nombre[80]; float saldo;} registro;
registro cliente1, cliente2;
Estructuras autorreferenciadas
• En ocasiones es necesario incluir dentro de una estructura un miembro que sea apuntador a este tipo de estructura
• Estas estructuradas son conocidas como autorreferenciadas
Ejemplo
struct lista{
int valor;
struct lista *sig;
}
Práctica
• Se requiere un programa para llevar el control de las multas de tránsito
• El programa debe realizar las siguientes funciones– Registrar multa– Pagar multa– Buscar multa– Reporte de multas
Práctica
• Los datos que se deben capturar son:– Numero de multa– Numero de licencia– Nombre– Importe– Estado de la multa
• 0 es pendiente• 1 es pagada
Uniones
• Las uniones, al igual que las estructuras, contienen miembros cuyos tipos de datos pueden ser diferentes
• A diferencia de las estructuras, los miembros que componen una unión comparten la misma área de almacenamiento en memoria
• Las uniones son útiles para aplicaciones que involucren múltiples miembros donde no se necesitan asignar valores a todos los miembros a la vez
Uniones
• La reserva de memoria requerida para almacenar miembros cuyos tipos de datos son diferentes es manejada automáticamente por el compilador
• Es necesario que el usuario conserve una pista del tipo de información que está almacenada en cada momento
• Un intento de acceso al tipo de información equivocado producirá resultados sin sentido
Uniones
• Sintaxisunion identificador{
miembro 1;
miembro 2;
...
miembro n;
};
Uniones
• Es importante señalar que solo uno de los miembros de una unión puede tener un valor asignado en cada momento
• El tamaño de la variable unión la define el tipo de dato más grande
• Para tener acceso a un miembro de la unión se sigue la misma sintaxis que en las estructuras
Enumeraciones
• El lenguaje C proporciona otra forma de definir un tipo de dato propio conocido como enumeración
• Sus miembros son constantes que se escriben como identificadores, pero que toman valores enteros con signo
• Estas constantes representan valores que pueden ser asignados a variables de enumeración
Enumeraciones
• Sintaxis:enum identificador {miembro 1, miembro 2, ..., miembro m}
• Los nombres de los miembros deben ser todos diferentes
Ejemplo
enum colores {negro, azul, cian, verde, magenta, rojo, blanco, amarillo};
colores color1, color2;
• Las constantes de enumeración tienen automáticamente asignados valores enteros, empezando por cero para la primera constante e incrementando en uno para las sucesivas
Ejemplo
• Las asignaciones automáticas pueden ser modificadas dentro de la definición de la enumeración
enum colores{negro = -1, azul, cian, verde, magenta, rojo = 2, blanco, amarillo};
negro -1
azul 0
cian 1
verde 2
magenta 3
rojo 2
blanco 3
amarillo 4
Enumeraciones
• Las variables enumeración pueden ser tratadas de la misma manera que otras variables enteras
• Se les puede asignar nuevos valores, compararse, etc.
• Generalmente serán usadas internamente para indicar condiciones que pueden surgir en el programa
Manejo de fecha y hora
• El lenguaje C cuenta con algunas funciones para el manejo de fecha y hora
• Estas funciones están contenidas en la biblioteca time.h
• También proporciona algunas estructuras para manejar tipos de datos fecha y hora
Manejo de fecha y hora
• Tipos de datos:– time_t: tipo de dato definido para almacenar
valores de fecha y hora del sistema. El tipo de dato es un valor aritmético, pero no se especifica ningún tipo particular, rango o codificación
– struct time: Estructura que contiene un fecha y hora divido en sus componentes
Manejo de fecha y hora
• Funciones:– time(time_t t). Obtiene el tiempo transcurrido en
segundos desde el 1 de enero de 1970 hasta la fecha actual
– strftime(char * ptr, size_t maxsize, const char * format, const struct tm * timeptr). Convierte una variable time_t a una cadena con un formato especificado
– localtime ( const time_t * timer ). Utiliza el tiempo almacenado en la variable timer para pasarlo a una estructura time
Especificador Descripción Ejemplo
%a Día de la semana abreviado Thu
%A Día de la semana completo Thursday
%b Mes abreviado Jan
%B Mes completo January
%c Fecha y hora completa Thu Aug 23 14:55:02 2001
%d Día del mes (01-31) 23
%H Hora en formato de 24H 14
%I Hora en formato de 12H 02
%j Dia del año (01-365) 235
%m Mes como número decimal(01-12)
08
%M Minutos (00-59) 55
%p AM o PM PM
%S Segundos (00-59) 02
%w Día de la semana (0-6) 4
%X Representación de hora 14:55:02
%Y Año 2001
Recursividad
Recursividad
• Generalmente existen dos formas de resolver un problema: de manera iterativa, o de forma recursiva
• La recursividad es un proceso mediante el cual una función se llama a si misma de forma repetida, hasta que se satisface alguna condición determinada
• El proceso se utiliza para cálculos repetitivos en los que cada acción se determina en función de un resultado anterior
Recursividad
• Se deben cumplir dos condiciones para que un problema pueda ser resuelto mediante recursividad:
1. El problema debe escribirse en forma recursiva
2. Se debe incluir una condición de fin, comúnmente denominada caso base
Ejemplo
• Función factorial. Dado un entero positivo n, se define el factorial de n como el producto de todos los enteros entre n y 1
• Factorial de 5 = 5*4*3*2*1=120• Factorial de 3 = 3*2*1• Algoritmo: prod=1; for(x=n;x>0;x--) prod= prod*x; return (prod);
Ejemplo
• En matemáticas se utiliza el símbolo de admiración (!) para representar la función factorial
• 0! = 0
• 1! = 1
• 2!= 2 * 1
• 3!=3*2*1
• 4!=4*3*2*1
Ejemplo
• Otra forma de definir el factorial es:
• 2! = 2 * 1!
• 3 = 3 * 2!
• 4! = 4 * 3!
• 5! = 5 * 4!
• La definición anterior tiene la característica de que la función factorial se define en términos de si misma
• La definición que describe un objeto en términos de un caso más simple de si mismo se llama definición recursiva
Factorial recursivo
int factorial(int n){
if (n<=1)
return (1);
else
return (n * factorial(n-1));
}
Pila de recursividad
4 * *n p f
3 * *
4 3 *n p f
2 * *
3 2 *
4 3 *n p f
1 * *
2 1 *
3 2 *
4 3 *n p f
Pila de recursividad
2 1 1
3 2 *
4 3 *n p f
3 2 2
4 3 *n p f
4 3 6n p f
Ejemplos
• Multiplicación de números naturales:6 * 3 = 6 * 2 + 6 = 6* 1 + 6 + 6 = 6 + 6 + 6 = 18
int mult(int a, int b){
if (b == 1)
return a;
else
return (mult (a, b-1) + a);
}
Propiedades de definiciones recursivas
• Un algoritmo recursivo no debe generar una secuencia infinita de llamadas sobre si mismo
• Siempre debe incluirse una forma de salir de la secuencia de llamadas recursivas
• Cualquier algoritmo recursivo debe terminar por reducirse a alguna manipulación de uno o más casos simples no recursivos
Propiedades de definiciones recursivas
• Finalmente es importante aclarar que generalmente una implementación no recursiva es más eficiente en términos de uso de memoria y velocidad de ejecución que una versión recursiva
Archivos
Archivos
• El almacenamiento de los datos en variables y arreglos es temporal
• Todos esos datos se pierden cuando se termina el programa
• Los archivos se utilizan para retener permanentemente grandes cantidades de datos
• Los archivos se almacenan en dispositivos secundarios
Archivos
• Un archivo es una colección de registros lógicamente relacionados e identificados bajo un único nombre
• Un registro es una estructura de campos o de elementos de información lógicamente relacionados
Archivos
1234 Juan Flores 5544332211
archivo
registro
campo
Archivos
• Un registro en un archivo usualmente está compuesto por los miembros de un estructura
• Para facilitar la recuperación de registros específicos de un archivo, se usa un campo como clave del registro
Archivos y flujos
• En el lenguaje C un archivo se considera un flujo secuencial de bytes
• Cada archivo termina con una marca de fin de archivo (EOF)
• Cuando se abre un archivo se le asocia un flujo
• Los flujos proporcionan canales de comunicación entre los archivos y los programas
• Para trabajar con un archivo es necesario establecer un área de buffer
• El área de buffer se establece mediante una estructura especial FILE y un apuntador al inicio de esta estructura
FILE *pf;• La estructura está definida dentro de la
biblioteca stdio.h
Apertura y cierre de un archivo
• Un archivo debe ser abierto antes de ser creado o procesado
• Esto asocia el nombre del archivo con el área de buffer
• También se especifica cómo se va a usar el archivo, de sólo lectura, sólo escritura, o lectura/escritura
Apertura y cierre de un archivo
• Para abrir un archivo se usa la función de biblioteca fopen
• Sintaxis:pf = fopen(nombre_archivo, tipo_archivo)
• Para cerrar un archivo se usa la función fclose
• Sintaxis:
fclose(apuntador_archivo)
Apertura y cierre de un archivo
• Ejemplo:
#include <stdio.h>
FILE *fp;
fp = fopen(“archivo.txt”, “w”);
.....
fclose(fp);
Especificaciones de tipo de archivoModo Descripción
r Abre un archivo existente de lectura
w Crea un archivo para escritura. Si el archivo ya existe, descarta el contenido actual (destruye el archivo)
a agrega; abre o crea un archivo para escritura al final del archivo
r+ Abre un archivo existente para actualización (lectura y escritura)
w+ Crea un archivo para actualización. Si el archivo ya existe, descarta el contenido actual
a+ Agrega; abre o crea un archivo para actualización; la escritura se hace al final del archivo
rb Abre un archivo existente para lectura en modo binario
wb Crea un archivo para escritura en modo binario. Si el archivo ya existe, descarta el contenido actual
ab Agrega; abre o crea un archivo para escritura al final del archivo en modo binario
rb+ Abre un archivo existente para actualización (lectura y escritura) en modo binario
wb+ Crea un archivo para actualización en modo binario. Si el archivo ya existe, descarta el contenido actual
ab+ Agrega; abre o crea un archivo para actualización en modo binario; la escritura se hace al final del archivo
Archivos secuenciales y aleatorios
• En C se pueden manejar dos tipos de archivos: secuenciales y de acceso aleatorio
• Los registros de un archivo secuencial se escriben y leen uno tras de otro; es decir no se puede tener acceso a un registro específico de manera directa
• Un archivo de acceso aleatorio permite tener acceso a un registro específico
Archivos secuenciales
• Una vez abierto el archivo podemos leer o escribir en el
• Para leer un archivo se utiliza la instrucción fscanf
• La función fscanf es equivalente a la función scanf, con la excepción de que fscanf recibe como argumento el apuntador al archivo desde el que se leen los datos
Lectura
• Ejemplo:
FILE *pf;
if((pf =fopen(“clientes.txt”, “r”))==NULL)
fscanf(pf, “%d%s%f”, &cuenta, nombre, &saldo);
• Cada vez que se ejecuta la instrucción fscanf el programa lee otro registro del archivo
Escritura
• La función para escribir en un archivo es fprintf
• La función fprintf es equivalente a la función printf, con la excepción de que fprintf recibe como argumento el apuntador al archivo al que se van a escribir los datos
Escritura
FILE *pf;
if((pf =fopen(“clientes.txt”, “w”))==NULL)
printf(“nombre:”);
scanf(“%s”, &nombre);
fprintf(pf, “%s”, nombre);
• Cada vez que se ejecuta la instrucción fprintf el programa escribe en el siguiente registro del archivo
top related