Lenguajes de programacin

Post on 23-Jun-2015

1.709 views 8 download

Transcript of Lenguajes de programacin

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