Está en la página 1de 35

PUNTEROS A

CARÁCTER
INTEGRANTES:
DANIEL FERNANDO SALAZAR PÉREZ
JUAN FELIPE GUARÍN GALVIS
OSCAR FABIAN NUCHE SIACHOQUE

AREA:
ALGORITMOS Y PROGRAMACIÓN
5.1
INTRODUCCIÓN
El lenguaje de programación C no provee un tipo de datos que permita definir cadenas o
string. Las cadenas se implementan sobre arrays de caracteres, pero, como arrays es un
tema que analizaremos más adelante, intentamos restarle importancia haciendo hincapié
en el hecho de que un array es un “conjunto” de variables del mismo tipo de datos por lo
que un array de caracteres representa a un conjunto de variables de tipo char.

5,2 CONCEPTOS INICIALES

A la introducción anterior, le agregaremos el siguiente dato: las variables o elementos del


array tienen direcciones de memoria consecutivas. Según esto, un array representa la
dirección de memoria del primer elemento de un conjunto de variables del mismo tipo cuyas
direcciones son consecutivas y, en particular, un char[] representa la dirección del primer
carácter de una serie de variables de tipo char con direcciones de memoria consecutivas. Es
decir que un char[] encaja (matchea) perfectamente en un char* y lo probaremos a
continuación.
5.2 CONCEPTOS
INICIALES
La salida de este programa será la
siguiente:
x = Esta es una cadena
x[3] = a
x = Esta es una cadena
x[3] = a

En el código del programa anterior,


verificamos que char[] matchea con char*.
Tanto recibeArray como recibePuntero
pueden recibir un char[].

Fig. 5.1
5.2.1 ARITMÉTICA DE
DIRECCIONES
Como el identificador de una cadena es equivalente a la dirección de memoria del primero de sus
caracteres y las direcciones de los caracteres subsiguientes son consecutivas entonces la dirección el i-
ésimo carácter se puede calcular sumando el valor entero i a dicho identificador.

Es decir, sea la variable a defi nida e inicializada de la siguiente manera:

char a[] = "Esto es una cadena"; a representa a la dirección de memoria del primer carácter de la
cadena, a+1 hace referencia a la dirección del segundo carácter y a+i hace referencia a la dirección de
memoria del carácter ubicado en la posición i.
5.2.1 ARITMÉTICA DE
DIRECCIONES
En el siguiente programa, definimos la cadena a e imprimimos algunas de las subcadenas que obtenemos luego de
sumarle valores enteros a su identificador.
5.2.2 PREFIJOS Y
SUFIJOS

Decimos que la cadena p es prefijo de la cadena x si los primeros caracteres de x coinciden con
todos los caracteres de p. Análogamente, diremos que la cadena s es sufijo de la cadena x si
los últimos caracteres de x coinciden con la totalidad de los caracteres de s.

Por ejemplo, sean las cadenas x, p y s definidas e inicializadas de la siguiente manera:

char x[] = "Esto es una cadena";


char p[] = "Es";
char s[] = "dena";

Según lo expuesto más arriba, p es un prefijo de x y s es un sufijo. Otros prefijos de x podrían ser:
“Esto”, “E”, “Esto es una”.
Otros sufijos de x serían: “cadena”, “a”, “na”, etcétera.
5.2.2.1 DETERMINAR SI UNA CADENA
ES PREFIJO DE OTRA (función
esPrefijo)
Desarrollaremos una función para determinar si una cadena es prefijo de otra.
La función esPrefijo recibirá dos cadenas x y p, y retornará true o false según p sea o no prefijo de
x.
Análisis: Si la cadena p es prefijo de la cadena x entonces x debe comenzar con una secuencia de
caracteres idéntica a p y su longitud debe ser mayor o igual que la longitud de p. Veamos
5.2.2.1 DETERMINAR SI UNA CADENA
ES PREFIJO DE OTRA (función
esPrefijo)
Para programarla utilizaremos la función de biblioteca strncmp que es análoga a la función
strcmp, pero recibe un parámetro extra que indica cuántos caracteres queremos comparar

Como n contiene la longitud de p la


función strncmp comparará los
primeros n caracteres de x con la La salida será:
totalidad de los caracteres de p. [Es] es prefijo de [Esta cadena]?
5.2.2.2 DETERMINAR SI UNA CADENA
ES SUFIJO DE OTRA (función
esSufijo)
Esta función recibirá dos cadenas: x y s y retornará true o false según s sea o no sufijo de x. Para
programarla, utilizaremos la función de biblioteca strcmp para comparar s con los últimos n
caracteres de x, siendo n la longitud de s.

Supongamos que x es “Esta cadena” y s es “na” entonces, si llamamos n a la longitud de s


podemos hacer referencia a los últimos n caracteres de x de la siguiente forma: x+strlen(x)-n que,
según nuestro ejemplo, será: x+11-2.
5.2.2.2 DETERMINAR SI UNA CADENA
ES SUFIJO DE OTRA (función
esSufijo)
Veamos el código de la función y luego un programa que la invoca

En este caso, invocamos a strcmp para


comparar la cadena s con la subcadena de x
comprendida entre el carácter desde y el ‘\
0’. La salida será:
[na] es sufijo de [Esta cadena]?
5.3 FUNCIONES QUE RETORNAN CADENAS

En C las funciones no pueden retornar arrays, por lo


tanto, seria incorrecto definir una función como la
siguiente:

//ERROR, el valor de retorno de una función no puede ser un


array

char [ ] obtenerSaludo ( ) ;

La forma correcta de definir la función anterior es:


Char* obtenerSaludo ( ) ;
La función obtenerSaludo retorna un puntero al
primer carácter de una serie de caracteres con
direcciones de memoria consecutivas donde,
además, el ultimo será ‘\0’.
Sin embargo, todavía tenemos un problema y lo
analizaremos con la siguiente implementación
errónea de la función obtenerSaludo.
5.3.1 La función malloc
La función malloc, definida en el archivo “stdlib.h”,
permite direccionar n bytes consecutivos de
memoria siendo n un entero que le pasamos como
argumento.
En esta implementación de obtenerSaludo
invocamos a la función malloc para crear
dinámicamente un char [ ] de n+1 caracteres,
donde n es la longitud de la cadena que
queremos retornar mas 1 para el caracter ‘\0’.
5.3.2 Subcadenas (función substring)
Dada la cadena a definida de la siguiente manera: char
a [ ] = "Esto es una cadena";

Llamamos “subcadena” a todo subconjunto de sus caracteres siempre y


cuando estos sean consecutivos y mantengan el orden
original.
Por ejemplo:
-“Esto es”
- “una cadena”,
- “es”
-“a cad”,
- “Est”,
-“dena”,
- “es una”,
- “Esto es una cadena”
Notemos que todos los prefijos y sufijos de una
son algunas de las subcadenas que podemos
cadena son también subcadenas de esta.
obtener a partir de a
Desarrollaremos la función substring que recibirá una cadena y dos enteros
indicando las posiciones desde y hasta (esta ultima será “no inclusive”) y retornara
la subcadena compuesta por los caracteres comprendidos entre dichas posiciones
de la cadena original.
Por ejemplo:
• substring("Esto es una cadena",0,4) retorna “Esto”.
• substring("Esto es una cadena",8,11) retorna “una”.

La estrategia para resolver este algoritmo consistirá en calcular la


longitud de la subcadena que tenemos que retornar, dimensionar
dinamicamente un char [ ] de exactamente esa longitud (mas 1 para
incluir al carácter ‘\0’) y luego asignar, uno a uno, los caracteres de
la cadena original ubicados entre las posiciones desde y hasta-1.
Problema 5.1
Analizando el código del siguiente programa. .Cual es la diferencia que existe entre las cadenas
a y b?
5.3.2.1 Eliminar los espacios ubicados a la izquierda (función ltrim)

Definiremos la función ltrim cuyo objetivo será retornar una cadena idéntica a
la que reciba como parámetro, pero sin espacios en blanco a la izquierda. Por
ejemplo:

• ltrim(" Hola") retorna "Hola"


• ltrim("Hola ") retorna "Hola ".
El algoritmo consistirá en recorrer la cadena original mientras que
el i-ésimo carácter sea ' ' . Cuando el ciclo de repeticiones finalice
será porque i contiene la posición del primer caracter de la cadena
que resulte ser distinto de ' '. Entonces retornaremos la subcadena
comprendida entre i y la longitud de la cadena s que recibimos
como parámetro.
5.3.2.2 Eliminar los espacios ubicados a la derecha (función
rtrim)

Está función es análoga a la anterior solo que se debe retomar una cadena sin espacios en blanco a la
derecha.
La estrategia será recorrer la cadena comenzando desde atrás hacia adelante y mientras que
encontremos espacios. Luego retornaremos la subcadena comprendida entre las posiciones 0 e i+1
de la cadena original.
5.3.2.2 Eliminar los espacios ubicados a la derecha (función
rtrim)
5.3.2.3 Eliminar los espacios en ambos extremos de la
cadena (función trim)
Como ya desarrollamos las funciones
ltrim y rtrim para eliminar
respectivamente los espacios ubicados a
izquierda y a derecha de una cadena
podemos pensar ahora en desarrollar la
función trim para que retorne una cadena
idéntica a la que reciba como parámetro,
pero sin espacios en blanco en sus
extremos.
Esta función se programa fácilmente
retornando el ltrim(rtrim(s)) siendo s la
cadena que recibe como parámetro.
5.3.3 Función de biblioteca strtok

Sea la cadena s definida en la siguiente línea de código: char s[] = "Juan|Marcos|Carlos|Matias"; Si


consideramos como separador al carácter ‘|’ (léase “carácter paip”) entonces llamaremos token a las
subcadenas encerradas entre las ocurrencias de dicho carácter y a las sub cadenas encerradas entre
este y el inicio o el fin de la cadena.
Para hacerlo más simple, el conjunto de tokens que surgen de la cadena s considerando como
separador al carácter ‘|’ es el siguiente: tokens = { “Juan”, “Marcos”, “Carlos”, “Matias” }
5.3.3 Función de biblioteca strtok

Pero si en lugar de tomar como separador al carácter ‘|’ consideramos como separador al
carácter ‘a’ sobre la misma cadena s el conjunto de tokens será: tokens = { “Ju”, “n|M”, “rcos|
C”, “rlos|M”, “ti”, “s” }; Utilizando la función strtok podemos separar una cadena en tokens
delimitados por un separador. En el siguiente ejemplo, veremos cómo hacerlo:

Codigo Dev C++


5.3.3 Función de biblioteca strtok

Notemos strtok recibe como primer argumento la


cadena que debe tokenizar. Luego, en cada
invocación sucesiva, retorna el siguiente token.
Evidentemente, strtok utiliza variables estáticas que
le permiten recordar la cadena y cuál fue el token
que retornó en la última invocación. La constante
NULL defi nida en stdio.h representa el valor de
una dirección de memoria nula.
Programa anterior en el compilador

Aplicaremos las funciones de biblioteca strtok y atoi para desarrollar una nueva versión del problema del cambio, estudiado
en los capítulos anteriores, cuyo enunciado recordaremos a continuación.
Problema 5.2

Dado un valor entero que representa un sueldo a pagar, y un conjunto de


denominaciones,que representan los valores nominalesde los billetes
disponibles; informar qué cantidad de billetes de cada tipo se necesitará
utilizar para abonar dicho sueldo. Se debe dar prioridad a los billetes de
mayor denominación
Problema 5.2

Aprovecharemos la función strtok para


parsear (interpretar) una cadena que contenga
las denominaciones, separadas entre sí por un
carácter separador.
Veamos: char denominaciones[] = "100|50|20|
10|5|2|1"; Luego, tokenizando esta cadena
podremos acceder a cada una de las
denominaciones y aplicando atoi a cada token
tendremos cada uno de los valores nominales
listos para procesar
Problema 5.2
Si bien las denominaciones
continúan hardcodeadas en
nuestro programa, esta solución
es mucho más flexible y
extensible que las anteriores
porque, si se llegase a agregar
una nueva denominación o si
dejase de existir cualquiera de
las existentes bastará con aplicar
estos cambios en la cadena de
denominaciones.
GRACIAS POR SU ATENCIÓN…

También podría gustarte