Introducción al lenguaje C

Anuncio
Centro de Investigación y de Estudios
Avanzados
Herramientas de programación
Ivan López Arévalo
[email protected]
17-21 de Julio de 2006
Objectivo: 1­ Conocer herramientas básicas de programación en ambiente Linux
2­ Conseguir una visión general de programación (lenguaje C)
Linux
Herramientas
Windows
Lenguaje C
Consideraciones
teoría y práctica
Conocimientos YA ADQUIRIDOS
Y
Capacidad de razonamiento y aprendizaje
1. Introducción
2. Herramientas de programación en Linux
2.1 Editor vi
2.2 Compilador gcc
2.3 Utilidad make
2.4 Utilidad man
3. Breve introducción al Lenguaje C 3.1 Tipos básicos y funciones
3.2 Operadores
3.3 Funciones
3.4 Control de flujo
3.5 Vectores
3.6 Registro
3.7 Ámbito de variables y funciones
3.8 Punteros
3.9 Registros
Introducción
Lenguajes de programación
Según el tipo de programación
●
Procedimentales, OO (C, C++, Java, Smalltalk, etc)
●
Declarativos (Prolog, LISP, CLISP, etc)
Según su forma de compilación/ejecución
●
Compilados (C, C++, Pascal, etc)
●
Interpretados (Basic, Java)
Lenguajes de programación Según el conjunto de instrucciones
●
Lenguaje máquina
●
Lenguaje ensamblador
●
Lenguaje de alto nivel
Desarrollo de aplicaciones
Análisis (Especificar lo que se desea)
●
Diseño (Decidir la estructura de datos y algoritmo que han de resolver el problema)
●
Codificación (Implementar el algoritmo usando un lenguaje de programación)
●
Pruebas (Validar que el programa obtenido es la solución al problema planteado)
●
Mantenimento
●
Lenguaje C
●
●
●
●
●
●
●
De propósito general, pequeño y sencillo pero muy potente y de aplicación ilimitada
No está ligado a ningún sistema operativo ni a ninguna máquina concreta
Permite escribir compiladores y sistemas operativos (programación de sistemas)
No mecanismos para tipos de datos no básicos
No mecanismos de almacenamiento de datos que no sea el estático No mecanismos de entrada ni salida
ANSI C
Creación de un programa en C
main()
{
}
­­­­­­­­­­­­­­­­­­­­­­­­­­­
#include <stdio.h>
main()
{
printf("Hola a todos!\n");
}
Modularización de un programa C A menor tamaño la compilación es más rápida
Mayor legibilidad y estructuración del programa
Los módulos se combinan con las librerías necesarias para formar el programa en su versión ejecutable.
La compilación, enlazado y ejecución de un programa dependen del sistema operativo. Por ejemplo
cc prog
<­­ compilación
cc modulo1, modulo2
<­­ compilación
link prog, modulo1, modulo2 <­­ enlazado
prog
<­­ ejecución
fuente prog.c
fuente comp1.c
fuente comp2.c
cc prog
cc comp1
cc comp2
objeto prog.obj
objeto comp1.obj
objeto comp2.obj
link prog, comp1, comp2
ejecutable prog.exe o prog.out
librería C
Mecánica de Codificación
Edición
Compilación
ANSI C (C estándar)
Ejecución
Herramientas de programación
Editores
vi
emacs
gedit
kwrite
kate
... ... ...
... ... ...
Compilador
gcc
Utilidades
make
man
editor vi
make man gcc
Editor vi
editor estándar de UNIX
no existen menús, existen órdenes
modos
inserción: teclear texto
comandos: guardar, salir, copiar, mover, etc.
tecla "ESC" para modo órdenes
tecla "i" para modo inserción
Para comandos se emplea “:” + comando
Comandos básicos (sin usar “:”)
Insertar texto i, a Movimientos teclas de cursor o h, l, k, j
Borrar caracter x, backspace, supr
Usando “:”
Salir sin grabar los cambios
Salir grabando los cambios
Guardar los cambios actuales
Guardar como archivo
Insertar desde el cursor archivo
Editar archivo
q
wq (aconsejable)
w
w archivo
r archivo
e archivo
Moverse hasta el fin de la línea
Moverse hasta el principio de la línea
Moverse hasta la siguiente palabra
Moverse hasta la anterior palabra
Moverse a la línea n***
Moverse hasta el final de la siguiente palabra
Moverse hasta el final de la siguiente palabra* Encontrar el siguiente caracter c en la línea actual
Encontrar el anterior caracter c en la línea actual
Moverse hasta la siguiente frase
Moverse hasta la anterior frase
Moverse hasta el anterior párrafo
Moverse hasta el siguiente párrafo
Moverse hasta la parte superior de la pantalla
Moverse hasta la parte media de la pantalla
Moverse hasta la parte inferior de la pantalla
L
Avanzar página
Retroceder página
$
0
w
b
nG
e
E
fc
Fc
(
)
{
}
H
M
^F
^B
Insertar después del caracter actual
a
Insertar al final de la línea
Añadir línea por debajo e insertar texto
Añadir línea por arriba e insertar texto
A
o
O
Borrar caracter
Borrar palabra Copiar linea Copiar palabra
Pegar
x
dw ­ dnw
yy
yw ­ ynw
p
Deshacer el último cambio
Buscar texto
Repetir última búsqueda
Repetir última búsqueda hacia abajo
Repetir última búsqueda hacia arriba
Repetir último cambio
u
/texto
n
/
?
.
IDE's Integrated Development Environment's
(“Entornos” integrados de programación) ­ personalizar
●
emacs
●
xemacs
●
nedit
●
jedit
●
elvis
●
crimson
●
cute
●
andjunta
●
MinGW
●
Kdevelop
Compilador
GCC (GNU Compiler Collection)
Conjunto de compiladores creados por el proyecto GNU
GCC es software libre (licencia GPL)
GCC significaba GNU C Compiler
Casi todo GCC está escrito en C
Lenguajes soportados
Ada (GNAT)
C (GCC)
C++ (G++)
Fortran (GFortran)
Java (GCJ)
Objective C
lcc para windows
GCC
Front ends para Pascal, Modula­2, Modula­3, Mercury, VHDL y PL/I
Arquitecturas
Alpha
ARM
H8/300
System/370, System 390
x86 y x86­64
IA­64 "Itanium"
Motorola 68000
Motorola 88000
MIPS
PA­RISC
PDP­11
PowerPC
SuperH
SPARC
VAX
GCC uso (preprocesamiento, compilación, ensamblado y enlazado)
gcc [ opción | archivo ]
gcc hola.c compila "hola.c" y genera el ejecutable a.out
gcc ­o hola hola.c
compila "hola.c" y genera ejecutable hola
gcc ­c hola.c
compila "hola.c" pero no genera el
ejecutable ­­> código objeto (hola.o)
gcc ­c ­o objeto.o hola.c compila "hola.c" y genera código objeto (objeto.o)
gcc ­o resulta.o hola.c adicional.c otromas.c
[host sources]$ gcc ­o ~/tmp/sources/execs/prueba.exe prueba.c
[host sources]$ gcc ­o execs/prueba.exe prueba.c
[host sources]$ ./execs/prueba.exe
Hola mundo
­Iruta
especifica la ruta hacia el directorio donde se encuentran los archivos marcados para incluir en el programa fuente. gcc ­I/usr/include fuente.c
­Lruta
especifica la ruta hacia el directorio donde se encuentran los archivos de biblioteca con el código objeto de las funciones referenciadas en el programa fuente. gcc ­L/usr/lib fuente.c
­Wall muestra todos los mensajes de error y advertencia del compilador
make
●
Herramienta para actualizar, en forma optimizada y automática, los archivos fuente que integran un proyecto de software.
●
Emplea un archivo de texto llamado makefile o Makefile (reglas)
●
Proyectos con diversos archivos fuentes
●
Recompila sólo partes que han sido modificadas y enlaza los módulos en código objeto construyendo el ejecutable. ●
Es independiente del lenguaje de programación.
●
Puede manejar cualquier conjunto de archivos en los cuales haya archivos que deban actualizarse
●
Control explícito de dependencias
Reglas make
destino : requisito ... requisitoN
comando
...
destino ­ el nombre del archivo a crear, un ejecutble o un archivo objeto (.o)
requisito ­ el nombre de un archivo del cual depende el destino a crear.
comando es una acción a realizar.
●
debe comenzar con TABULADOR, no sirven los espacios. ●
es un comando normal ejecutable desde el shell
legibilidad
\ es el caracter de continuación de línea
# indica comentario
# makefile ejemplo para tres archivos y una libreria
ejecutable: main.o fuenteA.o fuenteB.o fuenteC.o
gcc ­o ejecutable main.o fuenteA.o fuenteB.o getch.o
main.o: main.c libreria.h
gcc ­c main.c
fuenteA.o: fuenteA.c libreria.h
gcc ­c fuenteA.c
fuenteB.o: fuenteB.c
gcc ­c fuenteB.c
fuenteC.o: fuenteC.c libreria.h
gcc ­c fuenteC.c
elimina_todo_recompilar:
rm ejecutable \
main.o fuenteA.o fuenteB.o fuenteC.o
$ ./polaca <­­ ejecutar aplicacion
$ make clean <­­ eliminar todo lo generado y empezar de cero
# makefile ejemplo MODIFICADO
CC = gcc
ARCHIVOS = fuenteA.o fuenteB.o fuenteC.o ejecutable: main.o $(ARCHIVOS) $(CC) ­o ejecutable main.o $(ARCHIVOS)
main.o: main.c libreria.h
$(CC) ­c main.c
fuenteA.o: fuenteA.c libreria.h
$(CC) ­c fuenteA.c
fuenteB.o: fuenteB.c
$(CC) ­c fuenteB.c
fuenteC.o: fuenteC.c libreria.h
$(CC) ­c fuenteC.c
elimina_todo_recompilar:
rm ejecutable \
main.o fuenteA.o fuenteB.o fuenteC.o
destino
requisito
destino
destino
requisito
requisito
regla
destino
regla
regla
destino
regla
destino
regla
regla
destino
requisito
regla
man (manual)
comando que informa sobre otros comandos
útil para consultas rápidas (desde consola)
La ayuda está estructurada en las siguientes secciones:
1. Programas ejecutables o comandos del usuario.
2. Llamadas al sistema (programación).
3. Librerías (programación).
4. Archivos del sistema (normalmente relativos a dispositivos).
5. Formatos de fichero y convenciones.
6. Juegos.
7. Macro paquetes y convenciones.
8. Administración del sistema.
9. Rutinas del Kernel (sección no estándar).
Orden de búsqueda secuencial en secciones
man [no. seccion] [mandato]
man 3 printf
man 1 printf
Ayuda del comando man de la sección 7:
man 7 man
Consultar TODA la ayuda relativa a man:
man ­a man
Órdenes
Búsqueda de cadenas (tecla "/" + cadena).
Avance y retroceso de pagina
Teclas de dirección
Salir "q"
Recursos y comandos básicos Linux
ivanlopez.cjb.net/repositorio.html
Introducción al Lenguaje C
Tipos básicos y variables
caracteres (char) ­­ (normalmente 8 bits)
números enteros short ­­ entero corto con signo (normalmente 16 bits)
int ­­ entero con signo (depende de la implementación)
long ­­ entero largo con signo (normalmente 32 bits)
números de punto flotante
float – flotante simple (normalmente 32 bits)
double
Variable
Una variable es un área en memoria que tiene un nombre y un tipo asociado. Es obligatorio declarar las variables antes de usarlas. Declaración: tipo_variablenombre ;
int i; // declaracion de un entero char letra; // declaracion de un caracter
Comentarios:
// comentario para una linea
/* comentario para varias lineas */ Una variable o expresión de un tipo se puede convertir explícitamente a otro tipo, anteponiéndole el tipo entre paréntesis. Se le llama casting
void cambio_tipo (void) {
float a;
int b;
b = 10;
a = 0.5;
if ( a <= (float) b )
printf(“El valor de a es menor igual que el valor de b”);
}
float c = a + (float) b
Operadores
lógicos y booleanos
<<, >> rotación de bits a la derecha, izquierda
& AND booleano
| OR booleano
^ EXOR booleano
~ complemento a 1
! complemento a 2, NOT lógico
==, != igualdad, desigualdad
&&, || AND, OR lógico
<, <= menor, menor o igual
>, >= mayor, mayor o igual
Operadores
numéricos
+, ­ suma, resta
++, ­­ incremento, decremento
*, /, % multiplicación, división, módulo
operadores aritméticos con asignación: +=
igual a la suma de
­=
igual a la resta de
*=
igual a la multiplicación de
/=
igual a la división de
<e> ? <x> : <y>. Se evalúa si e entonces x; si no, y
Funciones
En C toda la lógica de programación (algoritmos) está agrupada en funciones. Al menos existe la función main()
se declara con el nombre de la función precedido del tipo de valor que retorna,
●
recibe parámetros o argumentos (opcionalmente), ●
contiene sentencias o instrucciones para realizar algo (opcionalmente) y ●
devuelve un valor de algún tipo conocido (opcionalmente).
●
Los paréntesis ­de argumentos­ son obligatorios.
●
Funciones
La sintaxis global es:
Tipo_Valor_devuelto nombre_función (lista_argumentos){
bloque_de_codigo;
}
int sumaEnteros ( int a, int b ) {
int c = a + b;
return c;
}
La claúsula return se usa para finalizar el método devolviendo algún valor o el control de flujo.
Funciones void
El tipo_dato de retorno es opcional. Si es necesario devuelva un valor se declara el tipo que devuelve. Si no necesita ningún valor el tipo_dato devuelto es void. void haceAlgo() {
. . .
}
No es necesaria la cláusula return. . . . .
haceAlgo(); // ningún valor no se asigna a ninguna variable. // (No hay nada que asignar).
int calculo_A (int param_1, int param_2){
... ... ...
}
int calculo_A (int param_1, int param_2){
... ... ...
}
void saludo(){
printf(“Bienvenidos de nuevo al lenguaje C”);
}
main(){
int var_A=calculo_A(1, 2);
int var_B=calculo_B(3, 4) * 1/2;
saludo();
return 0;
}
#include <....>
#include <....>
#define ­­­­­­­
#define ­­­­­­­
... ... ...
... ... ...
main(){
}
Todas las líneas que comienzan con el símbolo “#” indican una directiva del precompilador.
include incluye archivos en el codigo fuente define sustituye texto del codigo fuente con el definido
Se debe tener muy en cuenta que en C todos los argumentos son pasados 'por valor'. No existe el concepto de paso de parámetros 'por variable' o 'por referencia'.
int incr ( int v ){
return v + 1;
}
main(){
int a, b;
b = 3;
a = incr(b);
}
*******************************************
a = 4 mientras que
b = 3 no ha cambiado después de la llamada
*******************************************
Control de flujo
if () { }
else { }
int cero ( double a ){
if ( a == 0.0 )
return (TRUE);
else
return (FALSE);
}
Si la expresión no es condicional y es aritmética se considera falso si vale 0; y si no, verdadero.
Opciones múltiples
switch (valor) {
case valor1: <sentencias>; ... break;
case valor2: <sentencias>; ... break;
case valor3: case valor4: ...
default: <sentencias>
}
while (<expresión>){
<sentencias>
}
do {
<s>
}
while ( <expresión> );
for ( <inicialización>; <expresión>; <modificación> ){
<sentencias>
}
Vectores
Porción de memoria para almacenar un grupo de elementos del mismo tipo tipo nombre [tamaño];
int f, modulo[52];
for ( f = 0; f < 52; f++ )
modulo[f] = 0;
...
}
char vocal[5] = { 'a', 'e', 'i', 'o', 'u' };
int dimensiones[25][80][2];
char nombre[60], direccion[80];
Los elementos de un vector son accedidos por índices que van desde 0 hasta N­1 para un vector de N elementos. Tamaño con sizeof()
Registros
Agrupa distintos tipos de datos en una misma entidad. struct nombre { lista de declaraciones };
Los elementos (campos) pueden ser tipos básicos u otros registros. struct planeta {
struct 3D r, v, a;
double masa;
char nom[10];
};
struct 3D {
double x,y,z;
};
Registros
Los campos de cada registro son accesibles mediante el nombre del registro seguido de punto y el nombre del campo
venus.r.x = 1.0;
Cada campo se comporta como lo hace su tipo básico. typedef struct planeta PLANETA;
PLANETA mercurio, venus, tierra, marte;
PLANETA mercurio = { { 0.350, 0, 0 },
{ 0, 0, 0 },
{ 0, 0, 0 },
struct planeta {
100, "Mercurio" } };
struct 3D r, v, a;
double masa;
char nom[10];
};
struct 3D {
double x,y,z;
};
Ambito de funciones y variables
locales, globales, estáticas y constantes
locales y globales
#include<stdio.h>
int x, y; // globales
int calculo_A( int a, int b ){a = b*x}
int calculo_B( int c, int d ){d = c*y}
main(){
int a, b; // locales
a=calculo_A + calculo_B / x;
b=calculo_A + calculo_B / y;
}
estáticas
locales: Accesibles por la misma función y conservan su valor a través de llamadas sucesivas.
globales: No visibles desde otro fuente. Lo mismo para funciones.
void contar (){
static long cuenta = 0;
cuenta++;
printf("Llamada %ld veces\n", cuenta );
}
main(){
int i;
for (i=0; i < 5; i++){
contar();
}
}
Llamada 1 veces
Llamada 2 veces
Llamada 3 veces
Llamada 4 veces
Llamada 5 veces
static void saludoInicial(){
printf("Hola mundo\n"); }
Archivo fuente A
************************
#include<stdio.h>
main(){
saludoInicial();
printf("Otro mensaje\n");
}
Archivo fuente B
Hola mundo
Otro mensaje
**********************
undefined reference to 'saludoInicial'
const
Define variables cuyo valor debe permanecer constante durante toda la ejecución del programa. Se puede usar con argumentos de funciones.
const double pi = 3.14159;
double lcercle ( const double r ){
return 2.0 * pi * r;
}
Punteros
●
Variable que permite acceder y manipular otras variables mediante su dirección de memoria
●
Son el tipo más potente y la clave del éxito del lenguaje
●
Permiten que una función reciba y cambie el valor de una variable
variable vector de char's
Lorenzo Ávila
puntero
57a@25Q$284
Declaración
float *numero_flotante;
REG_DIMENSIONES *registro_dimension;
char *caracter;
Operaciones básicas
●
manipular un puntero (como variable) ­­> su nombre
●
acceder a la variable a la que apunta ­­> *nombre (indirección)
●
asignar/manipular dirección ­­> & (dirección de)
void operaciones(){
La edad es 50
long edad;
La edad es 25
long *p;
p = &edad;
edad = 50;
printf("La edad es %ld\n", edad );
*p = *p / 2;
printf("La edad es %ld\n", edad );
}
void imprimir_string ( char string[] ){
char *p;
for ( p = string; *p != '\0'; p++ )
imprimir_char(*p);
}
Punteros con registros
“­>” en lugar de punto. Ej. Sea p un puntero a un tipo PLANETA, y queremos conocer su masa:
p­>masa
#define NUM_PLANETAS
static PLANETA Ssolar[NUM_PLANETAS];
void init_SistemaSolar ( void ){
PLANETA *p;
for ( p = SSolar; p < SSolar[NUM_PLANETAS]; p++ )
init_planeta(p); // asigna datos iniciales
}
void init_planeta ( PLANETA *p ){
p­>masa = 0;
p­>nom = "";
init_co(&(p­>r));
init_co(&(p­>v));
init_co(&(p­>a));
}
void init_co ( struct coords *c ){
c­>x = c­>y = c­>z = 0;
}
Punteros como parámetros
void swap ( int *x, int *y ){
int tmp;
tmp = *x;
*x = *y;
*y = tmp;
}
void intercambio (){
int a, b;
a = 1;
b = 2;
swap( &a, &b );
printf(" a = %d b = %d\n", a, b );
}
Resumen de punteros
int f1();
función que devuelve un entero
int *p1;
puntero a entero
int *f2();
función que devuelve un puntero a entero
int (*pf)(int);
puntero a función que toma y devuelve un entero
int (*pf2)(int *pi); puntero a función que toma un puntero a entero y devuelve un entero
int a[3];
vector de tres enteros
int *ap[3];
vector de tres punteros a entero
int *(ap[3]);
vector de tres punteros a entero
int (*pa)[3];
puntero a vector de tres enteros
int (*apf[5])(int *pi);
vector de 5 punteros a función que toman un puntero a entero y devuelven un entero
Archivos
Todas las operaciones se realizan a través de streams. Un stream está formado por una serie ordenada de bytes. Leer o escribir de un archivo implica leer o escribir del stream. Se debe asociar un stream con un archivo, mediante un puntero a una estructura FILE. Este puntero se inicializa con la llamada a la función fopen() para abrir un archivo.
Streams comunes de consola:
stdin ­­> scanf()
stdout ­­> printf()
stderr ­­> archivo log de errores
text stream: serie de lineas de texto acabadas con un caracter newline. binario stream: colección de bytes sin ninguna estructura especial.
Manejo de archivos ­­> consumo de recursos ­­> BUFFERS
RAM
buffer
sistema de
archivos
operaciones (adición, archivo
modificación, eliminación, etc.
acceso secuencial o aleatorio
stdio.h define los prototipos de todas las funciones, la declaración de la estructura FILE y algunas macros y definiciones:
EOF: es el valor devuelto cuando se llega al final de archivo
Pasos: abrir, realizar el tratamiento y cerrar. fopen(nom_archivo, modo_acceso)
fclose ( puntero_archivo )
abrir un archivo
cerrar un archivo
Los modos de acceso para streams de texto son los siguientes:
r
w
a
r+
w+
a+
Abre un archivo existente para lectura
Crea un nuevo archivo para escribir
Abre un archivo que existente para añadir información al final
Abre un archivo que existente para actualizarlo Crea un nuevo archivo para actualizarlo, si existe lo sobreescribe.
Abre un fichero para añadir información al final. Si no existe lo crea.
fgetc y fputc ­­> manejo de caracteres
int fgetc ( FILE *stream ); lee el siguiente caracter del stream y los devuelve convertido a entero sin signo. Si no hay caracter devuelve EOF
int fputc ( int c, FILE *stream ); devuelve el propio carácter si no hay error. Si lo hay, devuelve el carácter EOF
feof() que devuelve cero si no se ha llegado al final del stream
while ( !feof(infile))
fputc ( fgetc ( infile ), outfile );
fgets y fputs ­­ manejo de líneas
char *fgets ( char *s, int n, FILE *stream ); lee caracteres del stream hasta que encuentra un final de línea o se lee el carácter n­1. Mantiene el carácter \n en el string y añade el carácter \0. Devuelve la dirección del string o NULL si se produce algún error.
int fputs ( const char *s, FILE *stream ); fputs pone el string en el stream, no añade ni elimina caracteres \n y no copia la marca de final de string \0.
fread y fwrite ­­> manejo de bloques (array, struct, tec). Se especifica el tamaño de cada elemento y el número de elementos.
size_t fread ( void *p, size_t s, size_t n, FILE *f );
size_t fwrite ( void *p, size_t s, size_t n, FILE *f );
p
s
n
*f
puntero hacia el área de datos que se desea leer o escribir
tamaño de cada elemento
número de elementos
stream. Ambas devuelven el número de elementos leídos o escritos, que debe ser el mismo que se le indica
acceso aleatorio ( fseek y ftell )
fseek ( FILE *stream, long offset, int whence ); mueve el cursor (indicador de posición) a un lugar determinado por el parámetro whence: SEEK_SET ­­> inicio del archivo
SEEK_CUR ­­> posición actual
SEEK_END ­­> final del archivo
long ftell ( FILE *stream ); devuelve la posición del cursor. Este valor indica el número de bytes desde el inicio del fichero
Descargar