Está en la página 1de 21

1227: ESTRUCTURA DE DATOS Y

ALGORITMOS I
1. Estructura de datos
1.1 Representación de datos en memoria.
1.1.A Cadenas y Funciones (Apéndice)

Durante este sección estudiaremos los diferentes tipo de funciones que se pueden
declarar en C, se describirán varios ejemplos para ilustrar su ventajas y reglas de uso.
Estudiaremos las cadenas de caracteres y cómo estas pueden manejarse como un
tipo de dato en C, así como algunas funciones de cadenas.

1
1.1.A Cadenas.
• Un string es un tipo de dato arreglo de tipo
char.
• Peculiarmente un string finaliza con un
carácter ’\0’, dicha característica la hace
diferente a cualquier arreglo de caracteres
común.

Una cadena de caracteres, también llamada string, son un tipo de dato vector o
arreglo de tipo primitivo char. Peculiarmente un string finaliza con un carácter ’\0'.

La diferencia entre un vector y una cadena, es que una cadena siempre termina con
el símbolo '\0' carácter nulo. Por lo tanto el tamaño del arreglo que almacena una
cadena es mayor que es de un arreglo que almacena un vector.

Debemos tener en cuenta el tamaño de la cadena para poder iterar sobre ella.

2
1.1.A Cadenas.
• Declaración de una cadena:
– char saludos[] = "Hello";

Cuando se declara una cadena se genera un conjunto de localidades en memoria


contigua para almacenar cada carácter de la cadena, incluso el carácter final nulo.

3
1.1.A Cadenas.
• Forma alternativas de declaración:

– char cadena[]="Hola";
– char otra_cadena[]={'H','o','l','a','\0'};
– char vector[]={'H','o','l','a'};
– char espacio_cadena[1024]="Una cadena en C";
– char cadena_vacia[]="”;

Existen varias forma de inicializar un string en C. Las siguientes son algunas formas
posibles:

char cadena[]="Hola";
char otra_cadena[]={'H','o','l','a','\0'}; // Igual al anterior
char vector[]={'H','o','l','a'}; /* Un vector de 4 elementos, con los elementos 'H','o','l' y
'a' */
char espacio_cadena[1024]="Una cadena en C";
char cadena_vacia[]="";

4
1.1.A Cadenas.
• ¿Cómo podemos saber el tamaño o longitud de
una cierta cadena?

int largo_cadena(char cadena[])


{
int largo=0
while (cadena[largo]!='\0') largo++;
return largo;
}

¿Cómo podemos saber la longitud que tiene una cadena?

El siguiente código implementa una función que obtiene el tamaño de una cadena.

/* devuelve la cantidad de caracteres en cadena sin contar el '\0' */


int largo_cadena(char cadena[])
{
int largo=0
while (cadena[largo]!='\0') largo++;
return largo;
}

5
1.1.A Cadenas.
• Existen muchas operaciones entre cadenas, una muy común
es la concatenación de dos de ellas.
bool unir_cadenas(char destino[], char origen[], int largo)
{
int largo_origen = largo_cadena(origen);
int largo_destino = largo_cadena(destino);
if ( largo_origen+largo_destino+1 > largo ) {
return false;
}
for (int i=0; i<largo_origen;i++) {
destino[largo_destino+i] = origen[i];
}
destino[largo_destino+largo_origen]='\0';
return true;
}

Una operación usual entre cadenas es su unión, es decir, dadas dos cadenas st1 y st2
quiero generar una tercer cadena st3 que contenga la concatenación de las dos
anteriores.

bool unir_cadenas(char destino[], char origen[], int largo)


{
int largo_origen = largo_cadena(origen);
int largo_destino = largo_cadena(destino);
if ( largo_origen+largo_destino+1 > largo ) {
return false;
}
for (int i=0; i<largo_origen;i++) {
destino[largo_destino+i] = origen[i];
}
destino[largo_destino+largo_origen]='\0';
return true;
}

6
1.1.A Cadenas.
• C nos permite usar una biblioteca llamada <string.
h> para el uso y operaciones con cadenas.

– strlen(cadena)
– strcpy(destino, origen)
– strcat(destino, origen)
– int resultado = strcmp(cadena1, cadena2)
– int posicion = strchr(cadena, carácter)
– int posicion = strstr(cadena,subcadena)

C nos permite usar una biblioteca llamada <string.h> en la cual se implementan


muchas funciones específicas con cadenas. Por ejemplo:

strlen(cadena) // Para obtener el largo de una cadena


strcpy(destino, origen) // Copia el contenido de origen en destino
// destino debe ser lo suficientemente grande
strcat(destino, origen) // Agrega el contenido de origen al final de destino
// destino debe ser lo suficientemente grande
int resultado = strcmp(cadena1, cadena2) // Compara dos cadenas
// devuelve un valor menor, igual o
mayor que 0 según si cadena1 es menor,
// igual o mayor que cadena2,
respectivamente.
int posicion = strchr(cadena, caracter) // Devuelve la posición en memoria de la
primer
// aparición de caracter dentro de cadena
int posicion = strstr(cadena,subcadena) // Devuelve la posición en memoria de la
primer
// aparición de subcadena dentro de
cadena

7
1.1.A Cadenas.
• Existen varias forma de leer cadenas de
teclado.
– gets(char *s)
– scanf(format_scan, direccion_memoria)
– fgets(char *s, int n, FILE *stream)

Standard file File pointer Device

Standard input stdin Keyboard


Standard output stdout Screen

Standard error stderr Your screen

Existen varias forma de leer una cadena desde teclado, a continuación se describen
tres de las más usuales.

gets(char *s) - Lee una línea de stdin y asigna el apuntador s a dicha línea.
scanf(format_scan,localidad_memoria) - Lee una línea de stdin y la mapa de acuerdo
al formato especificado almacenando en las variables especificadas por su dirección.
fgets(chat *s, int n, FILE *stream) - Lee una línea del archivo de entrada especificado,
ajustando al tamaño indicado n, cuya cadena es apuntada con s.

8
1.1.A Funciones.
• Son fragmentos de código que tienen como
objetivo en común resolver un problema
específico.
• Las funciones generalmente regresan un
resultado y vuelven al punto del código donde
fueron invocadas.
• Todo programa tiene al menos una función.

Las funciones son fragmentos de código que tienen como objetivo resolver un
problema (o sub problema) específico dentro de un programa. Después de ejecutar
su tarea, las funciones generalmente regresan un resultado y vuelven al punto del
código donde fueron invocadas.

Una función es también es a veces llamada subrutina, procedimiento o métodos.


Todo programa tiene al menos una función, es decir al menos un main().

9
1.1.A Funciones.
• Toda función agrupa código que ejecute una
cierta tarea para lograr un objetivo común.
• Permiten reusar código, podemos usar una
función como caja negra para resolver muchas
instancias de ese mismo problema.

Es recomendable separar el código de un programa en el número de funciones que


sea necesaria, el criterio de separación debe ser tal que toda función agrupe todo
código que ejecute una cierta tarea para lograr un objetivo o sub objetivo en común.

Las funciones también permiten reusar código, debido a que una función resuelve un
cierto problema entonces podemos usar dicha función como caja negra para resolver
muchas instancias de ese mismo problema.

10
1.1.A Funciones.
• Una variable de función o local solo vive en
memoria durante la invocación de la función que
la contiene.
• La sintaxis en C para declarar e implementar una
función es la siguiente:

[tipo_dato_respuesta] nombre_función ([lista_parámetros]){


//código para resolver cierto problema
}

Toda variable que es declara dentro de una función solo puede ser accedida por
cualquier línea de código dentro de esta misma función. Una variable de función o
local solo vive en memoria durante la invocación de la función que la contiene, una
vez que la función termine su ciclo de vida y regrese un resultado la variable será
eliminada de memoria.

La sintaxis en C para declarar e implementar una función es la siguiente:

[tipo_dato_respuesta] nombre_función ([lista_parámetros]){


//código para resolver cierto problema
}

11
1.1.A Funciones.
• Puede tomar como entrada un conjunto (que
puede ser vacío) de variables.
• Puede regresar (o no) una sola variable de un
tipo de dato como respuesta.

Tipo de funciones
Sin respuesta (void) Sin parámetros (void)
Con respuesta (tipo de dato) Sin parámetros (void)
Sin respuesta (void) Con parámetros (lista)
Con respuesta (tipo de dato) Con parámetros (lista)

Una función puede tomar como entrada (o parámetros) un conjunto (que puede ser
vacío) de variables. Y puede regresar (o no) una sola variable de un tipo de dato como
respuesta.

En el caso de que una función regrese un resultado, éste debe ser de uno de los tipos
de dato primitivo o compuesto con excepción de arreglos y funciones. Además en
cada final de todos los posibles flujos de la función debe haber una instrucción return
tipo_dato_resultado. Una vez que la función termina, el dato que será retornado
debe ser almacenado en una variable del mismo tipo. En caso de que una función no
regrese un resultado entonces, debe declararse como una función de tipo void y no
es necesario especificar una instrucción return dentro del código de la función.

Una función puede o no tener parámetros de entrada. En caso de tenerlos, estos


deben ser especificados entre paréntesis a continuación del nombre de la función, los
parámetros pueden ser de diferentes tipos de datos. En caso de que una función no
tenga parámetros de entrada, puede indicarse con void entre los paréntesis de la
función o simplemente dejar vacía la lista de parámetros.

12
1.1.A Funciones.
• Ejemplo de uso de funciones:
float suma(float a, int b){
return a+b;
}
void salto_linea(void){
printf("\n");
}
int main(){
float r=suma(1.5,2);
salto_linea();
}

El siguiente es un ejemplo declara e implementa dos funciones. La primera hace la


suma de dos números, uno entero y el uno flotante. El resultado es devuelto como un
número flotante. La segunda función es una de tipo void, por lo tanto no regresa
resultado alguno, solo ejecuta un salto de línea en la consola.

float suma(float a, int b){


return a+b;
}
void salto_linea(void){
printf("\n");
}
int main(){
float r=suma(1.5,2);
salto_linea();
}

13
1.1.A Funciones.
• Un parámetro puede ser enviado a una
función de dos formas diferentes:
– por valor
– por referencia/apuntador.

Un parámetro puede ser enviado a una función de dos formas diferentes:

Como paso de parámetro por valor o por referencia/apuntador.

La diferencia radica en que una parámetro por valor toma, como tal, solo el valor de
una variable mismo que es manipulado durante la ejecución de la función, pero no
altera para nada el contenido de la variable original. Mientras que por
referencia/apuntador, el contenido de dicha variable será modificado en cualquier
instrucción que ejecute la función, por lo tanto al terminar la invocación de ésta
podremos ver reflejado su correspondiente valor directamente en la variable original.

14
1.1.A Funciones.
int f1(int a){
a=a+10;
return a;
}

int f2(int *a){


*a=*a+10;
return *a;
}

int main(){
int n1=10,n2=0;
n2=f1(n1);
printf("Por valor: n1:%i, n2:%i\n",n1,n2);
n2=f2(&n1);
printf("Por apuntador: n1:%i, n2:%i\n",n1,n2);
}

El siguiente código ejemplifica ambos casos de paso de parámetros:

int f1(int a){


a=a+10;
return a;
}

int f2(int *a){


*a=*a+10;
return *a;
}

int main(){
int n1=10,n2=0;
printf("Valores iniciales n1:%i, n2:%i\n",n1,n2);

n2=f1(n1);
printf("Por valor: n1:%i, n2:%i\n",n1,n2);

n2=f2(&n1);
printf("Por apuntador: n1:%i, n2:%i\n",n1,n2);

return 0;

15
}
1.1.A Funciones.
• Algunas funciones implementadas en
bibliotecas de C, ayudan a realizar tareas
comunes:
– sizeof()
– strcat()
– printf()

Las bibliotecas de C habilitan muchas funciones que aceptan y devuelven diferentes


parámetros de acuerdo a la tarea que ejecutan. Por ejemplo la función sizeof(par),
toma como parámetro un tipo de dato y devuelve el número de bytes que dicho
parámetro usa en memoria. strcat(par1, par2), toma como parámetros dos cadenas y
devuelve la concatenación de ellas.

17
1.1.A Funciones.
• Las funciones deben al menos declararse antes de
que sean invocadas, de lo contrario el compilador
arrojará un error.
• Es posible declarar una función sin
implementarla, y posteriormente realizar la
implementación correspondiente.

• Sintaxis:
[tipo_dato_respuesta] nombre_función ([lista_parámetros]);

Las funciones deben al menos declararse antes de que sean invocadas, de lo


contrario el compilador no habrá definido el comportamiento de dicha función. Es
posible declarar una función sin implementarla, y posteriormente en el código
realizar la implementación correspondiente.

A continuación se presenta la sintaxis de declaración de una función sin


implementación:

[tipo_dato_respuesta] nombre_función ([lista_parámetros]);

El siguiente código ejemplifica el concepto anterior de declaración sin


implementación de una función:

float multi(float n1, float n2);

int main(){
float res=multi(3.7,7.1);
printf("%f",res);
return 0;
}

float multi(float n1, float n2){

18
return n1*n2;
}
1.1.A Funciones.
• Existen funciones con un número variable de
parámetros, por ejemplo printf().
• Es preferible que una función acepte un
apuntador de arreglo o una estructura.
• En caso necesario se puede hacer con:
– stdarg.h
– [tipo_dato] nombre_funcion (tipo_dato n_args, ...);

Existen funciones con un número variable de parámetros, por ejemplo la función


printf(), recibe una cantidad de parámetros variables de acuerdo a la cantidad de
datos que el programador quiera imprimir en consola. No es común que una función
definida por el usuario acepte una cantidad de parámetros variables, en ese caso es
preferible que una función acepte un apuntador de arreglo (cuyo tamaño puede ser
arbitrario) o una estructura.

Una función de argumentos variables se puede definir con ayuda de la biblioteca


stdarg.h. La siguiente sintaxis describe la declaración de una función de este tipo:

[tipo_dato] nombre_funcion (tipo_dato n_args, ...);

20
1.1.A Funciones.
• Dentro de una función x() podemos llamarla a ella misma, a
esto se le denomina recursión.

void f_recursiva(){
printf("Hola recursivo");
f_recursiva();
}

int main(){
f_recursiva();
return 0;
}

Dentro de una función x() podemos llamarla a ella misma, a esto se le denomina
recursión. Debemos tener cuidado con las invocaciones recursivas de una función
porque esto puede provocar problemas en memoria stack, o puede generar loops
infinitos.

void f_recursiva(){
printf("Hola recursivo");
f_recursiva();
}

int main(){
f_recursiva();
return 0;
}

La recursión es una herramienta poderosa que puede emplearse para resolver


muchos problemas, pero debe ser usada con mucho cuidado.

21

También podría gustarte