62
INSTITUTO TECNOLOGICO DE VERACRUZ DEPARTAMENTO DE SISTEMAS Y COMPUTACION PROGRAMA DE ACTUALIZACION DOCENTE CURSO: LENGUAJE C DR. ABELARDO RODRIGUEZ LEON PROGRAMA DE TUTORIAS 2014

Lenguaje C

Embed Size (px)

DESCRIPTION

Manual con las especificaciones basicas para programación en C.

Citation preview

Page 1: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

DEPARTAMENTO DE SISTEMAS Y COMPUTACION

PROGRAMA DE ACTUALIZACION DOCENTE

CURSO:

LENGUAJE C

DR. ABELARDO RODRIGUEZ LEON

PROGRAMA DE TUTORIAS 2014

Page 2: Lenguaje C

Contenido

1.FUNDAMENTOS DE C..................................................................................................................................4

1.1 ANTECEDENTES DE LENGUAJE C..........................................................................................................41.2CARACTERÍSTICAS. EL PORQUE DE SU POPULARIDAD...................................................................41.3PALABRAS RESERVADAS POR ANSI.........................................................................................................51.4ESTRUCTURA DE UN PROGRAMA..........................................................................................................5

1.4.1Partes......................................................................................................................................................61.4.2Reglas de ámbito.....................................................................................................................................6

2.LOS TIPOS Y LAS ESTRUCTURAS DE CONTROL...............................................................................8

2.1TIPOS DE DATOS Y SU DEFINICIÓN........................................................................................................82.2MODIFICADORES DE VARIABLES...........................................................................................................8

2.2.1Modificadores tipo..................................................................................................................................82.2.2Modificadores de almacenamiento.........................................................................................................92.2.3Modificadores de acceso........................................................................................................................9

2.3CONSTANTES LITERALES.........................................................................................................................92.3.1Numéricas enteras................................................................................................................................102.3.2Numéricas flotantes..............................................................................................................................102.3.3Caracteres Ascii....................................................................................................................................102.3.4Cadenas.................................................................................................................................................11

2.4OPERADORES ............................................................................................................................................112.4.1Aritméticos............................................................................................................................................112.4.2Asignación............................................................................................................................................122.4.3Relacionales..........................................................................................................................................122.4.4Lógicos..................................................................................................................................................122.4.5Sobre bits..............................................................................................................................................122.4.6Asociatividad y precedencia de los operadores....................................................................................13

2.5EXPRESIONES.............................................................................................................................................142.6CONVERSIÓN DE TIPOS EN LA ASIGNACIÓN.....................................................................................142.7CASTS...........................................................................................................................................................152.8-FUNCIONES BASICAS DE E/S ...............................................................................................................162.9ESTRUCTURAS CONDICIONALES.........................................................................................................21

2.9.1El if........................................................................................................................................................212.9.2El switch................................................................................................................................................222.9.3Programa muestra del uso del switch...................................................................................................23

2.10ESTRUCTURAS CÍCLICAS......................................................................................................................242.10.1La instrucción for...............................................................................................................................242.10.2La instrucción while...........................................................................................................................252.10.3La instrucción do/while......................................................................................................................252.10.4Programa muestra de diversas formas del for...................................................................................252.10.5Programa muestra del uso de while...................................................................................................26

3.FUNCIONES, APUNTADORES Y ESTRUCTURAS DE DATOS..........................................................29

3.1 FUNCIONES DEFINIDAS POR EL USUARIO........................................................................................293.1.1Tipos de parámetros en funciones........................................................................................................293.1.2Funciones que regresan valores ..........................................................................................................303.1.3La función especial main......................................................................................................................30

3.2FUNCIONES CON PARAMETROS VARIABLES.....................................................................................313.2.1Programa de ejemplo............................................................................................................................31

3.3DEFINICION DE ARREGLOS....................................................................................................................323.3.1Arrays normales....................................................................................................................................323.3.2Array multidimensionales.....................................................................................................................33

3.4MANEJO DE CADENAS DE CARACTERES.........................................................................................................343.4.1Funciones comunes para el manejo de cadenas...................................................................................34

3.5 CONCEPTOS DE APUNTADORES...........................................................................................................35

1* 2

2*

Page 3: Lenguaje C

3.5.1Funciones para el manejo de memoria dinamica.................................................................................353.5.2Operadores para punteros....................................................................................................................363.5.3Posibles problemas con punteros.........................................................................................................363.5.4Arrays y punteros..................................................................................................................................373.5.5El modificador const en punteros como parametros............................................................................383.5.6Tipos de indireccionamiento.................................................................................................................393.5.7PUNTEROS A FUNCIONES................................................................................................................40

3.6ESTRUCTURAS Y UNIONES.....................................................................................................................413.6.1Estructuras............................................................................................................................................413.6.2Arrays de estructuras............................................................................................................................423.6.3Apuntadores a estructuras....................................................................................................................423.6.4Campos de bits......................................................................................................................................443.6.5Uniones.................................................................................................................................................46

4.- ARCHIVOS..................................................................................................................................................48

5.TEMAS AVANZADOS DE “C”....................................................................................................................50

5.1EL PREPROCESADOR DE C......................................................................................................................505.2LOS MODELOS DE MEMORIA.................................................................................................................55

Page 4: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

1. FUNDAMENTOS DE C

1.1 ANTECEDENTES DE LENGUAJE C

1* Fue el resultado del desarrollo escalonado de los lenguajes BCPL y B.

2* BCPL fue desarrollado por Martin Richards en 1967 para escribir sistemas operativos.

3* BCPL influencio en el lenguaje llamado B, que fue inventado por Ken Thompson, en 1967 en los laboratorios BELL y fue usado en las versiones iniciales de UNIX.

4* A inicios de los 70, el lenguaje B llevo a Dennis Ritchie a desarrollar el lenguaje C en una Dec PDP-11, implantándolo en 1972 en UNIX, donde fue considerado como lenguaje base.

5* A finales de los 70, Brian Kernigham y Dennis Ritchie publicaron un libro en el cual describían las bases del C usado en la versión V de UNIX. Este libro sirvió como punto de referencia para que varias compañías crearan compiladores de C.

6* La principal características de estos compiladores era que todos soportaban de manera casi uniforme el C de Kernigham y Ritchie pero agregaban características especiales que eran muy útiles pero que no se aplicaba a todos lo compiladores.

7* Al notar lo anterior, la ANSI creo en 1983 un comite para que proporcionara una definición no ambigua e independiente de maquina, del lenguaje. Lo cual se logro en 1989 y se le conoce como el documento ANSI/ISO 9899: 1990.

8* En este documento también se establecen también las bibliotecas estandard de C, las cuales contienen una amplia colección de funciones que hace la vida del programador mas fácil, al proporcionarle herramientas bien pensadas y construidas con cuidado, y que además son comunes en todos los compiladores.

1.2 CARACTERÍSTICAS. EL PORQUE DE SU POPULARIDAD.

9* Existen una serie de características que hacen del lenguaje c, uno los mas usados en el ambiente computacional, en cualquier nivel. Esas características son las siguientes:

10* Lenguaje de nivel medio

11* Se considera así porque tiene algo de los dos extremos adyacentes; características de los lenguajes de alto nivel, y características de los ensambladores.

12* Sin embargo se extrañaran característica de los lenguajes de alto nivel (principalmente la protección de ámbito y abstracción) así como el control total del hardware que se puede tener en un ensamblador.

13* Es portable:

A.Rodriguez L. 4

Page 5: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

14* Significa que si se tiene cuidado de seguir las normas ANSI, se puede escribir código que funcione en cualquier compilador que se precie de ser compatible con ANSI; incluso en compiladores de otras plataformas.

15* Esta característica puede ser también limitante, ya que las mejoras particulares que un compilador agregue, no siempre son aceptadas por otros, lo cual es un factor de peso al desarrollar aplicaciones.

16* El estándar ansi solo define 32 palabras clave

17* El tener menos palabras reservadas que aprender resulta interesante, comparado con otros lenguajes en los cuales se tiene que aprender al menos un centenar de palabras reservadas.

18* El inconveniente resulta que estas palabras reservadas no incluyen procesos de E/S, los cuales se hacen a través de funciones de la biblioteca standard.

19* Es estructurado

20* Las características estructuradas de C no son tan amplias como las que proporcionan lenguajes de alto nivel, que permiten incluso anidar subrutinas.

21* En C solo se cuentan con subrutinas de tipo función, pero estas son flexibles que no es necesario contar con otro tipo para trabajar en el lenguaje.

22* Reemplazo de lenguajes ensambladores:

23* Se considera como un buen reemplazo de ensambladores, ya que genera programas que son casi tan eficientes como los creados en ensamblador.

24* Esto se debe a que muchos procesos que hacen lento el funcionamiento de los lenguajes de alto nivel en C quedan a cargo del programador.

25* Hecho para programadores profesionales

26* Se considera así, por que el programador debe de cuidar muchos detalles de tipo técnico que en los lenguajes de alto nivel, el compilador controla automáticamente.

1.3 PALABRAS RESERVADAS por ANSI

27* El estándar ANSI establece que cualquier implementacion deberá considerar siguiente palabras reservadas:

auto break case char const

continue default do double else

enum extern float for goto

A.Rodriguez L. 5

Page 6: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

if int long register return

short signed sizeof static struct

switch typedef union unsigned void

volatile while

28* Adicionales a estas palabras reservadas cada implementacion de C agrega otras palabras mas. En el caso de Turbo C, por ejemplo, se tiene las siguientes palabras reservadas.

sm _cs _ds _es _ss

cdecl far huge interrupt near

pascal

29* Conocer las palabras reservadas en un lenguaje de programación evita que estas sean usadas como identificadores, lo cual no esta permitido.

30* Lenguaje C distingue entre mayúsculas y minúsculas en sus identificadores a esta características se le llama sensibilidad al contexto (case sensitive).

1.4 ESTRUCTURA DE UN PROGRAMA

1.4.1 Partes

<declaraciones de variables globales>

<declaraciones de cabeceras de función>

main()

{ < variables locales>

<conjunto de sentencias>

}

<subrutina1> ( <parámetros>)

{ <variables locales>

<conjunto de sentencias>

}

:

<subrutinaN> ( <parámetros>)

{ <variables locales>

<conjunto de sentencias>

}

A.Rodriguez L. 6

Page 7: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

1.4.2 Reglas de ámbito

31* Determinan cual es el alcance de una función o variable dependiendo del lugar donde fue declarada.

32* Las principales reglas de ámbito en C son las siguientes:

33* Un bloque de código puede ser el cuerpo de una función, así como una agrupación de instrucciones delimitadas por llaves.

34* El código y las variables de una función son privados a la misma y solo pueden ser accesado a través del llamado a la función.

35* Una función solo es conocida del lugar donde fue definida hacia abajo.

36* Existen 3 tipos de variables.

37* Las variables locales

Se definen dentro de un bloque de una función, al inicio del mismo, antes de cualquier instrucción ejecutable (esto cambia en C++).

Se crean en el stack temporalmente mientras dure la función.

Su ámbito es solo el cuerpo de la función.

Toman como valor inicial, el que este en la memoria donde se aloja, por lo que es conveniente inicializarlas antes de usarlas.

38* Los parámetros formales

Se consideran como variables locales, aunque no se declaran dentro de la función, sino en la cabecera. Fuera de esto se comportan como variables locales.

39* Las variables globales

40* Se definen fuera del ámbito de un bloque. Son conocidas por cualquier función definida después de ella. Se inicializan automáticamente con 0

A.Rodriguez L. 7

Page 8: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

2. LOS TIPOS Y LAS ESTRUCTURAS DE CONTROL

2.1 TIPOS DE DATOS Y SU DEFINICIÓN

41* Los tipos de datos base en c son los siguientes:

TIPO VALORES RANGO BITS

char 1 carácter -128 a 127 8

int enteros -32768 a 32767 16

float flotantes cortos 3.4 E-38 a 3.4 E+38 32

double flotantes largos 1.7 E -308 a 1.7 E+308 64

void nulo sin valor 0

42* Para definir una variable en C, es necesario indicar lo siguiente:

43* El modificador tipo (opcional)

44* El tipo de dato

45* Nombre de la(s) variable(s), separadas por comas y terminadas con un punto y coma. El nombre de la variable puede ser de 1 a 32 caracteres y usa solo letras, números y guiones bajos.

46* Ejemplo:

int A,B,C_1;

47* También es posible inicializar una variable en el momento en que es definida haciéndolo de la siguiente forma:

int A=10, B=5, C=20;

48* Las variables globales solo son inicializadas al inicio del programa, sin embargo las locales se inicializan cada vez que se entre a la función o bloque de código.

2.2 MODIFICADORES DE VARIABLES

2.2.1 Modificadores tipo

49* Permiten alterar el rango del tipo base, para encajar mas exactamente en las diversas situaciones en que se encuentran los datos.

50* Los modificadores son: signed, unsigned, short y long

51* Estos modificadores se pueden aplicar solo a los tipos int, char y double (no a void y float).

A.Rodriguez L. 8

Page 9: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

52* Aunque es permitido indicar un entero con el modificador signed por default todos los enteros soportan valores signados, por lo que es redundante indicarlo.

53* En la tabla que sigue se puede observar como se combinan los modificadores con los diferentes tipos base y los rangos de valores que nos dan en cada caso.

TIPO EQUIVALENCIAS

BITS

RANGO

char signed char 8 -128 a 127

unsigned char

- 8 0 a 255

signed short int

signed, short, int, signed short,

signed int, short int

16

-32768 A 32767

unsigned short int

unsigned short,

unsigned,

unsigned int

16

0 a 65535

signed long int

long, signed long

32

-2,147483648 a 2147483647

unsigned long int

unsigned long 32

0 a 4294967295

float 32

3.4 E-38 a 3.4 E+38

double 64

1.7 E-308 a

1.7 E+30

long double 80

3.4 E-4392 a

3.4 E+4392

2.2.2 Modificadores de almacenamiento.

54* Le dicen al compilador como manejar y donde colocar las variables a las cuales se aplique este modificador. Los modificadores son los siguientes: extern, static, register y auto.

55* extern : evitar la redundancia en la declaración de variables, en diferentes archivos.

A.Rodriguez L. 9

Page 10: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

56* static : permite que una variable local o global conserve su valor entre diferentes llamadas, sin que sea conocida fuera de su ámbito

57* register : le indica al compilador que la variable especifica tenga alojamiento en los registros del cpu y no en la memoria, con lo cual el manejo de la variables es mas rápido. Es ideal para usarla como contadores y solo se aplica a variables de tipo char e int.

58* auto : no se usa, ya que sirve para definir a las variables locales. Sin embargo todas las variables por default son locales, por lo que no es necesario hacerlo.

2.2.3 Modificadores de acceso

59* Especifican las reglas con las que pueden ser accesadas (modificadas) las variables a las cuales afecta.

60* const : permite definir en una zona de memoria en la cual se almacena un valor que no puede ser modificado. Un uso útil de este modificador es el de evitar que una función modifique un parámetro pasado por referencia.

61* volatile : permite que se defina una variable cuyo valor no será modificado de forma explícita (por asignación, entrada, etc), evitando algún tipo de optimización que el compilador quiera hacer en ella.

2.3 CONSTANTES LITERALES

62* Tiene la finalidad de declarar un valor fijo en el código del programa, el cual puede ser almacenado en una variable o puede ser usado como operando de una expresión. A continuación se enlistan los tipos de constantes literales.

2.3.1 Numéricas enteras

63* Las constantes numéricas enteras se colocan sin valor fraccional y pueden expresarse en los siguientes sistemas numéricos:

-Decimales P.E.: 9, 16, 3241

-Octales P.E.: 012=10 dec. ó 076 =62 dec.

-Hexadecimales P.E.: 0x12=18 de. ó 0x2f=47 dec.

64* El espacio que ocupa en memoria una constante literal por default es el mismo que ocuparía una variable tipo int.

65* Sin embargo se puede indicar que se desea que ocupe el espacio de un long poniendo después del valor entero una letra L .

66* También se puede indicar que se desea un entero sin signo si se le agrega después del valor una letra U.

A.Rodriguez L. 10

Page 11: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

2.3.2 Numéricas flotantes.

67* Las constantes flotantes pueden expresarse en forma decimal o en forma exponencial.

68* En forma decimal solo se indica: la parte entera, el punto y la parte fraccionaria.

69* En formato exponencial se indica: la parte entera, el punto, la parte fraccional el letra E y la potencia.

70* Ejemplos:

Decimal: 123.4523

Exponencial: 1.234523e+2

71* Por default ocuparía una constante flotante ocuparía el espacio de una variable double. Sin embargo se le puede poner después las letras F o L.

72* F instruye al compilador para que la contante ocupe el espacio de una variable float y L le indica que ocupe el espacio de una long double.

2.3.3 Caracteres Ascii

73* Las constantes de caracteres Ascii se encierran entre comillas simples. P.E.: ‘z’ y ‘t’. Pudiéndose indicar cualquier carácter del código ascii.

74* Los caracteres de control (que no se pueden expresar directamente por teclado) se indican con el formato ‘\n’ donde n puede ser el caracter Ascii expresado numéricamente en:

- Decimal

- Octal.

- Hexadecimal.

- Una letra clave para los caracteres de control comunes.

75* La siguiente tabla muestra las constantes de carácter de control permitidos.

Caracter

Significado Caracter

Significado

‘\a’ bell ‘\b’ backspace

‘\f’ ff ‘\n’ cr+lf

‘\r’ cr ‘\t’ tab. Horizontal

‘\v’ tab. Vertical ‘\\’ diagonal invertida

‘\?’ signo interrogación

‘\’’ comilla simple

‘\”’ comilla doble ‘\0’ nulo (terminador

A.Rodriguez L. 11

Page 12: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

cadena)

76* Cabe mencionar que a pesar de poderse asignar valores Ascii en variables, C maneja internamente todo como números. Es decir se pueden sumar dos constantes caracter, cosa que en otros lenguajes es incongruente.

77* Ejemplo

‘\14’ = ‘\015’ = ‘\xd’ = ff

2.3.4 Cadenas

78* Las constantes de cadena, a diferencia de las de carácter, permiten almacenar mas de una letra. La cadena de caracteres se encierra entre comillas dobles a diferencia de las de carácter que van entre comillas sencillas.

79* Se puede usar cualquier caracter del código Ascii dentro de una cadena. Para indicar un caracter que no se puede poner a través de teclado se usa la misma convención vista para constantes caracter.

80* C no cuenta con un tipo nativo para manejar cadenas, para hacerlo usa arrays de datos char. Con lo que sigue siendo valido lo mencionado anteriormente, de que todo se maneja internamente como números.

81* Ejemplo

“\”Tec. de Veracruz\”\n”

2.4 OPERADORES

82* Lenguaje C cuenta con una rica variedad de operadores de diversos tipos, los cuales se clasifican en : aritméticos, asignación, relacionales, lógicos y sobre bits.

2.4.1 Aritméticos

+,-

signos unarios -a, +a

*,/,%

multiplicación, división, modulo

a*b, a/b, a%b

+,-

suma y resta a-b, a+b

++

incremento en 1 a++ (a=a+1)

--

decremento en 1 a-- (a=a - 1)

A.Rodriguez L. 12

Page 13: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

-

2.4.2 Asignación

*=

multiplica y asigna a*=b (a=a*b)

/=

divide y asigna a/=b (a=a/b)

+=

suma y asigna a+=b (a=a+b)

-=

resta y asigna a-=b (a=a-b)

<<=

Corre bits a la izq. y asigna

a<<=2 (a=a<<2)

>>=

Corre bits a la der. y asigna

a>>=2 (a=a>>2)

2.4.3 Relacionales

> mayor a>b

>=

mayor o igual a>=b

< menor a<b

<=

menor o igual a<=b

==

igual a==b

!=

diferente a!=b

2.4.4 Lógicos

! negación !a, !(a<b)

&&

and a&&b, (a<b)&&(b<c)

A.Rodriguez L. 13

Page 14: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

|| or a||b, (a<b)&&(b<c)

2.4.5 Sobre bits

83* Se aplican sobre : char, int y long

& and a&b

| or a|b

^ or exclusivo (xor) a^b

~ Complemento a uno (not) !a

>>

desplazamiento a la derecha a>>2

<<

desplazamiento a la izquierda

a<<1

84* Ejemplo de operadores sobre bits

char a=193,b=127,c;

c=a&b /* 11000001& 01111111=01000001 SON 65 */

a=128; b=3;

c=a|b /* 10000000 | 00000011=10000011 SON 131 */

a=127; b=120;

c=a^b /* 01111111 ^ 01111000=00000111 SON 7 */

a=7;

c=~a /* ~01111111=10000000 SON 128 */

c=a<<2 /* 00000111<<2=00011100 SON 28 */

b=c>>1 /* 00011100>>1=00001110 SON 14 */

2.4.6 Asociatividad y precedencia de los operadores

Operador Asociatividad Tipo Preced.

() [ ] . -> Izq. a Der. Agrupación Mayor

+ - ++ -- ! (tipo) & * ~ sizeof

Der. a Izq. Arit. unarios

* / % Izq. a Der. Arit. multiplicativos

+ - Izq. a Der. Arit. aditivos

<< >> Izq. a Der. Despl. de bits

A.Rodriguez L. 14

Page 15: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

< <= > >= Izq. a Der. Relacional

== ¡= Izq. a Der. Rel. igualdad

& Izq. a Der. And binario

ˆ Izq. a Der. Xor Binario

| Izq. a Der. Or Binario

&& Izq. a Der. And logico

|| Izq. a Der. Or lógico

?: Der. a Izq. Condicional

= += -= *= /= %= &= |= ˆ= <<= >>=

Der. a Izq. Asignación Menor

2.5 EXPRESIONES

85* Una expresión devuelve un resultado de un tipo especifico, según los operadores y tipos de las variables usadas. Casi todas las situaciones de expresiones normales caen bajo el dominio de las reglas del álgebra. Sin embargo existen algunas situaciones especificas que lenguaje C maneja de forma diferente.

86* Cuando se mezclan variables de diferentes tipos, C tiende a convertirlos al tipo mas alto de las variables usadas. Estas conversiones se rigen por las siguientes reglas:

87* Todos los char y short int se convierten a int. Todos los float a double.

88* Para cada par de operandos ocurre lo siguiente, en secuencia:

89* Si uno de los operadores es long double el otro se convierte a este mismo tipo.

90* Si uno de los operadores es double el otro se convierte a este mismo tipo.

91* Si uno de los operadores es long el otro se convierte a este mismo tipo.

92* Si uno de los operadores es unsigned el otro se convierte a este mismo tipo.

93* Ejemplo:

A.Rodriguez L. 15

Page 16: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

char ch;

int i;

float f;

double d;

resultado=ch / i + f * d - f + i

int double double

int double

double

double

double double

double

2.6 CONVERSIÓN DE TIPOS EN LA ASIGNACIÓN.

94* La conversión de variables en la asignación, se hace ajustando la variable de la derecha (fuente) al tipo del de la izquierda (destino). Con esto se puede perder valores si la variable destino es mas pequeña que la fuente. Para entender esto veamos el siguiente ejemplo:

#include <stdio.h>

main()

{ int x=300;

char ch=300;

float f=30.5;

ch=x; printf( %d\n,ch); /* Caso 1 da 44*/

x=f; printf( %d\n,x); /* Caso 2 da 30*/

f=300/ch; printf( %f\n,f); /* Caso 3 da 6.00*/

A.Rodriguez L. 16

Page 17: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

f=ch; printf( %f\n,ch); /* Caso 4 da 40.00*/

}

95* En el caso 1 se toman los 8 bits menos significativos, no considerando el byte alto por lo que los valores que pasen de 128 son truncados.

96* En el caso 2 se toma solo la parte entera de la variable float.

97* En los casos 3 da 6.00 en vez de 6.82 como debería, ya que como los dos operadores son enteros (char e int) el resultado da un division entera.

98* En el caso 4 se convierten del char a flotante.

99* La siguiente tabla resume las conversiones al asignar valores de diferentes tipos.

Destino Fuente

Posible perdida de información

unsigned char

char Si valor > 127, dest. es negativo.

char short int

Signo

char int El byte mas significativo

char long int

Los 3 bytes mas significativos

short int long int

Los 3 bytes mas significativos

int long int

Los 2 bytes mas significativos

int float Parte fraccional y prob. mas

float double Precisión, se redondea valor

double long double

Precisión, se redondea valor

2.7 CASTS

100* Es posible forzar una expresión a ser de un tipo especifico usando la construcción llamada casts (molde). El formato general de un casts es :

(tipo) expresión

A.Rodriguez L. 17

Page 18: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

101* Por ejemplo si x es int y quiero que la computadora evalué x/2 como un float, se escribe de la siguiente forma:

(float) x / 2

102* Es recomendable tener cuidado con los casts. En el ejemplo anterior se asocia a x como un float, sin embargo si se pone de la siguiente manera no se tendrá el mismo resultado:

(float) (x / 2)

103* En este caso primero se hace la división, (una división entera) y luego esta división se convierte a float.

2.8 -FUNCIONES BASICAS DE E/S

104* Las definición de las funciones de entrada/salida básicas que se pueden usar, se encuentran los archivos de cabecera stdio.h y conio.h.

105* Para poder usar dichas funciones, se debe poner disponible con la directiva del compilador include en la siguiente forma:

#include <stdio.h>

#include <conio.h>

106* Las funciones mas comunes son las siguientes:

Función: int getche(void); Libreria:conio.h

Acción: Lee un carácter desde el teclado, colocándolo en una variable de tipo entero (char o int), haciendo eco en pantalla del carácter captado.

Función: int putchar(int c); Libreria:stdio.h

Acción: escribe un carácter en la pantalla en la posición que este el cursor.

Función: int getchar(void); Libreria:stdio.h

Acción: Lee un carácter desde el teclado, pero espera el retorno de carro para pasarlo al sistema.

Función: int getch(void); Libreria:conio.h

Acción: Lee un carácter al igual que getche, pero no hace eco en pantalla.

Función: char *gets(char *s); libreria:stdio.h

A.Rodriguez L. 18

Page 19: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

Acción: Lee una cadena de caracteres de la consola y devuelve un puntero a s que es una string. Acepta toda la cadena hasta que se da retorno de carro, pero este no es almacenado. En lugar de este la función le coloca el carácter terminador nulo \0.

Función: char *puts(char *s) Libreria:stdio.h

Acción: Hace una salida a video de una cadena de caracteres, a partir del lugar donde se encuentre el cursor.

Función: int printf(char *cad_ctr, lis_ar); Libreria:stdio.h

Acción: Muestra en video la salida de datos formateados, usando una cadena de control, que muestra la distribución y el orden de las variables de salida en una cadena de caracteres. Las variables a salir se indican en una lista de argumentos, después de la cadena de control, separados por comas y en el orden que se deseen.

Los códigos de formato de salida para printf son los siguientes:

Código Formato

%c Un solo carácter

%d Decimal

%i Decimal

%e Notación científica.

%f Punto decimal flotante

%g Usa %e o %f la que sea mas corta

%o Octal

%s Cadena de caracteres

%u Decimal sin signo

%x Hexadecimal

%% Imprime signo %

%p Visualiza un puntero

Algunos ejemplos de salidas con printf()

printf("%-10.2f", 123.2) |123.2 |

printf("%10.2f", 3.236) | 3.24|

printf("%10s", "hola") | hola|

printf("%-10s", "hola") |hola |

printf("%7s","123456789") |1234567|

A.Rodriguez L. 19

Page 20: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

Función: int scanf(char *cad_ctr, lis_ar); Libreria:stdio.h

Acción: Esta función nos permite recibir desde el teclado cualquier tipos de datos y lo convierte automáticamente a un formato interno adecuado a la variable en que será recibido.

La cadena de control consta de tres tipos de caracteres: especificador de formato, caracteres de espacio, y caracteres de no espacio.

Los indicadores de formato que se pueden usar son los siguientes:

Código Significado

%c Lee un carácter único

%d Lee un entero decimal

%i Lee un entero decimal

%e Lee un num. En flotante.

%f Lee un num. En flotante

%o Lee un octal

%s Lee una cadena

%x Lee un hexadecimal

%p Lee un puntero

Algunos ejemplo del uso de scanf.

scanf("%d", &cont) Pasa la dirección de cont a scanf.

scanf("%s",cadena) Lee una cadena de caracteres.

scanf("%d%d",&r,&t) Lee dos valores, los cuales se separan por un blanco que puede ser espacio, tab o cr.

scanf("%d%*c%d",&x,&y) Lee tres valores pero ignora el intermedio.

scanf("%20s",cadena) Lee una cadena de solamente 20 caracteres, los restantes se quedan en el buffer.

scanf("%c%c%c",&a,&b,&c) Lee tres caracteres no respetando caracteres blancos. Si se lee "X Y", 'X' va a a, ' ' va a b y 'Y' va a c

A.Rodriguez L. 20

Page 21: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

scanf("%dt%d",&x,&y) Leerá dos valores con una t intermedia, la cual será ignorada.

107* Programa muestra de instrucciones E/S y printf

#include <conio.h>#include <stdio.h>main(){ char cad[20]; char b; int en=-32766; float fl=234.453;clrscr();gotoxy(10,1); puts(“programa de muestras de usos de instrucciones de E/S”);gotoxy(5,3);printf(“prueba de getchar: presione una tecla y luego enter..>“); b=getchar();b=getchar(); /*saca del bufer de la libreria ‘stdio’ el

carácter #10 */gotoxy(5,4);printf(“Prueba de getche: presiones una tecla.>“); b=getche();gotoxy(5,5);printf(“Prueba de getch: presione una tecla.>“); b=getch();gotoxy(15,6);printf(“La tecla presionada fue = [%c]”,b);gotoxy(5,8);printf(“Prueba de gets: escriba una cadena y enter.>“); gets(cad);gotoxy(10,10); printf(“Pruebas de impresion usando printf”);gotoxy(10,11); printf(“El carácter ‘%c’ capturado arriba”,b);gotoxy(10,12); printf(“El caracter ‘%c’, como decimal= %i”,b,b);gotoxy(10,13); printf(“El número %i en octal=%o”,b,b);gotoxy(10,14); printf(“El número %i en hexa.=%x”,b,b);gotoxy(10,15); printf(“El número %i pero sin signo=%u”,en,en);gotoxy(10,16); printf(“El número %f en notación cientifica= %8.3e,fl,fl);gotoxy(10,17); printf(“El número %f en flotante con decimales [%10.1f]”,fl,fl);gotoxy(10,18); printf(“La forma mas corta %g de los dos de arriba”,fl);gotoxy(10,19); printf(“Con un mensaje:[%s]”,cad);gotoxy(10,20); printf(“Cadena con tamaño especifico:[%30s]”,cad);gotoxy(10,21); printf(“Cadena con tamaño justificada:[%-30s],cad);

A.Rodriguez L. 21

Page 22: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

getch();}

108* Programa muestra de scanf

#include stdio.hmain(){ char cad[20]; char b; int en=-32766;clrscr();gotoxy(10,1); puts(“Programa de muestras de usos del scanf para entradas”);gotoxy(5,3);printf(“Escribe un número entero (char)=“); scanf(“%d”,&en);gotoxy(5,4); printf(“[%d]”,en);gotoxy(5,6);printf(“Escribe una cadena de caracteres=“); scanf(“%s”,cad);gotoxy(5,7); printf(“[%s]”,cad);gotoxy(5,9);printf(“Escribe dos enteros separados por espacio=“); scanf(“%d%d”,&b,&en);gotoxy(5,10); printf(“[%d][%d]”,b,en);gotoxy(5,12);printf(“Escribe dos enteros separados por una l=“);scanf(“%dl%d”,&b,&en);gotoxy(5,13); printf(“[%d][%d]”,b,en);getch();}

2.9 ESTRUCTURAS CONDICIONALES

109* Cualquier instrucción condicional o cíclica, trabaja sobre una sentencia. En C una sentencia puede ser:sentencia única, bloque de sentencias o sentencia vacía.

2.9.1 El if

110* Sintaxis :

If(condición) sentencia;

else sentencia;

111* Al igual que en otros lenguajes el else es opcional. Si la condición se cumple (distinta de cero) se ejecutara la sentencia del if, sino la del else.

112* Existe una variante del if normal que es el if con el escalonador else if. Esta variante permite escalonar tomas de decisión con varios posibles condiciones. La sintaxis es la siguiente:

A.Rodriguez L. 22

Page 23: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

if(condición) sentencia;

else if (condición) sentencia;

else if(condición) sentencia;

:

else sentencia;

113* En esta condicion se compara primero la condición del if mayor, si se cumple se ejecuta su sentencia y termina, pero sino verifica si se cumple en la segunda, sino en la siguiente, hasta que cumpla alguna o hasta que se llegue al else (el cual es opcional) cuando no se cumpla ninguna de los else if anteriores.

114* Al anidar varios if’s cada uno se agrupan con el else mas cercano, a menos que se indique con {} la jerarquía.

2.9.2 El switch

115* Es una toma de decisión con opciones múltiples, que tiene la siguiente sintaxis:

switch(variable)

{ case const1: secuencia de sentencias;

break;

case const2: secuencia de sentencias;

break;

case const3: secuencia de sentencias;

break;

:

default: secuencia de sentencias;

}

116* Las características de switch son las siguientes:

117* Solo comprueba igualdad.

118* No puede haber constantes case con el mismo valor en un switch de mismo nivel.

119* Es mas eficiente que el escalonador else if.

120* La opción default es opcional y se llega a ella cuando ningún caso se cumple.

121* Si se olvida un break la sentencia salta al siguiente grupo de sentencias, hasta que encuentre uno o hasta que termine. Los case se consideran en ese momento como invisibles.

A.Rodriguez L. 23

Page 24: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

122* No existe ningún problema en anidar sentencias switch siempre y cuando estén bien delimitadas.

2.9.3 Programa muestra del uso del switch

#include <conio.h>#include <stdio.h>main(){ int v,op;clrscr();gotoxy(10,10); printf(“CONVERCIONES DE DIFERENTES TIPOS BASE”);gotoxy(25,12); printf(“1: decimal a hexadecimal”);gotoxy(25,13); printf(“2: hexadecimal a decimal”);gotoxy(25,14); printf(“3: decimal a octal”);gotoxy(25,15); printf(“4: octal a decimal”);gotoxy(20,17); printf(“SELECCIONE UN NUMERO”); scanf(%d,&op);switch(op){ case 1: gotoxy(20,20); printf(“Introduzca un valor decimal”);

scanf(%d,&v);gotoxy(20,22); printf(“[%d] en hex. es [%x]”,v,v);break;

case 2: gotoxy(20,20); printf(“Introduzca un valor hex.”);scanf(%x,&v);gotoxy(20,22); printf(“[%x] en decimal es [%d]”,v,v);break;

case 3: gotoxy(20,20); printf(“Introduzca un valor decimal”);scanf(%d,&v);gotoxy(20,22); printf(“[%d] en octal es [%o]”,v,v);break;

case 4: gotoxy(20,20); printf(“Introduzca un valor octal”);scanf(%o,&v);gotoxy(20,22); printf(“[%o] en decimal es [%d]”,v,v);break;

default: gotoxy(20,20); printf(LO SIENTO SELECCION NO VALIDA); break;};getch();}

2.10 ESTRUCTURAS CÍCLICAS

123* En c existen 3 tipos de estructuras cíclicas: for, while y do while.

A.Rodriguez L. 24

Page 25: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

2.10.1 La instrucción for

124* Sintaxis :

for(Inicialización; Condición; Incremento) sentencia;

Inicialización: corresponde al valor que se le asigna a la variable que controlara el ciclo.

Condición: expresión que solo mientras se cumple (diferente a 0) entra a ejecutar la sentencia del ciclo. La condición se prueba al inicio del ciclo for.

Incremento: es una expresión que determina la forma en que cambia la variable de control del ciclo.

125* Variaciones que se pueden aplicar al for:

126* Puede especificarse cualquier expresión valida en C en cualquiera de las 3 partes del for.

127* La Condición debe dar un valor igual a 0 para terminar.

128* Pueden indicarse mas de una expresión en la Inicialización o en el Incremento, si se separan estos por comas.

129* Se puede romper un ciclo for (en realidad cualquier ciclo) usando las sentencia break.

130* Se puede forzar la verificación de la condición, (aunque no se halla terminado un bloque de sentencias) usando la sentencia continue.

2.10.2 La instrucción while.

131* Sintaxis:

while(condición) sentencia;

sentencia: es una sentencia única, un bloque de sentencias o una sentencia vacía.

condición: expresión que mientras sea cierta (resultado diferente de 0) se entra a ejecutar sentencias.

2.10.3 La instrucción do/while.

132* Sintaxis:

do

A.Rodriguez L. 25

Page 26: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

{ sentencia;

} while(condición);

133* Este ciclo evalúa la condición al final de la sentencia, por lo que al menos una vez se ejecuta las sentencias especificas.

134* La sentencia y condición tienen la misma característica que en los ciclos anteriores.

2.10.4 Programa muestra de diversas formas del for

#include <stdio.h>#include <conio.h>main( ){ int x,y; char cade[ ]=“PRUEBA DE DESPLIEGE\n”; char c=’a’; clrscr(); for (x=1 ; x<=20 ; x++) printf(“Asciende %d \n”,x); getch(); clrscr(); for (x=20 ; x>0 ; --x) printf(“Desciende %d \n”,x); getch(); clrscr(); for (x=50 ; x>0 ; x-=5) printf(“Desciende en 5 %d \n”,x); getch(); clrscr(); for (x=1, y=1 ; x+y<10 ; x++,++y) printf(“X= %d y Y=%d \n”,x,y); getch(); clrscr(); for (x=20, y=1; --x!=y++; printf(“Primero X= %d y Y=%d \n”,x,y) ); getch(); clrscr(); for (x=0; printf(“%c\n”,cade[x]),cade[x] ; x++ ); getch(); clrscr(); for (;! kbhit();) puts(“Este mensaje no para hasta que de una tecla”);getch();}

2.10.5 Programa muestra del uso de while

135* Programa muestra de for, que ayuda a un niño a aprender las tablas de multiplicar, del 1 al 10, llevando la cuenta de sus errores y aciertos.

#include <stdio.h>#include <conio.h>

A.Rodriguez L. 26

Page 27: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

#include <ctype.h>main(){ int x,y,flag,res=1,buenas=0,malas=0;clrscr();for (x=1; x<=10 && res!=0; x++) { printf(“Si deseas Terminar, solo presiona 0”);

printf( TABLA DEL %d\n\n,x);for (y=1; y<=10; y++){ gotoxy(10,y+4); printf(“Cuanto es %d x %d ?”,x,y); gotoxy(28,y+4); for(;!scanf(“%i”,&res);)

{ scanf(“%c”,&flag); gotoxy(28,y+4); } gotoxy(35,y+4);

if (!res) break; else if (res==x*y)

{ buenas++; printf(“BIEN”); } else { malas++; printf( “Error”); };

}; };gotoxy(20,20); printf(“Presione una tecla para continuar”);getch();clrscr();};

A.Rodriguez L. 27

Page 28: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

3. FUNCIONES, APUNTADORES Y ESTRUCTURAS DE DATOS

3.1 FUNCIONES DEFINIDAS POR EL USUARIO

136* Como en todo lenguaje estructurado, en C es posible definir subrutinas creadas por el usuario. Estas subrutinas son importantes, ya que permiten darle modularidad a un programa.

137* En C a diferencia de otros lenguajes, solo existen subrutinas tipo función. Sin embargo estas tienen la suficiente flexibilidad para no necesitar otro tipo de subrutinas como los procedimientos .

138* Para entender la forma de trabajar las funciones en C, debemos considerar que todo lo que hay en C (que no sean sentencias nativas o expresiones) son funciones. El caso mas típico de una función es el mismo programa principal main.

139* main es una función de tipo especial que sigue las mismas reglas que las funciones comunes pero que tiene el atributo especial de prescindir un programa.

140* La sintaxis de una función es:

tipo nombre_función(declaración_parámetros)

{ Sentencias_de_función

}

141* La expresión tipo es el tipo de valor que la función devolverá cuando se use la sentencia return. Si no se define devuelve por default un int.

142* La declaración_parametros es una lista que permite pasarle parámetros a una función. Para poder hacerlo, cada parámetro debe ser definido en la siguiente forma:

tipo nom_var, tipo nom_var1, tipo nom_var3

143* Cada parámetro definido se considera como una variable local del procedimiento. Si la función que definimos no necesita parámetros esta lista puede estar vacía, sin embargo es necesario colocarle los paréntesis.

144* Se debe de tener mucho cuidado con los parámetros que se pasan a las funciones sean del mismo tipo que los parámetros declarados, ya que esto puede ocasionar problemas, no en la compilación sino en la ejecución. Como ya se menciono, C es un lenguaje que no tiene verificación de tipos, por lo que hará lo que se le indique, aunque no sea lo que deseemos.

145* Por ejemplo si declaramos en una función un parámetro char, y le pasamos como argumento a la hora de llamarlo un int; c no marcara ningún error de tipo, sino que tomara el byte bajo del entero y con ese trabajara. Esto es correcto desde el punto de vista de C pero puede arrojarnos resultados que no esperamos.

A.Rodriguez L. 28

Page 29: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

3.1.1 Tipos de parámetros en funciones.

146* Existen dos forma de pasar parámetros a una función. Parámetros por valor y por referencia. El paso de parámetros por valor hace una copia del valor de una variable a un parámetro. Con esto no se afecta su valor original.

147* El paso de parámetros por referencia copia la dirección de la variable, por lo que se pueden realizados cambios directamente en la variable de la función llamadora, ya que se tiene la dirección de la variable. Para pasar la dirección de una variable se indica en el parámetro el tipo de la variable, seguido del nombre que recibirá en la función (pero precedida de *).p.e.

func(int *a, char*b)

148* De esta forma el primer parámetro que se pase a func será la dirección de un int y el segundo la dirección de un char. Cualquier referencia que se haga (dentro de la función) de las variables deberá usarse su nombre precedido del * .

149* Ejemplo:

#include <stdio.h>

cambia_dat(int a; int *b)

{ a+=5;

(*b)+=5;

}

main()

{ int h=10,i=10;

cambia_dat(h,&i);

printf(“h=%d i=%d”,h,i);

}

3.1.2 Funciones que regresan valores

150* Para poder regresar valores a la rutina llamadora existe la sentencia return. Esta sentencia termina la ejecución de una función; permitiéndonos regresar un valor especifico.

151* Este valor debe de ser del mismo tipo del declarado antes del nombre de la función. Sin embargo no debe ser de tipo void, ya que esto indica que no se desea regresar valor.

152* Si no se declara ningún tipo entonces devuelve int.

A.Rodriguez L. 29

Page 30: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

153* Normalmente una función que devuelva un valor, debe asignarlo a una variable. Sin embargo en C si no lo hace, solamente se pierde este valor, pero no marca un error, ya que esto es valido.

3.1.3 La función especial main

154* La función main, a diferencia de otras funciones definidas por el usuario, solo permite tres posibles parámetros. Estos parámetros le permiten comunicarse con el ambiente exterior (S.O.) cuando se ejecuta el programa. Los parámetros permitidos son los siguientes:

argc: Es un entero que indica la cantidad de parámetros tecleados en el prompt del sistema al momento de ejecutar el programa. El valor mínimo que devuelve es 1 (sin parámetros), ya que el nombre del programa se considera también como parámetro. Los parámetros deberán estar separados por espacios blancos o tab’s pero no así por comas, puntos y comas ya que estos no son separadores valido en el S.O.

argv: Es un puntero a un array de puntero char. Dicho de otra forma, contiene la dirección de memoria que ocupa un array de cadenas de caracteres. Este array contiene en cada posición (a partir de la 0) cada uno de los parámetros indicados por en argc. Por supuesto el primero es el mismo nombre del programa.

Env: también es un puntero a un array de cadenas que contiene todas las especificaciones de entornos de S.O. la última cadena del array es un nulo que marca el final de la lista.

155* Programa ejemplo de acceso a parámetros de main

#include <stdio.h>

#include <string.h>

void main(int argc,char *argv[],char *env[])

{ int i;

for(i=0;i<argc;i++) printf("P [%d]=%s\n",i,argv[i]);

for(i=0;strlen(env[i]);i++) printf("E [%d]=%s\n",i,env[i]);

}

3.2 FUNCIONES CON PARAMETROS VARIABLES

156* Existe una librería standard de C que permite manejar funciones que tengan parámetros variables.

A.Rodriguez L. 30

Page 31: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

157* Esta librería se llama stdarg.h

158* La librería cuenta con tres funciones macro, las cuales hacen lo siguiente:

159* va_start(va_list p, namefix);

Se encarga de inicializar el puntero p que permitirá sacar los datos de la lista variable. El namefix, es el nombre del último parámetro fijo. El tipo va_list esta definido en la misma librería. Esta macro solo se ocupa una vez al inicio de la función.

160* va_arg(va_list p, tipo);

Se encarga de extraer un dato de la lista p indicándose el tipo de cada dato sacado. Se hace un llamado a esta función por cada dato a sacar. Por lo general se encuentra dentro de un ciclo for.

161* va_end(va_list p);

Se encarga de liberar memoria y destruir el puntero p se usa solo una vez al finalizar la lectura de los parámetros variables.

3.2.1 Programa de ejemplo.

#include <stdio.h>

#include <stdarg.h>

int suma(char ne, ...)

{ int t , s=0;

va_list ap;

va_start(ap, ne);

for(t=0;t<ne; t++) s += va_arg(ap,int);

va_end(ap);

return s;

}

void main(void)

{ int i;

i=suma(5,1,2,3,4,0);

printf(“\n%d”,i); }

3.3 DEFINICION DE ARREGLOS

3.3.1 Arrays normales

162* Para declarar un array se indica el tipo base del array, el nombre del mismo y la cantidad de elementos. La sintaxis es la siguiente:

A.Rodriguez L. 31

Page 32: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

tipo nombre_var[tam];

163* El índice del primer elemento de un array es 0 (cero) y el ultimo es tam - 1. El tamaño total de un array se calcula multiplicando el tamaño del tipo base por la cantidad de elementos que tiene.

164* En general el manejo de array en C es como el que se da en otros lenguajes, sin embargo existe una característica que lo arrays de C no tiene y puede ocasionar problemas.

165* Esta característica es la carencia de comprobación de contornos.

166* Esta característica se da porque C fue pensado como un sustituto de ensambladores, y esta verificación (que es común en lenguajes de alto nivel) reduce el rendimiento de una aplicación. Por ello C asume que el programador es lo suficientemente responsable para llevar el control de su datos.

167* El principal problema que se puede presentar con esta característica es que se sobre-escriba en el área correspondiente a otro dato si se pasa del limite de un arreglo, lo cual destruiría los datos en otra área y nos ocasionaría los problemas correspondientes.

168* Internamente C considera cualquier array como una lista de datos contifuos en las que cada elemento de la lista ocupan el espacio indicado por el tipo base.

169* Ejemplo del problema que ocasiona la no comprobación de contorno.

#include <stdio.h>

void main(void)

{ int a[4]={3,3,3,3},b[4] ,i;

// En memoria quedan en el sgte. orden: i,b, y a

for(i=0;i<=4; i++) b[i]=0;

for(i=0; i<4; i++) printf("a[%d]=%d\n",i,a[i]);

}

En este ejemplo el primer ciclo accesa una posición mas de las originalmente asignadas, con lo que se invade la zona de la variable adyacente, el array “a”.

3.3.2 Array multidimensionales.

170* Un array multidimensional permite definir una estructura de datos que contiene muchas dimensiones. El tamaño máximo de un array depende de la forma en que se trabaje en el modelo de memoria y las limitaciones del compilador.

171* Para definir un array multidimensional se usa la siguiente sintaxis:

tipo nombre[tam1][tam2].......[tamn];

A.Rodriguez L. 32

Page 33: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

172* No es conveniente definir array extremadamente grandes, ya que fácilmente pueden quedar fuera de la memoria de la computadora. En el siguiente ejemplo se define el caso mas sencillo de array multidimensionales, los array bidimensionales.

Int marcas[4][3];

173* Para accesar cada elemento de un array se hace indicando los dos índices encerrado cada uno entre corchetes. Por ejemplo si en el array anterior se quisiera accesar el elemento del renglón 3 columna 2 se haría así:

marcas[2][1]=20;

174* El primer índice indica el numero de renglón dentro de la memoria y el segundo el numero de columna. Como los array son listas de datos, en la memoria quedaría en orden cada uno de los renglones indicado por el primer índice y en cada columna de cada renglón por el segundo índice.

175* Un caso aparte son los arrays de cadenas. Los arrays de cadenas son arrays de punteros. No se tiene mas problema al definirlos, pero si se debe tener cuidado al accesarlos. Recordemos que el solo nombre del array es la dirección de la cadena.

#include <conio.h>

#include <stdio.h>

void main(void)

{ char i,acad[4][6]={"caso1","caso2","caso3","caso4"};

clrscr();

for(i=0; i<4; i++) printf("Renglon %d =[%s]\n",i,acad[i]);

}

176* Por otro lado, la no comprobación de contornos hace que un array pueda ser accesado de diferentes formas. Ejemplo:

#include <conio.h>

#include <stdio.h>

void main(void)

{ int i,j,a[4][3]={0,1,2,10,11,12,20,21,22,30,31,32};

clrscr();

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

{ printf("Renglon %d =[",i);

for(j=0; j<3; j++) printf(" %d ",a[i][j]);

printf("]\n");

}

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

{ printf("Renglon %d =[",i);

A.Rodriguez L. 33

Page 34: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

for(j=0; j<4; j++) printf(" %d ",a[i][j]);

printf("]\n");

}

for(i=0;i<12; i++) printf(" %d ",a[0][i]);

}

3.4 Manejo de cadenas de caracteres

177* Una aplicación común de arrays, es la creación de cadenas. Cabe mencionar que el terminador de una cadena es el carácter nulo, por ello, si se desea tener una cadena de N caracteres, se debe definir un array de N+1 bytes, ya que el nulo también ocupa espacio.

178* No es necesario añadir el carácter nulo, el compilador o las funciones de E/S lo añaden automáticamente en casi todos los casos.

179* El nombre de una cadena (array de char) sin índices es la dirección de memoria donde esta almacenado el array.

3.4.1 Funciones comunes para el manejo de cadenas

180* Existe una librería de funciones que permite manejar cadenas y hacer algunas operaciones con ellas. Las funciones de esta librería se encuentran en el archivo de cabecera string.h . La librería cuenta con alrededor de 70 funciones, de las cuales a continuación se muestran 4 de las mas comunes

Función Acción

char * strcpy(char *dest,char *fuen)

copia la cadena fuen a la cadena dest

char * strcat(char *dest,char *fuen)

Agrega la cadena fuen a la cadena dest.

int strcmp(char *cad1,char *cad2) Compara lexicograficamente dos cadenas, devolviendo:0 si son iguales; positivo si cad1 es mayor que cad2 y negativo si cad1 en menor que cad2.

int strlen(char * cad) Regresa el numero de caracteres de la cadena sin contar el nulo.

A.Rodriguez L. 34

Page 35: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

3.5 CONCEPTOS DE APUNTADORES

181* Los punteros son variables que pueden almacenar una dirección de memoria, tomando el valor de la misma memoria en función al tipo base del puntero.

182* Estas variables especiales se definen de la siguiente forma:

tipo *nombre_var;

183* El tipo es algunos de los definidos por el C estandard o por el usuario. El * indica que se trata de una variable puntero que tiene el nombre especificado. El tipo indica ademas la cantidad de bytes y la forma que tiene el dato ahi almacenado.

3.5.1 Funciones para el manejo de memoria dinamica.

184* Normalmente un puntero se usa para manejar memoria del heap, asignada dinamicamente. Esta memoria se asigna y libera por medio de funciones predefinidas, que se encuentran (variando de la versión del compilador) en la libreria stdlib.h o alloc.h. Dichas funciones se describen a continuación:

void * malloc(unsigned tam);

Asigna una porción de memoria del heap, regresando la dirección de esta memoria o 0 no se pudo resolver la asignación. El valor devuelto se debe asignar a una variable tipo puntero.

void free(void *ptr);

Libera la memoria previamente asignada con malloc, calloc.o realloc.

void *calloc(unsigned size, unsigned elem);

Asigna memoria para un array donde el tamaño de cada elemento esta dado por size y el numero de elementos del array es elem. Depues de asignar la memoria, inicializa los elementos del array con cero.

void *realloc(void *ptr,unsigned tnew);

Relocaliza o asigna un espacio de memoria bajo la siguiente reglas:

- Si ptr es cero, crea un puntero de la cantidad de bytes indicado en tnew. Similar a como lo hace malloc.

- Si ptr es diferente de cero y tnew es igual a 0, libera la memoria usada. Similar como lo hace free.

- Si ptr es diferente de cero y tnew es mayor que cero, pero menor o igual que la memoria previamente asignada, no hace ningun cambio.

- Si ptr es diferente de cero y tnew es mayor que la memoria previamente asignada, busca una nueva localidad de memoria donde asignar la memoria solicitada y copia el contenido de la memoria anterior, con lo que no hay riesgo de perder datos. Si encuentra memoria, devuelve la dirección de esta, sino devuelve cero.

A.Rodriguez L. 35

Page 36: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

185* El siguiente programa es un ejemplo de como se usan los punteros con la memoria dinamica.

main()

{ int *m, *n, *p;

m=(int *)malloc(4);

n=(int *)calloc(sizeof(int),4);

p=(int *)realloc(n,6);

free(m); free(n); }

3.5.2 Operadores para punteros.

186* Existen dos operadores principales que nos permiten trabajar con punteros, esos son & y *. Ademas existen algunas otras operaciones que se pueden realizar con punteros. Estas operaciones seran descritas a continuacion.

OPERADOR

FUNCIONAMIENTO

& Proporciona la direccion de memoria que tiene la variable que precede.

* Proporciona el contenido de la dirección de memoria que contiene la variable a la cual precede. Por supuesto, la variable que precede debe ser de tipo puntero. Aqui es donde C utiliza el tipo base para saber la cantidad de bytes y la forma que tienen los datos.

+ , - Suma o resta un valor entero a un puntero, lo cual equivale a desplazar el valor de un puntero.

++, -- El incremento o decremento en punteros, es una operacion que es posible realizar en C. La direccion en que se incrementa un puntero, depende del tipo base que se tenga.

= La asignacion entre punteros es posible, aunque los tipos base no sean iguales. En este caso, el compilador indicara un mensaje de advertencia. Diciendonos que los tipos base no coinciden.

>, <, >=,<=, !=

Permite comparar el contenido de dos punteros

3.5.3 Posibles problemas con punteros.

187* Nada es mas peligroso que un puntero no controlado. Esto pueden ocasionar diversos problemas que van desde los resultados erroneos, hasta la perdida de

A.Rodriguez L. 36

Page 37: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

informacion o del sistema operativo. A continuación se enlistan los problemas mas comunes al manejar punteros.

188*

189* No inicializar un puntero. Provoca que se afecten zonas de memoria que tengan otros datos o incluso codigo.

No resulta suficiente asignarle nulo a un puntero, es necesario asignarle una direccion memoria valida.

190* Asignaciones de valores numericos a punteros. Esto se da cuando se asigna accidentalmente un valor numerico a un puntero, en vez de una dirección. C convertira este valor entero a un puntero que sería cualquier dirección de memoria dependiente del valor.

Si en esta dirección de memoria se asigna un dato, este destruirá el dato anterior en esa localidad de memoria.

191* Paso de punteros como parametros. Se debe comprender bien las forma en que C maneja el paso de parametros por valor y referencia.

192* Programa que se muestra a continuación, ejemplifica los casos de manejo erroneo de punteros. Es importante no intentar correrlo, ya que seguramente ocasionará problemas en la maquina.

pru(char *qwe)

{ qwe=(char*)malloc(10); //Asigna 10 bytes de memoria

//dinamica a la variable qwe

// pero al terminar la función la dirección

// que tiene qwe se pierde, ya que es local

}

main()

{ char *r, *n;

long rt=5450;

strcpy(r,”hola”); // Previamente hay que asignar memoria

// con malloc a la variable r

n=rt; // Hace falta & antes de rt

pru(r);

}

3.5.4 Arrays y punteros

A.Rodriguez L. 37

Page 38: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

193* Los punteros y los arrays guardan una relacion muy extrecha . De hecho el nombre de un array sin indices, es la direccion de memoria en la cual se almacena el array.

194* Es importante considerar esta caracteristica, ya que los array se pueden manejar tambien como si fueran punteros.

195* Existe ventaja y desventaja al manejar un array por indices o por punteros; de hecho depende del tipo de problema.

196* Si el problema necesita el manejo secuenciado de los elementos de un array, es conveniente resolverlo por punteros, ya que es mas optimo el codigo, sin embargo puede costarnos mas trabajo (al menos al inicio) visualizar claramente la solucion.

197* Si el problema necesita un manejo aleatorio de elementos, es mas facil y util usar indices, ya que por punteros seria muy problematico hacerlo.

198* Si alguna aplicacion lo requiere, es posible crear un array de punteros. Donde cada posicion guardara la direccion de un datos especifico (por ejemplo cadenas de mensajes ya mencionados).

Ejemplo:

#include <conio.h>

#include <stdio.h>

void ordena1(int *e)

{ int *tem,i,j,p,q,d;

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

{ d=e[i]; p=i; tem=&e[i]; //Acceso por indices

for(j=i+1;j<=9;j++)

{ tem++; // Recorrido del array por punteros

if(d>*tem) {d=*tem; p=j;}

}

q=e[i]; e[i]=d; e[p]=q; //Acceso por indices

}

}

void main(void)

{ int d[10]={12,17,21,23,2,9,16,5,3,14},g;

clrscr();

ordena1(d);

for(g=0;g<=9;g++) printf(" %d ",d[g]);

}

A.Rodriguez L. 38

Page 39: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

3.5.5 El modificador const en punteros como parametros

199* Si se desea evitar la modificación del dato que esta en la dirección de memoria que tiene un puntero, se le puede aplicar const al parametro. Con lo que se evitaria la modificación del dato, no asi del puntero.

200* Sin embargo, el parametro en realidad es una copia del puntero que se tiene pasa a la función al momento de llamarla.

201* Ejemplo

#include <stdio.h>

#include <conio.h>

void f1(const char *a)

{ while(*a)

{ printf("%c\n",*a); a++; }

};

/* Esta función ocasionará un error de compitalción al tratar

de asignar 0 a la cadena

void f2(const char *a)

{ while(*a)

{ printf("%c\n",*a); *a=0; a++; }

};

*/

void main()

{ char a[]="Cadena prueba";

clrscr();

f1(a);

printf(" Cadena original : %s \n",a);

};

3.5.6 Tipos de indireccionamiento

202* A la operacion de accesar un dato a traves de un puntero, se le llama indireccionamiento de memoria. Un indireccionamiento puede ser simple o doble.

203* El simple es el que ya hemos comentado, en el cual un puntero direcciona a un dato especifico en memoria.

204* El indireccionamiento doble, es aquel en el que se tiene un puntero, que apunta a otro puntero, el cual a su vez apunta a un dato.

A.Rodriguez L. 39

Page 40: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

205* Un ejemplo simple de como se hace el indireccionamiento doble es el siguiente:

#include <stdio.h>

main()

{ int x, *p, **t;

x=10;

p=&x;

t=&p;

printf(%d,**t);

}

La utilidad del indireccionamiento doble se tiene cuando se desean pasar punteros por referencia a una función, para poderlos modificar dentro de la misma.

Un ejemplo practico es el siguiente:

#include <stdio.h>

void def_cad(char **c,int m)

{ *c=(char *)malloc(m); }

main()

{ char *cadena;

def_cad(&cadena,25);

}

3.5.7 PUNTEROS A FUNCIONES

206* Un puntero a una funcion almacena la direccion en que inicia una funcion. Con esta direccion, la función puede ser ejecutada, solo es necesario pasarle los parametros correspondientes. Esta caracteristica permite que en lenguaje C el programador realice programas con alto grado de abstraccion. A continuacion se muestra un programa en el cual se observa el funcionamiento de estos punteros.

#include <stdio.h>

#include <conio.h>

int suma(int a,int b) { return a+b; };

int resta(int a,int b) { return a-b; };

int multi(int a,int b) { return a*b; };

int divid(int a,int b) { return a/b; };

void main()

{ char op[5]="+-*/\0",res,i;

A.Rodriguez L. 40

Page 41: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

int (*q[4])(int a,int b); int r,s;

q[0]=suma; q[1]=resta; q[2]=multi; q[3]=divid;

while(1)

{ printf("\nTecle el operador que desea aplicar:");res=getche();

for(i=0;i<5&&res!=op[i];i++);

if (i<5) { printf("\nDeme dos numeros enteros:");

scanf("%d%d",&r,&s);

printf("\nEl resultado es:%d\n",(*q[i])(r,s));

}

else break;

}; }

3.6 ESTRUCTURAS Y UNIONES

3.6.1 Estructuras

207* Una estructura es una coleccion de datos de diferente tipo, conocidos con el mismo nombre generico, pero con un nombre particular a cada uno de los elementos de la estructura.

208* A estos elementos se les conoce como campos. La forma general como se define estructura es la siguiente:

struct nom_tipo

{ tipo nom1;

tipo nom2;

:

:

tipo nomn;

} vars_stru;

209* El nom_tipo es el nombre con que se identificará un tipo struct. Las vars_stru son una lista de variables que tendran el tipo indicado entre llaves. Se pueden omitir una o la otra pero no ambas.

210* Para hacer referencia a cualquier elementos de una estructura, se indica el nombre de la variable, seguida de un punto y el nombre del elemento que se desea usar.

211* Ejemplo:

#include <string.h>

main()

A.Rodriguez L. 41

Page 42: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

{ struct datos

{ char nombre[20]; unsigned char edad;

char direccion[30]; char categ;

} pers;

strcpy(pers.nombre,”FERNANDO MACIAS”);

pers.edad=26;

strcpy(pers.direccion,”ANTARTIDA 345 ESQ. MAR MUERTO”);

pers.categ=’D’;

}

3.6.2 Arrays de estructuras

212* Se pueden definir array de estructuras previamente creadas, de la siguiente forma:

struct nom_estruc nom_array[tam];

213* Los array de estructuras son utiles para almacenar datos en forma de una lista. Usando el tipo de estructura ‘datos’ definido anteriormente, se define un array a continuacion:

struct datos list_dat[10];

214* Para accesar al campo edad del elemento 3 del array, se hace de la siguiente forma:

List_dat[2].edad=27;

3.6.3 Apuntadores a estructuras

215* Es posible pasar en C estucturas completas como parametros a una funcion, se puede hacer de dos formas por valor y por referencia. Al hacerlo por valor, se hace una copia de la estructura en el stack.

216* Si esta estructura es demasiado grande puede sobrecargar el stack, con demasiados datos, incluso pudiendo llenar el mismo a la hora de tratar de pasarla como estructura.

217* La otra forma de pasar una estructura es por referencia. Con esta forma se pasa la direccion que ocupa la estructura en memoria, con lo cual los cambios se hacen directamente en la estructura original. Esta forma de trabajo suele ser mas optima por que es mas rapida.

218* Para pasar la direccion de una estructura hay que declararla como un puntero, de la siguiente forma:

struct nom_tipo *nom_var;

A.Rodriguez L. 42

Page 43: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

219* Se deben tener los mismo cuidados que con los punteros normales (descritos anteriormente). Es decir, el puntero debe contener una direccion segura (preferentemente de una variable del mismo tipo base del puntero ya declarada).

220* El otro cuidado que se debe tener, es que se debe comprender bien lo que se esta haciendo. Para entender como se referencian los elementos de un parametro pasado por referencia observemos con cuidado el siguiente ejemplo:

#include <stdio.h>

#include <conio.h>

#include <string.h>

struct dat

{ char nom[25];

char dir[30];

char edad;

};

void f1(struct dat per)

{ strcpy(per.nom,"Epifanio Morales");

strcpy(per.dir,"Remes 134");

per.edad=28;

};

void f2(struct dat *per)

{ strcpy(per->nom,"Epifanio Morales");

strcpy(per->dir,"Remes 134");

per->edad=28;

};

void main()

{ struct dat p;

strcpy(p.nom,"Dario Moreno"); strcpy(p.dir,"Mar Ejeo #45");

p.edad=25;

clrscr();

f1(p); printf(" Nombre =%s\n",p.nom);

printf(" Direccion=%s\n",p.dir);

printf(" Edad =%d\n",p.edad);

f2(&p); printf(" Nombre =%s\n",p.nom);

A.Rodriguez L. 43

Page 44: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

printf(" Direccion=%s\n",p.dir);

printf(" Edad =%d\n",p.edad);

};

221* Con este ejemplo se puede apreciar como es que se hace referencia a algun elemento de una estructura pasada por referencia.

222* Es posible tambien crear estructuras dentro de estructuras, estructuras con elementos de array y otras variedades de formas de acomodamiento de los datos, de acuerdo al tipo de problemas que se nos presente.

223* Con estructuras podemos crear tambien los casos de listas enlazadas, si definimos, dentro de los campos, alguno como un puntero a una estructuras del mismo tipo que el que la contiene.

3.6.4 Campos de bits

224* El permitir acceso a bits independientes es una caracteristica unica en emsamblador, que C tambien implementa. Los campos de bits se basan en una estructura. Para definirlos hay indicar que los campos de una estructuras no seran del tamaño que indique un tipo base, sino que sera del tamaño (en bits) que le indique el usuario.

225* Un campos de bits pueden tener maximo 16 bits. Fuera de las consideraciones que se tiene para los limites de datos, su funcionamiento es igual que cualquier otro campo numerico.

226* La sintaxis para declarar un campo de bits es el siguiente:

struct nom_estruc

{ tipo nom1:longitud;

tipo nom2:longitud;

:

:

tipo nomM:longitud;

}

227* El tipo puede ser signed o unsigned. Donde los campos signados ocupan 1 bit para el signo.

228* Las restricciones de un campo de bits son:

229* No se puede tomar su direccion.

230* No se pueden usar para crear arrays.

231* Algunos compiladores se interpretan de izquierda a derecha y en otras alreves.

A.Rodriguez L. 44

Page 45: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

232* Al crearce un campo de bits, se le asigna automaticamente multiplo de 8 bits, los cuales pueden ser usados por varios campos, hasta que estos se agoten.

233* Cuando esto sucede se asignan de nuevo 8 mas. Si no usamos algunos bits del grupo de 8 asignado, estos no pueden ser usados, a menos que se asignen a un campo de bits.

234* Si se definen campos normales despues del campo de bit, este comienza a partir del siguiente byte ( no del siguiente bit).

235* Ejemplo :

#include <stdio.h>

#include <conio.h>

struct date

{ unsigned a:7; unsigned m:4; unsigned d:5; };

void lee_fecha(struct date *t)

{ int tem;

printf("\nDeme el año (1900 a 2028).");

scanf("%d",&tem); t->a=tem-1900;

printf("Deme el mes (1 a 12)......");

scanf("%d",&tem); t->m=tem;

printf("Deme el dia (1 a 31)......");

scanf("%d",&tem); t->d=tem;

}

void muestra_fecha(struct date t)

{ char tem;

printf("\nEl año es :[%d], el mes es:[%d]”,t.a,t.m);

printf(" y el dia es:[%d]", t.d);

}

void main()

{ struct date d[3]; char i;

clrscr();

for(i=0; i<=2; i++) lee_fecha(&d[i]);

for(i=0; i<=2; i++) muestra_fecha(d[i]);

};

3.6.5 Uniones.

A.Rodriguez L. 45

Page 46: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

236* Una union es la asignación de varios campos en una misma localidad de memoria. pudiendo ser cada campo de diferente tipo. En una union, se considera que la memoria es una sucesion de bytes, los cuales toman la forma del tipo de datos que tenga la variable con la cual es accesada esa zona particular de memoria.

237* La union se define de forma similar a una estructura, aunque tiene diferente funcionamiento:

Union nom_tipo

{ tipo nom_var1;

Tipo nom_var2;

:

} nom_union;

Desde el punto de vista sintactico, una union tiene la misma restriccion que una estructura. Puede omitirse nom_tipo o nom_union, pero no ambos. Para accesar a uno de los elementos se usa el punto como separador.

La union asigna el espacio en memoria que ocupara, en función del tamaño de mayor campo. Para enteder el funcionamiento veamos el siguiente ejemplo simple:

#include <stdio.h>

main()

union ent

{ int c; char t[2]; } entero;

entero.c=1125;

printf(“El valor del byte alto es: [%d]”,entero.c[0]);

printf(“ y del byte bajo es [%d]”,entero.c[1]);

}

A.Rodriguez L. 46

Page 47: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

4. - ARCHIVOS

238* En C las E/S son independientes del dispositivo, lo cual le da al programador un buen nivel de abstracción, ya que no se preocupa de los detalles de control del dispositivo.

239* Para lograr esta independencia del dispositivo, los diseñadores de la librería que permite la E/S, crearon dos conceptos: Corrientes (o flujos) y Archivos.

240* Una corriente es un flujo de información interna al programa, que no depende de un medio exterior, por ello su comportamiento siempre es el mismo. Existen dos tipos de corrientes binarias y de texto.

241* Las corrientes binarias son una consecución de bytes, uno a uno, sin interpretación por parte del dispositivo de salida (o entrada), por lo cual la misma cantidad de bytes enviados al dispositivo es la misma que almacena este último.

242* Las corrientes de texto son una secuencia de caracteres, organizadas en líneas terminadas por un caracter de nueva línea. El ANSI indica que el caracter de nueva línea es opcional dependiendo de la implementacion. En este tipo de corrientes suelen existir traducciones (o interpretaciones) de algunos de caracteres, dependiendo del dispositivo que se maneje, por lo que no siempre existe una relación 1 a 1.

243* Un archivo es un concepto lógico, que depende específicamente del tipo de dispositivo, el cual le da diferentes capacidades al archivo. P.E. Un archivo en disco permite acceso directo, y una impresora no.

244* Si el archivo soporta acceso directo, entonces se define e inicializa un indicador de posición del archivo, el cual se incrementa automáticamente en cada lectura o escritura que se haga.

245* Al abrir cualquier archivo, se define un buffer intermedio, en el cual se hacen las salidas temporales al archivo.

246* Para cortar una corriente de su archivo se hace con el cierre del archivo, lo cual ocasiona el vaciado de los datos del buffer al archivo.

247* A este proceso se le conoce como volcado de los datos. Cuando un programa termina, automáticamente se cierran todas las corrientes asociadas a este, por lo que se hace el volcado respectivo de los datos.

248* Las funciones de entradas / salidas vistas anteriormente ( getche, putchar, gets, puts, printf y scanf ) son similares a las que se usan para hacer E/S a archivos.

249* De hecho estas funciones son simplificaciones hechas para hacer E/S exclusivamente a consola.

A.Rodriguez L. 47

Page 48: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

250* Al iniciarse un programa de C en una PC, automáticamente se abren cinco corrientes de texto ya predefinidas, las cuales son: stdin, stdout, stderr, stdaux y stdprn.

251* A continuación se puede encontrar una colección de las funciones mas comunes para hacer E/S, estas funciones se encuentran en la librería stdio.h

FUNCION DESCRIPCION

FILE *fopen

(char *f_nom,

char *modo);

Abre un archivo con el nombre indicado en f_nom y devuelve la dirección del flujo indicado. El tipo de operaciones que se desea se indica en modo, la cual se rige por la siguiente tabla.

Modo Operación

r Abre un archivo texto para lectura.

w Crear un archivo texto para escritura.

a Abre para añadir un archivo de texto.

rb Abrir un archivo binario para lectura.

wb Crear un arch. binario para escritura

ab Abre para añadir un archivo binario

r+ Abre arch. texto para lec. / esc.

w+ Crea arch. texto para lec. / esc.

rb+ Abre un arch. binario para lec./esc.

wb+ Crear un arch. binario para lec./esc.

ab+ Abrir un arch. binario para lec./esc.

FUNCION DESCRIPCION

int fprintf

(FILE *flujo,

char *formato,

list_arg);

Hace una salida texto al flujo especificado, con el formato que se indica. list_arg es una serie de argumentos que tendrán salida. La cadena de formato es idéntica a las usadas en printf.

int fscanf (FILE *flujo,

char *formato, list_arg);

Funciona igual que scanf, pero ahora para el flujo indicado.

int fputc

( int ch,

FILE *flujo);

Hace una salida del caracter ch en flujo, en la posición que tenga el indicador de archivo. El valor devuelto por fputc es el valor del número de caracter escrito. Para

A.Rodriguez L. 48

Page 49: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

la salida, solo usa el byte bajo del entero, como unsigned char.

int fgetc(FILE *flujo) Devuelve el siguiente caracter del flujo de entrada, incrementando el indicador de posición del archivo. El caracter leído es un unsigned char que se convierte a entero.

int fputs

(char *cad,

FILE *flujo);

Escribe la cadena cad en flujo. Devuelve 0 cuando se da un error y otro número si no lo hay.

char *fgets

(char *cad,

int num,

FILE *flujo)

Lee una cadena de num-1 caracteres de flujo y los sitúa en cad. Los caracteres se leen hasta: CR, EOF o num-1. Agrega nulo después de leer la cadena y CR forma parte de la cadena. Si no hay error se devuelve la dirección de cad. Si no devuelve nulo.

FUNCION DESCRIPCION

int fwrite

(void *buf, int tam,

int cuenta, FILE *flujo)

Escribe la cantidad de elementos dados en cuenta, teniendo cada elemento tam bytes de tamaño. Los elementos son leídos de la dirección de memoria dada por buf, y son colocados en flujo. Devuelve el numero de caracteres leídos.

Si los caracteres leídos son menos que los pedidos, es posible que se halla dado un error.

int fread

( void *buf,

int tam,

int cuenta,

FILE *flujo);

Trabaja igual que la función que fwrite pero ahora sacando datos del flujo, y colocándolo en la dirección de buf.

int fseek

(FILE *flujo,

long despl, int origen)

Sitúa el indicador de posición de flujo a despl bytes a partir de origen establecido. La variable despl es long int para soportar archivos mayores de 64Kb . Origen puede sustituirse por cualquiera de las macros

A.Rodriguez L. 49

Page 50: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

siguientes:

SEEK_SET 0 Del comienzo del archivo.

SEEK_CUR 1 De la posición actual.

SEEK_END 2 Desde el fin del archivo.

long ftell(FILE *flujo) Función que devuelve la posición actual del indicador del flujo especificado. En flujos binarios es el número de bytes a partir del inicio del archivo. En flujos de texto este valor varia ya que la corriente real de caracteres usados depende del dispositivo. Si el dispositivo no soporta búsqueda aleatoria, si el valor es indefinido o si ocurrió un error da -1L.

FUNCION DESCRIPCION

void rewind(FILE *flujo)

Mueve el indicador de posición del archivo, al inicio del mismo. También inicializa los indicadores de error y fin de archivo.

void clearerr (FILE *flujo)

Inicializa el indicador de error a 0 en el flujo indicado. El indicador de error se inicializa solo con rewind o esta función.

int feof(FILE *flujo) Comprueba si el indicador de archivo ha alcanzado el fin. Da 0 (falso) sí no esta al final del archivo y diferente de 0 si esta.

int ferror(FILE *flujo) Comprueba si existió error en una operación con el archivo. 0 indica sin error otro valor indica algún error.

int fflush(FILE *flujo) Vuelca el buffer del archivo especificado.

int fclose(FILE *flujo) Cierra el archivo apuntado por flujo, volcando previamente su buffer al archivo. Devuelve 0 si se cierra correctamente, sino devuelve cualquier otro número.

void setbuf

(FILE *flujo, char *buf);

Se usa para especificar el buffer de flujo a utilizar o (si se lama con buf a nulo) para desactivar el buffer. Si un buffer va ha ser definido por el programador, debe ser de BUFSIZ caracteres (esta constante esta

A.Rodriguez L. 50

Page 51: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

definida en stdio.h).

int setvbuf

(FILE *flujo, char *buf,

Int modo, int tam)

Permite al programador especificar el buffer, su tamaño y su modo. El buf es un puntero a un lugar de memoria que se usará como buffer. El tamaño del buffer esta dado por tam y si buf es nulo lo desactiva. Si modo es:

_IOFBF = Op. de buffer complet, es por default.

_IONBF = No usa buffer definido.

_IOLBF = Buffer por línea, vuelca buffer cada CR

A.Rodriguez L. 51

Page 52: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

5. TEMAS AVANZADOS DE “C”

5.1 EL PREPROCESADOR DE C

#define <nom_macro> <cadena>

Se usa para crear un identificador <nom_macro> el cual antes de realizar la compilación será substituido por una cadena especificada.

Una vez declarada una macro, esta puede ser usada en otras macros.

También se pueden crear funciones con parámetros para realizar algunas operaciones sencillas:

Ejemplo:#include <stdio.h>#define Uno 1#define Dos Uno+Uno#define mensaje1 "Error en archivo"#define sum(a,b) a+bvoid main() { printf("Uno + Dos es:%d\n",Uno+Dos); //Uno + Dos es:3 printf("mensaje1 es.:%s\n",mensaje1); //mensaje1 es.:Error en archivo printf("sum es......:%d\n",sum(5,2)); //sum es......:7}

#error <mensaje_de_error>

Detiene la compilación de un programa mostrando el mensaje de error indicado. Dicho mensaje no va entre comillas.

#include “nom_arc.ext”

#include <nom_arc.ext>

Incluye en el lugar donde se coloca, un archivo fuente dentro del actual. El nombre del archivo fuente a incluir pueden ir entre comillas dobles o entre paréntesis angulares. Si se ponen comillas dobles se busca primero en el directorio actual, después en el directorio especificado en el ambiente y si no lo encuentra lo busca en los directorios estandard.

Si se ponen paréntesis angulares, se busca primero en el directorio indicado en el ambiente, después busca en el directorio standard. No se busca en ningún momento en el directorio actual.

Si se indica explícitamente el camino donde estará el archivo a incluir, solo buscará en este directorio.

DIRECTIVAS DE COMPILACION CONDICIONAL

A.Rodriguez L. 52

Page 53: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

#if <constante>

secuencia de sentencias

#else

secuencia de sentencias

#endif

Si la expresión constante se cumple, se compilan las sentencias que están entre #if y #else. Si no se cumple, se salta esta porción de código en la compilación y se compila lo que este entre #else y #endif.

Como en cualquier lenguaje, la parte del #else es opcional.

La constante puede usar macros creadas con define compara con valores numéricos.

Ejemplo:#include <stdio.h>#define ELEM 15void main(){ #if ELEM>20 char c[40]="Texto 40 caracteres"; #else char c[20]="Texto 20 caracteres"; #endif printf("Mensaje es.:%s\n",c);//Mensaje es.:Texto 20 caracteres}

#if <constante>

secuencia de sentencias

#elif <constante1>

secuencia de sentencias

:

#else

secuencia de sentencias

#endif

Trabaja en forma similar a como lo hace el if con escalonador, solo que en este caso el efecto de escalonamiento se da antes de realizar la compilación. De hecho determina la porción de código que se compilara en función de los valores constantes, los cuales a igual que para el #if pueden usar comparaciones de macros con números.

A.Rodriguez L. 53

Page 54: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

Si alguna de la condiciones se cumple se compila solo esa porción de código y se continua compilando la línea siguiente después del #endif.

Al igual que en el if escalonado la parte del #else es opcional y se entra en ella solo cuando ninguna de las anteriores condiciones se cumplió.

Ejemplo:#include <stdio.h>#define MX 0#define US 1#define UR 2#define Pais MXvoid main(){ #if Pais==US char moneda[]="$"; #elif Pais==MX char moneda[]="N$"; #else char moneda[]="&"; #endif printf("El total es.:%s %d\n",moneda,135); }

#ifdef <nom_macro>

secuencia de sentencias

#endif

Checa si fue definida un nombre de macro. Si es así compila el grupo de sentencias entre #ifdef y #endif. Sino fue definida, no compila estas sentencias, continuando en la instrucción inmediata después del #endif.

#ifndef <nom_macro>

secuencia de sentencias

#endif

Similar a la anterior, solo que ahora checa que no se halla definido la macro si esto se cumple, entonces compila la secuencia de sentencias dentro de #ifdef.

Ejemplo para los dos casos anteriores: #include <stdio.h> #define MS_C++7.0 void main() {

#ifdef MS_C++7.0 printf("Compilador Microsoft C ++ 7.0\n");

A.Rodriguez L. 54

Page 55: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

#endif #ifndef TURBO printf("Este no es un compilador Turbo\n"); #endif

}

#undef <nom_macro>

Elimina la definición de una macro previamente definida. Se usa cuando se desea que la macro solo se conozca dentro de cierto ambito.

A.Rodriguez L. 55

Page 56: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

5.2 LOS MODELOS DE MEMORIA

252* Un modelo de memoria es un arreglo (o acomodo) de código y datos dentro de la memoria, que el MsDos proporciona al programador.

253* Estos arreglos varían el tamaño máximo de los datos, el código y la rapidez de ejecución de un programa.

254* En general una regla de computación dice que entre mas alcance tengan el código o los datos de un programa, mas lento será este.

255* Estos arreglos se logran dándole a las registros de control de aplicación, un tamaño diferente para accesar la zona que le corresponde.

256* En general existen 4 registros de control para una aplicación en la memoria y son : el registro de inicio de código (CS), el de inicio de datos estáticos (DS), el de inicio del stack (SS) y el del último elemento del stack (SP)

257* Con estos 4 registros se controlan las 4 zonas importantes de un programa: código, datos estáticos, stack y heap.

MODELO TINY

Código

Datos Estáticos

Heap

Stack

Espacio Libre

Inicio de registrosCS, DS Y SS

SP

Hasta 64 kb

Memoria Baja

Memoria Alta

Modelo tiny

258* Compila un programa de tal manera que todos los registros, tengan el mismo valor y el direccionamiento se hace usando solo el desplazamiento (16 bits en un puntero cercano).

A.Rodriguez L. 56

Page 57: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

259* Por lo anterior el tamaño total de un programa (código + datos estáticos + stack + heap ) debe quedar en un mismo segmento de 64 k. El programa es pues pequeño y además muy rápido.

EL MODELO SMALL

Código

Datos Estáticos

Heap

Stack

Espacio Libre

CS

SP

Hasta 64 kb

Memoria Baja

Memoria Alta

DS,SS

Hasta 64 kb

Heap Far

Espacio Libre

Resto de lamemoria

Modelo small

260* Se pueden asignar máximo de 64 kb (1 segmento) para código y un máximo de 64 kb (1 segmento) para datos (datos estáticos + stack + heap cercano).

261* Como el puntero para manejar datos, sigue siendo solo el desplazamiento dentro del segmento, el rendimiento del programa es casi tan bueno como el del modelo tiny, pero ahora soporta una porción de código mucho mayor.

262* Este modelo es ideal para aquellos programas que tiene un buen balance entre tamaño del código y datos.

263* En este modelo se pueden empezar a manejar datos en el heap lejano (far) que ocuparían el resto de la memoria. La dirección de memoria de un dato en el heap lejano ocuparía 4 bytes.

A.Rodriguez L. 57

Page 58: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

EL MODELO MEDIUM

Código totalde varios archivos

Datos Estáticos

Heap

Stack

Espacio Libre

CS

SP

Hasta 64 kb

Memoria Baja

Memoria Alta

DS,SS

Cada archivode hasta 64 kb

Heap Far

Espacio Libre

Resto de lamemoria

Modelo Medium

264* Este modelo permite que se puedan tener varios archivos de código de máximo 64 kb cada uno. Por ello para manejar el código requiere una dirección dada en forma completa (segmento y desplazamiento).

265* El tamaño de la zona de datos no cambia con respecto al modelo anterior. Solo se maneja con el desplazamiento, por lo cual solo se tiene acceso a 64 de datos.

266* El modelo es bueno para programas con código grande pero pocos datos. El sistemas funcionará lento para procesos de llamados a funciones, pero en cuanto a manejo de datos es tan rápido como los modelos anteriores.

267* En este modelo se definen dos tipos de heap, el cercano que se encuentra antes del stack y el lejano que se encuentra después del stack. Los punteros al heap cercano (near) ocupan solo dos bytes para dar el desplazamiento de una variable dinámica.

268* Los punteros lejanos (far) ocuparan 4 bytes, ya que tiene que dar la dirección de memoria completa (segmento y desplazamiento) donde esta un dato.

A.Rodriguez L. 58

Page 59: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

EL MODELO COMPACT

Código totalde varios archivos

Datos Estáticos

Stack

Espacio Libre

CS

SP

Hasta 64 kb

Memoria Baja

Memoria Alta

DS

Hasta 64 kb

Heap

Espacio Libre

Resto de lamemoria

SS

Hasta 64 kb

Modelo Compact

269* En este modelo, el tamaño del código no puede pasar de un segmento de datos (64 kb), por lo que el puntero para código es solo el desplazamiento de una dirección de memoria.

270* Sin embargo los datos estáticos y el stack pueden ocupar hasta un máximo de 64 kb cada uno.

271* En este modelo los punteros para manejar la memoria del heap ocupan 4 bytes. No existe ya el heap cercano, y el heap lejano se encuentra después del stack.

A.Rodriguez L. 59

Page 60: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

EL MODELO LARGE

Código totalde varios archivos

Datos Estáticos

Stack

Espacio Libre

CS

SP

Cada variab.max.de 64 kb

Memoria Baja

Memoria Alta

DS

Heap Far

Espacio Libre

Resto de lamemoria

SS

Cada archivode hasta 64 kb

Cada variab.max.de 64 kb

Modelo Large

272* En este modelo el código pueden ocupar mas de 64 Kb, distribuyéndolo en varios archivos con una extensión máxima cada uno de 64 Kb.

273* El espacio proporcionado para los datos estáticos y el stack depende del que necesiten las variable en ellos declaradas, no pudiendo una variable (en cualquiera de las dos zonas) ocupar mas de 64 KB.

274* Por lo anterior, los punteros a lo datos en este modelo ocupan 4 bytes y su funcionamiento es mas lento que en los anteriores modelos.

A.Rodriguez L. 60

Page 61: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

EL MODELO HUGE

Código totalde varios archivos

Datos Estáticos devarios archivos

Stack

Espacio Libre

CS

SP

Memoria Baja

Memoria Alta

DS

Heap Far

Espacio Libre

Resto de lamemoria

SS

Cada variab.mas de 64 kb

Cada archivode hasta 64 kb

Cada variab.mas de 64 kb

Modelo Huge

275* Es similar al anterior, solo que aquí una sola variable si puede ocupar mas de 64Kb de espacio, lo cual lo hace aun mas lento que todos los anteriores.

Excepciones en el manejo de punteros.

276* Si se esta trabajando en un modelo pequeño, pero se tiene la necesidad de manejar unos pocos datos con las características que da un modelo grande (P.E. usar una variable que ocupe mas de 64), no es necesario cambiar el modelo completo.

277* Si se hiciera esto, el rendimiento del programa se vería afectado, solo por estos datos. Para solucionar este problemas, los compiladores de PC agregaron los modificadores : far, huge y near.

278* El modificador far se puede aplicar a variables y le indica al compilador que estas se manejaran con un puntero que ocupe 4 bytes (2 para el segmento y 2 para el desplazamiento).

A.Rodriguez L. 61

Page 62: Lenguaje C

INSTITUTO TECNOLOGICO DE VERACRUZ

Lenguaje C

279* Su uso se presenta cuando se trabaja con modelos tiny, small y medium. Si se trabaja con modelos mas grandes no tiene sentido, ya que estos modelos por default usan punteros far.

280* El modificador huge se aplica a variables que requieran tener un tamaño de mas de 64 kb, se usan en todos los modelos menos en el huge por razones obvias.

281* El modificador near instruye al compilador a usar un puntero de solo 2 bytes, con lo que se toma como inicio zona de datos la dirección del segmento actual (DS para variables globales y SS para locales), por ello las variables que pueden ser accesadas solo se pueden almacenar en los primeros 64 kb de datos.

282* Se usan en modelos medium, large y huge, para hacer que algunas variables se comporten mas rápidamente.

A.Rodriguez L. 62