0% encontró este documento útil (0 votos)
182 vistas39 páginas

Guía Completa de Programación en C

El documento explica conceptos básicos del lenguaje C como compilación, enlazado, variables, tipos de datos, operadores aritméticos, estructuras de control (condicionales, iterativas), funciones y punteros. Define variables, las asigna valores y las muestra usando printf. Usa if/else, for, while y switch para controlar el flujo del programa. Explica el paso de parámetros, punteros y arreglos.

Cargado por

Vicky Metallo
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
182 vistas39 páginas

Guía Completa de Programación en C

El documento explica conceptos básicos del lenguaje C como compilación, enlazado, variables, tipos de datos, operadores aritméticos, estructuras de control (condicionales, iterativas), funciones y punteros. Define variables, las asigna valores y las muestra usando printf. Usa if/else, for, while y switch para controlar el flujo del programa. Explica el paso de parámetros, punteros y arreglos.

Cargado por

Vicky Metallo
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd

Compilar: traducción del lenguaje c al lenguaje de máquina.

Enlazado: El programa compilado se une al código proporcionado por el


fabricante del compilador para obtener un ejecutable.

#include <stdio.h>
int main() {
/* comentario (modalidad propia de c) */
// comentario (esta modalidad de dos ‘/’ es tomada del c++)
printf(“Hola Mundo\n”); //secuencia de escape (salto de linea)
printf(“Hola de nuevo”);
return 0;
}

Secuencias de escape
\b -> retrocede un carácter (backspace)
\a -> campanilla
\t -> tabulador (se imprimen 8 espacios en blanco)

Variables: una variable define un espacio de almacenamiento en memoria


capaz de contener un valor y que se caracteriza por tres atributos:
1) Nombre:
a) Solo se permiten letras (alfabeto inglés), números, guion
bajo.
b) No puede comenzar con un número.
c) No pueden coincidir con las palabras reservadas del
lenguaje.

2) Tipo de dato:
a) int (números enteros)
b) char (caracteres, un solo carácter)
c) float (números con decimales, hasta 7 decimales exactos)
d) double (números con decimales, hasta 15 decimales exactos)
e) void (sin valor, solo para funciones que no retornen
valores)

3) Valor: debe estar en concordancia con el tipo de dato de la


variable.

Programa usando variables:

#include <stdio.h>
int main() {
int a, b, c;
float pi;
char letra;
a = 3; //estoy asignando una constante
b = a; //estoy asignando el valor de otra variable
c = a + b + 1; //estoy asignando una expresión (en c se guarda
//el resultado de esa expresión)
pi = 3.1416;
letra = ‘a’; //asigno la letra ‘a’ (usando comillas simples)
printf(“La variable a contiene %d, b contiene %d y c contiene
%d\n”, a, b, c);
printf(“La variable pi contiene %f y letra contiene %c\n”, pi,
letra);
return 0;
}

Especificadores de conversión: reservan un lugar dentro de la frase que


luego ocupa el valor de una variable
%d: variables de tipo Entero
%f: variables de tipo Reales
%c: variables de tipo Char

%4d -> el 4 hace las veces de ancho (cuantas columnas de pantalla uso
para ver ese número, si sobran columnas, se ponen adelante del número, si
el ancho fuera muy chico para el número, se ignora y el número se muestra
completo).
%04d -> en lugar de rellenar con espacios en blanco, rellena lo que falte
con ceros.

%f -> el formato por default es mostrar la variable con 6 decimales (si


sobran rellena con ceros: 3.141600)
%8.2f -> el 8 es el ancho (8 columnas de pantalla), el 2 son la cantidad
de decimales que quiero ver (3.14, el punto del 3.14 ocupa una columna de
pantalla)
%.2f -> no hago nada sobre el ancho, entonces veo el número con 2
decimales y el mínimo ancho necesario (en este caso, ancho 4: 3.14)

Ingreso de valores por teclado:


#include <stdio.h>
int main() {
int edad;
printf(“Ingrese su edad”);
scanf(“%d”, &edad);
printf(“usted lleva vividos aprox. %d días\n”, edad*365);
return 0;
}
Se recomienda que cada scanf ingrese un solo valor
Operadores Aritméticos:
‘+’ Suma
‘-’ Resta
‘*’ Multiplicación
‘/’ División
‘%’ Modulo o Resto

int main() {
int a = 10;
float b;
b = a/3;
printf(“%f”, b); //muestra: 3.000000, en lenguaje c dividir
dos //números enteros da como resultado un entero
return 0;
}

Para que me dé resultados con decimales debo dejar de dividir dos


enteros:
1) b = a / 3.0 //el 3.0 es real, ya no divido dos enteros
2) b = (float)a/3; //’cast’, casteamos una variable, afecta a la
variable que viene al lado del cast, en este caso a. Solo
temporalmente, a va a ser de tipo float, luego ya no.

Orden de precedencia: primero se realizan multiplicaciones y divisiones,


y luego sumas y restas
Operadores de asignación adicionales:
‘+=’ a+=3; a=a+3;
‘-=’
‘*=’ b*=8; b=b*8;
‘/=’
‘%=’
Operadores incrementales:
++ a++; a=a+1; a+=1;
-- a--; a=a-1; a-=1;

Estructuras de Control
Estructura Secuencial: de arriba hacia abajo, secuencial o lineal
Estructura Alternativa o Condicional: una condición solo puede valer
verdadero o falso.

Formato 1:
if (<condición>){
//si condición es verdadera, ingresa a este bloque
}
//si condición es falsa, no entra al bloque del if
Formato 2:
if (<condición>){
//si condición es verdadera, ingresa a este bloque
} else {
//si condición es falsa, entra a este bloque
}

Si hay una sola instrucción, no son necesarias las llaves:


if (a>10)
printf(“a es mayor que 10”);

Operadores relacionales:
´==´ igual ‘!=’ distinto
‘>’ mayor ‘<’ menor ‘>=’ mayor o igual ‘<=’ menor o igual
0 -> falso (el cero se considera como falso)
!0 -> verdadero (cualquiera distinto de cero es verdadero)

Operadores Lógicos:
&& and || or ! not

Operador Condicional
Se aplica sobre tres operandos
(<condición>) ? <valor1>:<valor2>;
Si condición es verdadera, devuelve valor1. Si condición es falsa,
devuelve valor2;
b = (a<0)?-a:a; (siempre devuelve el positivo, es como la función modulo)

Elecciones Múltiples
switch (<variableselectora>){
case <valor1>:
….;
….;
break;
case <valor2>:
….;
….;
break;
default:
….;
….;
break;
}
variableselectora: debe ser entera o char
#include<stdio.h>
int main(){
int mes;
printf(“Ingrese el mes”);
scanf(“%d”,&mes);
switch(mes){
case 1: printf(“enero”);
break;
case 2: printf(“febrero”);
break;
default: printf(“mes invalido”);
break;
}
return 0;
}

Estructura Iterativa o Ciclo


while (<condición>){
….; //mientras condición es verdadera, sigue entrando al ciclo
}

do{ //se ejecuta al menos una vez


….; //mientras condición es verdadera, sigue entrando al ciclo
}
while (<condición>)

for (<incializacion>; <condición>; <incremento>)


{
….; //mientras condición es verdadera, sigue entrando al ciclo
}

Funciones
#include <stdio.h>
int potencia(int a, int b); //prototipo de la función
int main(){

int base, exp;


printf(“Ingrese la base”);
scanf(“%d”,&base);
printf(“Ingrese el exponente”);
scanf(“%d”,&exp);
printf(“El resultado es %d\n”, potencia(base, exp));
//los parámetros en la llamada de función se llaman parámetros
reales
return 0;
}
int potencia(int a, int b){ //los parámetros en cabecera de función
se //llaman parámetros formales
int i, res = 1;
for(i=0; i<b; i++)
res=res*a;
return res;
}

#include <stdio.h>: Agrupa funciones de entrada y salida (por ej. printf


y scanf)

#include <stdio.h>
void duplicar(int * n);
int main(){
int a;
printf(“ingrese un numero entero”);
scanf(“%d”,&a);
duplicar(&a); //paso la dirección de memoria
printf(“el doble es %d\n”, a);
return 0;
}
void duplicar(int * n){ //recibe un puntero a entero
*n = *n * 2;
}

Pasaje de parámetros
1) Por referencia: pila, cola, arreglo.
El parámetro formal ocupa la misma zona de memoria que el
parámetro real, cuando cambio uno, se cambia el otro.
2) Por Valor: variable simple.
El parámetro formal ocupa un espacio de memoria diferente al del
parámetro real, lo único que envío a la función es el valor.

Punteros
Un puntero es una variable que contiene una dirección de memoria. El
puntero apunta a la variable. Guarda la dirección de memoria donde
comienza la variable a la que apunto. Un puntero es una categoría de
variable, no un tipo de dato.

Operadores de puntero
‘&’ operador de dirección, aplicado a una variable devuelve la dirección
que esta variable ocupa en memoria.
‘*’ operador de indirección, aplicado a un puntero devuelve el valor
almacenado en la zona de memoria a la que apunta el puntero. Solo se
puede aplicar a variables de tipo puntero.
#include <stdio.h>
int main(){
int a, b;
int *ptr;
a=3;
ptr= &a;
b= *ptr;
printf(“%d”, b); //voy a ver 3 en pantalla
return 0;
}

#include <stdio.h>
int main(){
int a, *ptr;
a=3;
ptr= &a; //la dirección de memoria de a vale 1000, por ej.
*ptr = *ptr + 1;
//si quisiera usar++: (*ptr)++
printf(“%d”, a); //voy a ver 4 en pantalla
printf(“%p”, ptr); //voy a ver 1000 en pantalla
//usando %p voy a ver un valor hexadecimal
return 0;
}

Usos de punteros:
1) Pasaje de parámetros por referencia
2) Trabajar con arreglos y cadenas de caracteres
3) Utilizar asignación dinámica de memoria

#include <stdio.h>
void intercambiar(int * a, int * b);
int main(){
int x,y;
x=3;
y=5;
intercambiar(&x, &y);
printf(“%d, %d\n”, x, y);
return 0;
}
void intercambiar(int * a, int * b){
int c;
c = *a;
*a = *b;
*b = c;
}
Arreglos
-Vectores: conjunto de variables (del mismo tipo de datos) agrupadas bajo
el mismo nombre, cada variable tiene un numero de orden (la posición
dentro del vector), subíndice (números enteros, comienzan desde cero),
dentro del contexto del vector.
int vec1[10]; //10 es el tamaño del vector, cantidad de variables que
//el vector admite.
int vec2[5] = {10, 20, 30, 40, 50}; //declaración e inicialización a
//la vez.
int vec3[100] = {10, 20, 30}; //inicializo solo 3 valores e
inicializa usando esos tres
valores hasta que se terminen,
luego pone valores nulo
(correspondiente al tipo de dato
del vector).
int vec4[2] = {10, 20, 30, 40}; //declaro más valores del tamaño
del vector, da error, no compila
int vec5[] = {10, 20, 30, 40}; //arreglo abierto, inicializa
con tamaño 5.

Ejemplo: ingresar 100 numeros enteros y calcular su promedio, luego


imprimir por pantalla aquellos valores leídos que sean mayores que el
promedio.

#include <stdio.h>
#define MAX 100 // las constantes simbólicas se acostumbran escribir
// con mayúsculas, sin ‘;’ y sin ‘=’
int main(){
int i, suma = 0, v[MAX];
float prom;
for (i=0; i<MAX; i++){
printf(“Ingrese un numero entero”);
scanf(“%d”, &v[i]);
suma = suma + v[i];
}
prom = (float)suma/MAX;
for (i=0; i<MAX; i++){
if (v[i]>prom)
printf(“%4d”,v[i]);
}
return 0;
}
Aritmética de punteros
Se permite la suma y la resta (nada más):
+ - += -= ++ --
#include <stdio.h>
int main(){
int a, *ptr;
a=5;
ptr=&a;
printf(“%p”, ptr);
ptr=ptr+1;
//si ptr=1000, ptr+1=1004, porque suma una unidad del tipo de datos
(para un int son 4 bytes)
printf(“%p”, ptr);
return 0;
}

#include <stdio.h>
int main(){
int i, w[]={10,20,30,40,50};
for (i=0;i<5;i++)
printf(“%4d”, w[i]);
return 0;
}

#include <stdio.h>
int main(){
int i, *ptr, w[]={10,20,30,40,50};
ptr=&w[0]; //podría escribirse: ptr=w (el nombre del vector es
simpre un puntero a su primer
elemento: &w[0]  w )
for (i=0;i<5;i++){
printf(“%4d”, *ptr);
ptr++;
}
return 0;
}
Pasaje de vectores como parámetro:
#include <stdio.h>
#define MAX 50
void inicializar(int w[MAX]); // void inicializar(int w[]) ó
// void inicializar(int *w);
int main(){
int v[MAX];
inicializar(v);


return 0;
}
void inicializar(int w[MAX]){
int i;
for (i=0;i<MAX;i++)
w[i]=0; //*(w+i)=0;
}

-Matrices: es un conjunto de vectores


#include <stdio.h>
#define MAXF 4
#define MAXC 3
void imprimir(int m[][MAXC]);
int main(){
int f, c, mat[MAXF][MAXC];
for (f=0;f<MAXF;f++)
for (c=0;c<MAXC;c++)
{
printf(“Ingrese un numero entero”);
scanf(“%d”,&mat[f][c]);
}
imprimir(mat);
return 0;
}

void imprimir(int m[][MAXC]){


int f, c;
for (f=0;f<MAXF;f++) {
for (c=0;c<MAXC;c++){
printf(“%d”,m[f][c]);
}
printf(“\n”);
}
}
Números al azar:
#include <stdlib.h> -> para srand() y rand()
#include <time.h> -> para time()
rand(): devuelve un numero entero al azar -> [0, RAND_MAX)
(RAND_MAX suele ser 32768)

moneda = rand()%2; el resto de dividir por 2 puede ser 1 ó 0


dado = rand()%6+1; obtengo valores entre 1 y 6
formula general: rand()%(VF-VI+1)+VI
(VI:valor inicial, VF:valor final)
El valor de inicialización de la función esta relacionado con el valor
de la semilla (SEED), esta se cambia con la función srand (se ejecuta
una sola vez durante todo el programa):
srand(<nueva semilla>); utilizamos la función time (porque siempre
cambia) como semilla:
srand(time(NULL));

Cadenas de caracteres
Conjunto de cero (cadena vacia, no contiene nada) o mas caracteres.
(ver código ascii)
Lo que se almacena son los valores ascii (ocupa un byte, no es un entero)
de la cadena.
El carácter ´\0´ representa al carácter nulo, su valor ascii es cero, y
toda cadena finaliza con este carácter. Por eso toda cadena tiene que
tener un carácter mas del necesario para poner este carácter de
finalización.
char cad1[80]; //tiene una capacidad útil de 79 caracteres
char cad2[]={‘M’,‘a’,‘x’,‘i’,‘\0’}; //declarada como arreglo abierto
char pais[]=”Alemania”; //constantes de cadenas de caracteres, el ‘\0’
lo agrega el lenguaje en este caso.
#include <stdio.h>
int longuitud(char cad[]);
int main(){
char nombre[40];
printf(“Ingrese nombre”);
scanf(“%s”, nombre); //no uso & porque la cadena es un puntero
a //la primer posición, el scanf permite ingresar de a una palabra,
//cuando encuentra un espacio deja de ingresar
printf(“Ud. Se llama %s”, nombre);
printf(“y su nombre contiene %d caracteres\n”, longitud(nombre));
return 0;
}
int longuitud(char cad[]){
int i=0;
while(cad[i]!=’\0‘)
i++;
return i;
}

Otra forma de escribir la función:


int longuitud(char cad[]){
int i=0;
while(cad[i]) //solo verifico que no sea 0 (con cero sale, cero
es falso en lenguaje c, cualquier otro valor es verdadero)
i++;
return i;
}

Otra forma de escribir la función:


int longuitud(char cad[]){
int i=0;
for (i=0; cad[i]; i++)
; //no tengo que hacer nada, la i se va incrementando
return i;
}

//fragmento de programa:
char materia[80];
copiarcadena(materia, “Programación”);
void copiarcadena(char destino[], char origen[]){
int i;
for (i=0; origen[i]; i++)
destino[i]=origen[i];
destino[i]=’\0’
}
void concatenar(char destino[], char origen[]){
int i, j;
for (i=0; destino[i]; i++)
;
for (j=0; origen[j];j++)
destino[i+j]=origen[j];
destino[i+j]=’\0’;
}

Errores frecuentes con cadenas de caracteres:

char cad[1]; //no sirve de nada, solo entra el ‘\0’

función que cuente las letras A en una cadena:


int contarA(char cad[MAX]){
int i, cont=0;
for (i=0; i<MAX; i++) //estamos recorriendo todo el vector
(MAX) //sin saber donde termina el vector
if (cad[i]==’a’ || cad[i]==’A’)
cont++;
return cont;
}

Guardar un numero entero en una cadena


char cad[]=”3”;
int n;
n=cad[0] - 48; //resto 48, que es el valor del cero del código ascii, y
en la cadena se guardan los valores ascii de los numeros

//funcion para generar una cadena de n guiones


void guiones(int n, char cad[]){
int i;
for (i=0; i<n; i++)
cad[i]=’-’;
cad[i]=’\0’;
para que una función devuelva una cadena de caracteres si o si hay que
pasarla por parámetro.
}
Arreglos de Cadenas de Caracteres
Es un vector donde cada uno de sus elementos es una cadena de caracteres,
una matriz.
D o m i n g o ‘\0’
L u n e s ‘\0’
M a r t e s ‘\0’
M i e r c o l e s ‘\0’
J u e v e s ‘\0’
V i e r n e s ‘\0’
S a b a d o ‘\0’

#include <stdio.h>
int main(){
char datos[2][40];
printf(“Nombre?”);
scanf(“%s”, datos[0]); //uso solo el subíndice de fila
printf(“Apellido?”);
scanf(“%s”, datos[1]);
printf(“Bienvenido %s%s\n”, datos[0], datos[1]);
return 0;
}

char días[7][10]={“Domingo”, “Lunes”, “Martes”, “Miercoles”…..}

Funciones de Biblioteca para el Tratamiento de Caracteres y Cadenas


biblioteca ctype:
isalpha(<char>) -> devuelve verdadero (un entero ¡=0) cuando el carácter
que le pasamos sea una letra, o falso (un entero=0)
#include <stdio.h>
#include <ctype.h>
int main(){
char cad[80];
int i;
printf(“Ingrese una cadena de caracteres”);
scanf(“%s”, cad);
for (i=0;cad[i];i++)
if (isalpha(cad[i]))
printf(“%c es un carácter alfabetico\n”, cad[i]);
return 0;
}

Para evitar que isalpha cancele todo cuando le paso un carácter mayor a
128 (que c los ve como negativos), tendría que castear el cad[i]:
isaplha((unsigned)cad[i])
Otra forma es declarar la cadena como:
unsigned char cad[80];
isdigit(<char>) -> devuelve verdadero (un entero ¡=0) cuando el carácter
que le pasamos sea un digito numerico, o falso (un entero=0)
#include <stdio.h>
#include <ctype.h>
int main(){
char cad[80];
int i;
printf(“Ingrese una cadena de caracteres”);
scanf(“%s”, cad);
for (i=0;cad[i];i++)
if (isdigit(cad[i]))
printf(“%c es un digito numerico\n”, cad[i]);
return 0;
}

isalnum(<char>) -> devuelve verdadero (un entero ¡=0) cuando el carácter


que le pasamos sea un digito numérico o un carácter alfabetico, o falso
(un entero=0)
isspace(<char>) -> devuelve verdadero (un entero ¡=0) cuando el carácter
que le pasamos sea un espacio o un carácter equivalente (el carácter
tabulador), o falso (un entero=0)
isupper(<char>) -> devuelve verdadero (un entero ¡=0) cuando el carácter
que le pasamos sea alfabetico y este en mayusculas, o falso (un entero=0)
islower(<char>) -> devuelve verdadero (un entero ¡=0) cuando el carácter
que le pasamos sea alfabetico y este en minusculas, o falso (un entero=0)
toupper(<char>) / tolower(<char>) -> reciben un char y devuelven un char,
convertido a mayúsculas o minúsculas cuando sea posible, sino es posible
devuleve lo mismo que recibio.

Convertir una cadena a mayúsculas (no usar strupr, pertenece a c++):


#include <stdio.h>
#include <ctype.h>
int main(){
char cad[80];
int i;
printf(“Ingrese una cadena de caracteres”);
scanf(“%s”, cad);
for (i=0;cad[i];i++)
cad[i]=toupper(cad[i]);
printf(“%s”, cad[i]);
return 0;
}
Biblioteca stdio:
gets(<cadena>); -> obtiene una cadena, reemplaza al scanf
//fragmento de programa:
int a;
char cad[80];
printf(“Ingrese un numero entero”);
scanf(“%d”,&a);
//cuando después de ingresar un numero (usando scanf) quiero ingresar una
cadena:
fflush(stdin); //borra todos los caracteres pendientes de procesamiento
(el enter que quedo esperando después de ingresar un numero + enter),
vacia el buffer del teclado, esto anda hasta el VS2012, a partir del 2013
uso:
getchar(); //toma el valor del enter que quedo suelto, si el enter no
estuviera el programa queda ahí esperando.

printf(“Ingrese una cadena de caracteres”);


gets(cad);
printf(“Los valores ingresados son %d y %s\n”, a, cad);

puts(<cadena>); -> recibe una cadena y la imprime en pantalla seguida de


un salto de línea (\n), reemplaza a printf(“%s\n”, cad)
sprintf(<cadena>,<cadena de control de formato>,<datos>); -> convierto
cualquier tipo de dato a cadena de caracteres.
#include <stdio.h>
int main(){
float pi=3.1416;
char cad[40];
sprintf(cad, “%f”, pi); //las variables float se imprimen con
6 decimales sino digo nada
cad[1]=’,’; //reemplazo un punto por una coma, ya dentro de la
cadena de caracteres
puts(cad); //me muestra: 3,141600
return 0;
}

//fragmento de programa:
char cad[80];
char cad1[]=”Lunes”;
char cad2[]=”Martes”;
char cad3[]=”Miércoles”;
sprintf(cad, “%s, %s, %s”, cad1, cad2, cad3); //concateno las cadenas, la
cadena que recibe (el primer parametro) no debe ser ninguna de las otras
cadenas que participan.
sscanf(<cadena>,<cadena de control de formato>,<direcciones de
variables>); -> toma datos de la cadena primer parametro y los guarda en
las variables del ultimo parámetro. La función convierte hasta donde
encuentra un carácter inválido.
#include <stdio.h>
int main(){
char cad[]=”3.1416”;
float pi;
sscanf(cad, “%f”, &pi); //pase una cadena a una variable numerica
printf(“%f”, pi); //voy a ver 3.141600
return 0;
}
//fragmento de código
char calle[]=”Lima 717”;
int altura;
sscanf(&calle[5], “%d”, &altura); //esto: &calle[5] lo hago porque quiero
que empiece a leer desde la quinta posición, porque si arranca desde cero
se corta porque ya no es numérico el primer carácter. Tambien podría usar
calle+5 (aritmética de punteros).

Biblioteca string (agrego include string.h)


strlen(<cadena>) -> Devuelve la longitud de la cadena (cantidad de
caracteres cargados, sin el \n) que le pasamos como parámetro. Devuelve
un tipo de dato size_t (un entero siempre positivo).
int a;
a=(int)strlen(“Hola”); //casteo el valor devuelto para que no tire la
advertencia de tipo de datos.
strcpy(<destino>, <origen>) -> copia cadena de caracteres en destino.
strcat(<destino>, <origen>) -> concatena origen al final de destino.
strchr(<cadena>, <char>) -> busca el carácter dentro de la cadena y
devuelve un puntero al lugar de la cadena donde encontró el carácter o
null si no lo encontro.
#include<stdio.h>
#include<string.h>
int main(){
char cad[]=”Programación”;
char *ptr;
ptr=strchr(cad,’g’);
if (ptr!=null){
printf(“La letra g se encontró en la posición %d\n”, ptr-
cad);
puts(ptr); //imprime “gramación”, parte de a donde apunta ptr
}
Return 0;
}
strstr(<cadena1>, <cadena2>) -> busca la cadena 2 dentro de la cadena 1,
devuelve la dirección de memoria donde la cadena 2 comienza dentro de la
cadena 1.

strcmp(<cadena1>, <cadena2>) -> compara el contenido de las cadenas 1 y


2. Devuelve un numero entero, 0 -> cadena1 = cadena2
<0 -> cadena1 < cadena2
>0 -> cadena1 > cadena2
La cadena mayor es la que se ubica después en el diccionario

strcmpi(<cadena1>, <cadena2>) -> compara el contenido de las cadenas 1 y


2. Devuelve un numero entero, 0 -> cadena1 = cadena2
<0 -> cadena1 < cadena2
>0 -> cadena1 > cadena2
La cadena mayor es la que se ubica después en el diccionario. Ignora
mayúsculas y minúsculas.

char cad1[]=”Hola”;
char cad2[]=”Hola”;
if (cad1==cad2) //comparo direcciones de memoria, no contenidos
puts(“son iguales”);
else
puts(“son distintas”); //son distintas!!
Estructuras
Una estructura es un conjunto de datos agrupados bajo un solo nombre. A
cada uno de estos datos se lo denomina ‘campo’ y, por lo tanto, una
estructura es un conjunto de campos. (Una estructura es un tipo de dato
creado.) La estructura tiene como mínimo dos campos, porque el objetivo
es agrupar campos, si tiene un solo campo no esta agrupando nada.

#include<stdio.h>
#include<string.h>
struct sfecha {
int dia, mes, anio;
}; //no olvidar el ; final de la estructura

struct salumno {
char lu[10];
char nombre[40];
char domicilio[40];
int materias;
struct sfecha fechanac;
};
int main(){
struct sfecha hoy;
struct sfecha ayer={14,2,2016}; //variable creada e inicializada
struct salumno alumno1, alumno2;
struct salumno curso[50]; //vector de estructuras
[Link] = 15; //el punto . es el operador de pertenecia
[Link] = 2;
[Link] = 2016;
//uso la función ‘strcpy’ porque no puedo asignar una cadena de
//caracteres de otra forma:
strcpy([Link], “1000000”);
strcpy([Link], “Juan Ruiz”);
strcpy([Link], “Lima 717”);
[Link] = 0;
[Link] = 1;
[Link] = 5;
[Link] = 1990;
alumno2 = alumno1; //asignación directa, copia todos los
campos. //Las estructuras no se pueden comparar, por los bits de
relleno en //los distintos campos
curso[0] = alumno1;
strcpy(curso[1].lu, “1000001”);
strcpy(curso[1].nombre, “Luis Arce”);
strcpy(curso[1].domicilio, “Lima 775”);
curso[1].materias = 0;
curso[1].[Link] = 25;
curso[1].[Link] = 12;
curso[1].[Link] = 1994;
}

Pasaje de estructuras como Parámetros


1) Pasaje de campos por valor:

void imprimirmaterias(int cuantas){


printf(“Materias aprobadas:%d\n”, cuantas);
}

//uso de la función:
Imprimirmaterias([Link]);

2) Pasaje de campos por referencia:

void incrementarmaterias(int *cuantas){


*cuantas=*cuantas+1;
}
//uso de la función:
incrementarmaterias(&[Link]); //el & va delante del
nombre de la variable y no delante del nombre del campo

3) Pasaje de Estructuras por valor:

void imprimirdatos(struct salumno quien){


printf(“LU:%s\nNombre:%s\n”, [Link], [Link]);
}
//uso de la función:
imprimirdatos(alumno1);
imprimirdatos(curso[0]);

4) Pasaje de Estructuras por referencia:

void inicializaralumno(struct salumno * quien){


strcpy((*quien).lu, “”);
strcpy((*quien).nombre, “”);
strcpy((*quien).domicilio, “”);
(*quien).materias = 0;
(*quien).[Link] = 0;
(*quien).[Link] = 0;
(*quien).[Link] = 0;
}
//uso de la función:
inicializaralumno(&alumno1);
//misma función usando sintaxis alternativa
void inicializaralumno(struct salumno *quien){
strcpy(quien->lu, “”);
strcpy(quien->nombre, “”);
strcpy(quien->domicilio, “”);
quien->materias = 0;
quien->[Link] = 0;
quien->[Link] = 0;
quien->[Link] = 0;
}

-> operador flecha u operador de puntero a estructura:


Debe ser aplicado a un puntero a estructura
Reemplaza el (*…)

typedef creo sinónimos para tipos de datos que ya existan

struct sfecha{
int dia, mes, anio;
};
typedef struct sfecha tfecha;

//otra forma de definir:


typedef struct sfecha {
int dia, mes, anio;
} tfecha;

//otra forma, tiene sinónimo pero no nombre:


typedef struct {
int dia, mes, anio;
}tfecha;
//de esta forma solo las puedo crear usando el sinónimo: tfecha
hoy;

// uso:
struct sfecha hoy;
tfecha ayer;

Operador sizeof
Obtengo los bytes de una variable o de un tipo de dato. No es una
función, es un operador de comparación, durante la compilación se
reemplaza las apariciones de sizeof por el valor que representa.

//fragmento de programa:
int a,b;
a = sizeof(char); //a recibe el valor 1
b = sizeof(a); //b recibe el valor 4, lo que ocupa un int
printf(“%d-%d\n”, a, b);
Archivos
Un archivo es un conjunto de elementos, llamados registros, todos del
mismo tipo que se almacenan en un dispositivo auxiliar para conservar su
contenido a través del tiempo.
Clasificacion de archivos:
1) Según el contenido de los registros:
a) Binarios: los datos se guardan respetando el mismo formato que
tienen en memoria.
b) De Texto: en los archivos de texto los datos se almacenan en
forma de cadenas de caracteres.
2) Según el sentido de la transferencia de datos:
a) Entrada (de lectura)
b) Salida (de escritura)
c) E/S
3) Según el método de Acceso:
a) Acceso Secuencial: para acceder al registro n debo pasar por los
n-1 registros anteriores.
b) Acceso Directo: conociendo el número de registro es posible
acceder a él en forma directa.

Etapas en el trabajo con archivos (siempre presentes en este orden):


1) Declaración:
//puntero a FILE (estructura que pertenece a la biblioteca stdio)
FILE * arch;
2) Apertura:
A través de los buffers el sistema adquiere mayor velocidad para el
trabajo con archivos
Se relaciona el archivo físico con nuestra variable:
arch = fopen(<nombre del archivo>, <modo de apertura>);
//si hay error, fopen devuelve un puntero null, por eso siempre
se //verifica después del fopen si la variable contiene null.
//los dos parámetros de fopen son de cadenas de caracteres, que
//pueden ser variables o constantes
//nombre de archivo: “[Link]”
//indicando una ruta especifica: “c:\\nuevo\\[Link]”
// la doble barra invertida se traduce como una barra invertida
// otra opción es usar una sola barra inclinada para el otro lado:
// “c:/nuevo/[Link]”
//modo de apertura: dos o tres caracteres,
//modos básicos:
// r (read): archivo de solo lectura, el archivo debe existir
// w (write): archivo de escritura solamente, sino existe se
crea // el archivo, si ya existe lo destruye y crea uno nuevo.
// a (append): archivo para el agregado de registros, sino
existe // se crea, si ya existe realiza toda nueva grabación al
final de // los datos actuales.
// modificadores al modo básico:
// b (binario)
// t (texto)
// segundo modificador:
// + se abre el archivo para actualización, puedo leer y
escribir // agregándolo a cualquier modo
3) Procesamiento:
Depende del tipo de archivo.
Archivos binarios de acceso secuencial:
fwrite(<dirección bloque a grabar>,<tamaño bloque>,<cantidad
bloques>, <archivo>);

fwrite(&alumno1, sizeof(alumno1), 1, arch);

//para grabar de una todo el vector, sin hacer un ciclo:


//curso es un vector, va sin &
fwrite(curso, sizeof(struct salumno), 50, arch);

fwrite devuelve un valor de retorno, que tampoco vamos a verificar.

4) Cierre:

//fclose(<archivo>)
//fclose lleva como parámetro una variable puntero a FILE
fclose(arch);
//fclose devuelve un entero, si devuelve 0 -> no hubo error
(esto //no lo verificamos)
//para cambiar de modo hay que cerrar primero el archivo y
luego //volver a abrirlo en el nuevo modo.

Programa integrador, crear archivo de alumnos con datos ingresados por


teclado, finalizando la carga con legajo de valor -1:
#include<stdio.h>
typedef struct {
int lu;
char nombre[80];
char domicilio[80];
} talumno;

int main(){
FILE * arch;
talumno alumno;
arch = fopen(“[Link]”, “wb”);
if (arch == NULL)
{
puts(“no se puede crear el archivo”);
return 1;
}
printf(“LU?(-1 para terminar)”);
scanf(“%d”, &[Link]);
while([Link]!=-1){
fflush(stdin); //ó getchar();
printf(“Nombre?”);
gets([Link]);
printf(“Domicilio?”);
gets([Link]);
fwrite(&alumno, sizeof(alumno), 1, arch);
printf(“LU?(-1 para terminar)”);
scanf(“%d”, &[Link]);
}
fclose(arch);
return 0;
}

Indicador de registro activo: le indica al sistema en que lugar del


archivo se realiza la próxima grabación o lectura.

fread(<[Link] bloque>, <tamaño>, <[Link]>, <archivos>);


feof(<archivo>)-> verdadero (¡=0 para verdadero)

#include<stdio.h>
typedef struct {
int lu;
char nombre[80];
char domicilio[80];
} talumno;

int main(){
FILE * arch;
talumno alumno;
arch = fopen(“[Link]”, “rb”);
if (arch == NULL)
{
puts(“no se puede abrir el archivo”);
return 1;
}
fread(&alumno, sizeof(alumno), 1, arch);
//feof necesita una lectura previa de fread
while(¡feof(arch)){
if ([Link]<1000000)
printf(“%d-%s\n”, [Link], [Link]);
fread(&alumno, sizeof(alumno), 1, arch);
}
fclose(arch);
return 0;
}

Archivos Binarios de Acceso Directo


Es el mismo archivo de acceso secuencial, procesado con técnicas de
acceso directo.
Funciones para acceso directo:

rewind(<archivo>); //el archivo debe ser binario y estar abierto.


Regresa el indicador de registro activo al comienzo de los datos.

fseek(<archivo>, <desplazamiento>, <punto de partida>);


desplazamiento: numero entero que indica la magnitud del movimiento sobre
el indicador de registro activo, expresado en bytes. Numero de registro *
tamaño de registro.
Punto de partida: desde donde se mide el desplazamiento:
SEEK_SET: se mide el desplazamiento desde principio de archivo
SEEK_CUR: se mide el desplazamiento desde posición actual, puede
ser positivo (avanzo) o negativo (retrocedo)
SEEK_END: se mide el desplazamiento desde el final de archivo
fseek(arch, 4*sizeof(reg), SEEK_END); //se estaría pasando 4 registros
del final del archivo, si luego intento un fread, dará error, pero si
hago un fwrite se va a grabar un registro en esa posición, con las
posiciones que queden entre la ultima posición del archivo y donde quedo
posicionado se rellena con basura, esto se llama expansión del archivo.

ftell(<archivo>): devuelve el valor del indicador de registro activo (un


numero entero) expresado en bytes, dividiéndolo por el tamaño de registro
obtengo el numero de registro.

//programa para ordenar un archivo:


#include<stdio.h>
#include<string.h>
typedef struct {
int lu;
char nombre[80];
char domicilio[80];
}talumno;

talumno leerregistro(FILE * f, int numreg);


void grabarregistro(FILE * f, int numreg, talumno dato);
int main(){
FILE * arch;
int cantreg;
talumno alumno1, alumno2;
//uso rb+, es el único modo para ordenar un archivo
arch=fopen(“[Link]”, “rb+”);
if (arch==NULL){
puts(“Error”);
return 1;
}

fseek(arch, 0, SEEK_END); //ubico indicador al final


cantreg = ftell(arch)/sizeof(talumno); //obtengo cantidad de reg.
//Metodo de selección
for(i=0;i<cantreg-1;i++)
{
for (j=i+1;j<cantreg;j++)
{
alumno1=leerregistro(arch,i);
alumno2=leerregistro(arch,j);
if (strcmp([Link],[Link])>0){
grabarregistro(arch,j,alumno1);
grabarregistro(arch,i,alumno2);
}
}
}
fclose(arch);
return 0;
}

talumno leerregistro(FILE * f, int numreg){


talumno dato;
fseek(f, numreg * sizeof(talumno),SEEK_SET);
fread(&dato, sizeof(dato), 1, f);
return dato;
}

void grabarregistro(FILE * f, int numreg, talumno dato){


fseek(f, numreg * sizeof(talumno),SEEK_SET);
fwrite(&dato,sizeof(dato),1,f);
}

//programa para borrar alumnos “antiguos”, no borrado físico, borrado


//lógico, se marcan (en este caso pongo el legajo como negativo,
//multiplicándolo por -1) como //borrados reemplazando algún campo
del //archivo.

#include<stdio.h>
typedef struct {
int lu;
char nombre[80];
char domicilio[80];
}talumno;

int main(){
FILE * arch;
talumno alumno;
arch = fopen(“[Link]”,”rb+”);
if (arch==NULL){
puts(“Error”);
return 1;
}
fread(&alumno,sizeof(alumno),1,arch); //fread antes de foef
while(!feof(arch)){
if ([Link]>0 && [Link] < 1000000){
//vuelvo una posición para grabar el alumno
modificado //en la misma posición donde estaba, porque
una vez que //lo leyó, el indicador de registro activo
se movio un //posicion
fseek(arch, -1*(int)sizeof(talumno),SEEK_CUR);
//casteo sizeof a int, para que tenga signo y pueda
//multiplicarlo por menos uno, porque sizeof me devuelve
un //entero sin signo

[Link]=-1*[Link];
fwrite(&alumno,sizeof(alumno),1,arch);
//si estoy leyendo y quiero grabar (o al reves)
estoy //obligado a usar un fseek, por eso lo uso con un cero, para que no
haga //nada
fseek(arch,0,SEEK_CUR);
}
fread(&alumno,sizeof(alumno),1,arch);
}
fclose(arch);
return 0;
}

///////////////////////////////////////////////////////
Fragmento de programa:
Utilizo técnicas de acceso directo para recorrer un archivo en forma
secuencial, no esta bien, es al pedo.
fseek(arch,0,SEEK_END);
cantreg=ftell(arch)/sizeof(…);
for(i=0;i<cantreg;i++){
fseek(arch,i*sizeof(…),SEEK_SET);
fread(&dato,sizeof(dato),1,arch);


}
fclose(arch);

Archivos de Texto

LUNES
MARTES
MIERCOLES
En disco se almacena asi: LUNES\nMARTES\nMIERCOLES\n
El \0 que marca el final de las cadenas en memoria no se graba en los
archivos de texto, aca se graba un \n, que separa un registro del
siguiente.
\n: delimitador en archivos de texto, al grabarlo se convierte en:
a) DOS/Windows: Retorno de carro (CR, ASCII 13) + Avance de Linea (LF,
ASCII 10)
b) Unix/Linux: Avance de Linea (LF, ASCII 10)
c) Mac: Retorno de carro (CR, ASCII 13)

Binarios De Texto
Contenido de los Datos binarios Cadenas de caracteres
registros Variables Simples y
Estructuras
Longitud de registro Fija Variable
Delimitador entre Ninguno \n
registros
Conversión de Texto No Si
Método de acceso Secuencial o directo Secuencial
Método de Apertura Entrada, Salida o E/S Entrada o Salida

No se usan fread y fwrite porque no hacen conversión de datos (por


ejemplo el \n que esta explicado arriba)

Modalidades de lectura y escritura


1) Carácter a carácter
fgetc(<archivo>) -> lee el próximo carácter del archivo y lo
devuelve como valor de retorno.
fputc(<caracter>,<archivo>) -> escribe un carácter en el archivo
//programa que lee un archivo de texto, lo convierte a mayúsculas y
lo graba con otro nombre:

#include<stdio.h>
#include<ctype.h> //para usar toupper
int main(){
FILE *entrada, *salida;
char c;
entrada = fopen(“[Link]”,”rt”);
if(entrada == NULL){
puts(“Error”);
return 1;
}
Salida = fopen(“[Link]”,”wt”);
if(salida == NULL){
puts(“Error”);
return 1;
fclose(entrada);
}

c=fgetc(entrada);
while(!feof(entrada)){
fputc(toupper(c),salida);
c=fgetc(entrada);
}
fclose(entrada);
fclose(salida);
return 0;
}

Si la ultima línea no tiene delimitador, c ignora la línea

2) Línea a Línea
fgets(<cadena de caracteres>, <maximo>, <archivo>);
lee la próxima línea del archivo de texto y la guarda en la
variable de cadena de caracteres que pusimos como parámetro, lee
hasta que encuentra el \n. El máximo establece un limite a la
cantidad de caracteres a leer, se detiene la lectura por lo primero
que ocurra.

Char cad[80];


fgets(cad, 80, arch);
Si leo una línea de 60 caracteres, se corta por \n
Si leo una línea de 90 caracteres, se corta por el máximo (80), se
leen 79 caracteres y se agrega automáticamente un \0. Los 11
caracteres que quedaban (90-79) se leen en una tercer lectura que
se cortara por el \n.
Si fgets corta por el máximo, no fue leído el \n y entonces no
estará en la cadena, si corta por \n, entonces lo agrega a la
cadena

fputs(<cadena de caracteres>, <archivo>); //graba la cadena en el


archivo

para grabar \n: luego de la cadena puedo grabar un \n con un


fputc()

//programa para contar letras, primero convierto todo a mayúsculas


#include<stdio.h>
#include<ctype.h>
int main(){
FILE *arch;
int i, v[26]={0};
char c, cad[256];
arch=fopen(“[Link]”,”rt”);
if(arch==NULL){
puts(“Error”)
return 1;
}
fgets(cad,256,arch);
while(!feof(arch)){
for(i=0;cad[i];i++){
c=toupper(cad[i]);
if(isalpha(c))
v[c-‘A’]++;
}
fgets(cad,256,arch);
}
fclose(arch);
for(i=0;i<26;i++)
printf(“La letra %c se encuentra %d veces\n”,i+’A’,v[i]);
return 0;
}

3) Con formato
//para leer (si encuentra espacio en blanco deja de leer):
fscanf(<archivo>, <cadena de control de formato>, <dir. de vars>);
podría leer un archivo de fechas
5/10/2001
6/3/2006
fscanf(arch,”%d/%d/%d”,&dia,&mes,&anio);
fgetc(arch); //retiro el \n que quedo porque sino sigue
esperando

//para grabar:
fprintf(<archivo>, <cadena de control de formato>, <datos>);

fseek con archivos de texto


1) fseek() con desplazamiento 0 desde cualquier extremo del archivo
para ubicarme al comienzo o al final (según use SEEK_SET o
SEEK_END)

2) fseek() con desplazamiento obtenido previamente con la función


ftell()
Asignación Dinámica de Memoria

Organización de la memoria (mapa de memoria):


Area del Montón (Heap) (es área mas grande de las cuatro):
*Variables Dinámicas
Area de la Pila:
*Variables Locales (cualquier variable declarada dentro de una función)
*Parámetros (los declarados en la cabecera de una función)
*Direcciones de Retorno (donde continúa la ejecución después de
ejecutar la función)
Area de datos Globales:
*Variables Globales
Area de Codigo:
*Programa (ya compilado y enlazado, ejecutable)
*Constantes

Las variables dinámicas no pueden tener nombre, por eso se utilizan


punteros que apuntan a esas variables:

Variable dinámica (se accede a través de ptr)


ptr (puntero, variable local)

#include<stdio.h>
#include<stdlib.h>

int main(){
int *ptr;
ptr = (int*)malloc(sizeof(int));
*ptr = 3;
*ptr = *ptr + 1;
printf(“%d”, *ptr);
free(ptr);
ptr = NULL;
return 0;
}

malloc: pide un bloque de memoria (del área del montón) para ser usado
como memoria dinámica, necesita un entero que representa el tamaño en
bytes que quiero (uso sizeof para eso). Me devuelve la dirección de
memoria donde comienza ese bloque, y guardo esa dirección en mi puntero.
Si fracasa la asignación de memoria, malloc me devuelve un valor null.
El cast (int*) está para evitar un error o advertencia, malloc no
devuelve un puntero a entero (ni a nada), devuelve un puntero genérico y
podría dar error. Lo que escribo dentro del cast es la declaración que
utilicé para declarar al puntero, en este caso int*.

free: libera la memoria anteriormente asignada, debo pasarle un puntero


al bloque de memoria que quiero devolver al sistema operativo, por eso le
asigno un null a ptr, como medida de seguridad.

#include<stdio.h>
#include<stdlib.h>

int main(){
char *cad;
cad = (char*)malloc(40);
strcpy(cad, “Programación”);
puts(cad);
free(cad);
cad = NULL;
return 0;
}

////////////////////////////

//si hago esto, pierdo la primer asignación que hice, ya no la podría


//usar, ni destruir:
ptr = malloc(sizeof(int));
ptr = malloc(sizeof(int));

/////////////////////////////

Listas Enlazadas
Conjunto de elementos a los que llamo nodos, el nodo es un bloque de
memoria, dividido en dos áreas:
Nodo:
Valor (puede ser un entero, toda una estructura, Sig (puntero hacia
etc, según el tipo de dato) el siguiente nodo
de la lista)

El acceso a un nodo de interés se hace recorriendo la lista, pasando de


nodo a nodo a través del puntero al siguiente nodo.

//programa para ingresar números enteros en una lista enlazada hasta


que //se ingrese -1:
#include<stdio.h>
#include<stdlib.h>

typedef struct snodo {


int valor;
struct snodo *sig;
} tnodo;
typedef tnodo * tpuntero;

void insertarenelprincipio(tpuntero *cabecera, int valor);


void imprimirlista(tpuntero cabeza);
void borrarlista(tpuntero * cabeza);

int main(){
tpuntero cabeza;
int e;
cabeza = NULL; //Fundamental!!!
printf(“ingrese números enteros, -1 para terminar”);
scanf(“%d”, &e);
while(e!=-1)
{
insertarenelprincipio(&cabeza, e);
scanf(“%d”, &e);
}
imprimirlista(cabeza);
borrarlista(&cabeza);
return 0;
}

void insertarenelprincipio(tpuntero *cabeza, int valor)


{
tpuntero nuevo;
nuevo = (tpuntero)malloc(sizeof(tnodo));
nuevo->valor = dato;
nuevo->sig = *cabeza;
*cabeza = nuevo;
}

void imprimirlista(tpuntero cabeza){


while(cabeza!=NULL){
printf(“%4d”, cabeza->valor);
cabeza = cabeza->sig;
}
}

void borrarlista(tpuntero *cabeza){


tpuntero actual;
while(*cabeza!=NULL){
actual = *cabeza;
*cabeza = (*cabeza)->sig;
free(actual);
}
}

//añadimos mas funciones:

void borrarprimernodo(tpuntero * cabeza){


tpuntero actual;
if (*cabeza!=NULL){
actual = *cabeza;
*cabeza = (*cabeza)->sig;
free(actual);
}
}

void insertaralfinal(tpuntero * cabeza, int dato){


tpuntero actual, nuevo;
tpuntero anterior; //siempre esta un nodo atrás de actual

actual = *cabeza;
anterior = NULL;
while(actual!=NULL)
{
anterior = actual;
actual = actual->sig;
}
nuevo = malloc(sizeof(tnodo));
nuevo->valor = dato;
nuevo->sig = NULL;
if (anterior != NULL)
anterior->sig = nuevo;
else
//sino había ningún nodo, cabeza pasa a ser el nuevo elemento
*cabeza = nuevo;
}

void borrarultimonodo(tpuntero * cabeza){


tpuntero actual;
tpuntero anterior, anteanterior;

actual = *cabeza;
anterior = NULL;
anteanterior = NULL;

while(actual!=NULL){
anteanterior = anterior;
anterior = actual;
actual = actual->sig;
}
if (anteanterior!=NULL){ //2 o mas nodos
free(anterior);
anteanterior->sig = NULL;
} else if (anterior!=NULL) {
free(anterior);
*cabeza = NULL;
}
}

void insertarenorden(tpuntero * cabeza, int dato){


//en rojo se ven las diferencias con insertar al final
tpuntero actual, nuevo;
tpuntero anterior; //siempre esta un nodo atrás de actual

actual = *cabeza;
anterior = NULL;
while(actual!=NULL && actual->valor < dato)
{
anterior = actual;
actual = actual->sig;
}
nuevo = malloc(sizeof(tnodo));
nuevo->valor = dato;
nuevo->sig = actual;
if (anterior != NULL)
anterior->sig = nuevo;
else
//sino había ningún nodo, cabeza pasa a ser el nuevo elemento
*cabeza = nuevo;
}
Listas Enlazadas Dobles
Cada nodo tiene dos punteros: sig (apunta al siguiente) y ant (apunta al
anterior)
ant Valor sig

typedef struct snodod{


int valor;
struct snodod *ant, *sig;
}tnodod;
typedef tnodod * tpunterod;

void insertaralprincipiod(tpunterod *cabeza, int dato){


tpunterod nuevo;
nuevo = malloc(sizeof(tnodod));
nuevo->valor = dato;
nuevo->ant = NULL;
nuevo->sig = *cabeza;
if(*cabeza!=NULL)
(*cabeza)->ant=nuevo;
*cabeza=nuevo;
}

void insertaralfinald(tpunterod *cabeza, int dato){


tpunterod actual, anterior, nuevo;
actual = *cabeza;
anterior = NULL;
while(actual!=NULL){
anterior=actual;
actual=actual->sig;
}
nuevo=malloc(sizeof(tnodod));
nuevo->valor = dato;
nuevo->sig = NULL;
if (anterior!=NULL)
anterior->sig = nuevo;
else
*cabeza=nuevo;
}

void insertarenordend(tpunterod *cabeza, int dato){


tpunterod actual, anterior, nuevo;
actual = *cabeza;
anterior = NULL;
while(actual!=NULL && actual->valor < dato){
anterior=actual;
actual=actual->sig;
}
nuevo = malloc(sizeof(tnodod));
nuevo->valor = dato;
nuevo->ant = anterior;
nuevo->sig = actual;
if (anterior!=NULL)
anterior->sig = nuevo;
else
*cabeza=nuevo;
if (actual!=NULL)
actual->ant=nuevo;
}

void imprimirlistad(tpunterod cabeza){


tpunterod anterior=NULL;
puts(“Ida”);
while(cabeza!=NULL){
printf(“%4d”, cabeza->valor);
anterior=cabeza;
cabeza=cabeza->sig;
}
puts(“\n\nRegreso”);
while(anterior!=NULL){
printf(“%4d”, anterior->valor);
anterior=anterior->ant;
}
}

También podría gustarte