Manual c

109
TABLA DE CONTENIDOS TABLA DE CONTENIDOS ............................................................................................................................ 1 1. INTRODUCCIÓN ................................................................................................................................... 3 1.1. HISTORIA DEL C ............................................................................................................................... 3 1.2. GENERALIDADES Y CARACTERÍSTICAS DEL LENGUAJE “C” .............................................................. 4 1.3. VISTA EXTERNA E INTERNA DE UN PROGRAMA EN C ....................................................................... 6 1.3.1. Vista externa ............................................................................................................................... 6 1.3.2. Vista interna ................................................................................................................................ 8 2. OPERADORES Y EXPRESIONES .................................................................................................... 10 2.1. TIPOS FUNDAMENTALES DE DATOS ................................................................................................. 10 2.1.1. Caracteres (tipo char) ............................................................................................................... 10 2.1.2. Números enteros (tipo int) ........................................................................................................ 11 2.1.3. Números reales (tipo float) ....................................................................................................... 12 2.1.4. Números reales (tipo double) .................................................................................................... 12 2.2. IDENTIFICADORES........................................................................................................................... 13 2.3. PALABRAS CLAVES ........................................................................................................................ 13 2.4. COMENTARIOS................................................................................................................................ 14 2.5. VARIABLES ..................................................................................................................................... 14 2.6. CONSTANTES .................................................................................................................................. 17 2.6.1. Constantes enteras: ................................................................................................................... 18 2.6.2. Constantes reales: ..................................................................................................................... 18 2.6.3. Constantes alfanuméricas. ........................................................................................................ 18 2.7. INCLUSIÓN DE ARCHIVOS EN C....................................................................................................... 19 2.8. OPERADORES.................................................................................................................................. 19 2.8.1. Operadores Aritméticos ............................................................................................................ 19 2.8.2. Operadores Relacionales .......................................................................................................... 19 2.8.3. Operadores Lógicos .................................................................................................................. 19 2.8.4. Operadores Lógicos a Nivel de Bit ........................................................................................... 20 2.8.5. Operadores de Asignación ........................................................................................................ 20 2.9. GRUPO DE PROCEDENCIA DE OPERADORES .................................................................................... 20 2.10. CONVERSIONES DE TIPO.................................................................................................................. 21 3. ELEMENTOS DE PROGRAMACIÓN ESTRUCTURADA ............................................................ 23 3.1. SENTENCIAS DE ENTRADA Y SALIDA DE DATOS. ............................................................................ 23 3.1.1. Introducción:............................................................................................................................. 23 3.1.2. Funciones de entrada y salida .................................................................................................. 23 3.2. SENTENCIAS DE CONTROL .............................................................................................................. 28 3.2.1. Introducción .............................................................................................................................. 28 3.2.2. Sentencias de Control Simples .................................................................................................. 28 3.2.3. Sentencias de Control Cíclicas ................................................................................................. 31 3.3. VARIABLES - ÁMBITO DE VALIDEZ................................................................................................. 35 4. TIPOS ESTRUCTURADOS DE DATOS ........................................................................................... 38 4.1. DEFINICIÓN .................................................................................................................................... 38 4.2. INICIALIZACION DE ARREGLOS ...................................................................................................... 39 4.3. TIPOS ARREGLOS............................................................................................................................ 41 4.3.1. Unidimensionales: .................................................................................................................... 41 4.3.2. Multidimensionales ................................................................................................................... 42 4.4. GENERALIDADES ............................................................................................................................ 43 4.5. ARREGLOS Y CADENAS .................................................................................................................. 45 4.5.1. ¿Qué es una cadena? ................................................................................................................ 45 4.6. PROCESAMIENTO DE ARREGLOS. .................................................................................................... 54 4.7. PASO DE ARREGLOS A FUNCIONES. ................................................................................................. 54

description

como programar en c++

Transcript of Manual c

Page 1: Manual c

TABLA DE CONTENIDOS

TABLA DE CONTENIDOS ............................................................................................................................ 1

1. INTRODUCCIÓN ................................................................................................................................... 3

1.1. HISTORIA DEL C ............................................................................................................................... 3 1.2. GENERALIDADES Y CARACTERÍSTICAS DEL LENGUAJE “C” .............................................................. 4 1.3. VISTA EXTERNA E INTERNA DE UN PROGRAMA EN C ....................................................................... 6

1.3.1. Vista externa ............................................................................................................................... 6 1.3.2. Vista interna ................................................................................................................................ 8

2. OPERADORES Y EXPRESIONES .................................................................................................... 10

2.1. TIPOS FUNDAMENTALES DE DATOS ................................................................................................. 10 2.1.1. Caracteres (tipo char) ............................................................................................................... 10 2.1.2. Números enteros (tipo int) ........................................................................................................ 11 2.1.3. Números reales (tipo float) ....................................................................................................... 12 2.1.4. Números reales (tipo double) .................................................................................................... 12

2.2. IDENTIFICADORES ........................................................................................................................... 13 2.3. PALABRAS CLAVES ........................................................................................................................ 13 2.4. COMENTARIOS ................................................................................................................................ 14 2.5. VARIABLES ..................................................................................................................................... 14 2.6. CONSTANTES .................................................................................................................................. 17

2.6.1. Constantes enteras: ................................................................................................................... 18 2.6.2. Constantes reales: ..................................................................................................................... 18 2.6.3. Constantes alfanuméricas. ........................................................................................................ 18

2.7. INCLUSIÓN DE ARCHIVOS EN C ....................................................................................................... 19 2.8. OPERADORES .................................................................................................................................. 19

2.8.1. Operadores Aritméticos ............................................................................................................ 19 2.8.2. Operadores Relacionales .......................................................................................................... 19 2.8.3. Operadores Lógicos .................................................................................................................. 19 2.8.4. Operadores Lógicos a Nivel de Bit ........................................................................................... 20 2.8.5. Operadores de Asignación ........................................................................................................ 20

2.9. GRUPO DE PROCEDENCIA DE OPERADORES .................................................................................... 20 2.10. CONVERSIONES DE TIPO.................................................................................................................. 21

3. ELEMENTOS DE PROGRAMACIÓN ESTRUCTURADA ............................................................ 23

3.1. SENTENCIAS DE ENTRADA Y SALIDA DE DATOS. ............................................................................ 23 3.1.1. Introducción:............................................................................................................................. 23 3.1.2. Funciones de entrada y salida .................................................................................................. 23

3.2. SENTENCIAS DE CONTROL .............................................................................................................. 28 3.2.1. Introducción .............................................................................................................................. 28 3.2.2. Sentencias de Control Simples .................................................................................................. 28 3.2.3. Sentencias de Control Cíclicas ................................................................................................. 31

3.3. VARIABLES - ÁMBITO DE VALIDEZ................................................................................................. 35

4. TIPOS ESTRUCTURADOS DE DATOS ........................................................................................... 38

4.1. DEFINICIÓN .................................................................................................................................... 38 4.2. INICIALIZACION DE ARREGLOS ...................................................................................................... 39 4.3. TIPOS ARREGLOS ............................................................................................................................ 41

4.3.1. Unidimensionales: .................................................................................................................... 41 4.3.2. Multidimensionales ................................................................................................................... 42

4.4. GENERALIDADES ............................................................................................................................ 43 4.5. ARREGLOS Y CADENAS .................................................................................................................. 45

4.5.1. ¿Qué es una cadena? ................................................................................................................ 45 4.6. PROCESAMIENTO DE ARREGLOS. .................................................................................................... 54 4.7. PASO DE ARREGLOS A FUNCIONES. ................................................................................................. 54

Page 2: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 2

5. FUNCIONES ......................................................................................................................................... 57

5.1. QUE SON FUNCIONES ...................................................................................................................... 57 5.2. DECLARACIÓN DE FUNCIONES ........................................................................................................ 57 5.3. LLAMADAS A FUNCIÓN ................................................................................................................... 60 5.4. PARÁMETROS POR VALOR. .............................................................................................................. 60 5.5. PARÁMETROS POR REFERENCIA ...................................................................................................... 62

6. PUNTEROS Y MANEJO DE ARCHIVOS ........................................................................................ 64

6.1. PUNTEROS ...................................................................................................................................... 64 6.1.1. Concepto de Puntero. ................................................................................................................ 64 6.1.2. Declaración de punteros ........................................................................................................... 64 6.1.3. Operadores de Punteros. .......................................................................................................... 64 6.1.4. Aritmética de Punteros.............................................................................................................. 68 6.1.5. Asignación dinámica de Memoria. ........................................................................................... 70 6.1.6. Punteros y arrays. ..................................................................................................................... 74 6.1.7. Inicializaciones de punteros ...................................................................................................... 80 6.1.8. Punteros a funciones. ................................................................................................................ 81 6.1.9. Modificador de acceso const y punteros. .................................................................................. 82 6.1.10. Declaraciones curiosas. ....................................................................................................... 84

6.2. ESTRUCTURAS ................................................................................................................................ 86 6.2.1. Concepto de estructura ............................................................................................................. 86 6.2.2. Declaración .............................................................................................................................. 86 6.2.3. Estructuras y funciones ............................................................................................................. 88 6.2.4. Arrays de estructuras ................................................................................................................ 91 6.2.5. Typedef ...................................................................................................................................... 92

6.3. FICHEROS ....................................................................................................................................... 93 6.3.1. Apertura .................................................................................................................................... 93 6.3.2. Cierre ........................................................................................................................................ 95 6.3.3. Funciones de Escritura y lectura .............................................................................................. 95

7. GRÁFICOS EN EL LEGUAJE C ..................................................................................................... 102

7.1. PROGRAMA TEXTO VS. PROGRAMA GRAFICO ................................................................................ 102 7.2. INICIALIZACIÓN DEL MODO GRAFICO ............................................................................................ 103 7.3. DIBUJAR EN EL MODO GRÁFICO (PRIMITIVOS GRÁFICOS) ............................................................. 104

7.3.1. Pintar un punto: ...................................................................................................................... 104 7.3.2. Dibujar un segmento de recta: ................................................................................................ 105 7.3.3. Para dibujar una circunferencia: ........................................................................................... 105 7.3.4. Para trazar un rectángulo: ..................................................................................................... 105 7.3.5. Dibujar un arco circular: ....................................................................................................... 105 7.3.6. Dibujar un arco elíptico: ........................................................................................................ 105

7.4. CAMBIAR EL ESTILO DE LÍNEA: ..................................................................................................... 106 7.5. FUNCIONES DE RELLENO ............................................................................................................... 106 7.6. FUNCIONES DE ESCRITURA DE TEXTO ........................................................................................... 108

7.6.1. Mostrar texto en un lugar específico ...................................................................................... 108 7.6.2. Seleccionar el estilo del texto .................................................................................................. 108 7.6.3. Cambiar los límites del dibujo. ............................................................................................... 108 7.6.4. Limpiar el viewport actual: ..................................................................................................... 109 7.6.5. Otras ....................................................................................................................................... 109

REFERENCIAS ............................................................................... ¡ERROR! MARCADOR NO DEFINIDO.

Page 3: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 3

1. Introducción

1.1. Historia del C

C fue desarrollado originalmente en los años setenta por Dennis Ritchie en Bell

Telephone Laboratories, Inc. (ahora una sucursal de AT&T). Es el resultado de

dos lenguajes anteriores, el BCPL y el B, que se desarrollaron también en los

laboratorios Bell. C estuvo confinado al uso en los laboratorios Bell hasta 1978,

cuando Brian Kernighan y Ritchie publicaron una descripción definitiva del

lenguaje. La definición de Kernighan y Ritchie se denomina frecuentemente «K.&R

C».

Tras la publicación de la definición de K&R, los profesionales de las

computadoras, impresionados por las muchas características deseables del C,

comenzaron a promover el uso del lenguaje. A mediados de los ochenta la

popularidad del C se había extendido por todas partes. Se habían escrito

numerosos compiladores e intérpretes de C para computadoras de todos los

tamaños y se habían desarrollado numerosas aplicaciones comerciales. Es más,

muchas aplicaciones que se habían escrito originalmente en otros lenguajes se

reescribieron en C para tomar partido de su eficiencia y portabilidad.

Las primeras implementaciones comerciales de C diferían en parte de la definición

original de Kernighan y Ritchie, creando pequeñas incompatibilidades entre las

diferentes implementaciones del lenguaje. Estas diferencias reducían la

portabilidad que el lenguaje intentaba proporcionar. Consecuentemente, el

Instituto Nacional Americano de Estándares** (comité ANSÍ X3J11) desarrolló una

definición estandarizada del lenguaje C. La mayoría de los compiladores e

intérpretes comerciales de C actuales adoptan el estándar ANSCII. Algunos

compiladores también pueden proporcionar características adicionales propias.

Page 4: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 4

En la década de los ochenta, Bjarne Stroustrup desarrolló en los laboratorios Bell

otro lenguaje de programación de alto nivel denominado C++. Éste se basa en C,

y por tanto todas las características estándar de C están disponibles en C++, Sin

embargo, C++ no es una mera extensión de C. Incorpora nuevos fundamentos

que constituyen una base para la programación orientada a objetos —un nuevo

paradigma de la programación de interés para los programadores profesionales—.

1.2. Generalidades y características del Lenguaje “C”

C es un lenguaje de programación estructurado de propósito general. Sus

instrucciones constan de términos que se parecen a expresiones algebraicas,

además de ciertas palabras clave inglesas como if, else, for, do y while. En este

sentido, C recuerda a otros lenguajes de programación estructurados como Pascal

y Fortran. C tiene también algunas características adicionales que permiten su uso

a un nivel más bajo, cubriendo así el vacío entre el lenguaje máquina y los

lenguajes de alto nivel más convencionales. Esta flexibilidad permite el uso de C

en la programación de sistemas (por ejemplo, para el diseño sistemas operativos)

así como en la programación de aplicaciones (por ejemplo, para redactar un

programa que resuelva un complicado sistema de ecuaciones matemáticas o un

programa que escriba las facturas para los clientes).

C se caracteriza por hacer posible la redacción de programas fuente muy

concisos, debido en parte al gran número de operadores que incluye el lenguaje.

Tiene un repertorio de instrucciones relativamente pequeño, aunque las

implementaciones actuales incluyen numerosas funciones de biblioteca que

mejoran las instrucciones básicas. Es más, el lenguaje permite a los usuarios

escribir funciones de biblioteca adicionales para su propio uso. De esta forma, las

características y capacidades del lenguaje pueden ser ampliadas fácilmente por el

usuario.

Page 5: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 5

Hay compiladores de C disponibles para computadoras de todos los tamaños, y

los intérpretes de C se están haciendo cada vez más comunes. Los compiladores

son frecuentemente compactos y generan programas objeto que son pequeños y

muy eficientes en comparación con los programas generados a partir de otros

lenguajes de alto nivel.

Los intérpretes son menos eficientes, aunque resultan de uso más cómodo en el

desarrollo de nuevos programas. Muchos programadores comienzan utilizando un

intérprete, y una vez que se ha depurado el programa (eliminado los errores del

mismo) utilizan un compilador.

Otra característica importante de C es que los programas son muy portables, más

que los escritos en otros lenguajes de alto nivel. La razón de esto es que C deja

en manos de las funciones de biblioteca la mayoría de las características

dependientes de la computadora.

Toda versión de C se acompaña de su propio conjunto de funciones de biblioteca,

que están escritas para las características particulares de la computadora en la

que se instale. Estas funciones de biblioteca están relativamente normalizadas y el

acceso a cada función de biblioteca es idéntico en todas las versiones de C. De

esta forma, la mayoría de los programas en C se pueden compilar y ejecutar en

muchas computadoras diferentes prácticamente sin modificaciones.

Page 6: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 6

1.3. Vista Externa e Interna de un Programa en C

1.3.1. Vista externa

No referimos con vista externa a la forma en que se encuentra estructurado un

programa en C.

A continuación se explica de forma sencilla la 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, la cual puede acceder a las demás funciones. Las definiciones de

las funciones adicionales se deben realizar aparte, bien precediendo o siguiendo a

main.

Cada función debe contener:

Una cabecera de la función, que consta del nombre de la función, seguido

de una lista opcional de argumentos encerrados entre paréntesis.

Una lista de declaración de argumentos, si se incluyen éstos en la

cabecera.

Una instrucción compuesta, que contiene el resto de la función.

Los argumentos son símbolos que representan información que se le pasa a la

función desde otra parte del programa. (También se llama parámetros a los

argumentos.).

Cada instrucción compuesta se encierra con un par de llaves, { }. Las llaves

pueden contener combinaciones de instrucciones elementales (denominadas

instrucciones de expresión) y otras instrucciones compuestas. Así las

instrucciones compuestas pueden estar anidadas, una dentro de otra. Cada

instrucción de expresión debe acabar en punto y coma (;).

Page 7: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 7

Los comentarios pueden aparecer en cualquier parte del programa, mientras estén

situados entre los delimitadores /* y */.

Por ejemplo: /* esto es un comentario */

Los comentarios son útiles para identificar los elementos principales de un

programa o para explicar la lógica subyacente de éstos.

He aquí un programa en C elemental que calcula el área de un círculo y escribe el

resultado calculado. Luego se nombran todas las partes que contiene el programa

en forma de comentarios.

/*Programa para calcular el área de un círculo*/

#include<stdio.h>

#define PI 3.1416

main ()

{

float area, radio;

radio = 10;

area = PI * (radio * radio);

printf ("Circulo.\n");

printf("%s%f\n\n", "Area de circulo radio 10: ", area);

}

Estructura de un Programa en C

/ * titulo (comentario) */

/ * acceso a archivo de biblioteca */

/ * definicion de una constante*/

/ * cabecera de función */

/ * declaración de variables */

/ * inicializacion de la variable radio*/

/ * expresion para calcular el area */

/ * instrucción de entrada*/

/ * instrucción de salida*/

Page 8: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 8

1.3.2. Vista interna

Nos referimos con vista interna, al proceso que se lleva acabo internamente, para

crear un programa ejecutable de un programa fuente escrito en c.

Primeramente hablaremos del compilador de C, que se llama GCC.

GCC es un compilador integrado del proyecto GNU para C, C++, Objective C y

Fortran; puede recibir un programa fuente en cualquiera de estos lenguajes y

generar un programa ejecutable binario en el lenguaje de la máquina donde ha de

correr. El compilador es capaz de detectar ciertos errores durante el proceso de

compilación, enviando al usuario el correspondiente mensaje de error.

La sigla GCC significa "GNU Compiler Collection". Originalmente significaba "GNU

C Compiler".

1.3.2.1. Etapas de compilación.

El proceso de compilación involucra cuatro etapas sucesivas:

Preprocesamiento, compilación, ensamblado y enlazado.

Para pasar de un programa fuente escrito por un humano a un programa

ejecutable se realizan estas cuatro etapas en forma sucesiva.

Preprocesado.

En esta etapa se interpretan las directivas al preprocesador. Entre otras cosas, las

variables inicializadas con #define son sustituidas en el código por su valor en

todos los lugares donde aparece su nombre.

Usaremos el ejemplo utilizado para demostrar la vista externa de un programa en

c, para explicar la etapa del preprocesado.

Page 9: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 9

/*programa para calcular el area de un circulo */

#include<stdio.h>

#define PI 3.1416

main ()

{

float area, radio;

radio = 10;

area = PI * (radio * radio);

printf ("Circulo.\n");

printf("%s%f\n\n", "Area de circulo radio 10: ", area);

}

En este ejemplo, en la expresión ”area=PI *(radio * radio);”, la variable PI se

reemplaza por el valor antes definido (3.1416).

Compilación.

La compilación transforma el código C en el lenguaje ensamblador propio del

procesador de nuestra máquina.

Ensamblado.

El ensamblado transforma el programa escrito en lenguaje ensamblador a código

objeto, un archivo binario en lenguaje de máquina ejecutable por el procesador.

Enlazado

Las funciones de C incluidas en nuestro código, tal como printf () en el ejemplo, se

encuentran ya compiladas y ensambladas en bibliotecas existentes en el sistema.

Es preciso incorporar de algún modo el código binario de estas funciones a

nuestro ejecutable. En esto consiste la etapa de enlace, donde se reúnen uno o

más módulos en código objeto con el código existente en las bibliotecas.

Page 10: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 10

2. Operadores y Expresiones

2.1. Tipos fundamentales de datos

C no soporta un gran número de tipos de datos predefinidos, pero tiene la

capacidad para crear sus propios tipos de datos. Todos los tipos de datos simples

o básicos de C son, esencialmente, números. Los tipos de datos básicos son:

Enteros

Números de coma flotante

Caracteres

A continuación se detalla su nombre, el tamaño que ocupa en memoria y el rango

de sus posibles valores.

Tipo Ejemplo Tamaño Rango de valores

char „C‟ 1 byte 0 a 255

int 1024 2 bytes -32768 a 32767

float 10.5 4 bytes 3'4 E-38 a 3'4 E+38

double 0.0025 8 bytes 1'7 E-308 a 1'7 E+308

2.1.1. Caracteres (tipo char)

Las variables carácter (tipo char) contienen un único carácter y se almacenan en

un byte de memoria (8 bits). La declaración de variables tipo carácter puede tener

la forma:

char nombre;

char nombre1, nombre2, nombre3;

Page 11: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 11

Se puede declarar más de una variable de un tipo determinado en una sola

sentencia. Se puede también inicializar la variable en la declaración. Por ejemplo,

para definir la variable carácter letra y asignarle el valor a, se puede escribir:

char letra = ’a’;

A partir de ese momento queda definida la variable letra con el valor

correspondiente a la letra a. Recuérdese que el valor ‟a‟ utilizado para inicializar la

variable letra es una constante carácter.

También puede utilizarse una variable char para dar valor a otra variable de tipo

char:

carácter = letra; /*Ahora carácter es igual a ’z’*/

Como una variable tipo char es un número entero pequeño (entre 0 y 255), se

puede utilizar su contenido de la misma forma que se utiliza un entero, por lo que

están permitidas operaciones como:

letra = letra + 1;

letra _ minúscula = letra _ mayúscula + (’a’ - ’A’);

2.1.2. Números enteros (tipo int)

Una variable tipo int se almacena en 2 bytes (16 bits). Una variable entera se

declara, o se declara y se inicializa en la forma: <tipo de dato> <nombre de la

variable> = <valor inicial>;

Ejemplos:

int numero;

int nota = 10;

int valor1, valor2;

Los enteros son adecuados para aplicaciones que trabajen con datos numéricos.

Page 12: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 12

2.1.3. Números reales (tipo float)

En muchas aplicaciones hacen falta variables reales, capaces de representar

magnitudes que contengan una parte entera y una parte fraccionaria o decimal.

Estas variables son del tipo punto flotante. Estos requieren 4 bytes de memoria

(32 bits).

Las variables tipo float se declaran de la forma: float número _ real; las variables

pueden ser inicializadas en el momento de la declaración, de forma análoga a las

variables tipo int.

Ejemplos:

float valor;

float valor1, valor2;

float valor = 99.99;

2.1.4. Números reales (tipo double)

Las variables tipo float tienen un rango y sobre todo una precisión muy limitada,

insuficiente para la mayor parte de los cálculos técnicos y científicos. Este

problema se soluciona con el tipo double, que utiliza 8 bytes (64 bits) para

almacenar una variable.

Las variables tipo double se declaran de forma análoga a las anteriores:

double real_grande;

Por último, existe la posibilidad de declarar una variable como long double, estas

se declaran en la forma:

long double real;

Ejemplos:

double h;

long double mayor;

double valor = 0.000056;

Page 13: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 13

2.2. Identificadores

Un identificador es una secuencia de caracteres, letras, dígitos y subrayados

(_).Un identificador es el nombre que damos a las variables y funciones. El primer

carácter debe ser una letra (algunos compiladores admiten carácter de

subrayado). Las letras mayúsculas y minúsculas son diferentes.

Ejemplos:

nombre_clase Indice Dia_Mes_Año

elemento_mayor Cantidad_Total Fecha_Compra_Casa

a Habitacion120 i

En C el identificador puede ser de cualquier longitud; sin embargo, el compilador

ignora cualquier carácter fuera de los 32 primeros. C es sensible a las

mayúsculas. Por consiguiente, C reconoce como distintos los identificadores

ALFA, alfa y ALFa. Un identificador no puede contener espacios en blanco, ni

otros caracteres distintos de los citados, como por ejemplo (*,+, etc.). En un

identificador no pueden ser utilizadas las palabras reservadas, tales como if,

switch o else.

2.3. Palabras Claves

En C, como en cualquier otro lenguaje, existen una serie de palabras clave

(keywords) que el usuario no puede utilizar como identificadores. Estas palabras

sirven para indicar al computador que realice una tarea muy determinada (desde

evaluar una comparación, hasta definir el tipo de una variable) y tienen un especial

significado para el compilador. A continuación vemos algunas de estas palabras

clave:

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

Page 14: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 14

2.4. Comentarios

A la hora de programar es conveniente añadir comentarios para poder saber que

función tiene cada parte del código. Además facilitaremos el trabajo a otros

programadores que puedan utilizar nuestro archivo fuente.

Para poner comentarios en un programa escrito en C usamos los símbolos /* y */:

/* Este es un ejemplo de comentario */

/* Un comentario también puede

estar escrito en varias líneas */

El símbolo /* se coloca al principio del comentario y el símbolo */ al final. El

comentario, contenido entre estos dos símbolos, no será tenido en cuenta por el

compilador

2.5. Variables

Variables en Lenguaje C

Las variables en C pueden ser de varios tipos y serán utilizadas en función del tipo

de datos que queramos almacenar en ellas. Las variables NOMBRE, nombre,

Nombre son tres variables totalmente distintas. (Lenguaje Case Sensitive) y el

nombre de una variable no puede comenzar por número (pero puede contener

varios) ni tener caracteres especiales (se admite el guión bajo).

Por ejemplo: numero1, j10a, num_alumno, serían variables válidas y 1abc,

numero?, num/alumnos serían variables inválidas.

Según dónde estén declaradas, las variables pueden ser globales (declaradas

fuera de todo procedimiento o función) o locales (declaradas dentro de un

procedimiento o función). Las primeras serán accesibles desde todo el código

fuente y las segundas sólo en la función donde estén definidas.

Page 15: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 15

Por otra parte, según el tipo de datos a almacenar, las variables serán de tipo

entero (int), flotante (float), doble (double) o carácter (char).

El tipo int se utiliza para guardar números enteros, es decir, que no tienen

decimales. El rango de valores admitidos varía según la CPU utilizada. Para

mostrar los valores contenidos en este tipo de variables, nos serviremos de %i o

%d.

Ejemplo:

/*Programa para mostrar variable en pantalla*/

#include<stdio.h>

main ()

{

int x=8;

int y=9;

printf("%i\n",x);

/*Podemos escribir varias variables en el mismo printf:*/

printf("%i %i",x,y);

}

Siendo el resultado por pantalla:

8

8 9

Para todos los tipos, podemos definir variables en una sola línea: int x=8,y=9;

tendría las mismas consecuencias que el código anterior. Pero, debemos tener

cuidado, pues: int x,y=9; no daría lo mismo: "x" no tendría valor e "y" valdría 9.

Si imprimimos una variable a lo que no hemos asignado valor, el compilador no

reconocerá ningún error, pero se imprimirá un valor cualquiera. Además, toda

variable puede cambiar su valor durante la ejecución del programa y ser impresa

las veces que creamos oportunas.

Page 16: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 16

Tras estas pequeñas aclaraciones, seguiremos comentando el uso de variables

con el tipo float. Este tipo sirve para almacenar números decimales o reales, así

como el double. El rango de valores admitidos en tan amplio que rara vez se nos

quedará obsoleto.

El modificador para operar con estos datos es %f y lo haremos del mismo modo

que con int. En otros artículos entraremos en detalles de cómo calcular el rango de

valores posibles y el tamaño de las variables.

De momento, continuamos el tipo char, capaz de almacenar un único carácter.

Internamente, un carácter es almacenado como un número, comprendido entre 0 y

128, que hace referencia a su código ascii (ascii standard).

Por ejemplo, declarando:

char letra='A'; /*los caracteres siempre entre comillas simples

tendríamos el mismo efecto que: char letra= 65; puesto que el ascii de A

es 65.*/

El modificador del tipo carácter es %c y también es empleado de la misma forma.

Si declaramos una variable char y imprimimos con %d, nos devolverá su código

ascii... así podremos crearnos nuestra propia tabla de caracteres. Y, si,

declaramos una variable de tipo int y escribimos su valor con %c, nos devolverá el

carácter correspondiente a ese número en el código ascii.

Page 17: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 17

2.6. Constantes

Al contrario que las variables, las constantes mantienen su valor a lo largo de todo

el programa.

Para indicar al compilador que se trata de una constante, usaremos la

directiva

#define

#define <identificador> <valor>

Observa que no se indica el punto y coma de final de sentencia ni tampoco el tipo

de dato.

Observa que no se indica el punto y coma de final de sentencia ni tampoco el tipo

de dato.

La directiva #define no sólo nos permite sustituir un nombre por un valor numérico,

sino también por una cadena de caracteres.

El valor de una constante no puede ser modificado de ninguna manera.

/* Uso de las constantes */

#include <stdio.h>

#define pi 3.1416

#define escribe printf

main() /* Calcula el perimetro */

{

int r;

escribe("Introduce el radio: ");

scanf("%d",&r);

escribe("El perimetro es: %f",2*pi*r);

}

Page 18: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 18

2.6.1. Constantes enteras:

Una constante entera es una cantidad sin punto decimal(con signo positivo

opcional) cuyos valores mínimo y máximo en precisión sencilla (ENTERO CORTO

que se almacena en 2 bytes) son: -32768 y 32768.

una variante es la entera sin signo (que se almacena en 2 bytes), con los valores

mínimo y máximo de: 0 y 65535

Mientras que en doble precisión (ENTERO LARGO que se almacena en 4 bytes):

-2147843648 y 2147843648

2.6.2. Constantes reales:

Una constante real es una cantidad que incluye punto decimal (con signo positivo

opcional) cuyos valores mínimo y máximo aproximados (en precisión sencilla de 4

bytes) son: -3.4 10-38 y 3.4 1038 (6 dígitos válidos).

Mientras que sus valores aproximados de doble precisión (8 bytes) son: -1.79 10-

308 y 1.79 10308

2.6.3. Constantes alfanuméricas.

Una constante alfanumérica es un conjunto de caracteres delimitados por comillas

dobles como por ejemplo: "-32,768","uno mas uno","ABCFXY","SI","NO"

Con una longitud máxima de 255 caracteres en C. Es importante comentar que si

el valor alfanumérico es un solo carácter, se usa comilla simple, por ejemplo: 'a','u'

Page 19: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 19

2.7. Inclusión de Archivos en C

La inclusión de archivos no es más que la declaración o la llamada de la o las

librerías donde se encuentran definidas las instrucciones del lenguaje. Las

librerías pertenecen al desarrollo del lenguaje C. Una de las librerías importantes

del lenguaje es la función main(), que sin ella no permite que el programa se

desarrolle, la cual se delimita con llaves.

2.8. Operadores

Son símbolos que indican al compilador que se lleve a cabo específicas

manipulaciones matemáticas o lógicas. Hay cinco clases de operadores

aritméticos, lógicos y bit, relacionales y de Asignación.

2.8.1. Operadores Aritméticos

+ Suma

- Resta

* Multiplicación

/ División

% División Modulo

-- Decremento

++ Incremento

2.8.2. Operadores Relacionales

> Mayor

>= Mayor o Igual

< Menor

<= Menor o Igual

== Igual

!= Distinto o Diferente

2.8.3. Operadores Lógicos

&& and (y lógico)

|| or (o lógico)

! not

Page 20: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 20

2.8.4. Operadores Lógicos a Nivel de Bit

& Operación and

| Operación or

^ Operación xor

<< Desplazamiento a la Izquierda

>> Desplazamiento a la Derecha

2.8.5. Operadores de Asignación

= Asignación Simple

+= Suma con Asignación

-= Resta con Asignación

*= Multiplicación con Asignación

/= División con Asignación

%= División Módulo con Asignación

2.9. Grupo de Procedencia de Operadores

Categoría del Operador Operadores Asociatividad

Operadores Monarios ( )

-, ++, --, !, sizeof Derecha Izquierda

Multiplicación, División,

División Modulo *, /, % Izquierda Derecha

Suma y resta aritméticas +, - Izquierda Derecha

Operadores relacionales <, <=, >, >= Izquierda Derecha

Operadores de Igualdad ==, != Izquierda Derecha

Operadores Lógicos && Izquierda Derecha

Operador condicional ?: Derecha Izquierda

Operadores de Asignación =, +=, -=, *=, /=, %= Derecha Izquierda

Page 21: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 21

2.10. Conversiones de tipo

Se conoce como conversión de tipo al proceso mediante el cual se ajusta el valor

de una variable de un tipo para que puede caber o ser usado como una variable

de otro tipo. Las conversiones se hacen todo el tiempo en un programa, por

ejemplo cuando sumamos un valor entero a un valor real. Pero en estos casos el

compilador se encarga de convertir el valor, son conversiones implícitas.

Si al convertir ganamos precisión, por ejemplo ir de un tipo int a float, se conoce

como promoción de tipos. Cuando hay pérdida de precisión, las conversiones se

conocen como democión de tipos. El compilador normalmente emite un aviso o

"warning", cuando se hace una democión implícita, es decir cuando hay una

democión automática.

Existe una forma en que el programador puede controlar estas conversiones, y así

evitar estos warning a esta técnica se le conoce como casting o conversiones

explicitas.

En general, el uso de "casting" es obligatorio cuando se hacen asignaciones, o

cuando se pasan argumentos a funciones con pérdida de precisión. En el caso de

los argumentos pasados a funciones es también muy recomendable aunque no

haya pérdida de precisión. Eliminar los avisos del compilador demostrará que

sabemos lo que hacemos con nuestras variables, aún cuando estemos haciendo

conversiones de tipo extrañas.

Un "casting" tiene una de las siguientes formas:

(<nombre de tipo>)<expresión> ó <nombre de tipo>(<expresión>)

Esta última es conocida como notación funcional.

Page 22: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 22

Ejemplo:

/* Uso de las constantes */

#include <stdio.h>

#define pi 3.1416

#define escribe printf

main() /* Calcula el perimetro */

{

/*Variable tipo entero*/

int x = 10;

/*Variable tipo real*/

double d = 24.251555;

/*Conversion de tipo realizada por el compilador*/

printf("Antes de convertir x = %d y d = %f\n");

x = d; /*El compilador emitira un warning "converting int to

double"*/

printf("Después de convertir por el compilador x = %d y d = %f\n");

/*Conversión explicita por el programador*/

x = (int) d;

/*Otra forma*/

x = int(d);

printf("Después de convertir explicitamente x = %d y d = %f\n");

}

Page 23: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 23

3. Elementos de Programación estructurada

3.1. Sentencias de Entrada y Salida de Datos.

3.1.1. Introducción:

Las funciones de Entrada y Salida de Datos se encuentran en la librería stdio.h y

básicamente son getchar, putchar, scanf, printf, gets y puts. Estas son utilizadas

para el flujo o transferencia de datos entre el usuario y la computadora.

3.1.2. Funciones de entrada y salida

3.1.2.1. Función getchar:

Esta no requiere de argumento alguno y su función es la de entrada de un

carácter.

Su sintaxis es:

getchar ();

, por lo tanto asignará y leerá un carácter desde el teclado. También se puede

utilizar para encontrar un fin de archivo (EOF).

Ejemplo:

/*Uso de getchar()*/

#include <stdio.h>

main()

{

char a; /*Declaración de a como carácter*/

a = getchar(); /*Lee un carácter del teclado y lo asigna a la

variable a*/

}

Page 24: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 24

3.1.2.2. Función putchar:

Esta complementa a la función putchar, se utiliza para visualizar en pantalla un

carácter, y recibe como parámetro la variable que desea usarse.

Su sintaxis es:

putchar (variable usada);.

Ejemplo:

/*Uso de putchar*/

#include <stdio.h>

void main (void)

{

char b; /* Declara b */

b = getchar(); /* Lee b */

putchar(b); /* muestra en pantalla el valor de b */

}

3.1.2.3. Función scanf:

Se emplea para leer cualquier dato numérico, de caracteres sueltos o en cadena

introducido por el usuario.

Su sintaxis es:

scanf(“cadena de control”, arg1, arg2,....,argn);

en la cual la cadena de control son argumentos formados por el signo de

porcentaje (%) y un carácter de abreviación el cual representa cada tipo de dato.

Y arg1, arg2,… argn son los nombres de las variables que convendrán los datos

que los cuales serán leídos, estos nombres deberán ir precedidos por un

ampersand (&) cada uno, excepto los nombres de formaciones como cadenas de

caracteres.

Page 25: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 25

Especificadores de formato

%d Lee variable entera (decimal)

%c Lee un carácter

%s Lee una cadena de caracteres

%f Lee variable punto flotante

%e Lee variable punto flotante pero con notación científica

%u Lee variable entera sin signos

%x Lee variable hexadecimal

%g Lee variable punto flotante

%h Lee variable entera cortas

%o Lee variable enteras octales

Ejemplo:

/*Uso de scanf*/

#include <stdio.h>

main()

{

int a, b; /*Declara los enteros a y b*/

char c[10]; /*declara la variable c de tipo char*/

/*Lee un entero, un entero sin signo y una cadena de caracteres*/

scanf("%d %u %s", &a, &b, c);

}

3.1.2.4. Función printf:

La función printf se utiliza para la escritura de datos, y esta es análoga a la función

scanf.

Su sintaxis es:

printf(“cadena de control”, arg1, arg2,… argn);

Page 26: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 26

donde la cadena de control hace referencia a la abreviación de los datos de salida

al igual que con la sentencia de entrada scanf, pero a diferencia de estos sus

argumentos no van precedidos de ampersands ya que no representan direcciones

de memoria.

Especificadores de formato:

Carácter de conversión Significado

C Carácter

D Entero decimal

E, f, g Entero en coma flotante

H Entero corto

I Entero decimal, octal o hexadecimal

O Entero octal

S Cadena de caracteres seguida de un espacio

U Entero decimal sin signo

X Entero hexadecimal

[…] Cadena de caracteres que puede contener

espacios

Ejemplo:

/*Uso de printf*/

#include "stdio.h"

main()

{

char frase[20]="Este es un ejemplo";

printf(" %s", frase); /* Imprime o muestra en pantalla el array

frase*/

}

Page 27: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 27

3.1.2.5. Función gets:

Su uso facilita la lectura de datos ya que no recibe mas parámetros que el nombre

de la variable que queremos leer, esta se introducirá del teclado, deberá ser una

cadena de caracteres, podrá contener espacios y terminará con un salto de línea.

Ejemplo:

/*Uso de gets*/

#include <stdio.h>

main()

{

char ejem[16];

/*Lee una cadena con espacio para 15 caracteres mas el carácter

nulo*/

gets(ejem);

}

3.1.2.6. Función puts:

Esta última función de las más comunes de entrada y salida de datos es el

equivalente a gets, posee las mismas características, pero en salida de datos.

Ejemplo:

#include “stdio.h”

void main(void)

{

char arreglo[30];

gets(arreglo); /* Lee un arreglo*/

puts(arreglo); /* imprime el mismo arreglo*/

}

Page 28: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 28

3.2. Sentencias de Control

3.2.1. Introducción

Estas se utilizan para hacer comprobaciones de condiciones, para realizar

repetidamente determinadas instrucciones, estas son palabras reservadas, por lo

tanto no necesitan de inclusión de librerías para su uso.

Principalmente son if-then-else, for, while, do-while, switch, break, goto y continue.

3.2.2. Sentencias de Control Simples

3.2.2.1. If – else

Esta sentencia evalúa una condición, para realizar una de dos acciones,

dependiendo si se cumple o no la condición.

Es decir el valor de la expresión a evaluar puede ser verdadero o falso.

La parte else de la sentencia es opcional, y su sintaxis sería:

if(expresión evaluada) instrucción1 ;

else instrucción2

ó también de forma sencilla

if(expresión) instrucción.

Otra característica de esta sentencia es que se pueden anidar otros if-else dentro

de otros.

Page 29: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 29

Ejemplo:

#include <stdio.h>

#include <conio.h>

main()

{

int a, b, c;

scanf( "%d %d %d", &a, &b ,&c);

if( a + b > c)

{

printf(" a + b es mayor que c");

}

else

{

if( a + b < c)

printf(" a + b es menor que c");

}

getch();

}

3.2.2.2. switch

Esta se utiliza para realizar una operación o varias de un grupo de instrucciones.

Su sintaxis es la siguiente:

switch (expresión) instrucción;

3.2.2.3. break

Se usa para terminar la ejecución de bucles o salir de un switch.

Page 30: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 30

Ejemplo:

/*Uso de switch y break:*/

#include <stdio.h>

#include <conio.h>

main()

{

int a;

scanf( "%d" , &a);

switch( a)

{

case 1: printf("Ha introducido un 1");

break;

case 2: printf("Ha introducido un 2");

break;

case 3: printf("Ha introducido un 3");

break;

default: printf("Intente del uno al tres");

}

getch();

}

3.2.2.4. goto

Esta instrucción se utiliza para cambiar el flujo secuencial de un programa,

trasladando el control hacia la parte donde se encuentra la etiqueta.

Su sintaxis es:

goto etiqueta;

y etiqueta es un indicador que se encuentra en la parte donde queremos transferir

el control de la forma etiqueta: instrucción.

Page 31: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 31

Ejemplo:

/*Uso de goto*/

#include <stdio.h>

#include <conio.h>

main()

{

int h, i, j, k;

Mensaje: printf("Los Datos que Introduzca deben ser tres enteros

distintos de cero:\n");

printf("h, i y j: ");

scanf("%d %d %d" , &h, &i, &j);

if( (h!=0) && (i!=0) && (j!=0) )

{

k = h + i - j;

}

else

{

printf("Vuelva a intentarlo:\n");

goto Mensaje;

}

printf("El resultado de h + i - j = %d", k);

getch();

}

3.2.3. Sentencias de Control Cíclicas

En numerosas ocasiones, nos interesa repetir mas de una vez ciertas operaciones

o instrucciones. También nos suele interesar los datos resultantes de algunas

operaciones para saber que operaciones debería ejecutar el programa y que

operaciones no. Para esto existen las sentencias de control de flujo y bucles.

Estas sentencias son: for, while, do while, if, else, switch, break y continue.

Aunque las sentencias if, else, break y continue no se utilizan para repetir un

proceso, se utilizan para cambiar el flujo de control de un programa. En función

al resultado de ciertas condiciones postuladas por el programador.

Page 32: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 32

3.2.3.1. Bucle for:

Su sintaxis es la siguiente:

for( dar valores iniciales ; condiciones ; incrementos )

{

Conjunto de instrucciones a ejecutar en el bucle

}

El bucle funciona recibiendo primero el valor inicial desde donde se va a empezar

a contar el número de repeticiones. Después recibe la condición a validar al fin de

cada ciclo para que el bucle se siga ejecutando. Y después recibe el incremento, o

decremento, que la variable de valor inicial recibirá para que la condición se haga

falsa y el bucle llegue a un fin.

A continuación veremos un ejemplo del uso del bucle for:

/*Uso de for*/

#include <stdio.h> /*declaración de bibliotecas de funciones*/

#include <conio.h>

main() /*inicio de la función principal*/

{

int i,j; /*declaración de variables*/

/*inicio del bucle for*/

for( i=0, j=5; i<10; i++, j=j+5)

{

/*instrucciones a repetir*/

printf("¡Hola!");

printf("\nEsta es la repetición numero: %d.", i);

printf("\nEl valor de j es: %d", j);

}

/*detenemos el control hasta que se oprima una tecla para visualizar

datos*/

getch();

return 0;

} /*fin de función principal*/

Page 33: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 33

Este ejemplo declara un bucle for que se repetirá desde i=0 hasta i<10 (es decir

10 veces) la oración ¡Hola!, contara el numero de repeticiones e incrementara el

valor de “j” en 5 cada ciclo, hasta que la condición sea falsa.

Como podemos observar en este ejemplo, cada parámetro que recibe el bucle

también puede estar seccionado, separados por comas y pudimos haber tenido

mas de una condición así como también pudimos haber omitido cualquier

parámetro.

3.2.3.2. Bucle while:

Su sintaxis es la siguiente:

while ( condición )

{

bloque de instrucciones a ejecutar

}

El bucle while ejecuta un conjunto de instrucciones mientras la condición

postulada se cumpla.

Por ejemplo:

/*Uso de while*/

#include<stdio.h> /*declaración de bibliotecas de funciones a usar*/

#include<conio.h>

main() /*inicio del programa principal*/

{

int contador=100; /*declaración de valor constante a variable*/

while(contador > 0) /*inicio del bucle while*/

{ /*instrucciones a repetir*/

printf("Faltan %d para terminar el bucle while\n",

contador);

contador--; /*reduce el numero de contador para poder hacer

falsa la condición*/

}

getch(); /*detiene el programa para su visualización*/

return 0;

} /*Fin función principal*/

Page 34: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 34

En este ejemplo se imprime de manera regresiva el número de veces que hacen

falta para finalizar el bucle. Empezando desde 100. El orden de las instrucciones

es importante en este bucle ya que si intercambiamos de posición las

instrucciones el conteo hubiese empezado desde 99. Es muy importante ponerle

atención al orden de instrucciones en este bucle ya que puede producir errores

muy difíciles de encontrar.

3.2.3.3. Bucle do while:

Su sintaxis es la siguiente:

do

{

Instrucciones a ejecutar

} while ( condición );

La gran diferencia entre el while y el do while es que en este último la condición va

después del conjunto de instrucciones, así dichas instrucciones podrán ejecutarse

por lo menos una vez. Su uso es similar al while.

Tenemos el siguiente ejemplo:

/*Uso de do-while*/

#include<stdio.h> /*declaración de bibliotecas de funciones*/

#include<conio.h>

main() /*inicio de la función principal*/

{

int i=1, j; /*declaración de variables*/

do /*inicio del bucle do-while*/

{

j=i*2; /*sentencias a evaluar dentro del bucle*/

printf("La tabla del dos:");

printf("2 x %d = %d\n",i,j); i++;

}while(i<=10); /*fin del bucle y evaluacion de la condicion*/

getch();

}

Page 35: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 35

En este ejemplo se imprime la tabla del 2 desde 1 hasta diez.

Aunque no es recomendado, debido a que se denota como mala practica de

programación, si solo se desea repetir una sola instrucción, utilizando los

diferentes bucles, el programador puede omitir las llaves. Aunque no sea un

problema en programas sencillos, estos pequeños detalles son los que pueden

ahorrar mucho tiempo a la hora de corregir errores en programas mas complejos.

3.2.3.4. Función continue:

Su sintaxis es la siguiente:

continue;

Funciona de forma similar a break. Sin embargo, en vez de forzar la terminación,

break. Sin embargo, en vez de forzar la terminación, continue fuerza una nueva

iteración del bucle y salta cualquier código que exista entremedio.

Para el bucle for, continue hace que se ejecuten las partes de prueba condicional

y de incremento del bucle. Para los bucles while y do-while, el control del

programa pasa a la prueba condicional.

3.3. Variables - Ámbito de Validez

Como ya sabemos una variable en C es un espacio reservado en la memoria del

computador para guardar datos fluctuantes dentro de la ejecución de un programa.

Es importante recordar que todos los datos guardados e interpretados por el

computador son siempre binarios, así que el tipo nos permite decirle al compilador

como interpretar los datos. El tipo de variable determinara el trato que se le dará a

cada variable.

Page 36: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 36

Es en este último punto en donde nos enfocaremos en este capitulo. Como

programador una de las primeras cosas que se aprenden es que el usuario de un

software es muy impredecible en cuanto a los datos que se le piden. Sin importar

que tan claras sean las instrucciones, es necesario saber si lo tecleado por el

usuario se adapta a los datos pedidos o no. Para poder así tomar medidas

adecuadas para evitar el fallo de cualquier aplicación determinada.

Leer lo tecleado por el usuario y comparar si los datos adquiridos concuerdan con

el tipo solicitado es lo que llamamos validación. Este ámbito constituye una función

muy importante dentro de la programación desde sus principios ya que la fiabilidad

de un software depende de los datos que contiene y es uno de los requisitos mas

exigidos. Y los programas desarrollados en C no son una excepción.

Por ejemplo, si se desea verificar, en un programa que pide una carácter

determinado, sea solo caracteres y solamente caracteres se podría utilizar la

siguiente validación:

/*Uso de validacion*/

#include<stdio.h>

#include<ctype.h>

#include<conio.h>

main()

{

int a;

Again: printf("Introduzca un carcter: ");

a = getchar();

tolower(a);

if(a >= 'a' && a <= 'z')

{ printf("El character intorducido fue el: %c\n",a); }

else

{ printf("El dato no es valido, intente nueva mente\n");

goto Again; }

getch();

}

Page 37: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 37

Otro ejemplo seria en un programa en donde se quiere abrir un fichero, se tiene

que verificar que el fichero no este vacío y se puede utilizar la siguiente validación:

/*Uso de validación 2*/

#include <stdio.h>

main(){

FILE* archivo;

int f[4];

double d[4];

archivo = fopen("fichero.txt","r");

if(archivo!=NULL){

int f[4],i;

double d[4];

fscanf(archivo,"%d %d %d %d\n",

&f[0],&f[1],&f[2],&f[3]);

fscanf(archivo,"%d, %d, %d, %d\n",

&f[0],&f[1],&f[2],&f[3]);

fscanf(archivo,"%lf ; %lf ; %lf ; %lf\n",

&d[0],&d[1],&d[2],&d[3]);

fclose(archivo);

}

}

En ambos ejemplos se nota la importancia de validar los datos con los que se

trabajan en un programa. En el caso de que un valor inesperado sea leído el

programa tomara un curso apropiado para asegurar que el programa no falle y los

datos obtenidos no sean erróneos.

Page 38: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 38

4. Tipos Estructurados de Datos

4.1. Definición

Arreglos

Es una variable que maneja una gran cantidad de datos del mismo tipo bajo un

mismo nombre .A cada elemento se le asigna un espacio de memoria, según el

orden o secuencia, se puede acceder a cada elemento según el espacio o

localidad de memoria que este elemento tenga.

Un arreglo debe de ir acompañado, del tipo del almacenamiento, este es opcional

los valores por defecto son automático para arreglos definidos dentro de un

función, y externo para arreglos definidos fuera de una función, también de una

especificación de tamaño (numero de elementos), en este caso seria un digito

entero positivo, encerrado entre corchetes.

El lenguaje C si se accede a un arreglo de n términos y el usuario se referencia a

un elemento que sobrepase al n-números de elementos, este no provoca ningún

mensaje de error en el caso de que sobrepase el final durante una operación de

asignación, entonces se asignarán valores a otra variable o a un trozo del código,

esto es, si se dimensionar. Como programador se es responsable de asegurar que

todos los arreglos sean lo suficientemente grandes para guardar lo que pondrá en

ellos el programa.

Por ejemplo, para declarar un arreglo de enteros llamado demos con diez

elementos se hace de la siguiente forma:

int demos[10];

En C, todos los arreglos usan cero como índice para el primer elemento. Por tanto,

el ejemplo anterior declara un arreglo de enteros con diez elementos desde

demos[0] hasta demos[9].

Page 39: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 39

Tipo_almacenamiento tipo nombre [número _ elementos];

Tipo: el tipo de dato que poseen cada uno de los elementos.

Nombre: variable que identifica el arreglo.

Numero de elementos: este indica la cantidad de elementos que contendrá el

arreglo, este referenciara el índice del elemento al cual será accedido

NOTA: No es el contenido que tendrá el arreglo.

Tipo_almacenamiento: se refiere al tipo de almacenamiento

4.2. Inicializacion De Arreglos

Un arreglo puede ser inicializado es decir asignárseles valores iniciales, los

arreglos automáticos no pueden ser inicializados, no obstante las definiciones de

arreglos estáticos y externos pueden asignárseles valores iniciales, los valores

inicializados deben de estar encerrados entre corchetes, escritos en el orden en

que serán asignados. Cuando un arreglo es inicializado es opcional número de

elementos, ya que los corchetes pueden estar vacíos.

Ejemplo: /*Uso de arreglos*/

#include <stdio.h>

#include <conio.h>

main()

{

double carro[20];

int i, t = 20;

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

{

printf("Ingrese el valor %d: ", i+1);

scanf("%lf", &carro[i]);

}

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

{ printf("%f\n", carro[i]); }

getch();

}

Page 40: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 40

Inicializándolo en la misma declaración, en la forma:

float v[6] = {1., 2., 3., 3., 2., 1.};

double d[] = {1.2, 3.4, 5.1};

int f[100] = {0};

int h[10] = {1, 2, 3};

int mat[3][2] = {{1, 2}, {3, 4}, {5, 6}};

Ejemplo:

/*Uso de arreglos*/

#include <stdio.h>

#include <conio.h>

main()

{

float v[6] = {1.0f, 2.0f, 3.0f, 3.0f, 2.0f, 1.0f};

int c;

printf("Valores del arreglo*/

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

{

printf("%f\n", v[c]);

}

getch();

}

Donde en el primer y segundo ejemplo es necesario poner un punto decimal tras

cada cifra, para que ésta sea reconocida como un valor de tipo float o double.

Recuérdese que, al igual que las variables escalares correspondientes, los arrays

con modo de almacenamiento external y static se inicializan a cero

automáticamente en el momento de la declaración.

Sin embargo, esto no está garantizado en los arrays auto, y el que se haga o no

depende del compilador.

Page 41: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 41

4.3. Tipos Arreglos

Los arreglos se clasifican en dos grupos:

4.3.1. Unidimensionales:

También llamados vectores llamados así, de una dimensión o lineales; sin

embargo no cambia el ámbito de los elementos, todos contendrán un espacio de

memoria.

Su sintaxis:

Tipo-datos nombre [tamaño];

Si notas el arreglo contiene un par de corchetes que indican que los elementos

del arreglo estarán almacenados de forma lineal en cada espacio de memoria

Ejemplo char Demos [4];

1 2 3 4

Demos [0] Demos [1] Demos [2] Demos [3]

Cada casilla corresponde a un único número de espacio o también llamados

índices el tamaño del arreglo es de 4 elementos como se especifica en el grafico.

En C el primer elemento de un arreglo esta indicado con el índice cero, así si se

quiere acceder al primer elemento de un arreglo se escribirá de esta forma: char

Demo [0], y así sucesivamente i se quiere acceder al n-enésimo elemento seria

char Demo [n-1].

Page 42: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 42

4.3.2. Multidimensionales

También existen arreglos multidimensionales, C por ser un lenguaje muy

interactivo incorpora en su gama de herramientas, este tipo de arreglos los cuales

permiten almacenar mas información más organizadas, por lo general son

llamadas matrices.

Las dimensiones que se incluyen en este grupo son arreglos bidimensionales (dos

pares de corchetes o 2 índices) se podría representar gráficamente como una

tabla con filas y columnas, tridimensionales (3 pares de corchetes o 3 índices)

Este es comúnmente usado para trabajos gráficos en 3D.

En general la definición de un arreglo multidimensional será;

Tipo de dato nombre [tamaño1] [tamaño2] [tamano3]…. [Tamaño n].

En el siguiente ejemplo se ilustra un pequeño programa en c en el cual se utiliza 1

for para leer las filas y otro para leer las columnas de un arreglo bidimensional.

Hemos visto que un arreglo unidimensional de n elementos puede ser visto como

un espacio de memoria lineal ya que todos serán almacenados de manera

secuencial .Similarmente bidimensionales de pxd puede ser como una tabla de

valores que tiene pxm filas y d columnas tal como se ilustra en la figura:

Se tiene un arreglo bidimensional A[p][d]:

x Columnas

Filas

A00 A01 A02 A03 A04 A05 A06

A10 A11 A12 A13 A14 A15 A16

A20 A21 A22 A23 A24 A25 A26

A30 A31 A32 A33 A34 A35 A36

Page 43: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 43

Cada variable en cada cuadro representa la posición en arreglo los subíndices

00,01,02,03…, el primer número no es más que la posición de fila y el segundo

indica a la columna. Así A11 indica que el elemento está ubicado en la fila 1 (a

simple vista podríamos decir que se refiere a la segunda fila)y en la columna 1 y

así sucesivamente.

Al acceder al valor de un elemento específico se deberá jugar con estas

posiciones, por esto es importante saber cuál es la posición en memoria.

4.4. Generalidades

Ya hemos visto como operan los arreglos a nivel de hardware, ahora, como

escribirlo en C:

He aquí una m lista de declaración de arreglos bidimensionales:

char frutas[2][3]={manzana, pera , uva, naranja, noni, mango};

int valores[23][45];

static double lista[20][15];

float grupo [45][80];

La primera línea define un arreglo de frutas de 2 filas y 3 columnas (2*3=6, lo cual

serian 6 elementos) y si notas esta inicializado con los elementos manzana en la

posición 0,0, pera 0,1, uva 0,2, naranja 1,0, noni 1,1, mango 1,2,

Si un arreglo bidimensional es inicializado se debe tener cuidado se debe tener

cuidado ya que el orden natura l de los elementos se pueden alterar formando

grupo de valores iniciales encerrados entre llaves ({..}).Los valores dentro de cada

par interno de llaves serán asignados alos pares elementos del arreglo cuyo ultimo

índice varíe mas rápidamente .Por e ejemplo en un arreglo bidimensional los

valores almacenados dentro de un par de llaves serán asignados alos elementos

Page 44: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 44

de una fila , ya que el segundo índice (columna) se incrementara más

rápidamente .Si hay pocos elementos dentro de cada par de llaves , al resto de

cada par de filas se le asigna aran 0. Loor otra parte, el numero de valores dentro

de cada par de llaves no p puede exceder del tamaño de fila definido. Es de

agrupación puede ser útil en la generalización de arreglos de mayor dimensión.

Ejemplo:

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

Esta asignación seria así:

Valores[0][0]=1 Valores[0][1]=2 valores[0][2]=3 valores[0][3]=4

Valores[1][0]=5 Valores[1][1]=6 valores[1][2]=7 valores[1][3]=8

Valores[2][0]=9 valores[1][2]=10 valores[2][2]=11 valores[2][3]=12

Una variación a este caso con la utilización de la n llaves internas es :

int valores[3][4]={

{1, 2,3}

{4, 5,6}

{7, 8,9}

{10, 11,12,}

}

Esto nos lleva alo mismo, los cuatro valores del primer par de llaves internas son

asignados a los elementos de la primera fila del arreglo los valores de segundo

par de llaves son asignados a la segunda fila del arreglo .Nótese que el par de

llaves internos se necesitan para contener las llaves internas. En caso de que en

las llaves sean agrupados más elementos de los que se especifican en el tamaño

del arreglo ejemplo:

int valores[][]= {

{1, 2, 3, 4,5}

{6, 7, 8, 9,10}

{11, 12, 13, 14,15}

}

Page 45: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 45

El compilador lo detectara como un error, ya que el número de elementos excede

al tamaño del arreglo ya declarado.

Si en algún dado caso el arreglo contuviese un elemento menos del tamaño

especificado, es decir,

int valores[3][4]={1,2,3,4,5,6,7,8,9,10,11};

El elemento será rellenado con cero en este caso será de la siguiente manera:

Valores[0][0]=1 Valores[0][1]=2 valores[0][2]=3 valores[0][3]=4

Valores[1][0]=5 Valores[1][1]=6 valores[1][2]=7 valores[1][3]=8

Valores[2][0]=9 valores[1][2]=10 valores[2][2]=11 valores[2][3]=0

4.5. Arreglos y Cadenas

4.5.1. ¿Qué es una cadena?

Una cadena no es más que la secuencia de caracteres consecutivos incluyendo

espacios en blancos esta parte de la pronación es muy importante de conocer ya

que se trabajo al menos en con la manipulación de cadenas de caracteres, ya que

la mayoría de programas se utiliza esta naturaleza de nuestro lenguaje.

A veces resulta complicado trabajar con cadenas de caracteres si no es con la

auxiliarían de los arreglos como anteriormente lo habíamos dicho en un arreglo

unidimensional será fácil, trabajar con cadenas de caracteres, porque cada

carácter de una cadena se estacionaria en cada casilla un carácter, Pero a veces

las cadenas de caracteres necesitan operar como entidades propias es decir ser

almacenadas en un solo espacio de memoria (casilla).

Page 46: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 46

El siguiente programa es un boleto que trabaja con arreglos bidimensionales para

almacenar en un espacio de memoria los nombres de las personas que viajaran

en un determinado vuelo, y también se utilizan dos arreglos unidimensionales para

almacenar el destino y categoría que el cliente desee. La aerolínea necesita que

luego que el usuario ingrese sus datos y preferencias se imprima de manera

implícita el número de boletos, que el usuario a su preferencia llenara. A

continuación el código en el compilador de C:

/*Programa de un boleto en c*/

#include<stdio.h>

#include<conio.h>

#include<stdlib.h>

main()

{

char nomb[50][20];

int i,bol;

int dest[50], cat[50];

/******************************************************/

printf("BIENVENIDOS A SU AEROLINEA DOSSELL\ndigite la cantidad

de boletos: ");

scanf("%d",&bol);

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

{

printf("\nNombre: ");

scanf("%s", nomb[i]);

printf("\nDestino:\n(1):Bluefields\n(2):San juan\nDestino

seleccionado ");

scanf("%d", &dest[i]);

printf("Categoria:\n(1):Alta\n(2):Media\n(3):Baja\nCategoria

seleccionada ");

scanf("%d", &cat[i]);

}/*fin del primer for*/

system("cls");

/*Imprime los boletos con los datos antes almacenados, */

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

{

Page 47: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 47

printf("\n\nAerolinea Dossell\n");

printf("Numero de boletos: %d\n",i+1);

printf("Nombre: %s\n",nomb[i]);

if(dest[i] == 1)

{

printf("Destino: Bluefields");

printf("\nHora de salida: 9:00 am\nHora de llegada:

12:00 pm\n");

}

else

{

printf("Destino: San juan ");

printf("\nHora de salida: 1:00pm\nHora de llegada:

3:00pm");

}

if(cat[i]==1)

{

printf("\nCategoria: Alta\nCosto:C$250 ");

}

else if(cat[i]==2)

{

printf("\nCategoria: Media\nCosto:C$230\n");

}

else

{

printf("\nCategoria: Baja\nCosto:220\n");

}

printf("Asiento numero: %d\n",i);

getch();

}

system("cls");

printf("Buen viaje");

getch();

}

Page 48: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 48

La salida del programa seria la siguiente:

Cuantos boletos desea? 2

Nombre: dorissell Narváez Pérez

Destino:

(1):Bluefields.

(2):San juan.

Destino seleccionado 1

Categoría:

(1):Alta

(2):Media

(3):Baja

Categoria seleccionada: 3

Nombre: Jorge Luis Meyer

Destino:

(1):Bluefields.

(2):San juan.

Destino seleccionado 1

Categoría:

(1):Alta

(2):Media

(3):Baja

Categoria seleccionada: 2

/* después de un entre*/

Aerolínea Dossell

Numero de boleto:1

Nombre: dorissell Narváez Pérez

Destino:Bluefields hora de salida: 9:00 am hora de llegada: 12:00 pm

Categoria: Baja

Costo$ 220.

Asiento numero:0

Aerolínea Dossell

Numero de boleto:2

Nombre:jorge Luis Meyer

Destino:Bluefields hora de salida: 9:00 am hora de llegada: 12:00 pm

Categoria: Mediana

Costo$ 230.

Asiento numero:0

Page 49: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 49

Nótese que el número de asiento será siempre cero ya que la variable i esta

inicializada en cero. Si usted desea que el compilador arroje el número de boletos

igual como el número de asiento lo único que abría que modificar es que al

imprimir sustituya la variable i por la variable que almacena el número del boleto,

de esta manera estamos diciendo que según el número de boleto es el número del

asiento del cliente. O bien si usted desea agregarle un digito de entrada se podría

hacer de las siguiente forma.

printf(“Asiento numero:2104-0%d”,i);

Y esto aparecerá de la siguiente manera:

Aerolínea Dossell

Numero de boleto:2

Nombre: Jorge Luís Meyer

Destino: Bluefields hora de salida: 9:00 am hora de

llegada: 12:00 pm

Categoria: Mediana

Costo$ 230.

Asiento numero: 2104-02.

La lógica del programador es lo que hace la calidad y eficiencia de un programa y

además lo más importante que hace lo más completo y comprensible que sea

para el usuario.

Es importante añadir a este tema la funciones de biblioteca para manipular

cadenas, estas librerías son comúnmente conocidas como funciones de strings

tales como: stdlib.h y ctype.h que incluyen una gama de funciones de biblioteca

como atof, que convierte la porción inicial de una cadena a una representación

de double., y la función atoi, que al contrario convierte la porción inicial en y un

entero.

Su sintaxis es la siguiente:

atof(variable que indica la cadena )

atoi(variable que indica la cadena )

Page 50: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 50

Ejemplo 1:

El siguiente programa convierte un cadena a double y a una cadena de

representación entero. Nótese que en la utilización de las funciones de biblioteca

son incluidas sus librerías antes declaradas en la cabecera del programa.

/*Uso de atoi y atof*/

#include<stdio.h>

#include<stdlib.h>

#include<conio.h>

main()

{

char n1[20] = "10254.4116";

printf("Cadena \'%s\' convertida a double = %f\n", n1, atof(n1));

printf("Cadena \'%s\' convertida a entero = %d\n", n1, atoi(n1));

getch();

}

Ejemplo 2:

El siguiente código es de un programa para leer una cadena de caracteres

minúscula a mayúscula. Se utilizan la función toupper: esta función tiene como

parámetro la variable que almacena el arreglo de cadena de caracteres, la cual

convertirá a mayúscula , en caso de que está este en minúscula.

# include<stdio.h>

# include<conio.h> /* declaración de librerías */

# include<ctype.h>

main()

{

char cadena[]="la victoria se consigue cayendo levantándose y volver

a caer";

int i;

printf("Cadena antes de convertir:\n%s\n", cadena);

for(i=0;cadena[i];i++)

{

cadena[i]=toupper(cadena[i]);

}

printf("Cadena despues de convertir:\n%s\n", cadena); getch();

} /*fin del programa principal*/

Page 51: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 51

Ejemplo 3:

En el siguiente código muestra más funciones strings como:

sprintf(): imprime un mensaje .

strstr(cad 1, cad 2):localiza la primera aparición en la cadena apuntada por la

constante escrita en el argumento de la secuencia de caracteres

(excluyendo el carácter nulo), es decir la primera cadena , en la

segunda cadena .

strcat(): añade una copia de la primera cadena escrita en el argumento de la

función , incluyendo el carácter nulo en la segunda cadena que se

escribió en el argumento de la función.

# include<stdio.h>

# include<string.h> /*declaración de librerías */

# include<conio.h>

main()

{

char mensaje[50];

char mens1[30]= "lo siento mucho ";/*declaración de arreglos de

cadenas */

char mens2[6]="mucho";

char mens3[]="mu";

printf("strstr(mens1[], mens2[])=%s\n",strstr(mens1, mens2));

if (strstr(mens2,mens3))/*localiza la primera letra ´m'*/

{

strcat(mens1,mens2);/*copia 'mucho' de ultimo de la cadena

'lo siento mucho'*/

sprintf(mensaje,"\nhola %s", mens1);

puts(mensaje);

}

getch();

}/*fin del programa principal*/

La salida del programa seria “hola lo siento mucho mucho”

Page 52: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 52

Ejemplo 4:

El siguiente código es acerca de un programa interactivo Para definir la profesión

del usuario.

Se utilizan las funciones, sprintf () y puts (): esta última tiene la misma función

como la conocemos pone un mensaje existente en el sistema y lo visualiza.

#include<stdio.h>

#include<stdlib.h>

#include<conio.h>

int main()

{

char nombre[10],mensaje[200];

unsigned int edad =0, U;

system("cls");

printf("\nCual es su nombre: "); gets(nombre);

printf("\nCual es su edad: "); scanf("%d", &edad);

printf("\nCual ES LA UNIVERISDAD EN LA QUE ESTUDIAS\n");

printf("1):UNI \n2):ex\n3);UNAN\nSeleccione una opcion: ");

scanf("%d", &U);

system("cls");

if(U==1)

{

sprintf(mensaje, "\nHola%s.\ntienes %d años de edad \n serás

un ingeniero de la %s", nombre,edad, "UNI");

}

else if(U==2)

{

sprintf(mensaje, "\n\nHola %stienes%d años\n serás un

licenciado en ciencias comerciales de: %s", nombre,edad, "EX");

}

else

{

sprintf(mensaje, "\n\nHola%s, tienes%d años\n y serás un

licenciado de la %s ", nombre,edad, "UNAN");

}

puts (mensaje); getch();

}

Page 53: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 53

Ejemplo 5:

Este programa utiliza las funciones strcpy (copia dos cadenas), strcat, strcmp

(compara dos cadenas).

/*programa que lee tres cadenas para formar dos copias las comparala y

define su longitud**/

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#include<conio.h>

main()

{

char pn[50]="DORISSELL", cn[50]=" PEREZ", tn[50]="NARVAEZ",

sn[50]="SOCORRO ", *n, *p;

int c;

system("cls");

strcat(pn," del "); /* copia "DORISSELL del" es decir 'del ' a

la cadena pn*/

n=strcat(pn, sn); /* copia "DORISSELL del SOCORRO", añadió */

printf("%s\n",n); /* imprime la cadena r almacenada en la varible

n*/

p=strcat(tn,cn);

printf("%s\n",p);

c=strcmp(pn,tn); /*Compararlas dos cadenas "DORISSELL" y

"NARVÁEZ"*/

printf("pn es ");

if (c<0)

printf("menor que");

else if(c == 0)

printf("igual que");

else

printf("mayor que");

printf(" tn\n");

strcat(pn,tn);

printf("pn=%s\n",pn);

printf("la cadena pn contiene: %d caracteres\n", strlen(pn));

getch();

}

Page 54: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 54

4.6. Procesamiento de arreglos.

No se permiten operaciones que impliquen arreglos completos. Por lo tanto para

realizar operaciones de asignación de dos arreglos similares (mismos tipo de

datos, misma dimensionalidad y mismo tamaño), deben de realizarse elemento

por elemento. Esto es posible normalmente dentro de un bucle donde cada paso

del bucle se usa para procesar un elemento del arreglo.

4.7. Paso de arreglos a funciones.

Un arreglo completo puede ser pasado a una función, para tal hecho el nombre

del arreglo debe de aparecer solo, es decir sin: corchetes ni índices como un

argumento actual dentro de la llamada a la función. El correspondiente argumento

formal se escribe de la misma manera, pero debe de ser declarado como un

arreglo de la función.

Al escribir prototipos de funciones que incluyan argumentos de arreglos una pareja

vacía de corchetes debe seguir el nombre del arreglo, es posible omitir el nombre

del argumento del arreglo pero entonces una pareja vacía de corchetes debe

seguir al tipo de datos de argumento de arreglo.

Cuando se pasa una arreglo a una función no se pasan a esta (función) los

valores de los elementos del arreglo, porque el nombre del arreglo se interpreta

como la dirección del primer elemento del arreglo por lo tanto lo arreglos se dice

que son pasados por referencia a una función.

Si un elemento del arreglo es modificado dentro de la función, esta modificación

será reconocida en la parte del programa desde la que se hizo la llamada.

Page 55: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 55

Ejemplo:

/*Programa que pasa un arreglo de 4 elementos a una función donde son

modificados los valores se escriben en tres ocasiones para mostrar los

cambios*/

#include <stdio.h>

#include <conio.h>

#define max 4

void cambiar (int numeros []);

main()

{

int sum, numeros[max];

clrscr();

printf("\t\ndesde el programa principal antes de llamar a la

función\n\n");

for(sum=0; sum<=max; ++sum)

{

numeros[sum]= sum +1;

printf("a[%d]=%d\n",sum,numeros[sum]);

}

cambiar(numeros);

printf("\ndesde el programa principal después de llamar a la

función:\n\n");

for(sum=0; sum<=max; ++sum)

printf("numeros[%d]=%d\n", sum, numeros[sum]); getch();

}

void cambiar(int numeros[])

{

int sum;

printf("desde la función después de modificar los elementos\n\n");

for(sum=0;sum<=max;++sum)

{

numeros[sum]=10;

printf("numeros[%d]=%d\n", sum, numeros[sum]);

}

return;

}

Page 56: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 56

En este ejemplo podemos observar que al arreglo se le asigna los valores de

a[0]=1, a[1]=2, a[2]=3 en la función main, luego estos valores se trasladan a la

función cambiar , donde se le asigna el valor de 10 a cada elemento del arreglo

estos valores se escriben en main, y finalmente arreglo es escrtto una vez que se

le pasa el control a main.

Podemos llegar a la conclusión que los elementos de “numeros” se modifican

dentro de main después de hacer una llamada a la función cambiar.

Page 57: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 57

5. Funciones

5.1. Que son funciones

Las funciones en el lenguaje “C” son subprogramas, cuya finalidad es hacer una

tarea específica y retornar un valor al programa principal, si es requerido. Otra

función de las funciones es el de hacer el programa principal no muy extenso.

5.2. Declaración de funciones

Las funciones se declaran, se definen, son llamadas desde el programa principal,

son hechas o creadas por el usuario, y están compuestas por una cabecera y el

cuerpo de la función.

La sintaxis de una función es la siguiente: (lo que esta entre corchetes no es

siempre necesario utilizarlo)

[clase] [tipo] nombre (

tipo argumento formal 1,

tipo argumento forma 2, ...,

tipo argumento formal n)

{

[Declaraciones]; --> parámetros actuales

Instrucciones;

return (expresión);

}

El return devuelve el carácter convertido al punto del programa de llamada de la

función.

El parámetro actual es aquel que se recibe en la función y debe tener dato. El

parámetro actual es declarado dentro del programa principal.

Page 58: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 58

El parámetro o argumento formal es aquel que se recibe en la definición de la

función y los parámetros, tanto formales como actuales debe de ser iguales.

La declaración de las funciones puede ser implícita o explicita. La implícita se da

cuando la función es llama y no existe una declaración previa, y por defecto “C”

construye una función prototipo de resultado entero. En la explicita se permite

conocer las características de la función antes de ser usada, es decir se conoce el

tipo. La declaración de funciones se hace después de la declaración de las

librerías. La llamada de las funciones de hacen desde el programan principal, es

decir dentro del main. Con la siguiente sintaxis:

[Variable] = nombre _ función ([argumentos actuales o parámetros

actuales]);.

Ahora veremos algunos ejemplos de lo descrito anteriormente:

Ejemplo:

#include <stdio.h> /* librerías */

#include <conio.h>

/* declaración explicita (no es necesaria si el valor de retornos es

entero) */

int escribir (int y);

main()

{ /* Inicio del Programa Principal */

int r, b=5; /* declaración de variables */

/* asignación a r el valor de la función con parámetro actual llamando a

la función */

r = escribir (b);

printf("r = %d \n", r); /* salida del valor r */

getch(); /* espera una tecla para salir */

} /* fin del programa principal */

int escribir (int y) /* definición de la función con parámetro formal

*/

{

return (y *3); /* instrucción que retorna el valor a la

función */

}

Page 59: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 59

Ejemplo:

/* librerías */

#include <stdio.h>

#include <conio.h>

#include <math.h>

/*declaración explicita (no es necesaria si el valor de retornos es

entero)*/

float hipotenusa (float a, float b);

main()

{ /* Inicio del Programa Principal */

/* declaración de variables */

float a, b, h;

clrscr(); /*borra pantalla*/

printf("Escriba el valor de los catetos: ");

scanf("%f %f", &a, &b);

h = hipotenusa(a,b); /* llamada de la función hipotenusa*/

printf("el valor de la hipotenusa es = %f",h); /*imprime el valor

de la hipotenusa*/

getch(); /* espera una tecla para salir */

} /* fin del programa principal */

/* definición de la función con parámetro formal */

float hipotenusa (float a, float b)

{

/*instrucción de la función*/

float y;

y = sqrt ((pow (a,2))+ (pow (b,2)));

/* instrucción que retorna el valor a la función */

return y;

}

Page 60: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 60

5.3. Llamadas a función

Se conoce como llamada a función cuando se invoca o manda a ejecutar una

función previamente creada, ya sea que esta se encuentre el las librerías o sea

programada por el usuario. Una llamada a función es una expresión con todo lo

que ello implica.

Para llamar a una función se escribe el nombre de la función y entre paréntesis se

especifican los valores que se desean dar a los argumentos.

Ej:

mi_funcion(expr1, expr2, …)

Cada Expresión se evalúa y el valor devuelto es pasado como argumento a la

función, la expresión debe devolver un tipo compatible al argumento de la función,

o se puede forzar otro tipo mediante la conversión de tipos.

No es obligatorio guardar el valor devuelto por la función, si es que esta devuelve

alguno, hay momentos en que no necesitamos saber que devuelve la función, por

ejemplo: la función printf y scanf devuelven un valor entero al ser llamadas, pero

es poco común para la mayoria utilizar estos valores.

5.4. Parámetros por valor.

Existen dos formas mediante las cuales se pueden pasar valores a las función, las

formas en que utilicemos una u otra forma depende de la necesidad que se nos

presente, el primero es el paso por valor, los que significa que el realidad nosotros

el la función recibimos una copia del dato mandado, no el dato original, por lo tanto

cualquier modificación sobre este dato no afectará al valor de donde fue llamada la

función, un ejemplo practico sería intercambiar los valores de dos variables:

Page 61: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 61

Ejemplo:

#include <stdio.h>

#include <conio.h>

/*Declaracion de la funcion*/

void intercambiar(int a, int b);

main() /*Programa principal*/

{

/*Declaracion de variables*/

int a = 10, b = 20;

printf("Valores antes de llamar a la funcion:\na=%d\tb=%d\n", a,

b);

intercambiar(a, b); /*Llamada a la funcion*/

printf("Valores después de llamar a la funcion:\na=%d\tb=%d\n", a,

b);

getch();

}/*Fin del main*/

/*Definicion de la funcion*/

void intercambiar(int a, int b)

{

int c;

c = a;

a = b;

b = c;

}

Resultado:

Valores antes de llamar a la función:

a=10 y b=20

Valores después de llamar a la función:

a=10 y b=20

Como podemos ver a pesar de haber modificado los valores recibidos dentro de la

función los valores originales no fueron alterados.

Page 62: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 62

5.5. Parámetros por referencia

Se les conoce como parámetros por referencia porque en realidad cuando se

llama a la función no se manda una copia del dato como parámetro sino una

referencia al dato original, o en otras palabras donde se encuentra este dato, esto

permite a la función modificar el dato original ya que esta tiene la dirección donde

se encuentra almacenado y simplemente precede a modificar el valor de esa

dirección, veamos el ejemplo anterior pero con parámetros por referencia.

#include <stdio.h>

#include <conio.h>

/*Declaracion de la funcion*/

void intercambiar(int *a, int *b);

main() /*Programa principal*/

{

/*Declaracion de variables*/

int a = 10, b = 20;

printf("Valores antes de llamar a la funcion:\na=%d\tb=%d\n", a,

b);

intercambiar(&a, &b); /*Llamada a la funcion*/

printf("Valores después de llamar a la funcion:\na=%d\tb=%d\n", a,

b);

getch();

}/*Fin del main*/

/*Definicion de la funcion*/

void intercambiar(int *a, int *b)

{

int c;

c = *a;

*a = *b;

*b = c;

}

Resultado:

Valores antes de llamar a la función: a=10 y b=20

Valores después de llamar a la función: a=20 y b=10

Page 63: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 63

A diferencia del ejemplo anterior ahora los valores de las variables si fueron

modificados, para declarar parámetros por referencia utilizamos el símbolo * antes

del nombre del parámetro, además de esto para poder acceder al valor del

parámetro y no su dirección se debe anteponer *, esto le indica al compilador que

queremos acceder al dato no a la dirección, también es importante aclarar que a

la hora de enviar los parámetros se debe utilizar el operador & el cual devuelve la

dirección de memoria donde se encuentra almacenado el dato. De manera general

la declaración de parámetros por referencia quedaría de la forma.

<tipo> <nombre_funcon> (

<tipo> *<identificador>,

<tipo> *<identificador>,

...)

Page 64: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 64

6. Punteros Y Manejo De Archivos

6.1. Punteros

6.1.1. Concepto de Puntero.

Un Puntero contiene una dirección de memoria.

Cuando una variable contiene la dirección de otra variable se dice que la primera

variable apunta a la segunda.

Dicho de forma específica, un puntero es una variable que contiene la dirección de

memoria de otra variable. Se utilizan para pasar información entre una función y

sus puntos de llamada.

6.1.2. Declaración de punteros

La forma general para declarar una variable puntero es:

tipo *nombre;

donde tipo es cualquier tipo valido de C (también llamado tipo base) y nombre es

el nombre de la variable puntero.

6.1.3. Operadores de Punteros.

Existen dos Operadores especiales de punteros: & y *. Estos dos operadores son

monarios y no tienen nada que ver con los operadores binarios de multiplicación

(*) y de and a nivel de bits (&).

Page 65: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 65

6.1.3.1. Operador &.

& es un operador monario que devuelve la dirección de memoria de su operando.

Por ejemplo, si queremos guardar en el puntero x la dirección de memoria de la

variable num, deberemos hacer lo siguiente:

x=&num;

Ejemplo:

#include<stdio.h>

#include<conio.h>

/*Funcion principal*/

main()

{

int x = 10; /*Declaracion de variable*/

/*Se muestra el valor y la direccion de memoria de x*/

printf("x=%d\n&x =%p\n",x,&x);

getch();

}

Salida del ejemplo anterior:

x=10

&x = 8FBC: OFFE.

Nota:

El valor y formato de las direcciones de las variables que se imprimen en esta

lección (con el código de formato %p) son dependientes de la implementación. En

mi caso las direcciones se escriben en formato segmento offset, y e valor de la

dirección de una variable es distinto según cuando y desde donde se ejecuta el

programa

Page 66: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 66

6.1.3.2. Operador*

El operador * es el complemento de &. Es un operador monario que devuelve el

valor de la variable localizada en la dirección que sigue es decir devuelve el valor

de la variable cuya dirección es contenida por el puntero. Este ejemplo sitúa el

contenido de la variable apuntada por x, es decir num, en la variable a:

a=*x;

Ejemplo1:

#include<stdio.h>

#include<conio.h>

/*Funcion principal*/

main()

{

int x = 10; /*Declaracion de x*/

printf("x = %d \n",x); /*Se muestra el valor de x*/

printf("*&x = %d", *&x); /*Se muestra el valor apuntado por direccion

&x*/

getch();

}

Salida del ejemplo1:

x = 10

*&x = 10

Page 67: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 67

Ejemplo 2:

#include<stdio.h>

#include<conio.h>

main()

{

int x = 10;

int *px;

px = &x;

printf("x = %d\n",x);

printf("&x = %p\n", &x);

printf("px = %p\n", px);

printf("&px = %p\n", &px);

printf("*px = %d", *px);

getch();

}

Salida del ejemplo:

x = 10

&x = 8FC4: OFFE

px = 8FC4: OFFE

&px = 8FC4: OFFA

*px = 10

Gráficamente:

En el ejemplo anterior se observa que hay tres valores asociados a los punteros:

Dirección en la que se encuentra.

Dirección a la que apunta.

Valor contenido en la dirección apuntada.

Nota:

Al ejecutar el siguiente programa los resultados pueden ser inesperados ya que

estamos asignado el valor 10 en una posición de memoria no reservada.

px

8FC4: OFFE

8FC4: OFFE

x

8FC4: OFFE

10

Page 68: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 68

#include<stdio.h>

#include<conio.h>

main()

{

int *p;

printf("Dirección: %p", p);

printf("Valor antes de asignar: %d", *p);

*p = 10;

printf("Valor asignado: %d", *p);

getch();

}

Seria correcto:

#include<stdio.h>

#include<conio.h>

main()

{

int x; /*se reserva memoria para x*/

int *p; /*se reserva memoria para la variable p, no para la

posición de memoria a la que apunta p*/

printf("Direccion de:\n&x = %p\np = %p\n", &x, p);

p = &x; /*p apunta a valor de x*/

printf("Direccion despues de asignar:\n&x = %p\np = %p\n", &x, p);

*p = 10; /*equivalente a x = 10*/

printf("Valor de x: %d\nValor apuntado por *p: %d\n", x, *p);

getch();

}

6.1.4. Aritmética de Punteros.

Existen 4 operadores que realizan operaciones aritméticas que pueden utilizarse

con punteros. Es posible desplazar un puntero recorriendo posiciones de memoria.

Para ello podemos usar los operadores de suma, resta, incremento y decremento

(+, -, ++, - -). Si tenemos un puntero ( p1 ) de tipo int ( 2 bytes ), apuntando a la

posición 30000 y hacemos: p1=p1+5; el puntero almacenará la posición 30010,

porque apunta 5 enteros por encima ( 10 bytes más ).

Page 69: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 69

Ejemplo:

#include<stdio.h>

#include<conio.h>

main ()

{

int *p;

#define imprimir_p printf("\np = %p",p);

imprimir_p;

printf ("\tsizeof (*p) = %d",sizeof(*p));

p++; imprimir_p;

p -=5; imprimir_p;

getch();

}

Salida del ejemplo:

p = 7203:8D51 sizeof (*p) = 2

p = 7203:8D53

p = 7203:8D49

En el ejemplo se aprecia que si hacemos p++; no aumenta el valor de p en 1 sino

que aumenta en 2, que s el tamaño en bytes de un int, es decir, el tamaño del

objeto al que apunta.

Por lo tanto, la sentencia p++ hay que interpretarla de la siguiente forma:<<p

apunta al siguiente elemento del tipo base>>. Lo mismo se puede decir e los

demás operadores aritméticos aplicados a los punteros.

Toda la aritmética de punteros esta en relación con el tipo base del puntero por lo

que el puntero esta siempre apuntado al elemento apropiado del tipo base.

Page 70: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 70

6.1.5. Asignación dinámica de Memoria.

Supóngase que queremos hacer un programa que lea n valores enteros

introducidos por teclado por el usuario, los almacene en un vector y los imprima en

un orden inverso.

Solución:

#include<stdio.h>

#include<conio.h>

main()

{

#define NMAX 100 /*número máximo de elementos*/

int v[NMAX]; /*vector*/

int n = 0; /*número de elementos introducidos*/

int varaux;/*variable auxiliar*/

register int i; /*indice*/

do

{

printf("\nIntroduce número de valores a leer (1 - %d): ",

NMAX);

scanf ("%d", &n);

} while (n < 1 || n > NMAX);

for (i = 0; i <= n - 1; i++)

{

printf("Introduce valor %d: ", i+1);

scanf("%d", &varaux);

v[i] = varaux;

}

printf("\n\nvalores en orden inverso: \n");

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

printf("Valore %d = %d\n", i+1, v[i]);

getch();

}

Page 71: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 71

Si el usuario introduce como valor de n, el valor 10, estaremos desperdiciando, si

un int ocupa 2 bytes, 90*2 bytes de memoria. Además, el usuario no puede

introducir más de NMAX valores. Estas restricciones vienen impuestas porque el

tamaño de un array en la declaración ha de ser una expresión constante. La

asignación de memoria en este caso se dice que es estática porque se determino

en el momento de la compilación. Cuando la asignación de memoria se determina

en tiempo de ejecución se dice que es asignación dinámica.

Veamos como se haría el programa anterior con asignación dinámica y luego

pasamos a explicarlo:

#include<stdio.h>/*printf(), scanf()*/

#include<conio.h>/*getch();*/

#include<malloc.h>/*malloc(), free()*/

main() {

int *v; /*vector*/

/*número de elementos introducidos y variable auxiliar*/

int n = 0, varaux;

register int i; /*indice*/

printf("\nIntroduce número de valores a leer: ");

scanf("%d", &n);

v = (int *) malloc(n * sizeof(int));

if (v == NULL)

printf("Memoria insuficiente.");

else {

for (i = 0; i <= n - 1; i++)

{

printf("Introduce valor %d: ", i+1);

scanf("%d", &varaux); v[i] = varaux;

}

printf("\n\n valores en orden inverso: \n");

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

printf("Valor %d = %d", i+1, v[i]);

free(v);

}

getch();

}

Page 72: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 72

La primera sentencia de main() es:

int *x;

En esta declaración estamos declarando v como un puntero a entero.

La siguiente línea <<extraña>> para nosotros es:

v = (int *) malloc (n * sizeof (int));

La función malloc reserva memoria; acepta como argumento los bytes de memoria

a reserva y devuelve un puntero al primer byte de la zona de memoria reservada;

los bytes de memoria solicitados los reserva en un espacio de memoria contiguo.

Si no hay suficiente memoria, devuelve NULL. Un puntero que tiene el valor NULL

es un puntero que no apunta a ningún sitio.

El prototipo de esta función se encuentra en el fichero malloc.h (de ahí el incluir

este fichero en nuestro ejemplo) y es el siguiente:

void * malloc (unsigned in bytes);

Veamos que devuelve un puntero a void; esto quiere decir que devuelve un

puntero que apunta a cualquier tipo base, o dicho de otro modo, un puntero que

apunta a una dirección de memoria sin tener tipo base.

El c de Kernighan y Ritchie, como no tiene tipo void, el prototipo de esta función

es:

char * malloc (unsigned int bytes);

En ambos casos, el tratamiento por parte del usuario de esta función es

exactamente el mismo. Veamos otra vez la llamada a esta función en nuestro

ejemplo:

v = (int *) malloc (n * sizeof (int));

Page 73: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 73

Al valor devuelto por la función malloc (puntero a void o puntero a char) siempre

se le realiza un moldeado (debemos recordar que esto se hacia con: (tipo)) para

adecuarlo al tipo base de nuestro puntero que va a apuntar a esa zona de

memoria reservada. En nuestro caso el molde es:

(int *x) /*puntero a entero*/

El puntero que le pasamos a malloc ha de ser el número de bytes de memoria a

reservar. Esto siempre se hace siguiendo la fórmula:

número_de_elementos * sizeof (tipo_de_cada_elemento).

Que traducido a nuestro caso queda:

n * sizeof (int)

Otra forma e hacer lo mismo es:

N * sizeof (*x)

Que suele ser muy corriente. Las dos formas son equivalentes.

La memoria asignada por malloc se desasigna con la función free(). Esta memoria

asignada no se desasigna al salir del bloque de código en que fue asignada como

ocurre con las variables locales sino con la función free(liberar) o al terminar el

programa. Por lo tanto, siempre que asignemos memoria con malloc, tenemos que

desasignarla con free cuando ya no nos sea necesaria.

El prototipo de la función free se encuentra en el fichero malloc.h y es el siguiente:

void free (void *p);

Un puntero a void como parámetro indica que acepta cualquier puntero,

independientemente del tipo base al que apunta. El puntero que se le pasa a free

como argumento ha de ser un puntero que apunta al principio de una zona

reservad anteriormente por malloc; sino es así, se puede caer el sistema.

El resto del ejemplo no tiene ya ninguna dificultad.

Page 74: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 74

Hay otra función, en la librería <alloc.h> equivalente a malloc, que es la función

calloc cuyo prototipo es el siguiente:

void * calloc (

unsigned número_de_elementos_a_reservar,

unsigned tamaño_en_bytes_de_cada_elemento);

Esta función es igual que malloc con la única diferencia de sus parámetros.

En turbo C, los prototipos de las funciones malloc(), calloc() y free(), además de

estar en el fichero alloc.h, también están en el fichero stdlib.h

6.1.6. Punteros y arrays.

Existe una estrecha relación entre los punteros y los arrays. El nombre de un array

es un puntero al primer elemento del array.

A cualquier elemento de un array podemos acceder mediante la aritmética de

punteros y viceversa, cualquier puntero lo podemos indexar con los []:

6.1.6.1. Arrays unidimensionales:

p[i] == *(p+i)

6.1.6.2. Arrays bidimensionales:

p[i][j] == *(p+(i *longitud_fila)+k) == *(*(p+i)+j)

6.1.6.3. Arrays muldimensionales:

Se sigue cualquiera de los dos procedimientos ejemplarizados en los arrays

bidimensionales.

Page 75: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 75

Ejemplo de acceso a un Array con un Puntero.

#include<stdio.h>

#include<conio.h>

main()

{

/*Arreglo unidimensional*/

float v[3] = {1.1, 2.2, 3.3};

/*Se muestran los valores*/

printf ("v[1] = %g; *(v+1) = %g", v[1], *(v+1));

getch();

}

Salida: v[1] = 2.2; *(v+1) = 2.2

Ejemplo de acceso a elementos indexando un puntero con [ ].

#include<stdio.h> /*printf (), NULL*/

#include<malloc.h> /*malloc (), free ()*/

#include<conio.h>

main()

{

float *p;

if ((p = (float *)malloc(3*sizeof (float)))== NULL)

printf("\nERROR: Memoria insuficiente.");

else

{

*p = 1.1; *(p+1) = 2.2; *(p+3) = 3.3;

printf ("*(p+1) =%g p[1] =%g",*(p+1), p[1]);

free(p);

}

getch();

}

Salida: *(p+1) = 2.2; p[1] = 2.2

Nota:

Los programadores profesionales de C suelen utilizar la notación puntero en vez

de la notación array porque es bastante más rápido y más cómodo, aunque para

los no acostumbrados a esta notación se ve un poco extraño al principio.

Page 76: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 76

Vemos que en la notación array, para acceder a un determinado elemento, el

compilador tiene que hacer una serie de cálculos para averiguar en que posición

está, mientras que en la notación puntero basta con una simple suma.

No obstante, cuando el código queda más claro en la notación array que con la

notación puntero es preferible la primera notación.

Cuando se trabaja con cadena de caracteres si se debe utilizar la notación

puntero, no ya solo por eficiencia sino también por convención.

Una estructura común en C es el array de punteros. Recordar que el argumento

array de la función main () es un array de punteros a caracteres.

Hay tres formas equivalentes de declarar el argumento argv en la función main():

main (int argc, char argv[ ][ ]);

main (int argc, char *argv[ ]);

main (int argc, char **argv);

Se observa que en la primera declaración no se ha especificado el tamaño de la

segunda dimensión de argv cuando habíamos dicho antes que era necesario, esto

solo está permitido hacerlo en la función main().

La declaración para un array de 10 punteros a int es:

int *x[10];

Para asignar la dirección de una variable entera llamada ver al tercer elemento del

array de punteros, se escribe:

x[2] = &var;

Page 77: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 77

Ejemplo de array de cadenas de caracteres.

#include<stdio.h>

#include<stdlib.h>

#include<conio.h>

void error (int numero_de_error)

{

char *errores[ ] =

{

"error al intentar abrir fichero",

"error al intentar cerrar fichero",

"error al intentar leer de fichero",

"error al intentar escribir en fichero"

};

printf ("Error %d. %s.",

numero_de_error, errores [numero_de_error]);

getch(); exit(1);

}

main()

{

int n = 1;

error(n);

}

Un array de puntero es lo mismo que punteros a punteros.

Este ejemplo comprueba dicha afirmación.

#include<stdio.h>

#include<conio.h>

main ()

{

int x, *p, **q;

x = 10; p = &x; q = &p;

printf("x = %d; *p = %d; **q = %d",x,*p,**q);

getch();

}

Salida:

x = 10; *p = 10; **q = 10.

Page 78: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 78

Vamos a mostrar dos formas de implementar la siguiente función: la función a

implementar acepta como argumentos una matriz de enteros y un elemento, y

devuelve 1 si ese elemento se encuentra en la matriz o 0 si dicho elemento no se

encuentra en la matriz.

/*Las funciones a buscar_en_matriz_versión_1()

buscar_en_matriz_versión_2() son equivalentes pero la segunda es mucho

más eficiente*/

#include<stdio.h>

#include<conio.h>

#define N 3

int buscar_en_matriz_version_1(int m[N][N], int x)

{

register int i, j;

int encontrado = 0;

for (i = 0; ! encontrado && i < N; i++)

for (j = 0; ! encontrado && j< N; j++)

if (m[i][j]== x)

encontrado = 1;

return (encontrado);

}

int buscar_en_matriz_version_2 (int m[N][N], int x)

{

register int i;

int encontrado = 0;

int *pm = (int*)m; /*declara pm como puntero a int y lo hace a

puntar a m*/

for (i = 1; ! encontrado && i<= N *N; i++)

{

if (*pm == x)

encontrado = 1;

else

pm++;

}

return(encontrado);

}

Page 79: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 79

main()

{

int matriz [N][N] = {{1,2,3}, {-1,-2,-3}, {5,6,7}};

int resultado_1 = buscar_en_matriz_version_1 (matriz,6);

int resultado_2 = buscar_en_matriz_version_1 (matriz,8);

int resultado_3 = buscar_en_matriz_version_2 (matriz,6);

int resultado_4 = buscar_en_matriz_version_2 (matriz,8);

printf("\n resultado_1 = %d", resultado_1);

printf("\n resultado_2 = %d", resultado_2);

printf("\n resultado_3 = %d", resultado_3);

printf("\n resultado_4 = %d", resultado_4);

getch();

}

Salida:

resultado_1 = 1

resultado_2 = 0

resultado_3 = 1

resultado_4 = 0

Page 80: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 80

6.1.7. Inicializaciones de punteros

Un puntero que tiene el valor NULL es un puntero que no apunta a ningún sitio.

Una inicialización muy común en C se ilustra con el siguiente ejemplo:

char *p = “cadena\n”;

En este caso el compilador guarda “cadena\n” en memoria y hace que p apunte al

principio de la cadena, es decir, el carácter „c‟.

Ejemplo de inicializaciones equivalentes.

int x = 10; <==> int x = 10;

int *p = &x; int *p;

p = &x;

int x, *p, y; <==> int x;

int *p;

int y;

int *p, *q, r = 10; <==> int *p ;

int *q;

int r =10;

int v[2] = {1,2}, f (void), *p, x = 3; <==> int v[2] = {1,2};

int f (void);

int *p;

int x = 3;

Page 81: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 81

6.1.8. Punteros a funciones.

Una característica algo confusa pero muy útil de C es el puntero a función. La

confusión surge porque una función tiene una posición física en memoria que

puede asignarse a un puntero aunque la función no es una variable. La dirección

de la función es el punto de entrada de la función; por tanto, un puntero a función,

puede utilizarse para llamar a la función.

Ejemplo:

#include<stdio.h> /*printf ()*/

#include<conio.h>

main()

{

/*escribir es una función que acepta un int como argumento y no devuelve

nada*/

void escribir (int);

/*pf es un puntero a una función que acepta un int como argumento y no

devuelve nada*/

void (*pf)(int);

pf = escribir;

escribir (1); /*llama a la función escribir*/

(*pf)(2); /*llama a la función escribir a través e un puntero*/

getch();

}

void escribir (int numero)

{

printf ("%d", numero);

}

Salida: 12

Page 82: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 82

6.1.9. Modificador de acceso const y punteros.

El modificador de acceso const aplicado a punteros ofrece varias posibilidades.

Veámosla en los siguientes ejemplos:

main()

{

char *p1 = "abc"; /*puntero*/

const char *p2 = "abc"; /*puntero a constante*/

char *const p3 = "abc"; /*puntero constante*/

const char *const p4 = "abc"; /*puntero constante a constante*/

*p1 = 'd'; /*correcto*/

*p2 = 'd'; /*error*/

*p3 = 'd'; /*correcto*/

*p4 = 'd'; /*error*/

p1++; /*correcto*/

p2++; /*correcto*/

p3++; /*error*/

p4++; /*error*/

p1 = p2; /*warning*/

p1 = p3; /*correcto*/

p1 = p4; /*warning*/

p2 = p1; /*correcto*/

p2 = p3; /*correcto*/

p2 = p4; /*correcto*/

p3 = p1; /*error*/

p3 = p2; /*error*/

p3 = p4; /*error*/

p4 = p1; /*error*/

p4 = p2; /*error*/

p4 = p3; /*error*/

}

Las líneas que contienen el mensaje de error provocan un error de compilación.

Page 83: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 83

Las líneas que contienen el mensaje de warning provocan en algunos

compiladores un mensaje de conversión de puntero sospechosa que se puede

solucionar haciendo la conversión de una forma explícita:

p1 = (char *) p2;

p1 = (char *) p4;

Si ahora hacemos:

*p1 = „d‟;

Estamos modificando los valores apuntados por p2 y p4; es decir, los valores

apuntados por p2 y p4; es decir, los valores apuntados por p2 y p4 no pueden ser

modificados por estos punteros pero si pueden ser modificados indirectamente por

otro puntero.

Otro ejemplo de cómo se puede modificar el valor de una constante

indirectamente a través de un puntero:

Const int x = 10; /*x es una variable constante*/

x = 20; /*esto provoca un error en compilación*/

*(int*)&x = 20; /*esto es correcto: obtenemos su dirección, que

es del tipo (const int*) y la moldeamos al tipo

(int *), una vez hecho esto accedemos al valor de

esa dirección con el operador de contenido* */

Page 84: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 84

6.1.10. Declaraciones curiosas.

El C permite la creación de formas de datos muy elaboradas.

Cuando se hace una declaración, el nombre (o “identificador”) que usamos se

puede modificador añadiéndole uno o varios modificadores:

Modificador Significado

* indica puntero

() indica una función

[] indica un array

La clave para desentrañar las declaraciones que mostraremos a continuación es

averiguar el orden en que se aplican los modificadores.

Para ello se siguen tres reglas:

La prioridad de un modificador es tanto mayor cuanto más próximo este el identificador.

Los modificadores [ ] y () tienen mayor prioridad que *.

Se pueden usar paréntesis para agrupar parte de la expresión otorgándole la máxima

prioridad.

Ejemplo:

main ()

{

/*array de arrays de int*/

int x1 [8][8];

/*puntero a puntero a int*/

int **x2;

/*array de 10 punteros a int*/

int *x3[10];

/*puntero a array de 10 int*/

int (* x4)[10];

/*array de 3 punteros a array de 4 int*/

int **x5 [3][4];

Page 85: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 85

/*puntero a array de 3*4 int*/

int (**x6)[3][4];

/*puntero a función que devuelve un tipo int*/

int (*x8) (void);

/*función que acepta un puntero a char como argumento y que devuelve un

puntero a un puntero a una función que devuelve un carácter*/

char(*(* x11(char*)))(void);

/*puntero a función que devuelve un puntero a puntero a carácter y acepta

dos argumentos: el primero es un puntero a puntero a puntero a carácter,

y el segundo es un array de 10 punteros a carácter*/

char**(*x12) (char ***, char *[10]);

/*función que acepta un puntero a puntero a puntero a constante y

devuelve un puntero constante a constante*/

const void *const x13 (const void ***);

/*función que no devuelve nada y acepta como argumento un puntero a

función que no devuelve nada y acepta como argumento un puntero a función

que no devuelve nada y no acepta ningún argumento*/

void x14 (void (*) (void(*)(void)));

/*función que acepta un int como argumento y devuelve un puntero a una

función que acepta un int como argumento y que devuelve un int*/

int(*(x15 (int))) (int);

}

Page 86: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 86

6.2. Estructuras

6.2.1. Concepto de estructura

Una estructura es un conjunto de una o más variables, de distinto tipo, agrupadas

bajo un mismo nombre para que su manejo sea más sencillo. Su utilización más

habitual es para la programación de bases de datos, ya que están especialmente

indicadas para el trabajo con registros o fichas.

6.2.2. Declaración

La sintaxis de su declaración es la siguiente:

struct tipo_estructura

{

tipo_variable nombre_variable1;

tipo_variable nombre_variable2;

tipo_variable nombre_variable3;

};

Donde tipo_estructura es el nombre del nuevo tipo de dato que hemos creado. Por

último, tipo_variable y nombre_variable son las variables que forman parte de la

estructura.

Para definir variables del tipo que acabamos de crear lo podemos hacer de varias

maneras, aunque las dos más utilizadas son éstas:

Una forma de definir la estructura:

struct trabajador {

char nombre[20];

char apellidos[40];

int edad;

char puesto[10];

};

struct trabajador fijo, temporal;

Page 87: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 87

Otra forma:

struct trabajador

{

char nombre[20];

char apellidos[40];

int edad;

char puesto[10];

}fijo, temporal;

En el primer caso declaramos la estructura, y en el momento en que necesitamos

las variables, las declaramos. En el segundo las declaramos al mismo tiempo que

la estructura. El problema del segundo método es que no podremos declarar más

variables de este tipo a lo largo del programa. Para poder declarar una variable de

tipo estructura, la estructura tiene que estar declarada previamente. Se debe

declarar antes de la función main.

El manejo de las estructuras es muy sencillo, así como el acceso a los campos ( o

variables ) de estas estructuras. La forma de acceder a estos campos es la

siguiente:

variable.campo;

Donde variable es el nombre de la variable de tipo estructura que hemos creado, y

campo es el nombre de la variable que forma parte de la estructura. Lo veremos

mejor con un ejemplo basado en la estructura definida anteriormente:

temporal.edad=25;

Lo que estamos haciendo es almacenar el valor 25 en el campo edad de la

variable temporal de tipo trabajador.

Otra característica interesante de las estructuras es que permiten pasar el

contenido de una estructura a otra, siempre que sean del mismo tipo

naturalmente:

fijo=temporal;

Page 88: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 88

Al igual que con los otros tipos de datos, también es posible inicializar variables de

tipo estructura en el momento de su declaración:

struct trabajador fijo={"Pedro","Hernández Suárez", 32, "gerente"};

Si uno de los campos de la estructura es un array de números, los valores de la

inicialización deberán ir entre llaves:

struct notas

{

char nombre[30];

int notas[5];

};

struct notas alumno={"Carlos Pérez",{8,7,9,6,10}};

6.2.3. Estructuras y funciones

Podemos enviar una estructura a una función de las dos maneras conocidas:

6.2.3.1. Por valor

Su declaración sería:

void visualizar(struct trabajador);

Después declararíamos la variable fijo y su llamada sería:

visualizar(fijo);

Por último, el desarrollo de la función sería:

void visualizar(struct trabajador datos)

Page 89: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 89

Ejemplo:

/*Paso de una estructura por valor*/

#include <stdio.h>

#include <conio.h>

struct trabajador

{

char nombre [20];

char apellidos [40];

int edad;

char puesto [10];

};

void visualizar (struct trabajador);

main() /*rellenar y visualizar*/

{

struct trabajador fijo;

printf ("Nombre: ");

scanf("%s", fijo.nombre);

printf("\nApellidos: ");

scanf("%s", fijo.apellidos);

printf("\nedad: ");

scanf("%d", &fijo.edad);

printf("\nPuesto: ");

scanf("%s", fijo.puesto);

visualizar(fijo);

getch();

}

void visualizar (struct trabajador datos)

{

printf("Nombre: %s", datos.nombre);

printf("\nApellidos: %s", datos.apellidos);

printf("\nedad: %d", datos.edad);

printf("\npuesto: %s", datos.puesto);

}

Page 90: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 90

6.2.3.2. Por referencia:

Su declaración sería:

void visualizar(struct trabajador *);

Después declararemos la variable fijo y su llamada será:

visualizar(&fijo);

Por último, el desarrollo de la función será:

void visualizar(struct trabajador *datos)

Fíjate que en la función visualizar, el acceso a los campos de la variable datos se

realiza mediante el operador ->, ya que tratamos con un puntero. En estos casos

siempre utilizaremos el operador ->. Se consigue con el signo menos seguido de

mayor que.

Ejemplo:

/* Paso de una estructura por referencia. */

#include <stdio.h>

#include <conio.h>

struct trabajador

{

char nombre[20];

char apellidos[40];

int edad;

char puesto[10];

};

void visualizar(struct trabajador *);

main() /* Rellenar y visualizar */

{

struct trabajador fijo;

printf("Nombre: ");

scanf("%s",fijo.nombre);

printf("\nApellidos: ");

scanf("%s",fijo.apellidos);

Page 91: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 91

printf("\nEdad: ");

scanf("%d",&fijo.edad);

printf("\nPuesto: ");

scanf("%s",fijo.puesto);

visualizar(&fijo);

getch();

}

void visualizar(struct trabajador *datos)

{

printf("Nombre: %s",datos->nombre);

printf("\nApellidos: %s",datos->apellidos);

printf("\nEdad: %d",datos->edad);

printf("\nPuesto: %s",datos->puesto);

}

6.2.4. Arrays de estructuras

Es posible agrupar un conjunto de elementos de tipo estructura en un array. Esto

se conoce como array de estructuras:

struct trabajador

{

char nombre[20];

char apellidos[40];

int edad;

};

struct trabajador fijo[20];

Así podremos almacenar los datos de 20 trabajadores. Ejemplos sobre como

acceder a los campos y sus elementos: para ver el nombre del cuarto trabajador,

fijo[3].nombre;

Para ver la tercera letra del nombre del cuarto trabajador, fijo[3].nombre[2];. Para

inicializar la variable en el momento de declararla lo haremos de esta manera:

struct trabajador fijo[20]=

{{"José","Herrero Martínez",29},{"Luis","García Sánchez",46}};

Page 92: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 92

6.2.5. Typedef

El lenguaje 'C' dispone de una declaración llamada typedef que permite la

creación de nuevos tipos de datos. Ejemplos:

/* acabamos de crear un tipo de dato llamado entero */

typedef int entero;

entero a, b=3; /* declaramos dos variables de este tipo */

Su empleo con estructuras está especialmente indicado. Se puede hacer de varias

formas:

Una forma de hacerlo:

struct trabajador

{

char nombre[20];

char apellidos[40];

int edad;

};

typedef struct trabajador datos;

datos fijo,temporal;

Otra forma:

typedef struct

{

char nombre[20];

char apellidos[40];

int edad;

}datos;

datos fijo,temporal;

Page 93: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 93

6.3. Ficheros

Ahora veremos la forma de almacenar datos que podremos recuperar cuando

deseemos. Estudiaremos los distintos modos en que podemos abrir un fichero, así

como las funciones para leer y escribir en él.

6.3.1. Apertura

Antes de abrir un fichero necesitamos declarar un puntero de tipo FILE, con el que

trabajaremos durante todo el proceso. Para abrir el fichero utilizaremos la

funciónfopen().

Su sintaxis es:

FILE *puntero;

puntero = fopen ( nombre del fichero, "modo de apertura" );

donde puntero es la variable de tipo FILE, nombre del fichero es el nombre que

daremos al fichero que queremos crear o abrir. Este nombre debe ir encerrado

entre comillas.

También podemos especificar la ruta donde se encuentra o utilizar un array que

contenga el nombre del archivo ( en este caso no se pondrán las comillas ).

Algunos ejemplos:

puntero=fopen("DATOS.DAT","r");

puntero=fopen("C:\\TXT\\SALUDO.TXT","w");

Un archivo puede ser abierto en dos modos diferentes, en modo texto o en modo

binario. A continuación lo veremos con más detalle.

Page 94: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 94

6.3.1.1. Modo texto

w crea un fichero de escritura. Si ya existe lo crea de nuevo.

w+ crea un fichero de lectura y escritura. Si ya existe lo crea de nuevo.

a abre o crea un fichero para añadir datos al final del mismo.

a+ abre o crea un fichero para leer y añadir datos al final del mismo.

r abre un fichero de lectura.

r+ abre un fichero de lectura y escritura.

6.3.1.2. Modo binario

wb crea un fichero de escritura. Si ya existe lo crea de nuevo.

w+b crea un fichero de lectura y escritura. Si ya existe lo crea de nuevo.

ab abre o crea un fichero para añadir datos al final del mismo.

a+b abre o crea un fichero para leer y añadir datos al final del mismo.

rb abre un fichero de lectura.

r+b abre un fichero de lectura y escritura.

La función fopen devuelve, como ya hemos visto, un puntero de tipo FILE. Si al

intentar abrir el fichero se produjese un error ( por ejemplo si no existe y lo

estamos abriendo en modo lectura ), la función fopen devolvería NULL. Por esta

razón es mejor controlar las posibles causas de error a la hora de programar. Un

ejemplo:

FILE *pf;

pf=fopen("datos.txt","r");

if (pf == NULL) printf("Error al abrir el fichero");

freopen(): Esta función cierra el fichero apuntado por el puntero y reasigna este

puntero a un fichero que será abierto. Su sintaxis es:

freopen(nombre del fichero,"modo de apertura",puntero);

Donde nombre del fichero es el nombre del nuevo fichero que queremos abrir,

luego el modo de apertura, y finalmente el puntero que va a ser reasignado.

Page 95: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 95

6.3.2. Cierre

Una vez que hemos acabado nuestro trabajo con un fichero es recomendable

cerrarlo. Los ficheros se cierran al finalizar el programa pero el número de estos

que pueden estar abiertos es limitado.

Para cerrar los ficheros utilizaremos la función fclose();. Esta función cierra el

fichero, cuyo puntero le indicamos como parámetro. Si el fichero se cierra con

éxito devuelve 0.

fclose (puntero);

Un ejemplo ilustrativo aunque de poca utilidad:

FILE *pf;

pf=fopen("AGENDA.DAT","rb");

if ( pf == NULL ) printf ("Error al abrir el fichero");

else fclose(pf);

6.3.3. Funciones de Escritura y lectura

A continuación veremos las funciones que se podrán utilizar dependiendo del dato

que queramos escribir y/o leer en el fichero.

6.3.3.1. Función fputc

fputc( variable_caracter , puntero_fichero );

Escribimos un carácter en un fichero (abierto en modo escritura). Un ejemplo:

FILE *pf;

char letra='a';

/* otra forma de controlar si se produce un error */

if (!(pf=fopen("datos.txt","w")))

{ printf("Error al abrir el fichero"); exit(0); }

else fputc(letra,pf);

fclose(pf);

Page 96: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 96

6.3.3.2. Función fgetc

fgetc( puntero_fichero );

Lee un carácter de un fichero (abierto en modo lectura). Deberemos guardarlo en

una variable. Un ejemplo:

FILE *pf; char letra;

/* controlamos si se produce un error */

if (!(pf=fopen("datos.txt","r")))

{

printf("Error al abrir el fichero");

exit(0); /* abandonamos el programa */

}

else

{

letra=fgetc(pf);

printf("%c",letra);

fclose(pf);

}

6.3.3.3. Función putw

putw( variable_entera, puntero_fichero );

Escribe un número entero en formato binario en el fichero. Ejemplo:

FILE *pf;

int num=3;

if (!(pf=fopen("datos.txt","wb"))) /* controlamos si se produce un

error */

{

printf("Error al abrir el fichero");

exit(0); /* abandonamos el programa */

}

else

{

fputw(num,pf); /* también podíamos haber hecho directamente:

fputw(3,pf); */

fclose(pf);

}

Page 97: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 97

6.3.3.4. Función getw

getw( puntero_fichero );

Lee un número entero de un fichero, avanzando dos bytes después de cada

lectura. Un ejemplo:

FILE *pf;

int num;

if (!(pf=fopen("datos.txt","rb"))) /* controlamos si se produce un

error */

{

printf("Error al abrir el fichero");

exit(0); /* abandonamos el programa */

}

else {

num=getw(pf);

printf("%d",num);

fclose(pf);

}

6.3.3.5. Función fputs

fputs( variable_array, puntero_fichero );

Escribe una cadena de caracteres en el fichero. Ejemplo:

FILE *pf;

char cad="Me llamo Vicente";

/* controlamos si se produce un error */

if (!(pf=fopen("datos.txt","w")))

{

printf("Error al abrir el fichero");

exit(0); /* abandonamos el programa */

}

Else {

/* o también así: fputs("Me llamo Vicente",pf); */

fputs(cad,pf);

fclose(pf);

}

Page 98: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 98

6.3.3.6. Función fgets

fgets( variable_array, variable_entera, puntero_fichero );

Lee una cadena de caracteres del fichero y la almacena en variable_array. La

variable_entera indica la longitud máxima de caracteres que puede leer. Un

ejemplo:

FILE *pf;

char cad[80];

if (!(pf=fopen("datos.txt","rb"))) /* controlamos si se produce un

error */

{

printf("Error al abrir el fichero");

exit(0); /* abandonamos el programa */

}

else

{

fgets(cad,80,pf);

printf("%s",cad);

fclose(pf);

}

6.3.3.7. Función fprintf

fprintf( puntero_fichero, formato, argumentos);

Funciona igual que un printf pero guarda la salida en un fichero. Ejemplo:

FILE *pf;

char nombre[20]="Santiago"; int edad=34;

/* controlamos si se produce un error */

if (!(pf=fopen("datos.txt","w"))) {

printf("Error al abrir el fichero");

exit(0); /* abandonamos el programa */

}

else {

fprintf(pf,"%20s%2d\n",nombre,edad);

fclose(pf);

}

Page 99: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 99

6.3.3.8. Función fscanf

fscanf( puntero_fichero, formato, argumentos );

Lee los argumentos del fichero. Al igual que con un scanf, deberemos indicar la

dirección de memoria de los argumentos con el símbolo & ( ampersand ). Un

ejemplo:

FILE *pf;

char nombre[20];

int edad;

if (!(pf=fopen("datos.txt","rb"))) /* controlamos si se produce un

error */

{

printf("Error al abrir el fichero");

exit(0); /* abandonamos el programa */

}

else

{

fscanf(pf,"%20s%2d\",nombre,&edad);

printf("Nombre: %s Edad: %d",nombre,edad);

fclose(pf);

}

6.3.3.9. Función fwrite

fwrite( *buffer, tamaño, nº de veces, puntero_fichero );

Se utiliza para escribir bloques de texto o de datos, estructuras, en un fichero. En

esta función, *buffer será la dirección de memoria de la cuál se recogerán los

datos; tamaño, el tamaño en bytes que ocupan esos datos y nº de veces, será el

número de elementos del tamaño indicado que se escribirán.

Page 100: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 100

6.3.3.10. Función fread

fread( *buffer, tamaño, nº de veces, puntero_fichero );

Se utiliza para leer bloques de texto o de datos de un fichero. En esta función,

*buffer es la dirección de memoria en la que se almacenan los datos; tamaño, el

tamaño en bytes que ocupan esos datos y nº de veces, será el número de

elementos del tamaño indicado que se leerán.

Puedes encontrar ejemplos sobre la apertura y cierre de ficheros, así como de la

lectura y escritura de datos, en el archivo IMAGECAT.C. Se trata de un programa

que crea un catálogo en formato HTML a partir de las imágenes que se

encuentran en un directorio determinado.

6.3.3.11. Función rewind

rewind( puntero_fichero );

Sitúa el puntero al principio del archivo.

6.3.3.12. Función fseek

fseek( puntero_fichero, long posicion, int origen );

Sitúa el puntero en la posicion que le indiquemos. Como origen podremos poner:

0 o SEEK_SET, el principio del fichero

1 o SEEK_CUR, la posición actual

2 o SEEK_END, el final del fichero

6.3.3.13. Función rename

rename( nombre1, nombre2 );

Su función es exactamente la misma que la que conocemos en MS-DOS. Cambia

el nombre del fichero nombre1 por un nuevo nombre, nombre2.

6.3.3.14. Función remove

Page 101: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 101

remove( nombre );

Como la función del DOS del, podremos eliminar el archivo indicado en nombre.

6.3.3.15. Función feof

Detección de final de fichero

feof( puntero_fichero );

Siempre deberemos controlar si hemos llegado al final de fichero cuando estemos

leyendo, de lo contrario podrían producirse errores de lectura no deseados. Para

este fin disponemos de la función feof( ). Esta función retorna 0 si no ha llegado al

final, y un valor diferente de 0 si lo ha alcanzado.

Page 102: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 102

7. Gráficos en el Leguaje C

7.1. Programa texto vs. programa grafico

Antes de comenzar con el modo gráfico es necesario adentrarse en los conceptos

básicos que permiten conocerlo a plenitud. Los programas que hemos hecho

hasta ahora se basan en un modo pobre en el que sólo puede mostrarse

caracteres, dicho modo es conocido como modo texto o alfanumérico.

En estos modos, generalmente la pantalla se encuentra dividida por una matriz de

80 columnas y 25 filas. Cada celda de dicha matriz sólo puede contener un

carácter.

El inconveniente de este modo es que si quieres hacer un gráfico tienes que

ilustrarlo con base a caracteres y lo peor es la resolución limitada (80 x 25). Los

modos gráficos se caracterizan por su variada combinación de resolución y

colores.

Un píxel es la unidad mínima de dibujo en una pantalla. En las pantallas actuales,

un píxel tiene forma cuadrada y su color propio el cual es formado de una

combinación de tres colores básicos (Rojo, Verde, Azul).

Resolución es la cantidad de píxeles por fila y columna de una pantalla en ese

modo. Por ejemplo, 640 píxeles por fila y 480 por columna caben en el modo VGA.

Cuando vayamos a utilizar los modos gráficos debemos tener en cuenta que la

esquina superior izquierda es el origen de coordenadas y que la máxima

coordenada posible es (x-1,y-1).

Por ejemplo, si la resolución es VGA (640x480) la coordenada máxima posible es

(639,479) medida a partir de la esquina superior izquierda.

Page 103: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 103

Podemos ver, entonces las grandes diferencias entre los modos texto y grafico. Se

puede crear fácilmente un dibujo a partir de conjuntos de píxeles y colores, pero

es no quiere decir que no puedan mostrarse caracteres, ya que estos son también

conjuntos de puntos.

7.2. Inicialización del modo grafico

Para poder utilizar el modo gráfico, antes que nada debe iniciarse. Primero hay

que detectar el adaptador:

int gdriver=DETECT, gmode;

Donde gdriver=DETECT especifica que queremos que se auto-detecte el tipo

genérico de tarjeta gráfica que tenemos instalada y gmode abrirá el modo y

combinación de colores predeterminado. Frecuentemente la tarjeta grafica más

habitual es la VGA y el modo grafico 640 x 480 con 16 colores.

Otra alternativa para detectar la tarjeta grafica es usar la instrucción detectgraph:

detectgraph(int *adaptador, int *modo);

En el primer argumento se guarda la tarjeta grafica detectada, en modo se

almacena el modo por defecto.

initgraph(&gdriver,&gmode,”bgi”);

La instrucción initgraph inicia el modo grafico con los argumentos

correspondientes. El primer argumento corresponde al tipo de tarjeta grafica que

tengamos, el segundo refiere al modo grafico que queremos, y el tercer parámetro

al directorio donde se encuentran los ficheros BGI, los cuales contienen

información acerca de los modos de videos y funciones graficas.

Cabe destacar que el uso de ficheros BGI (Borland Graphics Interface) es un

inconveniente en cuanto a que estos ficheros deben mantenerse en la misma de

carpeta del programa compilado para que funcione, es una opción enlazarlos con

el programa ya compilado pero esto aumenta notablemente el tamaño del

programa.

Page 104: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 104

int graphresult( );

Reporta el estado del modo gráfico. Envía 0 si no ocurrió error, de lo contrario

retorna un valor en el rango[-1,-16].

char grapherrormsg(int error_id);

Manda un apuntador al mensaje de error respecto al valor retornado en

graphresult.

Si queremos terminar el modo grafico y regresar al modo texto usaremos la

función closegraph(). No es necesario ningún argumento.

closegraph();

La función restorecrtmode() nos devuelve al modo original.

restorecrtmode();

7.3. Dibujar en el modo gráfico (Primitivos Gráficos)

7.3.1. Pintar un punto:

putpixel(int x, int y, int color);

(x,y) es la ubicación del punto que queremos pintar.

En color se indica una constante COLORS o bien el numero del color

correspondiente.

0 BLACK 4 RED 8 DARKGRAY 12 LIGHTRED

1 BLUE 5 MAGENTA 9 LIGHTBLUE 13 LIGHTMAGENTA

2 GREEN 6 BROWN 10 LIGHTGREEN 14 YELLOW

3 CYAN 7 LIGHTGRAY 11 LIGHTCYAN 15 WHITE

Page 105: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 105

7.3.2. Dibujar un segmento de recta:

line(int x1,int y1, int x2,int y2);

(x1,y1) y (x2,y2) puntos extremos del segmento de recta

7.3.3. Para dibujar una circunferencia:

circle(int x, int y, int r);

(x,y) es el centro de la circunferencia.

r es el radio de la circunferencia.

7.3.4. Para trazar un rectángulo:

rectangle(int x1 , int y1 , int x2 , int y2);

(x1,y1) es la esquina superior izquierda del rectángulo.

(x2,y2) es la esquina inferior derecha del rectángulo.

7.3.5. Dibujar un arco circular:

arc(int x , int y, int ai , int af , int r);

(x,y) es el centro del arco circular.

(ai-af) ángulo inicial y final del arco circular

r radio del arco circular

7.3.6. Dibujar un arco elíptico:

ellipse(int x, int y, int ai, int af, int rx, int ry);

(x,y) centro del arco eliptico

(ai-af) ángulo inicial y final del arco eliptico

rx, ry radio horizontal y vertical del arco eliptico

Page 106: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 106

7.4. Cambiar el estilo de línea:

setlinestyle(int estilo, int separación ,int ancho);

Estilo especifica el estilo a usar.

0 Línea Continua 3 Guiones largos

1 Guiones 4 Puntos

2 Guiones largos y cortos

Separación especifica la separación entre los elementos de una línea no continua.

Ancho, el grosor de línea.

7.5. Funciones de relleno

7.5.1.1. Rellenar una región

floodfill(int x , int y , int frontera);

Rellena a partir del punto (x,y) el área limitada por el color frontera.

En frontera se indica una constante COLORS o bien el numero del color

correspondiente.

0 BLACK 4 RED 8 DARKGRAY 12 LIGHTRED

1 BLUE 5 MAGENTA 9 LIGHTBLUE 13 LIGHTMAGENTA

2 GREEN 6 BROWN 10 LIGHTGREEN 14 YELLOW

3 CYAN 7 LIGHTGRAY 11 LIGHTCYAN 15 WHITE

Page 107: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 107

7.5.1.2. Elegir patrón de relleno

setfillstyle(int patron, int color);

El patrón puede tomar un valor de 0 a 12.

0 Patrón Vacío 7 Líneas horizontales y verticales cruzadas

1 Sólido 8 Líneas diagonales cruzadas

2 Líneas horizontales gruesas 9 Líneas diagonales cruzadas muy juntas

3 Líneas diagonales finas 10 Puntos separados.

4 Líneas diagonales gruesas 11 Puntos cercanos

5 Líneas diagonales gruesas 12 Patrón definido por el usuario

6 Líneas diagonales finas

En color se indica una constante COLORS o bien el numero del color

correspondiente.

0 BLACK 4 RED 8 DARKGRAY 12 LIGHTRED

1 BLUE 5 MAGENTA 9 LIGHTBLUE 13 LIGHTMAGENTA

2 GREEN 6 BROWN 10 LIGHTGREEN 14 YELLOW

3 CYAN 7 LIGHTGRAY 11 LIGHTCYAN 15 WHITE

7.5.1.3. Dibujar una barra rectangular

bar(int x1 , int y1, int x2 , int y2);

(x1,y1) esquina superior izquierda de la barra

(x2,y2) esquina inferior derecha de la barra

7.5.1.4. Dibujar una barra 3-D

bar3d(int x1, int y1, int x2, int y2, int altura, int tapa);

(x1,y1) esquina superior izquierda de la barra

(x2,y2) esquina inferior derecha de la barra

Altura es la profundidad de la barra

Tapa especifica si la barra debe incluir o no tapa

Page 108: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 108

7.5.1.5. Dibujar un sector circular

pieslice(int x, int y, int ai , int af , int r);

(x,y) centro del arco del sector circular

(ai-af) ángulo inicial y final del arco del sector circular

r radio del arco del sector circular.

7.6. Funciones de escritura de texto

7.6.1. Mostrar texto en un lugar específico

outtextxy(int x , int y , char *texto);

Muestra el texto indicado a partir del punto (x,y).

7.6.2. Seleccionar el estilo del texto

settextstyle(int fuente , int orientación , int tamaño);

fuente define el tipo de letra.

0 Normal 3 Sans Seriff

1 Triplex 4 Gótica

2 Fuente pequeña

Orientación describe si el texto es horizontal o vertical.

Tamaño aumenta las dimensiones de los caracteres.

7.6.3. Cambiar los límites del dibujo.

setviewport(int x1, int y1, int x2, int y2, int recorte);

Un viewport es una zona rectangular delimitada para el dibujo

Las coordenadas en un viewport son relativas a su esquina superior izquierda.

(x1, y1) y (x2, y2) esquinas superior izquierda e inferior derecha del viewport.

El recorte especifica si se ve sólo el viewport o todo.

Page 109: Manual c

UNI – Universidad Nacional de Ingeniería

_________________________________________________________________________

_________________________________________________________________________

Programación II Página 109

7.6.4. Limpiar el viewport actual:

clearviewport();

7.6.5. Otras

Obtener la coordenada máxima horizontal.

Horizontal: int getmaxx( ); Vertical: int getmaxy();

Obtener la coordenada actual.

Horizontal: int getx( ); Vertical: int gety( );

Moverse a una coordenada especifica.

moveto(int x , int y);

Cambiar color de

Dibujo y texto: setcolor(color);

Fondo de pantalla: setbkcolor(color);

0 BLACK 4 RED 8 DARKGRAY 12 LIGHTRED

1 BLUE 5 MAGENTA 9 LIGHTBLUE 13 LIGHTMAGENTA

2 GREEN 6 BROWN 10 LIGHTGREEN 14 YELLOW

3 CYAN 7 LIGHTGRAY 11 LIGHTCYAN 15 WHITE

Obtener el color actual de.

Dibujo y texto: int getcolor( );

Fondo de pantalla: int getbkcolor( );

Un pixel en particular: int getpixel(int x , int y);

(x,y) coordenadas del pixel al cual se quiere

extraer el color

Borrar toda la pantalla

cleardevice( );