Introducción: Estructuras de Datos y Algoritmos

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 73

El compilador traduce cada archivo fuente (.c) a código objeto (binario .

obj) y luego
Introducción el linker (enlazador) combina archivos objeto y bibliotecas (.lib), y genera un
programa (archivo binario ejecutable, por ejemplo, de extensión .exe).

Estructuras de datos y algoritmos


En Introducción a la Programación definimos un algoritmo como una secuencia
finita de acciones para lograr un resultado. Al programar, se implementan los
algoritmos en un lenguaje apropiado para la computadora. La diferencia entre Programas
fuente (.c) Procesador Compilador
algoritmo y programa es que un algoritmo es una secuencia de pasos a seguir,
mientras que un programa es una implementación en concreto de dicha secuencia
de pasos. Un algoritmo se puede expresar o implementar de muchas maneras:
seudocódigo, lenguaje C, java, etc.

A medida que los problemas a resolver son más complejos, los tipos de datos a
Bibliotecas y
usar se hacen complejizan también. Ya no es suficiente con tener tipos enteros o archivos objetos Linkeditor
flotantes sino que se hace necesario contar con organizaciones de datos más Archivos de (.obj, .lib)
completas. Por ejemplo, si necesitamos representar una fecha, quizás sea más encabezado (.h)
conveniente tener un tipo específico que agrupe en una sola entidad el día, el mes
y el año. Así, entonces, definimos formas más complejas de organización de datos,
las estructuras de datos y el lenguaje que vamos a utilizar es el lenguaje C. Programa
ejecutable
(.exe)
Lenguaje C
Algunas características de este lenguaje son:

• Orientado a la programación de sistemas.


• Altamente transportable. Code::Blocks
• Muy flexible.
• Genera código muy eficiente. Para realizar las actividades utilizaremos Code::Blocks, un entorno de desarrollo
integrado (IDE) para programadores. Es un IDE libre, de código abierto y puede usarse en
Fases del desarrollo de un programa en C diversos sistemas operativos. Está licenciado bajo la Licencia Pública General de GNU.

Para obtener el archivo ejecutable del programa, cada archivo fuente primero es
preprocesado. Las directivas para el preprocesador son las precedidas por #. El
preprocesador se ocupa de la inclusión de archivos, sustitución de macros,
compilación condicional y eliminación de comentarios.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
La línea int main ( )
Lenguaje C Forma parte de todo programa en C.

Los paréntesis después de main indican que es un bloque constructivo del programa
Sintaxis conocido como una función.
El lenguaje C facilita un método estructurado y disciplinado para el diseño de programas de Todos los programas de C empiezan a ejecutarse en la función main.
computación.
La llave izquierda { inicia el cuerpo de la función main. La llave derecha } da por terminada
En el siguiente capítulo presentaremos las funciones elementales para trabajar en el la función main.
lenguaje C.
Este par de llaves y el conjunto de instrucciones que abarca recibe el nombre de bloque.
Al comenzar a trabajar en cualquier IDE (Entorno de desarrollo integrado para desarrollar
Antes de la llave de cierre, colocamos “return 0;”. Esta instrucción brinda información de
un programa) aparecerá:
cómo el programa finaliza su ejecución. Todo programa que ha terminado exitosamente
#include <stdio.h> retorna el valor 0 (cero) al sistema operativo
#include <stdlib.h> La línea printf ("Hello World!\n");
int main() printf ( ) es una función que permite mostrar o imprimir en la pantalla una leyenda.
{ Los paréntesis se escriben después del nombre de toda función para escribir entre ellos el
printf("Hello world!\n"); argumento.

return 0; En este programa se quiere mostrar la cadena de caracteres enunciada entre comillas
dobles; al ejecutarlo, aparecerá en la pantalla Hello World!.
}
La cadena de caracteres escrita entre comillas también se llama mensaje, leyenda o literal,
Analicemos cada una de las líneas de este código
y al mostrarla se respetan exactamente todos los caracteres que aparecen allí, salvo la barra
Las líneas #include <stdio.h> e #include <stdlib.h> invertida ´\´y el carácter escrito inmediatamente después.
Son directrices del procesador de C. La \ se llama carácter de escape y siempre se combina con el siguiente carácter:
C tiene ciertos procesos ya desarrollados y guardados ordenadamente, según sus \n significa línea nueva (el cursor se coloca al comienzo de la siguiente línea).
aplicaciones, en distintas carpetas: entrada/salida, pantalla, string, matemática, etc.. Estas
\t tabulador horizontal
carpetas se llaman en general bibliotecas.
\\ imprime una diagonal invertida \
Las líneas que se inician con # son procesadas o ejecutadas por el procesador, antes de la
compilación del programa. Esta línea le indica al procesador que incluya dentro del \% imprime el símbolo %
programa, el contenido del "archivo de cabecera de entrada/salida estándar (stdio.h)". \" imprime la doble comilla
Este archivo de cabecera contiene información y declaraciones utilizadas por el compilador Para indicar que luego de una instrucción se debe seguir en secuencia con la siguiente línea,
al compilar funciones estándar de la biblioteca de entrada/salida como son: scanf (leer) y todo enunciado debe terminar con ";" (punto y coma).
printf (mostrar).

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
En el programa se puede indicar o agregar una línea como comentario para documentar
Número con decimales entre 3.4E- Float %f
los programas y mejorar la legibilidad de los mismos. Punto flotante
38 decimales(6)
6 byte
Si el comentario ocupa solo una línea, se coloca al comenzar el mismo //, si ocupa más de
una línea, comienza con /* y termina con */. Al ejecutar el programa los comentarios no Doble punto Número con decimales entre 1.7E- Double %lf
realizan ninguna acción. Son instrucciones no ejecutables. flotante 308 decimales(10)
8 byte

Un carácter Char %c
Variables, Tipos y Declaración: Caracter
1 byte
Una variable es una posición en memoria donde se puede almacenar un valor. Antes de
usar una variable en un programa se la debe declarar, decir de qué tipo es (para determinar Cadena de caracteres char %s
cuántos bytes se reservan en memoria para almacenar su valor) y cuál es su nombre (para variable[longitud]
tantos byte
poder nombrarla en el programa). Es conveniente declararlas todas inmediatamente String
como
después de la llave de inicio del main.
caracteres
Los nombres de las variables son cadenas de letras y dígitos de 1 a 32. Se acepta el guión
bajo en los nombres nom_1, pero no puede comenzar con dígitos. Por ejemplo, para declarar la variable a como flotante, b como entera, nom como una
cadena de caracteres de a lo sumo 10 caracteres y z como caracter:
En C se consideran distintas las minúsculas de las mayúsculas. Es distinta la variable contc a
la variable contC. float a;

Todo se escribe en minúscula salvo las constantes y otros casos que ya se detallarán. int b;

Declaración: char nom[10];

char z;
La forma general para la declaración de variables:

Tipo nombre variable; Operadores Aritméticos:

Tabla de datos: OPERADOR ACCION

FORMATO y _ Resta
TIPO DESCRIPCIÓN PALABRA CLAVE
TAMAÑO
+ Suma
Número sin decimales entre Int %d
Entero * Multiplica
-32768 y 32767 2 byte
/ Divide
Número sin decimales entre Long %ld
Entero largo % Resto de la división
±2.147.483.647
4 byte

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 3 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 4
-- Decrementa ! Not (negación)

++ Incrementa
La precedencia es:

Operadores Relacionales y Lógicos: Más alta

Los operadores relacionales son símbolos que se usan para comparar dos valores. Si el ➢ !
resultado de la comparación es correcto la expresión considerada es verdadera, en caso ➢ >= > < <=
contrario es falsa. ➢ = = !=
➢ &&
Operadores relacionales: ➢ ||
Más baja
OPERADOR SIGNIFICADO

> Mayor que


Operadores de asignación:
>= Mayor o igual En C, el operador de asignación es un único signo = (igual).
que
Una asignación significa que la variable que se encuentra a la izquierda del = toma el valor
< Menor que que contiene la variable de la derecha.

Si a la derecha hay un operando o más, primero se resuelve esa expresión y luego se asigna.
<= Menor o igual
que
Variable 1 = Variable 2; x = y;
== Igual

!= No igual x = y + z;
Variable 1 = Variable 2 operador Variable 3;
Los operadores lógicos retornan un valor lógico basados en las tablas de verdad.
C me permite un formato de "atajo" en el siguiente caso:
Operadores lógicos:
Variable1 = Variable 1 operador expresión;
OPERADOR SIGNIFICADO
Por ejemplo:
&& And ( y )
x = x +10;
Or ( o ) y = y /z;

Si la variable está a la derecha y a la izquierda del =, se pueden abreviar como:

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 5 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 6
Variable 1 operador = expresión;
x = x + 10; por x +=10;
printf ("argumento1");
y = y/z; por y / = z;
x = x - 23; por x -= 23; Si tiene solo un argumento es porque es una leyenda o secuencia de caracteres donde se
x = x * y; por x *= y; respeta la escritura entre comillas dobles.

La variable 1 se debe inicializar, según corresponda, en la declaración. printf ("leyenda");

int x = 0; Dentro de esta leyenda no hay variables.

Por ejemplo: printf(“Este es un ejemplo”);


Para tener en cuenta!!
printf( "argumento 1" , lista de argumentos);
• Si un operador aritmético tiene operandos enteros se ejecuta una operación entera
(sin decimales):
5/9 da 0 ( cero ) printf ("leyenda que contiene uno o varios formatos de variables”, nombre de la o las
• Si un operador aritmético tiene un operando en punto flotante y otro entero, este variables);
último será convertido a punto flotante antes de hacer la operación
5.0/9 da 0.55
Si hay más de una variable se deben nombrar en el orden en que sus formatos fueron
• En una asignación del tipo f = ini;
escritos dentro de la leyenda.
Donde fueron declaradas como
Por ejemplo: printf(“Juan tiene %d años y Pedro %d ”, añosjuan , añospedro);
float f;
Para ingresar datos por teclado utilizamos la instrucción scanf().
int ini;

Convierte ini a float antes de la asignación. scanf( "argumento 1" , &argumento 2);

• En una decisión del tipo


El primer argumento es la cadena de control de formato, especifica el tipo de dato que debe
if ( f <= ini)
entrar el usuario y va entre comillas dobles.
Convierte ini a float para la comparación.
El segundo argumento empieza con un ampersand & u operador de dirección, seguido por
el nombre de la variable cuyo formato se declaró como argumento 1.
Printf y Scanf (instrucciones de e/s):
Ejemplo
Para mostrar por pantalla o imprimir utilizamos la función printf(). ¿Cómo sumar 2 números enteros?
Existen dos formas de escribir esta función, con un argumento o con más de un argumento.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 7 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 8
scanf ("% d", &a);

Usa la función scanf para que el usuario entre por teclado un valor entero.

La función scanf toma la entrada del teclado.


# include < stdio.h>
Scanf tiene en este caso 2 argumentos "%d" y & a.
int main ( )
Recordemos:
{
La instrucción scanf se escribe de la siguiente forma:
int a, b, sum; /* declaración de variables*/

printf ("Ingrese el primer número entero\ n");


scanf( "argumento 1" , & argumento 2);
scanf (" %d" , & a); /* lectura del primer número entero a */
El primer argumento es la cadena de control de formato, especifica el tipo de dato que debe
printf ("Ingrese el segundo número entero \n");
entrar el usuario y va entre comillas dobles.
scanf ( "% d" , &b); /* lectura del segundo número entero b*/
El segundo argumento empieza con un ampersand & u operador de dirección, seguido por
sum= a+b; /* asignación en sum */ el nombre de la variable cuyo formato se declaró como argumento 1.
printf ( " La suma es % d”, sum); /* muestra la suma */ En caso de las variables carácter o las string el & es opcional.
return 0; &a le indica a scanf la posición de memoria en la cual está almacenada la variable a. La
} computadora almacena el valor de entrada por teclado en esa posición de memoria.

La línea: int a,b,sum;

Corresponde a una declaración: a,b y sum son los nombres de las variables. Importante

Una variable es una posición en memoria donde se puede almacenar un valor para uso de En los scanf delante de las variables se coloca &, salvo excepciones. En caso de no colocarlo,
un programa. no guarda la dirección de memoria donde la almacenó y luego encontrarla es casi imposible,
utilizando cualquier valor en su reemplazo. Este valor se lo conoce como basura.
Esta declaración especifica que a, b y sum son enteros, y reserva en memoria el lugar
correspondiente, según el tipo, para cada variable. Esta secuencia printf y scanf facilita la interacción entre el usuario y la computadora. Ya
que con el printf me muestra una leyenda que me indica que hacer, que dato ingresar y el
Las variables se declaran enseguida de la llave izquierda del main, antes de ser utilizadas en
scanf me permite ingresar por teclado los datos.
el programa.
Si sólo colocamos el scanf se muestra en la pantalla un cursor titilando y al no tener una
La línea:
indicación sobre que está esperando como entrada: mi edad, mi nombre, mi sueldo… se
printf ("Ingrese el primer número entero \ n") ; hace poco amigable para el usuario.
Muestra la leyenda en la pantalla y coloca el cursor al principio del renglón siguiente, por Por eso es recomendable colocar un printf() y luego el scanf().
terminar con \ n.
La línea:
La línea:
printf ("La suma es %d", sum);

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 9 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 10
Utiliza la función printf para mostrar por pantalla la leyenda: ”La suma es” seguida del valor campo de 6 lugares
numérico de la variable sum.

Importante
Salida:
Este printf tiene 2 argumentos:
Si quiero mostrar 2 números en distinto renglón y alineados a derecha, debo saber cual
• El primer argumento es la leyenda que incluye dentro de las comillas dobles %d que es la cantidad máxima de dígitos y colocar ese número antepuesto a la d.
indica que se mostrará un número entero en ese lugar.
• El segundo argumento especifica el nombre de la variable que contiene el valor para Por ejemplo si tengo 2 números y el que ocupa más es de 6 dígitos
ser impreso 123 de los 6 lugares ocupa los 3 últimos
Es decir al mostrar por pantalla, en la leyenda se reemplaza el %d por el valor que tomó
154378 considera el campo de 6 lugares alineando de derecha a izquierda
sum.

Dentro de un printf también se pueden hacer cálculos. o Para mejorar la salida de puntos flotantes
Se puede reemplazar: Para mejorar el formato %f, que mostrará el valor con 6 decimales aunque no sea real,
sum= a+b; por ejemplo en el caso de sueldo no queda bien mostrar

printf ("La suma es %d", sum); $1245,500000 podemos recurrir a estas mejoras.

Por: printf("La suma es % d", a+b); % 6.1f son 6 caracteres en total de los cuales 1 es decimal

y en este caso no es necesario el uso de la variable sum. %.2f si delante del ´.´ no hay dígito significa que la cantidad de caracteres totales no
está restringida, pero el dígito que está detrás del ´.´ es la cantidad de decimales que se
Para ser más clara la salida podría ponerse:
mostrarán.
printf ("La suma entre los números %d y %d es %d", a,b,sum);

Si en el primer argumento hay varios controles de formato significa que serán reemplazados
por los valores de las variables del segundo argumento en el orden en que están
enumeradas.

Primer %d corresponde al valor de a

Segundo %d corresponde al valor de b

Tercer %d corresponde al valor de sum

Importante

o Para justificar dentro de un campo a la derecha


printf ("%6d\ n%6d", a,b);

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 11 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 12
Estructuras de decisión o selección: El primer operando es una condición, el segundo operando es el valor de toda la expresión
condicional si la condición es verdadera, y el tercer operando es el valor de toda la expresión
Sentencia IF: condicional si la condición es falsa.

Sintaxis:
Permite tomar una decisión para ejecutar una acción u otra, basándose en el resultado V o
F de una condición.
Condición? expresión 1: expresión 2;
Sintaxis:

if (condición) Si la condición es verdadera se ejecuta la expresión 1, si es falsa se ejecuta la expresión 2.


sentencia 1; Ejemplo:
[ else Leer dos números y mostrar el mayor
sentencia 2;] opcional

# include <stdio.h>

La salida por el VERDADERO siempre debe existir. int main ( )

Es por eso que el else es opcional, es posible que ante una decisión por la opción V se {
tengan que ejecutar sentencias, pero por el F no se ejecute ninguna sentencia. int x,a,b;
En caso de no ser así, se debe colocar la condición inversa. printf ("Ingrese un número: ");
Si tanto por la salida de V o F se deben ejecutar más de 1 sentencia, las salidas se deben scanf ("%d", &a);
colocar entre { } para limitar el bloque.
printf ("Ingrese otro ; ");
Los operadores de relación que van en la condición son <, >, <=, >=,
scanf ("%d", &b);
== (igualdad) ! = ( distinto).
x= a>b? a:b;
Cualquier regla convencional de sangrías que escoja deberá aplicarse con cuidado en todo
printf ("El mayor es %d", x);
el programa.
return 0;
Un programa que no siga reglas de esparcimiento uniformes es difícil de leer.
}
Sin utilizar la variable x sería:
OPERADOR ?:
printf ("%d", a>b? a:b);
C tiene este operador que utiliza 3 operandos.

Los operandos junto con el operador condicional conforman una expresión condicional.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 13 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 14
ANIDAMIENTO DE IF: Cada ELSE se corresponde con el IF más próximo que no haya sido emparejado.

Sintaxis:

Cond. 1 Cond. 2 Sent 1 Sent 2


if (condición 1)

{ F F NO NO

if (condición 2) F V NO NO

sentencia 1; V F NO SI
}
V V SI NO
else
Al colocar las { } estamos indicando que el else pertenece al primer if. Esas llaves son
sentencia
obligatorias ya que estamos 2;el orden de pertenencia de los else.
alterando
Operadores Lógicos:
/* siguiente instrucción ejecutable */
AND Y &&
Cond. 1 Cond. 2 Sent 1 Sent 2
OR O ||
F F NO SI Para recordar

F V NO SI
En un && (y), la salida es verdadera sólo si ambas condiciones son
V F NO NO VERDADERAS.

V V SI NO En un || (o), la salida es falsa sólo si ambas condiciones son FALSAS.

y si quitamos las claves:


Ejemplo:

if (condición 1) Realizar un programa para sumar dos números reales tales que, si la suma es mayor que 10,
if (condición 2) se divide por 2 y si la suma es menor que 10 se multiplica por 3, si es 10 no se modifica.
Listar en todos los casos el resultado logrado.
sentencia 1;
else
sentencia 2;
/* siguiente instrucción ejecutable */

El else correspondería al segundo if.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 15 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 16
Sentencia WHILE
#include <stdio.h>

int main( ) Sintaxis:

{
while (condición)

sentencia 1;
float sum, num1, num2, res=0;

printf ("Ingresa el primer número ");


Si se repiten más de una sentencia
scanf ("%f",&num1);

printf ("Ingresa el segundo número ");


while (condición)
scanf ("%f",&num2);
{
sum=num1+num2;
sentencia 1;
if (sum>10)
sentencia 2;
res=sum/2;
}
else
/* próxima sentencia ejecutable */
if(sum<10)

res=sum*3;
Si la condición es verdadera entra al while o sea se ejecutan las sentencias del while.
else
Si la condición es falsa no entra y ejecuta la próxima instrucción ejecutable fuera del while.
res=sum;
IMPORTANTE!!
printf ("Resultado %.2f",res);
Cuando la variable es un contador que se incrementa en +1 se puede escribir como:
return 0;
variable++;
}
Cuando la variable es un contador que se incrementa en -1 se puede escribir como:

variable--;

Estructuras de repetición
Sentencia DO/WHILE
Una estructura de repetición le permite al programador que se repita una acción, en tanto
cierta condición se mantenga verdadera. Es similar al while. En el while la condición se encuentra al principio, antes de ejecutarse el
cuerpo del mismo.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 17 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 18
La estructura DO/WHILE prueba la condición de continuación del ciclo después de Sentencia FOR
ejecutarse el cuerpo del ciclo, y por lo tanto el cuerpo se ejecutará por lo menos una vez.
La utilizo sólo cuando sé exactamente la cantidad de repeticiones que se debe hacer:
Cuando la condición es falsa se ejecuta la acción siguiente a la del while.
Sintaxis:

Sintaxis: for (variable1 = expresión1; condición ; progresión de la condición)

sentencia1;
do

{ for (variable1 = expresión1; condición ; progresión de la condición)


sentencia 1; {
sentencia 2; sentencia1;
} while (condición); sentencia2;

}
¡IMPORTANTE!

En variable1= expresión1 inicializa la variable1 con el valor de expresion1.


❖ En el caso de repeticiones controladas por contadores se requiere: La condición es la prueba de control de fin (nunca va un igual), mientras sea VERDADERA se
El nombre de una variable de control (controlador del ciclo). repite el ciclo.
El valor inicial de dicha variable. La progresión de la condición es el incremento de avance de la variable1.
El incremento (o decremento) con el cual, cada vez que se termine un ciclo, la variable El ciclo termina si la condición es falsa.
de control se modifica.
En caso de ser más de una sentencia lo que se repite se encierra entre { }.
La condición que compruebe la existencia del valor final de la variable de control.
Ejemplos:
❖ En caso de no ser variables de tipo controlador siempre debe haber una primer lectura
Imprimir los múltiplos de 7 que hay entre 7 y 112.
antes de la condición en el while (sino la condición se compararía contra "basura") y las
siguientes lecturas antes de la llave de fin del while. # include <stdio.h>
primer lectura; int main ( )
while (condición) {
{ int x;
sentencias; for (x = 7; x < = 112; x + = 7)
siguiente lectura; } printf ("%d ", x);

}
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 19 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 20
El valor inicial es 7, la condición es que sea <=112 y el incremento o progresión es de 7, por
pedir múltiplos de 7.

Imprimir los números del 9 al 1.

# include <stdio.h>

int main ( )

int k;

for (k = 9; k > = 1 ; k - - )

printf ("%d ", k);

En este caso el valor inicial es 9, pero el final es 1, valor menor al inicial.

Es por eso que la condición debe ser con >=1 y el incremento es de -1 ya que va
disminuyendo la variable.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 21


Guía de ejercicios

1. Calcular el índice de masa corporal ingresando el peso de una persona en kilos y su


estatura en metros. Este índice se obtiene realizando el cociente entre el peso y el
cuadrado de la estatura.

2. Ingresar el día y la cotización del dólar durante un mes. Calcular y mostrar el día
donde hubo la mayor cotización.

3. Se ingresan la cantidad de autos vendidos en los últimos 9 años. Calcular y mostrar:


a) El año que se vendieron la mayor cantidad de autos.
b) La cantidad total de autos vendidos

4. Ingresar números hasta que dicho número sea negativo. Calcular y mostrar:

a) Cantidad de números mayores a 4 y menores a 25.


b) Promedio de aquellos números múltiplos de 6.
c) El menor número leído.

5. Ingresar la edad y sueldo de los empleados de una empresa hasta que ambas sean
cero. Calcular y mostrar:

a) El promedio de edad de los que ganan más de $10000


b) El sueldo de aquellas personas mayores a 58 años, sabiendo que
cobran un plus del 5% de su sueldo.
c) El porcentaje de empleados cuyo sueldo es menor a 15000, que está
entre 15000 y 20000, y mayor a 20000.

6. Ingresar números hasta que dicho número sea negativo. Por cada número leído,
ingresar esa cantidad de números y obtener:

a) El promedio de cada lote leído.


b) Contar la cantidad de números pares de todos los números leídos.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1


Funciones en C Una estructura de función es:

Tipo de retorno nombre (lista de parámetros)


Sintaxis
{
cuerpo de la función
Una función es un mini programa dentro de un programa.
return expresión;
Las funciones contienen varias sentencias bajo un solo nombre.
}
Proporcionan un medio de dividir un proyecto grande en módulos pequeños.

Las funciones existen de modo autónomo, cada una tiene su ámbito.

La división del código en funciones hace que las mismas se puedan reutilizar en su programa
y en otros programas.

Para reutilizar una función dentro de un programa, solo se necesita llamar a la función. tipo de retorno nombre parámetros
Si se agrupan funciones en bibliotecas otros programas pueden utilizar estas funciones

Las funciones en C no pueden anidarse es decir una función no se puede declarar dentro de float suma (float num1, float num2)
otra función. {
Dicho de otra forma: float res;
Una función proporciona una forma conveniente de encapsular algunos cálculos, que se res = num1 + num2;
pueden emplear después sin preocuparse de su implementación.
return res;
Una función es un subprograma que se llama dentro de un programa principal. Las
}
funciones son independientes del programa que la llama, por eso una función puede ser
utilizada varias veces dentro de un programa o ser utilizada dentro de otros programas.

Una definición de función tiene la siguiente forma: Tipo de retorno o resultado: Es el tipo de dato que vuelve la función y aparece antes del
nombre de la función

TIPO DE RETORNO NOMBRE ( TIPO 1 ARG1, TIPO 2 ARG2.....) Lista de parámetros: lista de parámetros tipificados (con tipo) tipo1 parametro1, tipo2
parametro2.

Cuerpo de la función: se encierra entre llaves {....} no hay punto y coma después de la llave
Argumentos formales
de cierre
ya que representan los nombres de los elementos que se transfieren a la función desde la
Declaración local: las constantes, tipo de datos y variables declaradas dentro de las
parte del programa que llama. También se los conoce como parámetros o parámetros
funciones son locales a la misma y se perderán fuera de ella
formales.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
Valor devuelto por la función: mediante la palabra return se regresa el valor de la función. La última instrucción del cuerpo es return; o

return expresión;

Una llamada a una función produce la ejecución de las sentencias del cuerpo de la return para volver un valor al punto de llamada, el tipo de la expresión debe ser el mismo
función y un retorno a la unidad de programa llamadora después que la ejecución de la que se define como tipo de salida o retorno en la definición de la función.
función se ha terminado, normalmente cuando se encuentra una sentencia return. Una función no necesita regresar un valor, un return sin expresión hace que el control
regrese al programa sin pasar ningún valor al programa principal. En este caso, que no
Nombre de una función: El nombre de una función comienza con una letra y puede
contener hasta 32 letras. regresa nada, se coloca como tipo de retorno void.

Tipo de dato de retorno: Si la función no devuelve un valor “int”, se debe especificar el tipo Ejemplo 1:
de dato devuelto por la función. Dados dos números, mostrar el mayor (los números son distintos)

void maximo ( int x, int y)


Cuando devuelve un valor “int”, se puede omitir ya que por defecto “C” asume que todas
{
las funciones son enteras.
if(x>y)

printf ("El valor máximo es %d", x);


Si la función no devuelve un resultado, se puede utilizar el tipo “void” else

printf ("El valor máximo es %d", y);

Resultados de una función return;

Una función puede devolver un único valor. El resultado se muestra con una sentencia }
“return”.

Llamada a una función


Las funciones para poder ser ejecutadas, han de ser llamadas.

La función llamada que recibe el control del programa se ejecuta desde el principio y cuando
termina (se llega a la sentencia “return” o a la “ }” final).

Es decir:

En el momento del desarrollo de la función luego de la definición se colocan “{ “para


indicar el inicio y “}” para indicar el fin de la función.
Ejemplo 2:
El cuerpo de la función es el conjunto de instrucciones entre esas llaves y debe incluir una
o más instrucciones . Dado un número natural mostrar su factorial.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 3 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 4
¿Cómo se utilizan las funciones en un programa?
long fac ( int n)
Si se utilizan funciones dentro de un programa, éstas deben estar en 3 formas distintas:
{ int i ;
la primera es el prototipo,
long prod = 1;
la segunda es la llamada de la función dentro del main(), y
if ( n > 1)
la tercera es la definición y desarrollo.
for ( i = 2; i < = n; i++ )
La primera es el Prototipo de una función. Es la declaración de una función.
prod * = i;
Los prototipos contienen la cabecera de una función pero terminan con punto y coma.
return prod ;
Se ubican normalmente al principio de un programa, antes de la definición del “main()”.
}
Cuando una función se declara se da su nombre y la lista de sus parámetros.
Ejemplo 3:
Cuando se define significa que existe un lugar en un programa donde existe la función
Calcular la suma de n números reales.
desarrollada.

Los nombres de los argumentos en los prototipos no tienen significado, son independientes.

float suma (int n)

{ TIPO DE RETORNO NOMBRE ( TIPO 1 ARG1, TIPO 2 ARG2 ... );

int i;

float sum = 0.0, x; Los nombres de los argumentos formales o locales no tienen porque coincidir con los de los
reales.
printf(“Introduce %d números reales”, n);

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


El tipo de dato del argumento local debe ser igual que al del tipo de dato del argumento
{
real que recibe desde el punto de llamada.
scanf(“%f”, &x);
Ejemplo de prototipos:
sum + =x;
#include <stdio.h>
}
long fac ( int n);
return sum;
void maximo ( int x, int y);
}
int main()

{…

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 5 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 6
#include <stdio.h>
La segunda es la llamada de la función dentro del main(), int suma(int a, int b);
Cuando se llama a la función dentro del programa principal los argumentos se llaman int main()
argumentos reales, ya que definen la información real que se transfiere.
{
En la llamada los argumentos van sin su tipo, ya que ya fueron definidos al inicio del
int n1,n2,c;
programa.

Recordemos que los argumentos reales son variables que se utilizan en el programa o
valores constantes. c=suma (n1,n2);

La llamada a una función puede ser de 2 formas distintas, según retornen o no un valor. }

Si la función no regresa ningún valor en la llamada solo se nombra la función.


En el prototipo puedo no colocar el nombre de las variables, pero si es obligatorio el tipo y
Si la función regresa un valor, en la llamada debe haber una asignación del valor que regresa
respetar el orden:
a otra variable del mismo tipo..
int power (int, int);
Ejemplos de prototipos y sus llamadas:

#include <stdio.h>
Si no se nombran parámetros, se toman como int
void mostrar(int n, int res);
int power ( );
int main()

{
La tercera es la definición y desarrollo.
int n,res;
Al terminar el int main() se hace el desarrollo de la función con su definición, su cuerpo

y su return.
mostrar(n,res);
La declaración prototipo y la definición de la función deben coincidir en cantidad de
… parámetros y formatos y el orden en que se enumeran.
} Los nombres de los parámetros no siempre coinciden, son optativos.

La función que se invoca no puede alterar directamente una variable de la función que hace
la llamada; sólo puede modificar su copia temporal.

Es decir, si entra una variable del programa principal y la modifico en la función, al volver
no llega modificada al programa principal si la función es void.

Ejemplo:

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 7 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 8
Escribir a 2 columnas las potencias de 2 y de 3 con exponentes 0 al 9.

#include <stdio.h>
Cada llamada pasa 2 argumentos a power(), y cada vez regresa un entero p.
int power (int m,int n); /* función prototipo, luego se
desarrolla.*/ En el programa principal, los argumentos que se pasan a power() son uno por valor ya
que pasa una constante y uno por referencia ya que pasa una variable.
int main( )
Paso por valor (o paso por copia) significa que cuando “C” compila las funciones y el
{
código que llama a la función, la función recibe una copia de los valores de los parámetros.
int i,a,b;
En la definición o desarrollo de power() los nombres base y n son argumentos locales. Por
for (i = 0; i < 10; ++ i) el orden en que están, la constante se corresponde con base y la variable i con n
{if (i==0)

{ a = power (2, i);


a=1;

b=1;

} int power (int base, int n)


else

{ Las variables i y p que se declaran en la función son variables locales, es decir variables que
a= power (2,i); /* llamadas a la función.*/ no se ven en el principal y que si no regresan pierden su valor al salir de la función.

b=power (3,i); En nuestro ejemplo p regresa su valor por estar declarada en el return y en el principal su
valor se asigna a una variable del mismo tipo, y la i como no regresa no modifica el valor de
}
la variable i del principal.
printf ("%3d %6d %6d \ n", i, a , b);
Sus ámbitos son distintos, una es global o general (la del programa principal) y la otra es
}/*fin del programa principal*/ local (de la función).
int power (int base, int n) /*definición (no va ;)*/

int i, p;

p = 1;

for (i = 1; i < = n, i++)

p *= base;

return p; /*variable local */

}
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 9 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 10
¿Cómo declarar los vectores en C?
Vectores en C
Se debe especificar el nombre del vector, el tipo y la cantidad de elementos.
Sintaxis
int a [7];

Definición guarda 7 lugares para guardar enteros o sea cada uno de 2 bytes.

Un vector es un grupo de posiciones en memoria relacionadas entre sí porque tienen el


mismo nombre y son del mismo tipo. Ejemplo:

Para referirse a una posición en particular o elemento dentro del vector, Inicializar un vector de 5 elementos en cero y mostrarlos con formato tabulado:
especificaremos el nombre del vector y el número de posición del elemento particular
# include < stdio . h >
dentro del mismo.
int main ( )
a: nombre del vector
{
3 5 8 6 0 4 3
int n [ 5 ];
0 1 2 3 4 5 6 posición
int i;

for ( i = 0; i <5 ; i++ ) /*inicializa en cero*/


a [ 1 ] = 5 contenido
n [ i ] = 0;
a es un vector de enteros que contiene 7 elementos, cualquiera de éstos elementos
printf( " %8s%13s\n", "elemento","valor");
puede ser referenciado dándole el nombre seguido por el número de posición de dicho
elemento en particular entre [ ]. for ( i = 0; i<5; i++)

El primer elemento de cualquier vector es el elemento de posición cero. printf ( "%8d%13d\n", i , n [ i ];

a [0], a [1],.., a [6] }

El elemento de orden i se conoce como a [i-1]. Los elementos de un vector también se pueden inicializar en la declaración del
El número que está entre los [ ] se llama subíndice y debe ser un entero o expresión entera. vector:
Para multiplicar el tercer elemento por 4 y asignarlo a una variable x sería: int a[6] = { 1, 3, 5, 3, 4, 6};
x = a [2] * 4; int a[6] = {0} inicializa el primer elemento a cero y los 5 restantes les pone en cero
automáticamente.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
Si en la declaración no se coloca el tamaño asume la cantidad de elementos que
luego se cargan entre { }. #include <stdio.h>
int vec[ ] = {1, 2, 8, 4}; asume vec[4] int main ( )

int vec [ 50 ];
Operaciones con vectores:
int n1,i;
1) Cargar
do {
2) Recorrer
3) Mostrar printf ( "Ingrese la cantidad real de elementos");
4) Buscar un elemento
5) Desplazar scanf ( "%d", &n1);
6) Intercambiar
} while ( n1 > 50 || n1 < 1 );
7) Ordenar
for ( i=0 ; i < n1 ; i++ )

1) Cargar un vector de n1 elementos, siendo n1 a lo sumo 50. {

Para cargar un vector se usa una instrucción repetitiva, por ejemplo for. printf ( " Ingrese la componente % d ", i ) ;

Si no se sabe exactamente la cantidad de elementos que tendrá el vector, lo declaramos scanf( " %d ", &vec [ i ] ) ;
con la cantidad máxima de elementos posibles. }
int vec[50]; }
La cantidad de elementos que tendrá el vector la obtenemos ingresándola por teclado.
Luego validamos que no supere la cantidad máxima.

do {

printf ( "Ingrese la cantidad real de elementos"); 2) Recorrer el vector


scanf ( "%d", &n1); Utilizamos, en general, también un ciclo repetitivo for
} while (n1 > 50 || n1 < 1); Por ejemplo si queremos sumar los elementos del vector, el código es:

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 3 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 4
Como es posible que el elemento lo encontremos antes de terminar de recorrer el
...
vector no es conveniente hacerlo con un for. Es preferible utilizar un while pues nos
for ( i=0; i< n1; i++) permite comparar con la condición y cortar la búsqueda al encontrarlo.

sum + = vec [ i ]; La búsqueda de un elemento no significa que ese elemento esté en el vector. Por eso
la condición del while debe ser doble, una por la condición pedida y la otra para ver si
...
Por supuesto antes definimos sum como int y en cero. la posición no llegó al último elemento.

3) Mostrar un vector Por ejemplo, para decir en qué posición está el elemento cuyo contenido es 10.

Para imprimirlo también usamos un for pues debemos recorrerlo para mostrarlo.

...

... n=0;

for ( i= 0; i < n1 ; i ++ ) while ( vec [ n ] ! = 10 && n < n1)

printf ( " vec [ %d ] = %d\n" , i , vec [ i ] ) ; n ++;

... if (n == n1)

printf ( " El valor 10 no se encuentra" ) ;


O usando tabulaciones:
else
... printf ( " El valor 10 está en la %d posición" , n ) ;
printf ( " %8s% 13s \ n " , " elemento ", " valor "); ...
for ( i = 0 ; i < n1 ; i ++ )
Una vez que sale del while doble, debemos preguntar por cuál de las dos condiciones
printf ( " %8d %13d\n" , i , vec [ i ] ) ; salió y accionar según corresponda.
... 5) Desplazar los elementos de un vector.

Para desplazar los elementos de un vector podemos hacerlo hacia delante (a la


izquierda) o hacia atrás (a la derecha).
4) Buscar un elemento en un vector
Si lo hacemos hacia delante un lugar, se pierde el primer valor ya que en la posición 0
queda lo que está en la posición 1 y así sucesivamente hasta la posición última que

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 5 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 6
quiero desplazar. Pero el valor que está en el último lugar queda repetido en la posición
anterior, es por esto que muchas veces se aclara que hacer en esa posición, por ejemplo ...
reemplazar por 0.
for ( i = posfinal -1; i > = posinicial; i -- )

vec [ i+1 ] = vec [ i ];


...
// si me pide que reemplace por 0 colocaría :
for ( i = 1; i < = posfinal ; i ++ )
vec [ posinicial ] = 0;
vec [ i-1 ] = vec [ i ];
...
// si me pide que reemplace por 0 colocaría :

vec [ posfinal ] = 0;
El for comienza en posfinal-1 porque se asigna a la posición i+1 y si i valiese posfinal
... quedaría en una posición más que el máximo del vector que NO EXISTE.

6) Intercambiar
El for comienza en 1 porque se asigna a la posición i - 1 y si i valiese 0 quedaría
Para intercambiar dos elementos de un vector deben conocerse las dos posiciones que
posición -1 que NO EXISTE. Si el desplazamiento es hasta posfinal se copia el valor a la se quieren intercambiar.
posición anterior.
Supongamos que quiero intercambiar la pos1 con la pos2.
Si es más de un lugar el desplazamiento solo varía en lo que le restamos a la i y en el
Si ponemos
valor inicial del for.
vec [ pos2 ] = vec [ pos1 ];
Si lo hacemos hacia atrás un lugar, se pierde el último valor ya que en la posición
posfinal queda lo que está en la posición anterior a esa y así sucesivamente hasta la ¡En la pos2 queda el valor que está en la pos1, PERO CUIDADO!!! El valor que tenía
posición primera que quiero desplazar. Pero el valor que está en el primer lugar queda originalmente la pos2 se PERDIO y en la pos1 sigue quedando su valor original. Es decir
repetido en la posición siguiente, es por esto que muchas veces se aclara que hacer en no logramos lo pedido!!!
esa posición, por ejemplo reemplazar por 0. Para poder intercambiar, debemos declarar una variable auxiliar, para guardar allí el
En este caso tenemos que tener cuidado con el for, en que sentido? Si el for valor de pos2 antes de hacer la asignación.
incrementa la variable, es decir si vamos asignando desde la primera posición a la última Esto quedaría así:
pedida, perderíamos todos los valores y lograríamos repetir el primer valor a lo largo de
aux = vec [ pos2 ];
todo el intervalo. MAL!!!!
vec [ pos2 ] = vec [ pos1 ];
Que debemos hacer?
vec [ pos1 ] = aux;
Recorrer el for de atrás hacia adelante

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 7 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 8
7) Ordenar: La llamada a una función sería:

Para ordenar un vector sobre sí mismo hay varios métodos uno de ellos llamado x = maximo ( vec, n1 );
burbujeo es el siguiente:

Ejemplo:
Nombre del Cantidad de
Ordenar un vector de n1 elementos en forma ascendente.
vector elementos reales

pasa el vector y el tamaño a la función.


... C pasa en forma automática los vectores a las funciones utilizando simulación de
int i, j, aux; llamadas por referencia (las funciones llamadas pueden modificar los valores de los
elementos en los vectores originales de los llamadores).
for ( i = 0; i < n1 -1; i++ )
El nombre del vector es la dirección del primer elemento.
for ( j = i + 1; j < n1 ; j ++ )
Si no deseo pasar el vector completo, sino un elemento del mismo lo debo pasar por
if ( vec [ i ] > vec [ j ] )
valor, es decir, colocando el nombre y el subíndice o posición del elemento a pasar.
{
Por ejemplo:
aux = vec [ i ];
pepe ( vec [ 3 ] );
vec [ i ] = vec [ j ];

vec [ j ] = aux;
Ahora bien:
}
En el prototipo y en el desarrollo si un argumento es un vector se debe escribir con su
... tipo, nombre y los corchetes.

Para que una función reciba un vector a través de una llamada de función la lista de
¿Cómo pasar vectores en funciones? parámetros de la función debe especificar que se va a recibir un vector.
Para pasar un vector como argumento real en la llamada de una función hay que Por ejemplo:
especificar el nombre del vector sin los corchetes.
el encabezado de la función máximo sería:
Ejemplo:
int maximo (int vec [ ], int n1)
si se declara:
indicando que máximo espera recibir un vector de enteros en vec y su cantidad de
int vec [ 10 ]; elementos en el parámetro entero n1.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 9 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 10
#include <stdio. h>

void cargar ( int x [ ] , int n );

No es necesario colocar el tamaño del vector entre los [ ]. void mostrar ( int x [ ] , int n );

El prototipo podría escribirse: void vectorc ( int a [ ] , int b [ ], int c [ ], int n1 );

int máximo (int [ ], int); int posmax ( int a [ ] , int n1 );

void unos ( int b [ ], int n1 );

Recordar: el prototipo le indica al C la cantidad de parámetros y su tipo void ordenar ( int a [ ] , int n1 );

int main ( ){
Problema: vectores con funciones int n1, a [50], b [50], c [50];
Dados 2 vectores de n1 elementos, siendo n1 de a lo sumo 50, calcular: int i , x ;
a) El vector C como la suma del vector a + vector b, es decir do {
b) c [ i ] = a [ i ] + b [ i ] printf ( "Ingrese la cantidad real de elementos");
c) Indicar la posición del máximo elemento de a. scanf ( "%d", &n1);
d) Reemplazar por 1 (uno) los elementos de posición par de b.
e) Ordenar el vector a en forma ascendente. } while ( n1 > 50 || n1 < 1 );

cargar ( a, n1 ) ;

printf ("VECTOR A\n") ;

mostrar ( a, n1) ;

cargar ( b, n1 ) ;

printf ("VECTOR B\n") ;

mostrar ( b, n1) ;

vectorc ( a, b, c, n1 );

x = posmax ( a, n1 )

printf ("\n En la posición %d del vector a está el máximo valor", x );

unos (b, n1 );

ordenar ( a, n1 );

printf ("VECTOR A ORDENADO\n");

mostrar ( a, n1 );

getch( );

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 11 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 12
void cargar ( int x [ ], int n ) void unos ( int b [ ], int n1 )

{ {

int i; int i;

for ( i = 0 ; i < n ; i ++ ) for ( i = 0; i < n1; i +=2)

{ b [ i ] = 1;

printf ("\n Ingrese el elemento %d del vector" , i ); for ( i = 0; i < n1; i++)

scanf ("%d", & x [ i ] ); printf(“b[%d]= %d\n”, i, b[i]);

} return;

return; }

}
void ordenar(int a[ ], int n1)

void mostrar ( int x [ ], int n ) {

{ int i, j, aux;

int i; for ( i = 0 ; i < n1-1 ; i++)

printf ("ELEMENTO VALOR"); for ( j = i+1 ; j < n1; j++)

for ( i = 0 ; i < n ; i ++ ) if ( a [ i ] > a [ j ])

printf ( "% 8d %8d" , i , x [ i ] ); {

return; aux = a[ i ];

} a[ i ] = a [ j ];

a [ j ]= aux;

void vectorc ( int a [ ], int b [ ], int c [ ], int n1 ) }

{ return;

int i; }

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

c[i]=a[i]+b[i];

printf(“\n c [%d]= %d”, i, c [ i ]);

}return;}

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 13 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 14
int posmax ( int a [ ] , int n1 )

{
a) Los datos ordenados de menor a mayor por número de cuenta
Guía de Ejercicios b) El nombre y apellido y el tipo de cuenta con menor saldo.
c) Generar un vector con todos los datos de aquellos clientes que
tienen saldo negativo. Mostrarlo.
Desarrollar un algoritmo y luego codificarlo en C para cada problema. d) El porcentaje de clientes que tiene un saldo en la cuenta mayor a
$100.000.
1. Se ingresan los datos de vuelos a distintas ciudades para obtener estadísticas. Para e) Se ingresan los datos de una cuenta nueva a insertarla en el vector
ello se pide: Día de vuelo, nombre de la ciudad, capacidad del avión y cantidad de de tal manera que la información siga ordenada por número de cuenta.
pasajes vendidos. Estos datos se ingresan hasta que el día de vuelo sea cero. (desplazando los elementos a derecha).

Mostrar los datos ingresados.

Calcular y mostrar:

a) La ciudad y el día con la mayor cantidad de pasajes vendidos


b) El porcentaje de pasajes vendidos de cada ciudad.
c) Mostar las ciudades en forma ordenada de menor a mayor según la
cantidad de pasajes vendidos

2. Leer números enteros hasta cargar un arreglo de 10 elementos donde los primeros
5 son positivos y los restantes negativos.

a) Mostrar los primeros 4 elementos mayores del arreglo.


b) Generar otro arreglo intercalando el número positivo con los
números negativos. Mostrarlo.

3. Ingresar los datos de las cuentas de distintos clientes de un banco. Ellos son:
▪ Nro. de cuenta
▪ Nombre y Apellido
▪ Tipo de cuenta (1. caja de ahorro, 2. cuenta corriente)
▪ Saldo.

La carga de datos finaliza cuando el número de cuenta es 0.

Calcular y mostrar:

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
MUY IMPORTANTE: La indización comienza en 0 y es igual que en los vectores.
ARREGLOS MULTIDIMENSIONALES

Matrices
Funciones: Generar y mostrar una matriz en C
En matemática, una matriz es una disposición de números en filas y columnas:
Detallamos las funciones necesarias para generar una matriz con datos ingresados
2 7 −1 por teclado y mostrarla por pantalla.
(3 4 8)
−2 11 5
void GenerarMatriz (int A[][8], int filas, int cols){
La matriz A tiene 3 filas y 3columnas. Para denotar el elemento de la fila i columna j
se escribe Aij.. Podemos escribir entonces en este ejemplo que A12 =7 int i, j;
Diferencia con un arreglo: En la
for (i = 0; i < filas; i++)
También al programar podemos necesitar de tablas de valores dispuestas en filas y matriz, al pasarla por parámetro,
columnas. Por ejemplo, para representar una tabla de posiciones, una tabla de tarifas u { debe tener el número de
horarios de transportes, etc. Las matrices se usan entonces en programación y se conocen
columnas, sino es un error de
como arreglos multidimensionales. for (j = 0; j < cols; j++)
compilación
{
Matrices en C scanf(“%d”,&num);
A[i][j] = num;
}
Un arreglo bidimensional de 3 filas y 3 columnas como el del ejemplo anterior se
define en C indicando el tipo, el nombre del arreglo y entre corchetes la cantidad de filas y }
la cantidad de columnas: }
int array [3][3]; void MostrarMatriz (int A[][8], int filas, int cols){
Se puede inicializar en el mismo momento, de la siguiente manera: int i, j; Para que cada fila se
int array [3][3] = {{3, 4, 5}, for (i = 0; i < filas; i++) vea es un renglón
{5, 7, 8}, diferente
{ printf(“\n”);
{4, 3, 5}}; for (j = 0; j < cols; j++)
{
Para hacer referencia a un elemento particular, entre corchetes se indica la fila y la printf(“%d \t”,A[i][j]); \t de tabulación,
columna: } deja un espacio
array[0][0]vale 3 } entre los números
} de la matriz
array[0][1] vale 4
Programa principal

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
Diagonal principal:

int main()

{ int A[10][10], filas, cols;

printf(“ingrese cantidad de filas”);

scanf(“%d”,&filas); Diagonal secundaria:


printf(“ingrese cantidad de columnas”);

scanf(“%d”,&cols);

GenerarMatriz (A, filas, cols);

MostrarMatriz (A, filas,cols)


}

Simétrica

TIPOS DE MATRICES Es una matriz cuadrada que es igual a su traspuesta.

Traspuesta Ejemplo:

Dada una matriz A, se llama traspuesta de A a la matriz que se obtiene cambiando


ordenadamente las filas por las columnas.

Se representa por At ó AT
1 2 1 3
𝐴=( ) 𝐴𝑡 = ( )
3 4 2 4

Opuesta

La matriz opuesta de una dada es la que resulta de sustituir cada elemento por su
opuesto. La opuesta de A es -A.
1 2 −1 −2
𝐴=( ) −𝐴 =( )
3 4 −3 −4
Cuadrada

Aquella matriz que tiene igual número de filas que de columnas.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 3 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 4
Guía de Ejercicios

Desarrollar un algoritmo y luego codificarlo en C para cada problema.

1. Cargar una matriz de n*n de números enteros. Mostrar:


a) la sumatoria de los elementos de la 2º fila.
b) el mayor elemento de la segunda columna.
c) el promedio de todos los múltiplos de 5 en la matriz.
d) la sumatoria de la diagonal principal de la matriz.
e) el elemento mínimo de cada fila.
f) los elementos de la diagonal secundaria.
g) los elementos que se encuentran debajo de la diagonal principal.
h) si la matriz es simétrica.

2. Cargar una matriz de n*n de números enteros y mostrar:

a) la matriz transpuesta
b) El promedio de los elementos de las dos diagonales (principal y secundaria)
c) Multiplicar la matriz por su transpuesta.
d) Determinar cuántos números primos hay en la matriz.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1


El % indica que es un formato, [ ] entre los corchetes se pueden enumerar todos los
Cadena de caracteres caracteres que se permiten ingresar. Esta opción no es aconsejable, ya que son muchos
caracteres los que tendrían que escribirse; es mejor indicar cuál es el caracter que no se
quiere considerar, es decir, el caracter que va a indicar el fin de entrada de datos. Para
Introducción
ello, se coloca el símbolo ^ y el carácter de fin (\n indica que la finalización de entrada de
Una cadena es una serie de caracteres tratados como una sola unidad, que puede incluir datos está dada con un ENTER).
letras, dígitos y varios caracteres especiales como +, -, *, /, $, % y otros. Una leyenda o
constante de caracteres se escribe entre comillas dobles "BUEN DIA".
[ ^\n ] considera todos caracteres menos el ENTER.
En C, una cadena de caracteres es un arreglo de caracteres donde arreglo es una
estructura de datos consistentes en elementos relacionados del mismo tipo y bajo un
mismo nombre. Los arreglos ocupan lugar en memoria que depende de la cantidad de
Importante
elementos que posee. Para indicar el nombre puede tener como máximo quince
caracteres. Entre las primeras comillas " y el signo de % se debe dejar un espacio para que cada vez
Se define así: que cargue un nombre limpie el buffer de entrada de datos. Para mostrar una cadena de
caracteres se usa, printf con el formato %s en el lugar que debe aparecer el contenido de
char apellido [15] la variable.
tipo nombre longitud máxima estimada de la variable
printf (“El apellido es %s”, apellido);
Para ingresar una cadena de caracteres usamos la función scanf con el siguiente formato:
Funciones para cadenas de caracteres
scanf (“%s”, apellido); Para usar funciones relacionadas con cadenas de caracteres hay que incluir la biblioteca
string.h, en la que estas están definidas.

%s es el formato correspondiente para string o cadena de caracteres.


Copiar
La variable apellido, no lleva el & adelante pues C guarda automáticamente la dirección
del primer elemento del arreglo y, como guarda en forma consecutiva los caracteres, solo Para asignar una variable de tipo char a otra se utiliza la función strcpy.
sumando la dirección de memoria inicial al número de caracteres sabe cuál es la última La sintaxis de dicha función es:
dirección.

Si al ingresar una cadena de caracteres se deja un espacio intermedio, la variable solo


strcpy (S1, S2);
guarda los caracteres hasta el espacio. Para que la variable guarde todos los caracteres,
incluyendo el espacio, se utiliza el siguiente formato:
strcpy significa string copy, es decir, copia una cadena de caracteres en otra.

scanf ( " % [ ^\n ] ", nombre La instrucción permite guardar en contenido de s2 en s1.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
- s1: cadena de caracteres destino Comparar
- s2: cadena de caracteres origen
La función strcmp (string compare) sirve para comparar el contenido de dos cadenas de
caracteres.
s2 y s1 deben ser del mismo tamaño.
Su sintaxis es:

Ejemplo strcmp ( S1, S2 );

Leer los nombres y promedios de diez alumnos. Mostrar el nombre del mejor alumno.

#include <stdio.h> Compara la cadena S1 con S2 y devuelve un valor entero:


#include <stdlib.h> 0 si ambas cadenas son iguales
#include <string.h>
> 0 si la cadena S1 es mayor a S2

int main() < 0 si la cadena S1 es menor a S2


{
int i;
¿Qué significa que una cadena sea mayor que otra?
char nom [30], mejor [30];
float prom, auxprom; Cada caracter (letra, dígito o símbolos especiales) se corresponde con un código numérico
auxprom = 0.0; universal como ASCII o EBCDIC, que siguen el orden alfabético. La función strcmp compara
for ( i = 1; i <= 10; i ++) numéricamente caracter a caracter y, si todos los códigos son iguales, devuelve un 0; si el
{ caracter de S1 es anterior al de S2, devuelve un número menor que cero (< 0) y, de lo
printf ("Ingrese el nombre del alumno:"); contrario, devuelve un número mayor a cero (> 0).
scanf ( " %[^\n]", nom); Ejemplo 1
printf ("Su promedio es:");
- en S1 está guardada la cadena N A D A
scanf ("%f", & prom);
- en S2 está guardada la cadena NULO
if (prom > auxprom)
{ La instrucción strcmp (S1, S2) realiza la comparación de la siguiente forma:
auxprom = prom; - N y N son iguales
strcpy (mejor, nom); - "A " está antes que " U", es decir, el código ASCII de la “A” es menor al de la “U”.
} Al restarlos el resultado es negativo, no compara más y devuelve < 0.
} Se puede interpretar que si strcmp devuelve un valor negativo, la primera cadena está
printf ("El mejor alumno es %s con un promedio de %.2f", mejor, auxprom);
alfabéticamente antes que la segunda.
return 0; Ejemplo 2
} - en S1 está guardada la cadena ESPECIE
- en S2 está guardada la cadena ESPECIAL

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 3 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 4
Hasta la " I ", las cadenas son iguales. Luego se compara la “E” de S1 con la "A" de S2. En Tratamiento de la cadena caracter a caracter
este caso, strcmp devuelve un numero positivo ( > 0), ya que el código ASCII de la "E" es
Nuestro propósito es, dada una cadena de caracteres, procesar caracter a caracter y
mayor al de la "A" y al restarlos el resultado es positivo.
mostrar algunas conclusiones.

Ejemplo
Ejercicio de aplicación
- Si ingresamos: La vida es maravillosa
Ingresar los nombres de los 10 alumnos de un curso y decir cuántos se llaman JUAN
Queremos conocer cuántas palabras terminan con la letra a, cuántas palabras tiene la
frase, cuántos blancos hay, sin utilizar arreglos ni matrices para guardar la frase. La idea es
procesar cada caracter y, una vez leído, se pierde (no se puede volver para atrás).
#include <stdio.h> ¿Cómo lo hacemos?
#include <string.h>
Hay dos funciones en C que permiten leer caracter a caracter y mostrarlo en pantalla.

int main() La función getchar() permite leer un caracter (solo uno). Esta función internamente
{ traduce el carácter leído al número que le corresponde en la tabla ASCII, es decir, procesa
char nombre[15]; ese número. Esto se hace así ya que con un entero podemos representar tanto el
int cont=0, i; conjunto de caracteres que cabe en el tipo carácter (normalmente el conjunto ASCII de
for(i=0; i<10;i++) caracteres) como el carácter EOF de fin de fichero. Estos caracteres se suelen representar
{ como un entero que va del 0 al 127 o 256. El carácter EOF entonces es representado con
printf("Ingrese el nombre del alumno\n"); un -1
scanf("%s",nombre); La función putchar() muestra el carácter en pantalla. Internamente traduce el valor
if(strcmp(nombre,"Juan")==0 || strcmp(nombre,"JUAN")==0) numérico a la letra que le corresponde en la tabla.
{
El esquema básico en C es:
cont++;
}
}
printf("\nEn el curso hay %d alumnos llamados Juan", cont);
return 0;
}

Observación
Veamos entonces un ejemplo: Ingresar una frase terminada en punto y contar cuántos
En el strcmp del ejercicio anterior, comparamos la variable nombre con una cadena
blancos tiene la frase.
determinada, por eso la cadena está escrita entre comillas.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 5 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 6
Ingresamos la frase y c
guarda el primer carácter
de la frase.
En este caso, al anidar los if se busca en
la frase el grupo ‘sa’ y los cuenta. Puede
Se empieza a recorrer la estar en cualquier lugar de la frase
frase hasta encontrar el
punto

Si el caracter es un
blanco, se incremente el
La variable c guarda el
contador
próximo carácter de la
frase.

Veamos ahora pequeños códigos que les van a ayudar a construir los programas del
trabajo práctico.

Este ciclo recorre una palabra.

Este ciclo recorre los blancos de una


frase.

Este ciclo recorre una palabra y la


variable aux guarda la última letra de
esa palabra.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 7 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 8
13. Leer un texto carácter por carácter terminando en PUNTO y contar la cantidad de
Guía de Ejercicios letras iguales a la primera distinta de blanco.

14. Leer un texto carácter por carácter terminando en PUNTO. Contar grupos "TA".
Desarrollar un algoritmo y luego codificarlo en C para cada problema. Mostrar reemplazando por “TE”.

1. Leer un texto carácter a carácter, terminado en PUNTO. Mostrar cuántas palabras


tienen más de 3 letras. 15. Leer un texto carácter por carácter terminando en punto. Contar cuántas veces
aparecen dos letras iguales. Mostrarlas intercalándoles el signo “=”.
2. Leer un texto carácter a carácter, terminado en PUNTO. Mostrar el texto con un
blanco y eliminando las palabras de 1 letra.
16. Leer un texto carácter por carácter terminando en punto. Reemplazar grupos “y”
3. Leer un texto carácter a carácter, terminado en PUNTO. Mostrar cuántas palabras por “ll”.
tienen más de 2 letras y terminan con “s”.

4. Leer un texto carácter a carácter, terminado en PUNTO y repetirlo reemplazando 17. Leer un texto carácter por carácter terminando en punto. Contar palabras
los grupos ‘vl’ por ‘bl’. terminadas en “n” y mostrarlas pasándolas al plural.

5. Leer un texto carácter a carácter terminado en PUNTO. Contar cuantas palabras


empiezan y terminan con la misma letra.

6. Leer un texto carácter a carácter, terminado en PUNTO. Mostrar el texto


intercambiando la última letra con la anteúltima de las palabras de 2 o más letras.

7. Ingresar un texto carácter a carácter y determinar e informar cuantas palabras


capicúas hay de 2 o 3 letras.

8. Ingresar un texto carácter a carácter terminado en PUNTO. Contar cuantas


palabras empiezan con la anteúltima letra de la palabra anterior. En palabras de 1
sola letra deberá tomar esta única letra como anteúltima.

9. Leer un texto carácter a carácter terminado en PUNTO. Contar cuantas palabras


comienzan con las mismas 2 letras de la palabra anterior.

10. Leer un texto carácter por carácter terminando en PUNTO. Contar cuántas
palabras con 2 letras seguidas iguales hay.

11. Ingrese un texto carácter a carácter terminado en PUNTO contar cuantas palabras
tienen más de una vez repetida la primera vocal que aparece en el texto.

12. Ingrese un texto carácter a carácter terminado en PUNTO y repítalo agregando una
‘u’ entre cada letra ‘q’ seguida de ‘i’ o ‘e’.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
Diseño de funciones recursivas
Recursividad Al diseñar un algoritmo recursivo hay que identificar:

- cuál es el caso particular y cómo se resuelve (caso base).


Introducción - cómo se obtiene cada caso general a partir de uno más reducido,
“Para entender la recursividad primero hay que entender la recursividad”. convergiendo hacia el caso base.

En el diccionario de la RAE, la palabra “recurrencia” se define así: 1. f. Cualidad de


En el diseño de la función factorial identificamos:
recurrente. 2. f. Mat. Propiedad de aquellas secuencias en las que cualquier término
- que es una función recursiva porque el factorial de un número se puede
se puede calcular conociendo los precedentes.
obtener del anterior.
La recursividad está presente en muchos sistemas del mundo real. Y, por eso, muchos - hay un caso base, el 0, que siempre da 1.
problemas que queremos afrontar tienen una esencia recursiva. La recursividad es - para cada número mayor que 0, el resultado se obtiene multiplicándolo por el

una herramienta conveniente y muy útil para diseñar modelos informáticos de la anterior.
- siempre se finaliza en el caso base.
realidad que deseamos modelizar. Se dice que un sistema es recursivo cuando está
parcial o completamente definido en términos de sí mismo. Quizá todos nos hemos
Por todo lo anterior, es posible diseñar la función recursiva factorial:
planteado alguna vez una imagen recursiva: una fotografía que muestra a una
persona que sostiene entre sus manos esa fotografía, que muestra a esa persona que En C, dicha función resulta:
sostiene entre sus manos esa fotografía, que muestra a esa persona que sostiene
entre sus manos esa fotografía, que muestra…

Definición
Los algoritmos recursivos son aquellos que se invocan, directa o indirectamente a sí
mismos.

Encontramos ejemplos de invocaciones recursivas en algunas definiciones de entes


matemáticos y en algoritmos. Por ejemplo, podemos definir factorial de un número
natural n de la siguiente manera:

- Si n = 0, 0! = 1
- Si n > 0, n! = n * (n-1)!
Se observa que al definir factorial de un número se está basando en el factorial del
número anterior. También se puede observar que esto no es así indefinidamente,
sino que hay un caso particular que es el del cero que tiene su propia definición.

En C podemos escribir una función factorial que aproveche las características


recursivas de la definición matemática.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
Si se invoca factorial con, por ejemplo 4, la secuencia de llamadas recursivas es:

factorial(4) = 4 * 6 24

factorial(4) = 4 * factorial(3)
factorial(3) = 3 * 2

factorial(3) = 3 * factorial(2)
factorial(2) = 2 * 1

factorial(2) = 2 * factorial(1)
factorial(0) = 1 * 1

factorial(1) = 1 * factorial(0)
factorial(0) = 1

factorial(0) = 1 Espacio usado por un algoritmo recursivo


Si miramos la traza de las llamadas, veremos que, para que la ejecución de la función
pueda recorrer el camino de vuelta, en algún lugar se deberán guardar los valores de
Al resolver el caso base, se puede ir resolviendo las invocaciones que quedaron
los parámetros y de las variables locales de las llamadas anteriores. Este lugar es la
pendientes:
pila de ejecución. Su nombre responde a que en una pila de platos solamente
podemos colocar cosas encima y acceder al elemento de la cima (que es el último
que hemos introducido). Debido a que en la ejecución de un método recursivo
podemos tener que realizar muchas llamadas hasta alcanzar los casos simples, puede
darse la situación de que se llena la pila de ejecución y se produzca un error de
desbordamiento de pila (Stack Overflow).

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 3 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 4
Guía de ejercicios

1. Diseñar un algoritmo recursivo que permita hacer la división por restas sucesivas.

2. Diseñar un algoritmo recursivo que permita invertir un número. Por ejemplo,


Entrada: 123 Salida: 321.

3. Diseñar un algoritmo recursivo que permita sumar los dígitos de un número. Por
ejemplo, Entrada: 123 Resultado: 6.

4. Diseñar un algoritmo recursivo que permita multiplicar los elementos de un vector.

5. Diseñar un algoritmo recursivo que permita sumar los elementos de una matriz.

6. Diseñar un algoritmo recursivo que muestre el número menor de un vector.

7. Diseñar un algoritmo recursivo que nos permita obtener el determinante de una


matriz cuadrada de dimensión n.

8. Cargar un vector con n elementos enteros y calcular la suma de sus elementos en


forma recursiva.

9. Cargar un vector con n elementos enteros y calcular el promedio de sus elementos


en forma recursiva.

10. Cargar una matriz de n filas y n columnas, calcular y mostrar el elemento máximo
de cada fila en forma recursiva.

11. Cargar una matriz de n filas y n columnas, calcular y mostrar el producto de los
elementos de la diagonal principal en forma recursiva.

12. Ingresar dos números y calcular el m.c.d. en los mismos en forma recursiva.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1


Con la declaración de variable, la instrucción reserva memoria para la variable pi. Un
Punteros decimal de tipo float ocupa 4 bytes. Dependiendo de la arquitectura del computador, la
cantidad de bytes requerida para cada tipo de datos puede variar.

Introducción Estado de la memoria después de la declaración de la variable pi:

La memoria asociada a un programa se organiza como una colección de memorias


consecutivas formadas por un conjunto de bytes. En ella se almacenan los distintos tipos - pi -
de datos, que ocupan:
3 . 1 4
char -> 1 byte

Int - > 2 bytes 111 112 113 114 115 116…

Float -> 4 bytes


Dirección de comienzo de pi

Cada byte tiene un número asociado, una dirección en esa memoria.

Contenido de cada posición de memoria Cuando se muestra pi, ocurren dos pasos diferenciables. En primer lugar, el programa
busca la dirección de memoria reservada para pi (en nuestro ejemplo sería la dirección
112). Hecho esto, en segundo lugar, el programa recupera el contenido de esa dirección
de memoria. Así, por un lado distinguimos la dirección de memoria asignada a una
variable y, por el otro, el contenido de la posición de memoria reservada.

Podemos acceder a la dirección de una variable utilizando el operador &, y así accedemos
111 112 113 114 115 116… Direcciones de memoria a la dirección de memoria de una variable. Esta dirección es un número en sistema
hexadecimal con el que podemos trabajar directamente.

Veamos un ejemplo:
Concepto
int main()

{ Como su nombre lo indica, un puntero es algo que apunta, es decir, nos indica la ubicación
de algo. Imaginemos que tenemos un gran organizador en el que guardamos informes.
float pi; // reserva memoria para la variable pi
Este organizador está dividido en compartimentos, cada uno de los cuales contiene uno
pi=3.14; // almacena o guarda el valor 3.14 de nuestros informes (esto sería equivalente a las variables con las que hemos trabajado
printf ("%.2f\n", pi); // muestra el contenido de pi hasta ahora -informes- que contienen información, y el organizador representa la
memoria; obviamente las variables se almacenan en la memoria). Sin embargo, otros
return 0;
compartimentos no contienen informes sino que una nota que nos dice dónde está ese
} informe.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
Supongamos que, como máximo, trabajamos con cinco informes a la vez. Por lo tanto, num
reservamos cinco compartimentos en los que indicamos en qué compartimentos se
encuentran esos cinco informes. Estos cinco compartimentos serían nuestros punteros y
FA23FF01 FA23FF02
como ocupan un compartimento en el organizador (nuestra memoria) son realmente
variables, pero muy especiales. Estas variables punteros ocupan siempre un tamaño fijo y Un puntero podrá guardar la dirección donde comienza la variable num
contienen el número de compartimento en el que se encuentra el inicio de la información; (FA23FF01):
no contienen la información en sí.
pNum
Así, en nuestro supuesto de que solo trabajemos con cinco informes a la vez,
dispondríamos de cinco compartimentos en los que indicaríamos dónde se encuentran FA23FF01
esos informes que buscamos y, de esta forma, cuando terminemos con ellos y deseemos num
FA23FA21
trabajar con otros, solo tendremos que cambiar el contenido de esos cinco
compartimentos indicando dónde se encuentran los nuevos informes. 27

Esto es lo que en programación se conoce como referencia indirecta o indirección: FA23FF01


accedemos a la información a través de un puntero que nos dice dónde se encuentra. A
grandes rasgos, los punteros son referencias indirectas a datos en la memoria del
int *pnum;
ordenador. En C, los punteros son muy importantes puesto que su utilización es básica
para la realización de numerosas operaciones, entre ellas: paso de parámetros que El asterisco delante del nombre de la variable indica que no es una variable estándar sino
deseamos modificar, tratamiento de estructuras dinámicas de datos (variables que no se un puntero. Además, indica que apuntará a un valor de tipo int o a una variable de tipo
declaran en el programa y se crean durante la ejecución del programa), cadenas de int. Todos los punteros ocupan 4 bytes pues todos guardan una dirección de memoria.
caracteres… Ejemplo:

float precio, *punteroreal;


Definición de puntero

En el famoso libro de Kernighan y Ritchie El lenguaje de programación C se define un


puntero como “una variable que contiene la dirección de una variable”. En este ejemplo, se declara una variable estándar precio que contendrá valores reales
(tipo float) y, después, un puntero llamado puntero real que apuntará a valores reales o a
una variable de tipo real.
Declaración de un puntero
El operador & permite obtener la dirección de memoria de una variable. Así, si queremos
En su declaración, delante de su nombre debe añadirse un asterisco y especificarse el tipo que el puntero puntero real contenga la dirección de memoria de la variable real precio,
de dato al que apunta. debemos escribir la línea:

Tipo de dato al que apunta *nombre_de_variable; punteroreal = &precio;

Por ejemplo:

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 3 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 4
Se dice que “el puntero real apunta a la variable real precio” cuando contiene la dirección
int main()
de memoria de la variable. Si un puntero contiene una dirección de memoria está
apuntando al dato guardado en dicha dirección. Para poder acceder a él, debe usarse el {
operador asterisco delante del puntero. int edad; // Declaramos una variable entera.
Ejemplo: int *puntero; // Declaramos un puntero a un valor entero.

edad=45; // Almacenamos en la variable el valor entero 45.


int main()
puntero=&edad; // Almacenamos en el puntero la dirección de memoria de la variable
{
edad (usando &).
int edad; // Declaramos una variable entera.
/* Se dice que “puntero apunta a edad”. Ahora desde el puntero se puede obtener el valor
int *puntero; // Declaramos un puntero a un valor entero. almacenado en edad usando el asterisco. */
edad=45; // Almacenamos en la variable el valor entero 45. /* Ahora mostramos el valor almacenado en la dir. de memoria a la que apunta el puntero
puntero=&edad; // Almacenamos en el puntero la dirección de memoria de la (usando *)*/
variable edad (usando &). printf(“El valor almacenado en la variable es: %d”, *puntero);
/* Se dice que “puntero apunta a edad”. Ahora desde el puntero se puede obtener el valor // Aparecerá en pantalla: El valor almacenado en la variable es: 45
almacenado en edad usando el asterisco. */
/* Ahora modificamos el valor almacenado en la variable a través del puntero que apunta
// Ahora mostramos el valor almacenado en la dir. de memoria a la que apunta el puntero a ella usando * */
(usando *).
*puntero=7;
printf(“El valor almacenado en la variable es: %d”, *puntero);
printf(“El valor almacenado en la variable es: %d”,edad);
// Aparecerá en pantalla: El valor almacenado en la variable es: 45.
// Aparecerá en pantalla: El valor almacenado en la variable es: 7
return;
return 0;
}
}

Es importante no confundir el asterisco que se antepone al nombre del puntero al ¿Para qué usar punteros?
declararlo para indicar que es un puntero (en la zona de declaraciones de variables), y el
Supongamos que queremos intercambiar el valor de dos variables en una función y
asterisco antepuesto al nombre de un puntero dentro del código del programa para
mostrarlas en el programa principal (main).
indicar que se quiere obtener el dato almacenado en la dirección de memoria a la que
apunta el puntero.

Cuando un puntero apunta a una variable, puede obtenerse el valor almacenado en dicha
variable usando el operador asterisco, pero también se puede modificar dicho valor.

Ejemplo:

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 5 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 6
Después de la ejecución de intercambio en esta zona de memoria, los valores están
void intercambio a,( int a,int b)
intercambiados, nuestro parámetro a se corresponde con la variable c en la llamada a
{ int t; intercambio contendrá el valor 75, y el parámetro b, correspondiente a d en la función
t = a; main, contendrá el valor 54. Esto es lo que se encuentra almacenado en la zona privada de
memoria de la función.
a = b;
Con este esquema, y cuando la función intercambio termine su ejecución y se devuelva el
b = t;
control al programa principal main, los valores de c y d no habrán cambiaron, puesto que
} los compartimientos o posiciones de memoria x e y no han sido tocados por la función
int main () intercambio, que solo ha actuado sobre el compartimiento z.

{ Ejemplo correcto
int c,d;
Si declaramos ahora nuestra función intercambio como sigue:
c = 54;

d = 75;
{ void intercambio (int *p1,int *p2)
intercambio (c,d);
{

int t;
return 0 ;
t = *p1; /*Metemos en t el contenido de p1 */
}
*p1 = *p2; /* Contenido de p1 = contenido de p2 */

*p2 = t;
Veamos que pasa en la memoria de nuestro ordenador. return;
- Función main() }
- Espacio para la variable c (posición de memoria x)
- Espacio para la variable d (posición de memoria y)
- Inicialización de las variables La llamada en el main sería:
- Intercambio (c,d) Intercambio(&c, &d);
- Fin de main()
Tendremos el mismo esquema de nuestra memoria que antes pero, en lugar de almacenar
- Función intercambio
en la zona privada de la función intercambio para los parámetros los valores 54 y 75,
- Código de la función intercambio
tenemos almacenados en ella los compartimientos en los que se encuentran, esto es,
- Espacio privado para almacenar los parámetros (posición de memoria z)
hemos almacenado las posiciones x e y en lugar de 54 y 75. De esta forma, accedemos
En este último compartimiento almacenamos los valores de nuestros parámetros, que mediante un puntero a las variables c y d del programa principal que se encuentran en las
serán respectivamente 54 y 75.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 7 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 8
posiciones x e y, modificándolas directamente de manera que, al regresar al programa
principal, sus valores se encuentran ahora intercambiados.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 9


*(p + 0 )= 5
Le sumamos a la dirección de p tantos bytes como el tipo de
Punteros y arreglos dato al que apunta. Si le sumo 1 es equivalente a sumar 4
*(p + 1) = 6
bytes ya que p apunta a un entero.
*(p + 2) = 7

Inicialización
Un puntero puede inicializarse con la dirección de una variable existente. Otra Esto es lo mismo que realizar la siguiente asignación:
forma de inicializarlo es con NULL. El valor NULL es una constante definida en la
librería stdio.h que indica que el puntero es nulo, es decir, no apunta a ningún array [0]=5

lado aún.
array [1]=6
Hay una estrecha relación entre punteros y arreglos que hace que puedan usarse
array [2]=6
casi de manera indistinta.

El nombre del arreglo es un puntero al primer elemento del mismo. Es decir, si


tenemos:
Al sumar un entero n a un puntero, la dirección almacenada se modifica en n veces el
int array[5];
tamaño de lo que apunta. Si el puntero apunta a un char, entonces al sumarle 1 apunta al
array equivale a &array[0] byte siguiente porque los char ocupan un byte. Pero si el puntero apunta a un entero y el

Podríamos cambiar el contenido de la primera posición del arreglo efectuando: entero es de 4 bytes, deberá sumar 4 bytes a la dirección actual.

int array[5]; ¿Cómo se puede mostrar un arreglo utilizando un puntero?


int *p=NULL;

p = array; for (i=0; i<5; i++)


{
*p = 5;
printf("%d\n", *(p+i));

Ya que dicha expresión equivale a array[0] = 5;

La aritmética de punteros nos permite acceder a los otros elementos del arreglo:

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
Para poder hacerlo, necesitamos de tres funciones en C:
Punteros y asignación dinámica de memoria
La función Malloc permite reservar memoria. Se encuentra en la librería stdlib.h y está

definida por:
Introducción
La asignación dinámica de memoria es una característica del lenguaje C. Consiste void *malloc (size_t_size)
en asignar la cantidad de memoria necesaria para almacenar un tipo de dato
Malloc devuelve un puntero genérico.
durante la ejecución del programa, en vez de hacerlo en la fase de compilación de
este. Cuando se crea un programa en el que es necesario manejar memoria La función Sizeof permite calcular cuántos bytes se quieren reservar.
dinámica el sistema operativo divide a la memoria en cuatro partes que son:
sizeof (int) calcula cuantos bytes necesita un entero

La función Free permite liberar la memoria que se reservó con Malloc.

Segmento de código Entonces, vamos a crear un puntero p y asignarle el valor de 10.

Memoria estática
int *p;

Memoria dinámica (Heap) p = (int *)malloc (sizeof(int));

*p=10;
Pila (Stack)

Reservamos memoria: malloc

- Segmento de código: Almacena el código del programa. ¿Cuánta? sizeof (int)


- Memoria estática: Aquí se hace la reserva de los arreglos o matrices
Cómo la función malloc devuelve un puntero genérico (es decir, no apunta a nada) lo
durante la compilación del programa.
casteamos a que apunte a un entero (int *). Y esta dirección que devuelve malloc se la
- Pila: Se almacenan las llamadas a funciones recursivas.
asignamos al puntero p.
- Memoria dinámica: Es la memoria que utiliza el programador para reservar

espacio durante la ejecución del programa y luego la libera.

¿Cómo se accede a la memoria dinámica? Mediante los punteros.

Vamos a crear un puntero en memoria dinámica y asignarle un valor.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
4.
Guía de ejercicios

Detallar qué imprime el siguiente código en los ejercicios:

1.

5. Escribir un programa efectúe las siguientes operaciones:


a) Declarar un arreglo de quince posiciones de tipo float. Cargar sus elementos y
mostrarlo.
b) Declarar un puntero a float.
c) Asignar al puntero la dirección del arreglo.
d) Recorrer con el puntero el arreglo, mostrando la dirección y el contenido de cada
posición.

2.
6. Escribir un programa efectúe las siguientes operaciones:
a) Declarar una matriz de 3x4 de tipo int. Cargar sus elementos y mostrarla.
b) Declarar un puntero a entero.
c) Asignar al puntero la dirección de la matriz.
d) Recorrer con el puntero la matriz, mostrando la dirección y el contenido de cada
posición.

7. Un programa en C contiene la siguiente declaración:


int x[8]={10,20,30,40,50,60,70,80,80};

a) ¿Cuál es el significado de x?
3. b) ¿Cuál es el significado de (x+2)?
c) ¿Cuál es el valor de *x?
d) ¿Cuál es el valor de (*x+2)?
e) ¿Cuál es el valor de *(x+2)?

8. Un programa en C contiene las siguientes sentencias:


int A[10]={12,15,17,21,34,45};
int *B;
B=A; *B=A[4];

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
a) ¿Qué valor representa A[4]?
b) ¿Qué valor representa *(&B[3])?
c) ¿Qué valor representa *(B+2)?
d) ¿Qué valor representa A[0]?
e) ¿Qué valor representa *(B+0)?

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 3


Concepto
Estructuras Una estructura es una colección de una o varias variables, que pueden ser de distinto

tipo, agrupadas bajo un único nombre. Esto posibilita su manipulación, por ejemplo, al ser
Introducción
pasadas como argumento o al retornarse de funciones. Se puede usar una estructura para
Hasta ahora hemos trabajado con vectores, o arreglos, que nos permiten agrupar con un
representar un registro de un archivo de empleados: apellido, nombre, documento,
mismo nombre una colección de elementos de un mismo tipo.
legajo, categoría pueden formar una única estructura. Otro ejemplo es para agrupar los
distintos componentes de una fecha: dia, mes, año.
Edades La sintaxis para declarar un tipo estructura es:

struct identificador
Elementos de tipo 23 31 28 … 26
{

tipo1 miembro1;
Sueldos
tipo2 miembro2;

5435.28 4820.55 6400.25 … 9567.43 ...

Texto principal Ejemplo

struct fecha {
Puede ocurrir que necesitemos trabajar con colecciones de elementos, pero de distinto
tipo, como los datos personales de un alumno. int dia;

int mes;
Estructura int anio;

};
Nombre Juan Etcheverry 25789 21 5 Cantidad de materias A las variables que componen la estructura se las denomina miembros.

MUY IMPORTANTE: Una declaración struct define un nuevo tipo de datos.


Edad

Para definir una variable de tipo estructura se escribe la palabra reservada struct seguida
Número de
Apellido legajo del identificador de la estructura y luego el nombre de la variable:

struct identificador nombrevariable;

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
Por ejemplo

struct fecha mifecha  la variable mifecha es de tipo estructura fecha

Typedef
La palabra reservada typedef permite redefinir un tipo bajo otro nombre. Es decir, crea
sinónimos. Por ejemplo, podríamos redefinir int como “entero” o podríamos redefinir la
estructura fecha:

Typedef struct fecha tFecha;  tFecha es sinónimo de la estructura fecha.

Inclusive se puede declarar la estructura y establecer el sinónimo al mismo tiempo:

typedef struct fecha{

int dia;

int mes;

int año;

} tFecha;

Acceso a los miembros de una estructura


Para acceder a los miembros de una estructura se utiliza el punto.

En nuestro ejemplo:

mifecha.dia  accedemos al día de la estructura.

Pero existe otra forma de acceso a través de un puntero y utilizando el operador  Si p es


un puntero a una estructura, accedemos a sus miembros:

p  miembroEstructura

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 3 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 4
Caso contrario, apuntará al siguiente:
Listas simplemente enlazadas
Dato sig Dato
Concepto 2
1

Una lista es una secuencia de 0 o más nodos de un mismo tipo almacenados en memoria.
Son estructuras lineales: cada nodo (excepto el último) tiene sucesor y tiene anterior
(excepto el primero). Una lista se puede implementar de forma tal que los nodos no estén
físicamente contiguos, aunque se mantenga la relación de sucesión. Una implementación
La estructura de cada nodo en C la definiremos con Nodo
de este tipo es la de lista enlazada.
Una lista es una estructura dinámica ya que no es necesario reservar previamente
memoria como en los arreglos o las matrices. Durante la ejecución del código, se reserva typedef struct Lista{
Habrá que poner acá el tipo de dato que
memoria dinámica para cada nodo de una lista, y se libera cuando ya no se necesita. int clave ; compone la lista. Podríamos tener un int, un
float, un char, un arreglo o una estructura
En una lista enlazada, a diferencia de una lista contigua, cada elemento sabe quién le struct Lista *sig ;
do *
sigue. Podemos hacer la analogía con una sala de espera de un médico: cada persona sabe } Nodo ;
quién le sigue, aun cuando el siguiente no se haya sentado al lado.

Entonces, en la lista enlazada, cada nodo tendrá la información propia y un enlace al


siguiente elemento. Si en la lista no tenemos ningún elemento (lista vacía) la lista estará en NULL.

El enlace al siguiente nodo será a través de un puntero.

dato sig

Operaciones sobre las listas enlazadas


1. Crear una lista.
2. Mostrar la lista.
Si no tiene siguiente, el campo sig deberá estar en NULL. 3. Insertar elemento en la lista.
4. Eliminar un elemento de la lista.

dato En este módulo vamos a detallar cómo se crea y se muestra una lista.

Crear una lista simplemente enlazada

Para crear una lista debemos seguir lo siguientes pasos:

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
- Asignar memoria para un elemento del tipo de dato definido en la estructura y sig 0
4
generar los siguientes nodos hasta que no haya más entrada de datos. 1

Prim
En el código:

prin=(nodo *)malloc(sizeof(nodo)); El código de la función Crear y el main es:

En esta línea de código, reservamos memoria. La cantidad la indica sizeof y depende de la void crear (nodo *registro)
{
estructura definida. La dirección que devuelve malloc la recibe el puntero Prim.
registro->num =;

if (registro->num==0)
Prim registro->sig=NULL;
else
{

- Luego, llamamos a la función crear y le pasamos por parámetro el puntero registro->sig=(nodo*)malloc(sizeof(nodo));

Registro, esto es: Registro recibe la dirección donde apunta Prim. crear (registro->sig);

}
return;
Prim }

int main()
{
Registro int i=0;
nodo *prin;

prin=(nodo*)malloc(sizeof(nodo));
- Le pedimos el dato al usuario y lo ingresamos a la lista. crear(prin);
mostrar (prin);
return 0;
}

MUY IMPORTANTE: ¡NO PERDER LA CABEZA!


Prim
4
Se usó un puntero auxiliar anterior y no se recorrió con el mismo puntero la
lista para no perder su comienzo. Al puntero en el inicio de la lista se lo
Registro suele denominar “cabeza”, en este caso, Prim. Al efectuar ciertos
recorridos sobre las listas hay que tener cuidado de “no perder la cabeza”
y, por eso, es conveniente usar punteros auxiliares (Registro).
- Hasta que sea cero el dato ingresado le pedimos más datos.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 3 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 4
Mostrar una Lista

Ya creamos la lista cuyo puntero en la cabeza de lista es Prim. Llamamos a la función


Mostrar que tiene como único parámetro este puntero. En dicha función, la dirección de
Prim recibe Registro y empieza a recorrer la lista recursivamente, mostrando el elemento
en pantalla.

El código de la función mostrar es:

void mostrar (nodo *registro)


{
if (registro->sig !=NULL)
{
printf ("%d\n",registro->num);
mostrar (registro->sig);
}
return;
}

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 5


b)
Guía de ejercicios q

Utilizar la siguiente declaración en los ejercicios del 1 al 3.

r
typedef struct lista { c)
int info;
p lista
struct lista * sig;

}nodo;

1. Mostrar lo que harían las siguientes instrucciones en la lista simplemente enlazada:

3 5 9
d)
lista p
p q i

a) p = p  sig d) p  info = i  info


b) q = p e) p  info = q  sig  info
c) i = p  sig f) i  sig = p
3. Mostrar lo que escriben los siguientes segmentos:

a) crear (p); b) crear(p);

crear (q); pinfo=3;


2. Escribir una sentencia para efectuar el cambio indicado en la línea de puntos.
pinfo=5; crear(q);
a)
qinfo=6; pinfo= qinfo;

p=q; qinfo=0;

pinfo=1; emitir(p info);

emitir (pinfo); emitir (qinfo);


p
emitir (qinfo);

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
4. Dada la siguiente lista simplemente enlazada que contiene la siguiente información: a) Crear y mostrar la lista (la carga finaliza cuando codmat=0). Se cargan todos los
códigos de materias iguales seguidos y ordenados.
DNI: entero positivo de hasta 8 dígitos.
b) Mostrar los alumnos que pertenecen a una materia.
Nombre: cadena de 15 caracteres
c) Mostrar el código de materia que cuenta con más alumnos.
Tipo de cuenta: carácter (C,E,A)

Saldo: real

Siguiente: puntero al próximo elemento de la lista.

Desarrollar un procedimiento que busque en la lista un nodo cuyo DNI sea igual a uno
dado. El mismo devolverá un puntero al nodo hallado o NULL, si no existiera tal nodo.

5. Dada la siguiente estructura:

Dni (int) sig (puntero)

Nombre (char ) saldo(float)

a) Crear y mostrar la lista. La carga de datos termina con dni=0. La carga de datos se hace
en forma ascendente por dni.
b) Generar otra lista con todos los saldos negativos.

6. Dada la siguiente estructura:

typedef struct lista {

int codmat;

char nombre [15];

struct lista * sig;

} nodo;

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 3 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 4
Insertar y eliminar nodos en una lista simplemente prim

enlazada
aux

Introducción
En este módulo, conoceremos en detalle cómo se insertan y se eliminan nodos en una r
lista. Esto se realiza durante la ejecución del programa, por ello las listas son estructuras
dinámicas: se reserva memoria para insertar datos y se libera la memoria para eliminarlos.
r=aux
aux->sig=r
Inserción
Para insertar un nodo en una lista, hay que seguir lo siguientes pasos:

‐ Reservar espacio de memoria (con la función Malloc; la cantidad se calcula con la


función Sizeof).
‐ Enlazar el nuevo nodo con la lista. Aquí están detallados los pasos:
‐ Enlazar la lista con el nuevo nodo.
1. Se reserva memoria y esa dirección la toma el puntero aux.
Hay que distinguir dos tipos de inserción: por cabeza de lista, es decir, insertar un nodo al 2. Se realiza el primer enlace del nuevo nodo a la lista.
comienzo de la lista y en cualquier lugar de la lista. 3. Se modifica el puntero a cabeza de lista (r) para que apunte a la dirección de aux.
4. Se devuelve esta dirección al main, que es recibida por el puntero a cabeza de lista
Inserción de un nodo por cabeza de lista (prim) que se actualiza.

Para insertar un nodo por cabeza de lista es necesario construir una función que permita
Código de la función insertar por cabeza de lista
devolver la dirección del puntero a cabeza de lista que se ha modificado, para indicárselo
al programa principal.

En la siguiente lista (solo como ejemplo) se detallan los enlaces necesarios para la nodo* insertar1(nodo *r)
{
inserción del nuevo nodo. El puntero a cabeza de lista es prim, pero al llamar a la función nodo *aux;
if()//condicion de insercion
insertar por cabeza de lista, esa dirección la recibe el puntero que denominaremos r. {
aux=(nodo *)malloc(sizeof(nodo));
aux->num=0;//valor a insertar
aux->sig=r;
r=aux;
}
return r;
}

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
Inserción de un nodo en cualquier lugar de la de lista Eliminación de nodos en una lista

En este caso, no se modifica la dirección del puntero a cabeza de lista. Para eliminar un nodo en una lista hay que seguir lo siguientes pasos:

‐ Se establece un puntero al siguiente nodo que se quiere eliminar.


registro ‐ Se libera el espacio de memoria reservado con la función Malloc con la función
prim Free.
‐ Enlazar los nodos de la lista.

registro->sig=aux

Eliminación de un nodo por cabeza de lista

aux Al eliminar nodos por cabeza de lista, se debe actualizar la dirección del puntero a cabeza
aux>sig=registro->sig de lista en el programa principal. Para esto, se debe construir una función que devuelva
esta dirección.
Gráficamente:

Aquí están detallados los pasos:


prim prim
1. Se reserva memoria y esa dirección la toma el puntero aux.
2. Se realiza el primer enlace del nuevo nodo a la lista.
3. Se enlaza la lista al nuevo nodo.

Código de la función insertar en cualquier lugar de la lista

aux
void insertar2 (nodo *registro)
{nodo *aux=NULL;
while(p->sig!=NULL)
{
if() //condicion de insercion
{ Enlace y liberación de la memora:
aux=(nodo *)malloc(sizeof(nodo));
aux->num=0;//valor a insertar - aux=prim->sig
aux->sig=registro->sig; - free(prim)
registro->sig=aux;
- prim=aux
}
registro=registro->sig;
}
}

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 3 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 4
Código de la función eliminar por cabeza de lista Código de la función eliminar en cualquier lugar de la lista

nodo* eliminar1(nodo* prim,) void eliminar2(nodo* registro)


{nodo *aux; {nodo *aux=NULL;
while()//condicion de eliminacion while(registro->sig!=NULL&& registro->sig->sig!=NULL)
{ {
aux=prim->sig; if()//condicion de eliminacion
free(prim); {
prim=aux; aux=registro->sig->sig;
free(registro->sig);
} registro->sig=aux;
return prim; }
} else
{
registro=registro->sig;
}
}
Eliminar un nodo en cualquier lugar de la de lista }

En este caso, no se modifica la dirección del puntero a cabeza de lista.


Gráficamente:

registro
prim

registro->sig=aux aux

Cuando se borra un nodo no se avanza en la lista ya que no se podrían borrar nodos


consecutivos, cuando no se borra si se avanza.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 5 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 6
Guía de ejercicios
3 5 6 9 11 22

1. Dada la siguiente estructura:

typedef struct lista {


2. Dada la estructura del ejercicio anterior, desarrollar un procedimiento que, dados dos
int num; valores P y Q, elimine todos los elementos de la lista desde P hasta Q inclusive. Ante
posibles errores, emitir mensajes aclaratorios.
struct lista * sig;
- Nota: P y Q son valores, no punteros.
} nodo;
3. Desarrollar un procedimiento que permita borrar una lista completa (deberá ser lo más
rápido posible).
a) Cargar una lista con números ordenados de menor a mayor y con dos consecutivos cada
tanto. La carga termina con número = 1000. 4. Desarrollar un procedimiento que, dado un número M, elimine:

b) Agregar el tercero consecutivo. a) l elemento M-ésimo de la lista.


b) Todos los elementos menores a M.

5. Desarrollar un procedimiento para invertir una lista lineal, es decir, cambiar sus enlaces
3 5 6 9 11 12 para que aparezcan en orden inverso.

6. Considerar una lista ordenada ascendentemente con la estructura del ejercicio 1, y

7 generar a partir de ella dos listas distintas, una con los valores pares y otra con los valores
impares.
c) De dos consecutivos, eliminar el primero.
7. Dadas dos listas con la estructura del ejercicio 1, intercalar los elementos de la segunda
lista en la primera, respetando el orden.

8. Desarrollar un procedimiento que ordene una lista en forma ascendente.

3 5 6 9 11 12

d) De dos consecutivos, eliminar el segundo.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
FILE *fp;
Archivos secuenciales en C fp = fopen(“miarchivo.txt”,”w”);

Introducción La variable fp es un puntero a FILE. Al efectuar fopen con el nombre de un archivo en


particular, y para un determinado modo (w es para escritura), retorna un puntero a una
Al finalizar un programa, los datos almacenados en variables se pierden. Si se requiere que
estructura de tipo FILE que se almacena en fp. A partir de entonces, todo lo que haya que
esos datos se conserven en forma permanente es necesario guardarlos en archivos. Los
hacer sobre el archivo se hará a través de dicha variable.
archivos se grabarán en algún dispositivo de almacenamiento.
Para cerrar el archivo y liberar el puntero se efectúa:
En C, es posible crear, actualizar y procesar archivos de datos. El lenguaje C ve a los
archivos como un flujo secuencial de bytes. Si el contenido del archivo es un conjunto de fclose(fp);
valores ASCII imprimibles, separados por saltos de línea (ASCII 13) entonces tenemos un
archivo de texto.
Modos de apertura de un archivo
Si, en cambio, el archivo contiene bytes con cualquier valor del intervalo [0, 255]
entonces es un archivo binario y su estructura interna depende de cada archivo en El modo de apertura de un archivo es una cadena de texto que indica cómo se usará el
particular. C provee funciones que facilitan el tratamiento de ambos tipos de archivos. En archivo:
este módulo, solo vamos a trabajar con archivos secuenciales de texto.
w Write (escribir). No debe existir. Si existe, se elimina.
r Read (leer). Debe existir, si no da error.
Estructura File
a append (agregar). Escritura al final. Si no existe, se crea vacío.
Antes de que un archivo pueda ser leído o modificado, debe abrirse. Para ello existe la
w+ Lectura y escritura. No debe existir. Si existe, se elimina.
función fopen.
r+ Lectura y escritura. Si no existe, se crea vacío.
FILE *fopen(char *nombre, char *modo);
a+ Lectura y escritura al final. Si no existe, se crea vacío.

Dicha función toma un nombre real de archivo (una cadena de texto con la ubicación y el
nombre del archivo), efectúa la negociación correspondiente con el sistema operativo y Si hay un error, fopen retorna un puntero nulo (NULL) así que es conveniente siempre
retorna un puntero a una estructura que contiene la información necesaria para manejar validar si el puntero obtenido no es NULL:
dicho archivo. Permite almacenar información de la conexión entre el archivo físico y el
if((fp = fopen(“miarchivo.txt”, w))== NULL)
programa, por lo que podemos denominarlo el archivo lógico. Entre otras cosas, contiene
la ubicación del buffer, la posición del carácter actual en el buffer, un indicador que printf(”Error al abrir el archivo”);
muestra si el archivo está siendo escrito o leído, y si se ha alcanzado el fin de archivo. La
estructura depende del sistema operativo y se puede ver la estructura tipo FILE en la Lectura y grabación de datos en un archivo
librería stdio.h.
La biblioteca estándar de C provee funciones que facilitan la operación sobre archivos de
Ejemplo: texto. Así, para la lectura de caracteres de un archivo tenemos la función fscanf:

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
Esta función se usa para obtener valores con un determinado formato. Dichos valores se Código para crear y leer un archivo en C
obtienen del archivo y se almacenan en los argumentos variables.
fopen tiene dos parámetros:
la ubicación y el nombre del

fscanf(FILE *fp, char *format, ...); archivo, y para qué se va a


El puntero cfptr recibe el
abrir el archivo.
puntero que devuelve
fopen

La función fprintf se usa para escribir en un archivo en un determinado formato.

fprintf(FILE *fp, char *format, ...);

fprintf requiere de tres parámetros:


el puntero, el formato de las
variables que va a grabar en el buffer
Control de errores
y dichas variables.
En el manejo de archivos, es muy importante controlar los errores que podrían suceder.
Por ejemplo, querer efectuar una lectura más allá del fin de archivo, o querer escribir en
un archivo abierto solo para lectura dan errores que deben controlarse.

Para ello, contamos con la siguiente función:

int feof (FILE * stream); fscanf requiere de tres parámetros:

el puntero, el formato de las variables


que va a leer del archivo y dichas
La función feof indica si se ha llegado al final del archivo. Retorna un valor distinto de cero variables (no olvidar el &).
si se alcanzó fin de archivo y cero en caso contrario.

Cada vez que se abre el


archivo, se debe cerrar con
fclose.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 3 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 4
Guía de ejercicios

1. Generar un vector de 30 números enteros y crear un archivo con los números pares.
Mostrarlo y mostrar el registro número 3.

2. Crear un archivo con:

‐ Código de artículo.
‐ Cantidad de artículos.
‐ Precio unitario.
 Generar un vector con el precio total por artículo.
 Mostrar el código de artículo con más cantidad.

3. Generar una matriz de 4*4 con números enteros. Calcular en forma recursiva cuántos
números primos hay y cargarlos en un archivo. Mostrar dicho archivo.

4. Generar una matriz de n*n con números enteros. Mostrarla. Generar un archivo con la
suma de los dígitos de cada número de la matriz.

5. Ingresar un texto caracter a caracter terminado en enter o punto. Generar un archivo


con dicho texto separando con tres blancos cada una de las palabras.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1


último nodo, se continua con el primero y, si se llega al primer nodo, se puede pasar al
Listas doblemente enlazadas, listas circulares, último.

multilistas
Multilistas
Introducción Una lista puede tener, como elemento, otra lista. Por ejemplo: se lee un archivo de texto

A veces es conveniente efectuar algunas modificaciones en la implementación de listas (solo palabras) y se quiere clasificar las palabras por su longitud, para luego efectuar

para facilitar ciertas operaciones sobre ellas. Además, podemos tener algunas cuyos ciertas estadísticas. Como máximo, una palabra puede tener 30 letras. Podríamos hacer

elementos posean, a su vez, otras listas enlazadas. En este módulo se verán algunas de un arreglo de 30 listas de palabras, pero desperdiciaríamos memoria. Entonces, es

esas variantes. conveniente hacer una lista ordenada por tamaño de las palabras y que cada elemento de
esa lista tenga las palabras de ese tamaño.

Al liberar memoria de la lista habrá que recorrer cada nodo de la lista principal y liberar
Listas doblemente enlazadas
cada lista que se encuentra ahí. En el ejemplo anterior, por cada tamaño libero su lista de
Si es necesario recorrer una lista en sentido directo y, luego, en sentido inverso es palabras y luego libero el nodo de ese tamaño.
conveniente que todo nodo tenga un puntero al anterior, además de tener un puntero al
siguiente. Dicha implementación de listas se conoce como listas doblemente enlazadas.
Estructura de una multilista

Supongamos que queremos guardar los vuelos de distintas aerolíneas. En la lista principal
guardaremos el nombre de la aerolínea y, para cada aerolínea, se almacenará el destino
del vuelo, la hora de partida y la hora de llegada. Definimos dos estructuras de la siguiente
manera:

typedef struct aerolínea


{ Se define un nuevo
char nombreA[40];
struct aerolinea *sig; puntero a la estructura
struct vuelos *v;
}nodoA;
vuelos.
Listas circulares simplemente enlazadas
typedef struct vuelos
Se caracterizan porque el último elemento apunta al primero. Dicha implementación de {
listas se conoce como listas doblemente enlazadas. char destino[20];
char horA[8];
char horP[8];
struct vuelos *sigV;
Listas circulares doblemente enlazadas }nodoV;

Permiten un recorrido en sentido horario y antihorario de toda la lista. La estructura es la


de una lista doblemente enlazada, pero implementada de tal manera que, al llegar al

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
Crear y mostrar una multilista c)

Introducción
Los pasos para crear una multilista son:

a) Definir las estructuras necesarias.


b) Reservar memoria en el programa principal para un nodo de la lista principal.
c) Desarrollar una función para ingresar los datos de la lista principal.
d) Dentro de esta función, desarrollar otra función para ingresar los datos de la lista.

Veamos un ejemplo: se necesita generar una mulilista con los nombres de listas de
reproducción y los nombres de cada una de las canciones de esas listas.

a) Definimos las siguientes estructuras:

d)

b)

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
Para mostrar la mulitlista, primero mostramos el nodo de la lista principal (en este caso el
nombre de la lista de reproducción) y, luego, todas las canciones de esta lista para
después pasar al nombre de la siguiente lista de reproducción y así sucesivamente.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 3


Puntero a Puntero Se define una variable q
como doble puntero a
un entero
Concepto

Como vimos en módulos anteriores un puntero es una variable que apunta a otra, El puntero p toma la
fácilmente podemos deducir que pueden existir punteros a punteros, y a su vez los dirección de la variable
segundos pueden apuntar a punteros, y así sucesivamente. Estos punteros se declaran a y el puntero q toma
colocando tantos asteriscos (‘*’) como sea necesario. Para especificar que una variable es el valor del puntero p,
un puntero a un puntero, la sintaxis que debemos utilizar es la siguiente: es decir 10
Tipo **variable;

donde Tipo especifica el tipo de dato apuntado después de una doble indirección. ¿Pero
qué es una doble indirección? Veamos el siguiente ejemplo:
El puntero q toma el contenido de la
int a, *p, **pp;
variable a. Esto es, la dirección de memoria
a=10;
donde se almacenó a (&a) ,*(&a) toma el
p=&a; //Puntero que apunta al dato contenido de a.

pp=&p; //Puntero que apunta al puntero que a la vez apunta al dato


*p mostrará 20 porque
p apunta a la variable a
Decimos que p es una variable con un solo nivel de indirección, es decir, a través de p no y esta se actualizó.
accedemos directamente al dato, sino a la dirección que indica donde está el dato. **q mostrará 20
Haciendo un razonamiento similar, diremos que pp es una variable con dos niveles de
indirección.

Veamos el siguiente código:


A partir de ahora en muchos códigos utilizaremos punteros a punteros.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
Colas Pilas

Introducción Introducción
Una cola (queue) es una colección de elementos ordenada cronológicamente. Cada Una pila (stack) es una colección de elementos ordenada por orden de llegada. los
elemento se ubica detrás del anterior. El primero en ser utilizado es el que primero llegó. El elementos se añaden o quitan por la parte superior de la pila (la cima o tope). El último
primer elemento en entrar es el primero en ser eliminado o utilizado. Por eso estas elemento en entrar es el primero en ser eliminado. Por eso estas colecciones se denominan
colecciones se denominan FIFO (First In, First Out). LIFO (Last In, First Out).

Las aplicaciones de una cola son muy frecuentes en la vida diaria y en las ciencias de Las aplicaciones de una pila son muy frecuentes en la vida diaria y en las ciencias de
la computación. En la vida diaria, hacemos cola para el colectivo, en el banco, en el cine. En la computación: una pila de platos, las llamadas a funciones se manejan con una pila en
sistemas se manejan colas de impresión, colas de procesos, etc. memoria, los compiladores usan pilas para evaluar las expresiones, etc.

Implementación mediante listas simplemente enlazadas. Implementación mediante listas simplemente enlazadas.
Las colas se pueden implementar con arreglos o con listas implementadas con Las pilas se pueden implementar con arreglos o con listas implementadas con
punteros. Realizaremos esta última implementación. punteros. Realizaremos esta última implementación.

Los elementos que se pueden almacenar en una cola pueden ser de cualquier tipo. Los elementos que se pueden almacenar en una pila pueden ser de cualquier tipo.

La inserción de un elemento en la cola se la denomina ENCOLAR o ENQUEUE. En definitiva, trabajaremos con un caso particular de lista: una lista de elementos donde la
inserción y la eliminación se hace siempre por el mismo lugar.
La eliminación de un elemento de la pila se la denomina DESENCOLAR o DEQUEUE
La inserción de un elemento en la pila se la denomina APILAR o PUSH.
La observación (sin eliminación) del primer elemento de la cola la denominaremos
La eliminación de un elemento de la pila se la denomina DESAPILAR o POP.
PRIMERO o FIRST.
La observación (sin eliminación) del elemento superior de la pila la denominaremos
Para lograr una implementación eficiente, debemos poder acceder fácilmente al
TOPE o TOP.
lugar de inserción, y también fácilmente obtener el próximo elemento a eliminar.

Para ello, utilizaremos dos punteros: uno al inicio de la cola (apunta al primero a
eliminar) y otro al último (apunta al último elemento de la cola) Ejemplo:

Vacía:

MiPila = NULL

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 3
Guía de Ejercicios Guía de Ejercicios

Pilas y Colas Pilas y Colas


Para los siguientes ejercicios crear una pila con la siguiente información: Para los siguientes ejercicios crear una pila con la siguiente información:

A: entero. A: entero.

SIG: puntero al próximo elemento de la pila. SIG: puntero al próximo elemento de la pila.

y calcular:

1) La cantidad de números múltiplos de 3. 1) Desarrollar un programa que permita dado un entero N, asignar el valor I al
2) El promedio de aquellos números divisores de 4. elemento N-ésimo desde la parte superior de la pila, volviendo a dejar los N-1
3) La sumatoria de aquellos números múltiplos del primer elemento ingresado a la pila. elementos inferiores donde se encontraban.
4) El número máximo y su posición en la pila.
5) El número mínimo y su posición en la pila.
2) Desarrollar un programa que permita eliminar el nodo que contenga la información
6) Ingresar un numero por teclado y calcular la cantidad de veces que está en la pila.
Z de la pila.
Si no está, mostrar una leyenda.

3) Desarrollar un programa que permita invertir los elementos de la pila.


Para los siguientes ejercicios crear una cola con la siguiente información:

A: entero. 4) Desarrollar un programa que permita dadas dos pilas, concatenarlas eliminando los
SIG: puntero al próximo elemento de la cola. elementos repetidos.

y calcular:

1) La productoria de los números múltiplos de 7.


2) El promedio de aquellos números divisores del último número ingresado a la cola
3) Sumatoria de aquellos números divisores de primer elemento ingresado a la cola.
4) El número máximo y su posición en la cola.
5) El número mínimo y su posición en la cola.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1
Para los siguientes ejercicios crear una cola con la siguiente información:

A: entero.

SIG: puntero al próximo elemento de la cola.

1) Desarrollar un programa que permita eliminar el nodo que contenga la


información W de la cola.

2) Desarrollar un programa que permite agregar el número T a la cola (considerar que


la cola está ordenada ascendentemente).

3) Desarrollar un programa que permita invertir los elementos de la cola.

4) Desarrollar un programa que dada la cola A, ordenada descendentemente, generar


a partir de ella dos colas B y C. B contiene los elementos impares de A y C contiene
los elementos pares de A. B deberá ordenarse descendentemente y C
ascendentemente.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2


‐ Árbol B+
Árboles
En este módulo en particular, solo estudiaremos los árboles binarios de búsqueda.

Los árboles binarios tienen, por cada nodo, como máximo dos hijos a los que llamaremos
Introducción
subárbol izquierdo y subárbol derecho.
Un árbol (tree) es una estructura no lineal que se presenta tanto en la vida cotidiana como
Un árbol binario de búsqueda es aquel en el que, para cualquier nodo, su valor es mayor
en la ciencia de la computación: árboles genealógicos, árbol de búsqueda, árbol de juegos,
que los valores de los nodos en su subárbol izquierdo y menor que los valores de los
un organigrama. Es una estructura no lineal que parte de un primer elemento, llamado
nodos en el subárbol derecho.
raíz, y luego se “ramifica” en dos o más líneas. Un árbol es un conjunto de nodos y líneas
(grafo). Cada nodo contiene información.
Implementación mediante listas simplemente enlazadas.

Características de los árboles Los árboles binarios se pueden implementar con arreglos o con estructuras enlazadas con
punteros. Realizaremos esta última implementación.
Los árboles tienen las siguientes propiedades:
Cada nodo tendrá la siguiente estructura:
‐ Existe un nodo distinguido llamado raíz.
‐ Todos los nodos, excepto la raíz, tienen una sola línea de entrada.
‐ Si hay una ruta de a a b, entonces b es hijo de a. typedef struct Arbol{
‐ Los nodos que no tienen hijos (nodos terminales) se llaman nodos hoja. int clave;
‐ El grado de un nodo es la cantidad de hijos que tiene. struct nodoArbol *izq;
struct nodoArbol *der;
‐ La fila en que reside un nodo es su nivel.
‐ La altura de un árbol es la cantidad de líneas en una ruta que empieza en la raíz y } *nodoarbol;
termina en el nodo más lejano. Un árbol que solo tiene un nodo (el raíz) tiene altura 0.

Con respecto al recorrido, como es una estructura no lineal, hay distintas maneras de
Tipos de árboles recorrer el árbol:
Hay distintos tipos de árbol:  en orden:
 Binario: todos sus nodos tienen como máximo dos hijos. ‐ Se recorre el subárbol izquierdo.
‐ binario de búsqueda.
‐ Se lee la raíz.
‐ binario de expresión. ‐ Se recorre el subárbol derecho.
‐ binario equilibrado.  en preorden:
‐ AVL. ‐ Se lee la raíz.
 Árbol B: pueden tener tres o más hijos cada nodo. ‐ Se recorre el subárbol izquierdo.
‐ Árbol B* ‐ Se recorre el subárbol derecho.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
 en postorden:
‐ Se recorre el subárbol izquierdo. Guía de ejercicios
‐ Se recorre el subárbol derecho.
‐ Se lee la raíz.
1. Diseñar una función que, dado un árbol binario y un valor, determine si el valor
pertenece al árbol.

2. Diseñar una función que, dado un árbol binario, calcule su cantidad de nodos.

raíz
3. Diseñar tres funciones para el recorrido de un árbol binario (pre orden, orden y post
8 orden).

4. Diseñar una función que, dado un árbol binario de búsqueda, calcule el promedio de
aquellos nodos múltiplos de la raíz.

5. Diseñar una función que, dado un árbol binario de búsqueda, calcule la cantidad de
nodos hojas divisores de la raíz.
6 12
6. Diseñar una función que, dado un árbol binario de búsqueda, calcule la sumatoria de
aquellos nodos pares con un solo hijo.

7. Diseñar una función que, dado un árbol binario de búsqueda, calcule la cantidad de
nodos impares con dos hijos.

10 13

Ingresó: 8, 6, 12, 10, 13

Pre order: 8, 6, 12, 10, 13

In order: 6, 8, 10, 12, 13

Post order: 6, 10, 13, 12, 8

Muy importante: El orden en que se ingresan los valores determina la forma del árbol.

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 3 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1
Ejercicio: Modelo de Parcial
Dada:

Lista

Num (int) sig (puntero)

Se pide:

a) Crear y mostrar la lista. Termina con num=1000.


b) Generar otra lista con aquellos números múltiplos de 3. Mostrarla

c) Si la suma de nodos consecutivos de la lista original es mayor a 20 agregar


adelante del primer nodo (que se suma) un nodo con num=0.
Si la suma de nodos consecutivos es menor a 10 eliminar el segundo nodo que
se suma.

Mostrar la lista.

Nota: Usar funciones con parámetros.

No usar banderas.

No usar salidas abruptas de los ciclos de repetición

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1


Ejercicio: Modelo de Parcial
Dada:

Lista

Num (int) sig (puntero)

a) Crear y mostrar la lista con números enteros. Termina con num=-2.


b) Insertar en otra lista los números impares. Mostrarla.
c) Eliminar todos los valores menores al promedio de la lista original en la lista de
números impares. Mostrarla

Ejemplo:

Lista original:

5 7 14 6 2 9 3 21 3 6 2 4 8
Nueva Lista:

5 7 9 3 21 3

Promedio: 6

Lista Modificada

7 9 21

Nota: Usar funciones con parámetros.

No usar banderas.

No usar salidas abruptas de los ciclos de repetición

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1


Se pide:
Ejercicio: Modelo de Parcial a) Crear y mostrar las 2 listas.
b) Insertar los nodos necesarios para completar cada polinomio.
c) Generar otra lista que contenga la suma de los dos polinomios.
Se ingresan los coeficientes y potencias de un polinomio a la lista 1 d) Eliminar del polinomio suma los nodos cuya coeficiente sea a cero.

Lista 1
Ejemplo:

Ingreso:

coeficiente (int) sig (puntero)

potencia (int)

• La lista termina cuando la potencia es -1


• Los datos se ingresan ordenados por potencia de mayor a menor
• No es necesario que el polinomio esté completo..
Se ingresan los coeficientes y potencias de otro polinomio a la lista 2

Lista 2

coeficiente (int) sig (puntero)

potencia (int)

• La lista termina cuando la potencia es -1


• Los datos se ingresan ordenados por potencia de mayor a menor.
• No es necesario que el polinomio esté completo..

Nota: Usar funciones con parámetros.

No usar banderas.

No usar salidas abruptas de los ciclos de repetición

© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2

También podría gustarte