elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Guía actualizada para evitar que un ransomware ataque tu empresa


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  [DUDA] Punteros
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: [DUDA] Punteros  (Leído 1,948 veces)
kayron8

Desconectado Desconectado

Mensajes: 28


¡Tú mismo con tu mecanismo!


Ver Perfil WWW
[DUDA] Punteros
« en: 24 Marzo 2014, 12:25 pm »

Hola buenos días,

Llevo todo el fin de semana dándole vueltas a un ejercicio de punteros que no hay forma humana de que me funcione correctamente, el caso es que en el tema de punteros ando un poco pez, por lo que me debería de poner las pilas.

El ejercicio en cuestión, dice lo siguiente: Dada una frase, se contará el numero de as, es, is, os y us que tiene. La cantidad de cada vocal se almacenará en un vector de 5 enteros. Se
mostrará una estadística de vocales.

La manipulación de la frase y del vector se hará con punteros.
La declaración de variables será así:
(···)
char frase[256], *pf=frase;
int vocales[5];
int * pv;
pv = &vocales[0];
(···)

Ahora bien, os comento que haciendo el ejercicio sin punteros, me funciona perfectamente, dejo el código para que sirva de ejemplo:

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. //Prototipo
  6. void cuentavocales(char v[]);
  7.  
  8. int main()
  9. {
  10.  char frase[256];
  11.  cuentavocales(frase);
  12.  
  13.  system("PAUSE");
  14.  return 0;
  15. }
  16.  
  17. //Función que cuenta les vocales de la frase
  18. void cuentavocales(char frase[])
  19. {
  20.     int i=0,vocales[5]={0};
  21.  
  22.     printf("Introduce una frase: \n");
  23.     gets(frase);
  24.     for(i=0;i<strlen(frase);i++)
  25. {
  26.           if(frase[i]=='a'|| frase[i]=='A') vocales[0]++;
  27.           else if(frase[i]=='e' || frase[i]=='E') vocales[1]++;
  28.           else if(frase[i]=='i' || frase[i]=='I') vocales[2]++;
  29.           else if(frase[i]=='o' || frase[i]=='O') vocales[3]++;
  30.           else if(frase[i]=='u' || frase[i]=='U') vocales[4]++;
  31.    }
  32. //Mostramos los resultados por pantalla
  33. printf("Estadística \n");
  34. printf("as: %d \n",vocales[0]);    
  35. printf("es: %d \n",vocales[1]);
  36. printf("is: %d \n",vocales[2]);
  37. printf("os: %d \n",vocales[3]);    
  38. printf("us: %d \n",vocales[4]);
  39. printf("\n TOTAL: %d\n",vocales[0]+vocales[1]+vocales[2]+vocales[3]+vocales[4]);
  40. }

Ahora bien, pasamos al apartado de los punteros... No se si lo que he hecho está bien o es una barbaridad...

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. //Prototipo
  6. void cuentavocales(char v[5]);
  7.  
  8. int main()
  9. {
  10.  char frase[256],*pf=frase;
  11.  cuentavocales(frase);
  12.  
  13.  system("PAUSE");
  14.  return 0;
  15. }
  16.  
  17. //Función que cuenta las vocales de la frase
  18. void cuentavocales(char frase[5])
  19. {
  20.     int i=0,vocales[5]={0};
  21.     int * pv;
  22.     pv = &vocales[0];
  23.  
  24.     printf("Introduce una frase: \n");
  25.     gets(frase);
  26.     for(i=0;i<strlen(frase);i++)
  27. {
  28.   if(frase[i]=='a'|| frase[i]=='A') {
  29.   pv++;
  30.   }
  31.  
  32.   else if(frase[i]=='e' || frase[i]=='E') {
  33.   pv=pv+1;
  34.   pv++;
  35.   }
  36.  
  37.   else if(frase[i]=='i' || frase[i]=='I') {
  38.   pv=pv+2;
  39.   pv++;
  40.   }
  41.  
  42.   else if(frase[i]=='o' || frase[i]=='O') {
  43.   pv=pv+3;
  44.   pv++;
  45.   }
  46.  
  47.   else if(frase[i]=='u' || frase[i]=='U'){
  48.   pv=pv+4;
  49.   pv++;
  50.   }
  51.    }
  52.  
  53. //Mostramos los resultados por pantalla
  54. printf("Estadística \n");
  55. printf("as: %d \n",*pv);    
  56. printf("es: %d \n",*(pv+1));
  57. printf("is: %d \n",*(pv+2));
  58. printf("os: %d \n",*(pv+3));  
  59. printf("us: %d \n",*(pv+4));
  60. printf("\n TOTAL: %d\n",*pv+*(pv+1)+*(pv+2)+*(pv+3)+*(pv+4));
  61. }

Compilar, compila pero da unos resultados que no son nada correctos xD

Espero que me podáis echar un cable.

Un saludo :D


« Última modificación: 24 Marzo 2014, 13:35 pm por kayron8 » En línea

¡Salu2 a to2!
eferion


Desconectado Desconectado

Mensajes: 1.248


Ver Perfil
Re: [DUDA] Punteros
« Respuesta #1 en: 24 Marzo 2014, 12:47 pm »

Mira que dudo yo que el primer ejemplo te funcione...

Código
  1. int i=0,vocales[5];

En qué momento se supone que inicializas los valores para "vocales"??

Y bueno, pasando al segundo código, te cuento.

Imagínate que tienes un puntero, no se, algo tal que

Código
  1. int * pv;
  2. pv = &vocals[0];

Si tu depuras, pv tendrá algo tal que...

Código:
pv = 0x45672240 // Posicion de memoria apuntada por pv
*pv = 234523 // Valor de vocals[ 0 ] porque no la has inicalizado

Si tu coges pv y, por ejemplo, haces:

Código
  1. pv++;

entonces pv queda tal que:

Código:
pv = 0x45672244 // Nueva posicion, ahora es vocals[1]
*pv = -345023 // vocals[ 1 ] tampoco esta inicializada, tiene un valor aleatorio

Es decir, con pv++, pv = pv+6 y cosas así únicamente modificas la posición de memoria a la que apunta, pero no modificas el valor de esa posición de memoria apuntada.

Sin embargo, ahora imagínate ( para simplificar el ejemplo ) que has inicializado vocals. Entonces pv queda algo así:

Código:
pv = 0x45672240 // Posicion de memoria apuntada por pv
*pv = 0// Valor de vocals[ 0 ]

y ahora haces lo siguiente:

Código
  1. *pv = *pv + 1

Ahora la cosa queda tal que

Código:
pv = 0x45672240 // Posicion de memoria apuntada por pv ( no ha cambiado )
*pv = 1// Valor de vocals[ 0 ]

Que es el resultado esperado si lo que quieres es contar apariciones.

Ahora bien, esto te sirve para el valor apuntado por pv... pero si ahora nos encontramos con algo tal que:

Código
  1. else if(frase[i]=='e' || frase[i]=='E')
  2. {
  3.  pv=pv+1; // Esta linea no la he cambiado
  4.  *pv = *pv + 1;
  5. }

Entonces, efectivamente, haces que pv apunte a vocals[1] e incrementas el contador de la 'e'... pero después, pv se queda apuntando al contador de 'e'... imagínate que te encuentras con una frase tal que 'ee'... al ejecutar el código verás que te va a contar una e y una i... ¿por que? pues porque NO DEBES hacer pv = pv + 1. O al menos, si lo haces, restaura pv a su posición original...

Una recreación del fallo:

* Situacion original:

Código:
pv = 0x45672240
*pv = 0

Primera 'e':

Código:
pv = 0x45672244 // pv = pv + 1
*pv = 1 // *pv++

Segunda 'e'

Código:
pv = 0x45672248 // pv = pv + 1 MAL, deberia ser 0x45672244, este es el contador de 'ies'
*pv = 1

No se si ha quedado claro lo que pretendo transmitir.


En línea

kayron8

Desconectado Desconectado

Mensajes: 28


¡Tú mismo con tu mecanismo!


Ver Perfil WWW
Re: [DUDA] Punteros
« Respuesta #2 en: 24 Marzo 2014, 13:34 pm »

Hola eferion,

Gracias por tu explicación. El ejercicio anterior di que me funciona correctamente, el problema es que había echo un copy paste de una versión antigua. Faltaba inicializar el vector vocales:

Código
  1. int vocales[5]={0};

Respecto el tema de los punteros más o menos entiendo que es lo que hago mal, pero no consigo arreglar el problema que tengo :( Soy un negado para la programación y me cuesta bastante entender las cosas.

Se que no eres un profesor (al menos en el foro) y no recibes un salario por ello, pero me gustaría que me ayudases otro poco, sí es posible, para acabar de comprender el ejercicio.

Un saludo y muchas gracias :D
« Última modificación: 24 Marzo 2014, 13:51 pm por kayron8 » En línea

¡Salu2 a to2!
eferion


Desconectado Desconectado

Mensajes: 1.248


Ver Perfil
Re: [DUDA] Punteros
« Respuesta #3 en: 24 Marzo 2014, 13:46 pm »

Efectivamente, ni soy profesor ( ni en el foro ni en "la vida real" jejeje ) ni tampoco cobro por ayudar en la medida de mis posibilidades.

Sin embargo tu puedes preguntar tus dudas que aquí te ayudaremos lo mejor que podamos.

PD.: si alguien se apiada de mí, acepto donaciones encantado XDDDD
En línea

kayron8

Desconectado Desconectado

Mensajes: 28


¡Tú mismo con tu mecanismo!


Ver Perfil WWW
Re: [DUDA] Punteros
« Respuesta #4 en: 24 Marzo 2014, 13:55 pm »

PD.: si alguien se apiada de mí, acepto donaciones encantado XDDDD

No iría nada mal y menos en los tiempos que corren xDD

Bueno, regresando a mi cruda realidad, me gustaría que me echaras un cable para ayudarme a detectar el/los problema/s que pueda tener mi programa.

Buscando por éste fantástico foro, encontré éste ejemplo que es la mar de simple (lo entiendo perfectamente): http://foro.elhacker.net/programacion_cc/duda_contador_de_vocales_mediosolucionado_xd-t312146.0.html;msg1551059#msg1551059

Pero veo mi ejercicio y la declaración de variables que hay que hacer por narices y no se cómo continuar :(

Un saludo y muchas gracias :D
En línea

¡Salu2 a to2!
leosansan


Desconectado Desconectado

Mensajes: 1.314


Ver Perfil
Re: [DUDA] Punteros
« Respuesta #5 en: 24 Marzo 2014, 17:32 pm »

.............................................................
Bueno, regresando a mi cruda realidad, me gustaría que me echaras un cable para ayudarme a detectar el/los problema/s que pueda tener mi programa.
......................................................
Pero veo mi ejercicio y la declaración de variables que hay que hacer por narices y no se cómo continuar :(
.............................................

Si tienes en cuenta la relacion intima entre punteros y arrays no te pasaria esto:

Código
  1. *(pv+2))=vocales[2]=0
  2.  
  3. Y lo que quieres hacer es incrementar vocales[2] que lo harias como
  4. vocales[2]++;
  5.  
  6. Pues con el puntero lo mismo:
  7.  
  8. (*(pv+2))++;
  9.  

Con esta idea sale el siguiente código:

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. //Prototipo
  6. void cuentavocales(char v[5]);
  7.  
  8. int main()
  9. {
  10.  char frase[256],*pf=frase;
  11.  cuentavocales(frase);
  12.  system("PAUSE");
  13.  return 0;
  14. }
  15.  
  16. //Función que cuenta las vocales de la frase
  17. void cuentavocales(char frase[5])
  18. {
  19.     int i=0,vocales[5]={0};
  20.     int * pv,pv0;
  21.     pv = &vocales[0];
  22.  
  23.    pv0=pv;
  24.     printf("Introduce una frase: \n");
  25.     gets(frase);
  26.     for(i=0;i<strlen(frase);i++){
  27.       if(frase[i]=='a'|| frase[i]=='A')
  28.        (*(pv+0))++;
  29.      else if(frase[i]=='e' || frase[i]=='E')
  30.        (*(pv+1))++;
  31.      else if(frase[i]=='i' || frase[i]=='I')
  32.       (*(pv+2))++;
  33.       else if(frase[i]=='o' || frase[i]=='O')
  34.        (*(pv+3))++;
  35.      else if(frase[i]=='u' || frase[i]=='U')
  36.        (*(pv+4))++;
  37.    }
  38.  
  39. //Mostramos los resultados por pantalla
  40. printf("Estadistica \n");
  41. printf("a: %d \n",*pv);
  42. printf("e: %d \n",*(pv+1));
  43. printf("i: %d \n",*(pv+2));
  44. printf("o: %d \n",*(pv+3));
  45. printf("u: %d \n",*(pv+4));
  46. printf("\n TOTAL: %d\n",*pv+*(pv+1)+*(pv+2)+*(pv+3)+*(pv+4));
  47. }





En línea

Yoel Alejandro

Desconectado Desconectado

Mensajes: 254



Ver Perfil WWW
Re: [DUDA] Punteros
« Respuesta #6 en: 24 Marzo 2014, 18:19 pm »

Kayron,

Para explicarte un poco las cosas, un arreglo es un puntero. O sea, cuando declaras:

int x[3];

entonces "x" no es más que un apuntador al primer elemento del arreglo. Entonces será lo mismo:

*x que x[0]
*(x+1) que x[1]
*(x+2) que x[2]

En *(x+1) entre los paréntesis se realiza aritmética de punteros para incrementar en 1 en valor del puntero (la dirección física del dato). O sea, que x+1 contiene la dirección del dato x[1]. Ojo, la dirección no el dato en sí mismo. Para acceder el valor contenido en dicha dirección debemos usar el operador de indirección "*". Por eso, *(x+1)

Espero lo hayas podido entender clarito, jeje. Ahora, te cuento que hay gente que escribe &x[0] que es redundante, es lo mismo que x; del mismo modo &x[1] es lo mismo que x+1.

En tu programa si quieres usar exclusivamente puntero y no indexación de arreglos, debes disponer de un apuntador a char para recorrer los caracteres de la frase. Ese creo que lo llamaste fp. Su valor inicial es frase, de este modo queda apuntado al primer elemento del arreglo. Luego, las expresiones

frase

se han de cambiar por *fp y en cada ciclo el valor del puntero es incrementado con fp++ para que direccione a la siguiente letra de la frase.

Para el caso de las vocales, el mismo arreglo vocales sirve como puntero (!!!).
La expresión

vocales[ i ]++

se cambia por (*(vocales + i))++ con cada valor de i desde 0 hasta 4. Los dobles paréntesis son necesarios porque el operador de incremento "++" tiene igual precedencia que el de indirección "*", pero se evalúa de derecha a izquierda. De colocar:

*(vocales + i)++

se hubiera interpretado *((vocales + i)++) que no es lo que queremos.

El código:
Código
  1. void cuentavocales(char frase[])
  2. {
  3.   int vocales[5] = {0};
  4.   char * fp;
  5.  
  6.   printf("Introduce una frase: \n");
  7.   gets(frase);
  8.  
  9.   /* La idea es que fp recorra el arreglo frase. Se inicializa al primer
  10.     * ELEMENTO (no el primer INDICE) del arreglo. */
  11.   fp = frase;
  12.  
  13.   while ( *fp != '\0' )
  14.   {
  15.      if (*fp=='a'|| *fp=='A') (*vocales)++;
  16.      else if (*fp=='e' || *fp=='E') (*(vocales + 1))++;
  17.      else if (*fp=='i' || *fp=='I') (*(vocales + 2))++;
  18.      else if (*fp=='o' || *fp=='O') (*(vocales + 3))++;
  19.      else if (*fp=='u' || *fp=='U') (*(vocales + 4))++;
  20.  
  21.      fp++; /* aumentamos el puntero que recorre la frase */
  22.   }
  23.   //Mostramos los resultados por pantalla
  24.   printf("Estadística \n");
  25.   printf("as: %d \n", *vocales);
  26.   printf("es: %d \n", *(vocales + 1));
  27.   printf("is: %d \n", *(vocales + 2));
  28.   printf("os: %d \n", *(vocales + 3));
  29.   printf("us: %d \n", *(vocales + 4));
  30.   printf("\n TOTAL: %d\n", *vocales + *(vocales + 1) + *(vocales + 2)
  31.          + *(vocales + 3) + *(vocales + 4) );
  32. }
  33.  

Ahora no usas índices en ninguna parte, sólo punteros. Por cierto, lo probé y funciona correctamente.

================================
EDITO:

Estaba revisando tu código y la verdad es que le faltaba poco para funcionar. Por ejemplo, para incrementar el conteo de la vocal 'e' reemplaza

pv=pv+1;
pv++;

por

*(pv + 1) = *(pv + 1) + 1;

lo cual es completamente equivalente a

pv[1] = pv[1] + 1;

También puedes sintetizarlo a:

(*(pv+1))++;


Quedaría entonces:
Código
  1. void cuentavocales2(char frase[5])
  2. {
  3.   int i=0,vocales[5]= {0};
  4.   int * pv;
  5.   pv = vocales;
  6.  
  7.   printf("Introduce una frase: \n");
  8.   gets(frase);
  9.   for(i=0; i<strlen(frase); i++)
  10.   {
  11.      if(frase[i]=='a'|| frase[i]=='A')
  12.         (*pv)++;
  13.      else if(frase[i]=='e' || frase[i]=='E')
  14.         (*(pv+1))++;
  15.      else if(frase[i]=='i' || frase[i]=='I')
  16.         (*(pv+2))++;
  17.      else if(frase[i]=='o' || frase[i]=='O')
  18.         (*(pv+3))++;
  19.      else if(frase[i]=='u' || frase[i]=='U')
  20.         (*(pv+4))++;
  21.   }
  22.  
  23. //Mostramos los resultados por pantalla
  24.   printf("Estadística \n");
  25.   printf("as: %d \n",*pv);
  26.   printf("es: %d \n",*(pv+1));
  27.   printf("is: %d \n",*(pv+2));
  28.   printf("os: %d \n",*(pv+3));
  29.   printf("us: %d \n",*(pv+4));
  30.   printf("\n TOTAL: %d\n",*pv+*(pv+1)+*(pv+2)+*(pv+3)+*(pv+4));
  31. }
  32.  

Tu código anterior estaba malo porque con

pv = pv + 1;
pv++;

estás incrementando los valores del puntero, o sea las DIRECCIONES de los datos, y no los datos en sí mismos. Tal vez con

pv = pv + 1;
(*pv)++;

donde modificas pv para que apunte a la posición de la vocal 'e', y luego incrementas el valor en el arreglo. El problema es que ya el valor del puntero te queda alterado, no apunta a vocales[0] sino a vocales[1]. Tendría que ser en todo caso

pv = pv + 1;
(*pv)++;
pv = pv - 1;

donde "acomodas" de nuevo el valor del puntero. Pero eso es completamente equivalente a

*(pv + 1) = *(pv + 1) + 1;

 :)
« Última modificación: 24 Marzo 2014, 18:37 pm por yoel_alejandro » En línea

Saludos, Yoel.
P.D..-   Para mayores dudas, puedes enviarme un mensaje personal (M.P.)
kayron8

Desconectado Desconectado

Mensajes: 28


¡Tú mismo con tu mecanismo!


Ver Perfil WWW
Re: [DUDA] Punteros
« Respuesta #7 en: 24 Marzo 2014, 19:08 pm »

Muchísimas gracias a todos por el esfuerzo que habéis hecho con mi problema.

¡Jo! cómo me gustaría a mi tener esa habilidad que tenéis vosotros de resolver problemas cómo si se tratase de abrir un frasco de garbanzos xDD

Le pongo todas las ganas que puedo pero es que no hay manera de que me entre, debo de ser tonto o no se... U.u''

Nuevamente, daros las gracias a todos y cada  uno de vosotros por ser mejor que mi profe (espero que no llegue a leer esto) xDD

Un saludo :D
En línea

¡Salu2 a to2!
Yoel Alejandro

Desconectado Desconectado

Mensajes: 254



Ver Perfil WWW
Re: [DUDA] Punteros
« Respuesta #8 en: 24 Marzo 2014, 20:23 pm »

Modestia aparte kayron  :-[. Luego que pases años programando como nosotros, lo harás igual jajaja  :D
En línea

Saludos, Yoel.
P.D..-   Para mayores dudas, puedes enviarme un mensaje personal (M.P.)
Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
[C] - Duda punteros
Programación C/C++
h0oke 2 2,338 Último mensaje 23 Mayo 2010, 02:19 am
por h0oke
Duda con punteros
Programación C/C++
cazagavilan 5 2,845 Último mensaje 14 Abril 2012, 05:47 am
por cazagavilan
Duda Punteros Dobles/Array de punteros
Programación C/C++
MisterJava 2 4,860 Último mensaje 30 Diciembre 2012, 20:19 pm
por MisterJava
Duda con Punteros en C
Programación C/C++
LeoJ24 2 1,695 Último mensaje 13 Enero 2013, 20:49 pm
por ameise_1987
Duda con Punteros - C
Programación C/C++
LeoJ24 6 2,921 Último mensaje 21 Enero 2013, 01:34 am
por dato000
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines