[C con Clase] Ejercicio 12.1 curso web

Steven Davidson srd4121 en njit.edu
Jue Sep 16 18:43:52 CEST 2010


Hola Alejandro,

On 9/16/2010 7:05 AM, Alejandro Alcalde wrote:
> Hola,Me gustaria dejarles el ejercicio para que me digan si es
> correcto, ya que hubo cosas que no entendi, como 'En main probar con
> distintos tipos de cadenas: arrays y punteros.'
>

Te hacemos saber que puedes enviar los ejercicios del curso de C++ a 
nuestro apartado de correo-e: "ejercicioscpp en conclase.net" (sin las 
comillas). Esto es para dejar a los demás seguidores del curso presentar 
sus propios ejercicios sin tentaciones de copiarse de las 
implementaciones de otras personas.

En cuanto al enunciado, queríamos que invocaras la función, que debes 
crear, con cadenas de caracteres implementadas como arrays y como 
punteros. Por ejemplo,

const char szCadena[] = "hola mundo";

int n = lenCad( szCadena );
lenCad( szCadena+5 );
lenCad( szCadena + n/2 );
lenCad( szCadena + n-3 );

const char *pszCadena = &szCadena[3];
lenCad( ++pszCadena );

const char *pszCadena2 = "adios mundo";
lenCad( ++pszCadena );

y cualquier otra invocación que se te ocurra.

Veamos el código fuente.

> #include<iostream>
>
> using std::cout;
> using std::cin;
> using std::endl;
>
> int lenCad(char*);
>
> int main(int argc, char **argv)
> {
> 	char cad[] = {"Hola que tal"}, *punteroC=cad;

La inicialización no es correcta. Al usar las comillas, ya estamos 
usando un conjunto (array) de caracteres. Por lo tanto, no uses las 
llaves para esta inicialización.

También deberías cambiar el tipo de la cadena para que sean caracteres 
constantes. Esto es,

const char cad[] = "Hola que tal";

> 	
> 	int resul = lenCad(cad);
> 	cout<<  "La cadena tiene"  <<  resul<<  "  caracteres"  <<  endl;
> 	
> 	return 0;
> }
> //-------------------------------
> int lenCad(char* cad){

Deberías indicar que el tipo apuntado sea 'const char', ya que no 
tenemos intención alguna de modificar el contenido de la cadena.

> 	char* copia = cad;
> 	
> 	int i=0;
> 	while(*copia++) i++;
>
> 	return i;
> }
>

El enunciado del ejercicio dice que debes usar aritmética de punteros. 
Además, aquí usas un número entero para contar los caracteres, pero 
también usas una copia del puntero 'cad' que también avanzas. Ambas 
variables no son necesarias simultáneamente; o bien usas 'i' o bien usas 
'copia'.

Lo que pretendíamos es que se calcule la cantidad de caracteres usando 
solamente punteros. Te dejo que implementes este tipo de solución.

>
> Una ultima duda, me lio mucho con los punteros, y nose porque, si en
> el while pongo copia++ en vez de *copia++ entra en un bucle
> infinito.
>
> Creo que es porque con *copia++ estoy diciendo 'avanza uno en el
> contenido de copia, osea copia[1]', y con copia++, no avanzaria
> sizeof(char)??, osea, el siguente elemento del array?? :), siento
> rebuscar tanto la pregunta, pero es que estuve un tiempo sin ensayar
> con punteros, y ahora me cuesta volver a entenderlos.
>

En el caso de '*copia++' estás aplicando dos operaciones. En orden, 
hacemos el incremento póstumo (++) al puntero. Esto implica que 
agregamos 1 al contenido del puntero el cual es una dirección de 
memoria. Seguidamente, aplicamos el operador de acceso a memoria (*). 
Con esta operación conseguimos el carácter apuntado. En tu programa, 
este carácter se usa en una expresión condicional para el bucle 'while'. 
Si el código ASCII no es cero, entonces seguimos iterando. Esto indica 
que no hemos llegado al final de la cadena, ya que 0 representa el 
carácter nulo. Podemos reescribir el código manteniendo la secuencia de 
las operaciones para que lo veas con mayor claridad:

copia++;
while( *copia )
{
   i++;
   copia++;
}

En el otro caso de 'copia++', sólo estás incrementando el puntero, pero 
no accedes al carácter. Por lo tanto, para llegar a la dirección de 
memoria 0 (cero), seguramente tenemos que esperar muchísimas 
iteraciones, hasta que se dé la vuelta al número entero que es la 
dirección de memoria. Si se trata de una dirección de memoria de 32 
bits, entonces tenemos que esperar hasta llegar al máximo entero (sin 
signo) que sería 4294967295. Al sumar uno a este número, pasaríamos a 0, 
porque 4294967296 requiere 33 bits, pero como tenemos 32, obtendremos 32 
ceros al final con un uno en el 33º bit, el cual se desvanece, quedando 
32 ceros. Claro está todo esto es posible si el sistema operativo nos 
deja acceder a todas estas direcciones de memoria, que seguramente no 
será el caso.

Como puedes ver, en este último caso, no accedes al carácter, sino que 
simplemente incrementas el puntero. La secuencia de operaciones es la 
siguiente:

copia++;
while( copia )
{
   i++;
   copia++;
}


Espero haber aclarado las dudas.

Steven





Más información sobre la lista de distribución Cconclase