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

 

 


Tema destacado: ¿Eres nuevo? ¿Tienes dudas acerca del funcionamiento de la comunidad? Lee las Reglas Generales


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  Problema con los punteros C++
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: 1 [2] 3 Ir Abajo Respuesta Imprimir
Autor Tema: Problema con los punteros C++  (Leído 3,075 veces)
K-YreX
Moderador
***
Desconectado Desconectado

Mensajes: 918



Ver Perfil
Re: Problema con los punteros C++
« Respuesta #10 en: 26 Agosto 2019, 18:50 pm »

Citar
Pero si lo uso con int me muestra la posición, por?
Código
  1. int nombre[] = {1,2,3}, *p_nombre2;
  2. cout<<"Dir.1: "<<nombre[1]<<" | "<<p_nombre2<<endl;
  3. //Salida: Dir.1: 2 | 0x6ffdf0
En este caso creo que no hay dudas. <p_nombre2> sería un puntero que apunta al mismo sitio que <nombre> aunque no se vea ahí (es decir, imagino que has omitido el <p_nombre2 = nombre> o <p_nombre2 = &nombre[0]> que es equivalente). Entonces al mostrar <nombre[1]> estamos mostrando el valor almacenado en la posición 1 del array y al mostrar <p_nombre2> estamos mostrando la dirección de memoria a la que está apuntando.

Citar
Si uso con char me muestra toda la cadena:
Código
  1. char nombre[] = {'a','b','c'}, *p_nombre2;
  2. cout<<"Dir.1: "<<nombre[1]<<" | "<<p_nombre2<<endl;
  3. //Salida: Dir.1: b | abc
Aquí es donde la cosa cambia, los arrays de <char> que se conocen también como cadenas estilo C porque existían en C y fueron heredadas por C++. Cuando tienes un array de <int> por ejemplo, para mostrarlo hacemos lo siguiente:
Código
  1. for(int i = 0; i < size; ++i)
  2.    cout << arrayEnteros[i] << " ";
Pero imagina que tienes una cadena de <char> con un nombre y que quieres mostrar el nombre. Sería muy incómodo tener que hacer:
Código
  1. char nombre[] = "Pepe";
  2. cout << "Tu nombre es: ";
  3. for(int i = 0; i < 4; ++i)
  4.    cout << nombre[i];
Entonces como las cadenas de <char> no se suelen usar sólo para almacenar valores aislados sino también palabras o frases, para hacerlo más cómodo el lenguaje permite hacer:
Código
  1. char nombre[] = "Pepe";
  2. cout << "Tu nombre es: " << nombre << endl;
Y la máquina ya entiende que tiene que mostrar desde donde apunta <nombre> (&nombre[0]) hasta el caracter de fin de cadena '\0'. Cosa que con un array de enteros no podemos hacer. Entonces digamos que puedes entenderlo como que los arrays de <char> tienen sus excepciones respecto al resto.

Además en C++, al introducir la POO y con ello las clases y objetos, aparece la clase <string> que funciona como una cadena <char> pero sin necesidad de tener que reservar nosotros la memoria:
Código
  1. string nombre = "Pepe";
  2. cout << "La primera letra de " << nombre << " es: " << nombre[0] << endl;


En línea

Código
  1. cout << "Todos tenemos un defecto, un error en nuestro código" << endl;
98Fran

Desconectado Desconectado

Mensajes: 35


Ver Perfil
Re: Problema con los punteros C++
« Respuesta #11 en: 26 Agosto 2019, 23:51 pm »

Gracias!, es un poco lió que para cada cosa cambien la nomenclatura. Esto de los punteros en serio es un invento del diablo jajaja. Estaba siguiendo hace nada con el curso y ahora estaba viendo punteros con matrices, el otro programador usaba punteros y variables globales y yo lo intente en un principio con valores desde el main() y pasarlos a la función y me da problemas, luego intente hacerlo por variables globales y también se traba o al escribir la matriz o a la hora de mostrarla, te paso el codigo.
Código
  1. #include <iostream>
  2. #include <cstdlib>
  3. using namespace std;
  4.  
  5. void pedirDatos(int**,int&,int&);
  6. void imprimirDatos(int**,int,int);
  7.  
  8. int **p_m2;
  9.  
  10. int main(){
  11. int **p_m,fil,col;
  12.  
  13. pedirDatos(p_m,fil,col);
  14. //imprimirDatos(p_m,fil,col); No funciona, se para al mostrar la matriz
  15. cout<<*(*(p_m2+1)+1); //tampoco va, ahora se corta al insertar las variabes
  16.  
  17. //liberar memoria;
  18. for(int i=0;i<fil;i++){
  19. delete[] p_m[i];
  20. }
  21.  
  22. delete[] p_m;
  23.  
  24. cin.get();
  25. return 0;
  26. }
  27.  
  28. void pedirDatos(int** p_m,int &fil,int &col){
  29. cout<<"Digite numero de Filas: ";
  30. cin>>fil;
  31. cout<<"Digite numero de Columnas: ";
  32. cin>>col;
  33.  
  34. //Reservar memoria para matriz dinámica.
  35. p_m2 = new int*[fil]; //Reservando memoria para las filas.
  36. for(int i=0;i<fil;i++){
  37. p_m2[i] = new int[col]; //Reservando memoria para columnas
  38. }
  39.  
  40. cout<<"\nDigite elementos matriz: "<<endl;
  41. for(int i=0;i<col;i++){
  42. for(int j=0;j<fil;j++){
  43. cout<<"Digite un numero ["<<i<<"]["<<j<<"]: ";
  44. cin>>*(*(p_m+i)+j);
  45. }
  46. }
  47.  
  48. //Comprobar si lo ha grabado bien:
  49. for(int i=0;i<fil;i++){
  50. for(int j=0;j<col;j++){
  51. cout<<*(*(p_m+i)+j);
  52. }
  53. cout<<"\n";
  54. }//funciona, edit: despues de tocarlo todo 3000 veces ya no xD.
  55. }
  56.  
  57. void imprimirDatos(int** p_m,int f,int c){
  58. cout<<"\n------------------------------------\nLa matriz es: "<<f<<"x"<<c<<"\n\n";
  59. cout<<*(*(p_m+1)+1); //Tambien se traba a intentar imprimirlo
  60. /*for(int i=0;i<f;i++){
  61. for(int j=0;j<c;j++){
  62. cout<<*(*(p_m+i)+j);
  63. }
  64. cout<<"\n";
  65. }*/
  66. }

Lo que esta en /* es que me falla y para no borrarlo he intentarlo por variables globales e intentar imprimir un solo dato de la matriz lo deje así.

PD: ahora estoy intentando usar variables de columna y fila dentro de la función pero ni eso, se traba al intentar grabar la matriz.
Código
  1. void pedirDatos(int** p_m,int &fil,int &col){
  2. int f,c;
  3.  
  4. cout<<"Digite numero de Filas: ";
  5. cin>>f;
  6. cout<<"Digite numero de Columnas: ";
  7. cin>>c;
  8. cout<<f<<c<<endl; //Comprobar que guarde bien
  9. //Reservar memoria para matriz dinámica.
  10. p_m2 = new int*[f]; //Reservando memoria para las filas.
  11. for(int i=0;i<fil;i++){
  12. p_m2[i] = new int[c]; //Reservando memoria para columnas
  13. }
  14.  
  15. cout<<"\nDigite elementos matriz: "<<endl;
  16. for(int i=0;i<c;i++){
  17. for(int j=0;j<f;j++){
  18. cout<<"Digite un numero ["<<i<<"]["<<j<<"]: ";
  19. cin>>*(*(p_m+i)+j);
  20. }
  21. }

SALIDA: Digite numero de Filas: 3
Digite numero de Columnas: 2
32

Digite elementos matriz:
Digite un numero 0 0:
--------------------------------
Process exited after 3.64 seconds with return value 3221225477
Presione una tecla para continuar . . .


« Última modificación: 27 Agosto 2019, 00:12 am por 98Fran » En línea

K-YreX
Moderador
***
Desconectado Desconectado

Mensajes: 918



Ver Perfil
Re: Problema con los punteros C++
« Respuesta #12 en: 27 Agosto 2019, 00:25 am »

Has hecho tantos cambios que estás mezclando <p_m> con <p_m2> en las funciones... :xD
Para evitar estas cosas es mejor usar nombres que se vean mejor y que se distingan mas facilmente. Y si te acostumbras a usar buenos nombres siempre al final los usarás hasta cuando estés haciendo programas de prueba.

Bueno el tema de matrices... Ibas bastante bien. Pero hay un detalle que te puse unos comentarios atrás... Voy a buscarlo:
Citar
Como te he comentado antes el paso de un puntero por referencia es muy aislado. Hasta donde yo he visto y además si estás empezando sólo lo necesitarás para pasar un puntero a una función y dentro de la función reservar memoria con <new> o bien pasar un array (es decir, un puntero al que ya le has hecho <new>) y liberar esa memoria con <delete>. Quitando esos casos, no creo que necesites pasar un puntero por referencia. Por lo que puedes olvidarte un poco de él hasta que veas memoria dinámica.

Entonces tienes dos opciones:
  • Opcion 1: Reservar memoria en el <main> y pasar el doble puntero por valor (como lo estás pasando ahora).
  • Opcion 2: Pasar el doble puntero por referencia y listo. Ya que has llegado hasta donde has llegado, te recomiendo esta segunda:
Código
  1. void pedirDatos(int**&, int&, int&);
Con ese cambio ya estaría listo. A la hora de llamar a la función solo tienes que pasarle el nombre como estás haciendo (es decir, que no debes cambiar la llamada a la función del <main>).

Y en el bucle para pedir la matriz de <pedirDatos()> tienes un pequeño error. Si trabajas siempre con: matriz[filas][columnas], entonces para mostrar la matriz el bucle externo maneja las filas y el interno las columnas (lo tienes al revés).
Si ves que se te complica la aritmética de punteros, puedes usar indexación que es más cómodo de ver y más fácil de trabajar y cuando ya tengas más experiencia usar la aritmética de punteros:
Código
  1. cout << *(*(matriz + i) + j) << endl; // aritmetica de punteros
  2. cout << matriz[i][j] << endl; // indexacion
En línea

Código
  1. cout << "Todos tenemos un defecto, un error en nuestro código" << endl;
98Fran

Desconectado Desconectado

Mensajes: 35


Ver Perfil
Re: Problema con los punteros C++
« Respuesta #13 en: 27 Agosto 2019, 16:15 pm »

Ahora sí jajaja, ayer estuve apunto de probar el método de pasar el puntero por referencia, pero como no sabía exactamente lo que hacía deseche esa opción  :xD.

Al final a quedado algo tal que así:
Código
  1. #include <iostream>
  2. #include <stdlib.h>
  3. using namespace std;
  4.  
  5. void pedirDatos(int**&,int&,int&);
  6. void imprimirDatos(int**,int,int);
  7.  
  8. int main(){
  9. int **p_m,fil,col;
  10.  
  11. pedirDatos(p_m,fil,col);
  12. imprimirDatos(p_m,fil,col);
  13.  
  14. //liberar memoria;
  15. for(int i=0;i<fil;i++){
  16. delete[] p_m[i];
  17. }
  18.  
  19. delete[] p_m;
  20.  
  21. cin.get();
  22. return 0;
  23. }
  24.  
  25. void pedirDatos(int**& p_m,int &fil,int &col){
  26.  
  27. cout<<"Digite numero de Filas: ";
  28. cin>>fil;
  29. cout<<"Digite numero de Columnas: ";
  30. cin>>col;
  31.  
  32. //Reservar memoria para matriz dinámica.
  33. p_m = new int*[fil]; //Reservando memoria para las filas.
  34. for(int i=0;i<fil;i++){
  35. p_m[i] = new int[col]; //Reservando memoria para columnas
  36. }
  37.  
  38. cout<<"\nDigite elementos matriz: "<<endl;
  39. for(int i=0;i<col;i++){
  40. for(int j=0;j<fil;j++){
  41. cout<<"Digite un numero ["<<i<<"]["<<j<<"]: ";
  42. cin>>*(*(p_m+i)+j);
  43. }
  44. }
  45. }
  46.  
  47. void imprimirDatos(int** p_m,int f,int c){
  48. cout<<"\n------------------------------------\nLa matriz es: "<<f<<"x"<<c<<"\n\n";
  49. for(int i=0;i<f;i++){
  50. for(int j=0;j<c;j++){
  51. cout<<*(*(p_m+i)+j)<<" ";
  52. }
  53. cout<<"\n";
  54. }
  55. }

Esto de los punteros me parece todo un mundo la verdad, para cada cosa me cambian la nomenclatura, yo no se como puedes acordarte de todo esto si no lo usas diariamente jajaja.

PD: No se suponía que un puntero es un referencia al espacio de memoria? y que usando "cin>>puntero" te permite guardar el valor en ese espacio, por qué ahora al usar new hace falta pasarlo como puntero referencia y no lo englobaron en 1 sola categoría???, estas cosas son las que me matan  ;D ;D ;D.

PD2: Donde aprendiste a programar por cierto?, al final te voy a tener que contratar como profesor particular xDDD.

PD3: Acabo de hacer un problema para ver si lo interiorizado todo correctamente y ahora parece que sí, a la primera sin fallos (sin contar erratas que de esas siempre hay xD)

Código
  1. #include <iostream>
  2.  
  3. using namespace std;
  4.  
  5. void pedirMatriz(int**&,int**&,int&,int&,int&,int&);
  6. bool sumarMatriz(int**,int**,int**&,int,int,int,int);
  7. void mostrarSuma(int**,int,int);
  8.  
  9. int main(){
  10. int **p_m1, **p_m2, c1, f1/*filas y columnas de la matriz dinámica 1*/, c2, f2;
  11. int **suma;
  12. bool coinciden;
  13.  
  14. pedirMatriz(p_m1,p_m2,c1,f1,c2,f2);
  15. coinciden = sumarMatriz(p_m1,p_m2,suma,c1,f1,c2,f2);
  16.  
  17. if (coinciden == true){
  18. mostrarSuma(suma,f1,c1);
  19.  
  20. //Borrar memoria matriz suma (Solo si se crea)
  21. for(int i=0;i<f1;i++){
  22. delete[] suma[i];
  23. }
  24. delete[] suma;
  25. }
  26. else{
  27. cout<<"Las matrices no tienen las mismas dimensiones.";
  28. }
  29.  
  30. //Borrar memoria M[1] y M[2];
  31. for(int i=0;i<f1;i++){
  32. delete[] p_m1[i];
  33. }
  34. delete[] p_m1;
  35.  
  36. for(int i=0;i<f2;i++){
  37. delete[] p_m2[i];
  38. }
  39. delete[] p_m2;
  40.  
  41. //Fin programa
  42. cin.get();
  43. return 0;
  44. }
  45. void pedirMatriz(int**& m1,int**& m2,int& f1,int& c1,int& f2,int& c2){
  46.  
  47. cout<<"Digite num. de filas para M[1]: "; cin>>f1;
  48. cout<<"Digite num. de columnas para M[1]: "; cin>>c1;
  49. cout<<"\nDigite num. de filas para M[2]: "; cin>>f2;
  50. cout<<"Digite num. de columnas para M[2]: "; cin>>c2;
  51.  
  52. //Revervar espacio puntero filas, ya que cada fila apunta al resto de columnas (Como un puntero de un vector encima de otro);
  53. m1 = new int*[f1];
  54.  
  55. //Reservar espacio columnas;
  56. for(int i=0;i<f1;i++){
  57. m1[i] = new int[c1];
  58. }
  59.  
  60. cout<<"\n-----------------------------------------"<<endl;
  61. cout<<"Digite los valores de M[1]: "<<endl;
  62.  
  63. //Empezar recogida de datos M[1];
  64. for(int i=0;i<f1;i++){
  65. for(int j=0;j<c1;j++){
  66. cout<<"Valor de M1["<<i<<"]["<<j<<"]: ";
  67. cin>>*(*(m1+i)+j); //Equivale a m1[i][j]
  68. }
  69. }
  70.  
  71. //Reservar espacio memoria M[2];
  72. m2 = new int*[f2];
  73.  
  74. for(int i=0;i<f2;i++){
  75. m2[i] = new int[c2];
  76. }
  77.  
  78. cout<<"\n-----------------------------------------"<<endl;
  79. cout<<"Digite los valores de M[1]: "<<endl;
  80.  
  81. //Empezar recogida de datos M[1];
  82. for(int i=0;i<f2;i++){
  83. for(int j=0;j<c2;j++){
  84. cout<<"Valor de M2["<<i<<"]["<<j<<"]: ";
  85. cin>>m2[i][j]; //Equivale a *(*(m2+i)+j);
  86. }
  87. }
  88. }
  89.  
  90. bool sumarMatriz(int** m1,int** m2,int**& suma,int f1,int c1,int f2,int c2){
  91. bool coin;
  92.  
  93. if(f1 == f2 && c1 == c2){
  94. //Crear matriz dinamica suma; uso f1 ya que f1 == f2, asi no creo mas variables;
  95. suma = new int*[f1];
  96.  
  97. for(int i=0;i<f1;i++){
  98. suma[i] = new int[c1];
  99. }
  100.  
  101. for(int i=0;i<f1;i++){
  102. for(int j=0;j<c1;j++){
  103. suma[i][j] = m1[i][j] + m2[i][j];
  104. }
  105. }
  106. coin = true;
  107. }
  108. else{
  109. coin = false;
  110. }
  111.  
  112. return coin;
  113. }
  114.  
  115. void mostrarSuma(int** suma,int f1, int c1){
  116.  
  117. cout<<"\n-----------------------------------------"<<endl;
  118. cout<<"La suma de las 2 matrices es: "<<endl;
  119.  
  120. for(int i=0;i<f1;i++){
  121. for(int j=0;j<c1;j++){
  122. cout<<suma[i][j]<<" "; //Es lo mismo que usar: *(*(suma+i)+j);
  123. }
  124. cout<<endl;
  125. }
  126. }

Espero que esto de los punteros no se complique más o al final acabare loco  ;-) ;-) ;-)
« Última modificación: 27 Agosto 2019, 17:19 pm por 98Fran » En línea

K-YreX
Moderador
***
Desconectado Desconectado

Mensajes: 918



Ver Perfil
Re: Problema con los punteros C++
« Respuesta #14 en: 27 Agosto 2019, 17:25 pm »

Bueno, sigues teniendo un pequeño error. Fíjate que para mostrar la matriz haces:
Código
  1. for(int i = 0; i < filas; ++i){
  2.    for(int j = 0; j < columnas; ++j)
  3.        cout << *(*matriz + i) + j) << " ";
  4.    cout << endl;
  5. }
En cambio en la función <pedirDatos()> para almacenar los valores en la matriz haces:
Código
  1. for(int i = 0; i < columnas; ++i){
  2.    for(int j = 0; j < filas; ++j)
  3.        cout << *(*matriz + i) + j) << " ";
  4.    cout << endl;
  5. }
Por lo que este segundo bloque está mal. En matrices cuadradas no vas a notar la diferencia pero en matrices que no son cuadradas vas a tener errores de acceso a memoria.

Citar
PD: No se suponía que un puntero es un referencia al espacio de memoria? y que usando "cin>>puntero" te permite guardar el valor en ese espacio, por qué ahora al usar new hace falta pasarlo como puntero referencia y no lo englobaron en 1 sola categoría???, estas cosas son las que me matan  ;D ;D ;D.
Cuando pasas un puntero estás pasando su contenido que es la dirección de memoria del dato al que está apuntando.
Código
  1. int numero = 2; // pongamos que se guarda en 0x1 (voy a usar numeros cortos para que sea mas sencillo)
  2. cout << "Numero vale: " << numero << " y su direccion de memoria original es: " << &numero << endl;
  3. // Salida: Numero vale: 2 y su direccion de memoria original es: 0x1
  4.  
  5. // Pasamos la variable por referencia para pasar la direccion de memoria en la que esta guardado <numero> (0x1)
  6. void incrementar(int &numero){ // pasamos 0x1
  7.    ++numero;
  8.    cout << "Numero vale: " << numero << " y su direccion de memoria ORIGINAL es: " << &numero << endl;
  9. }
  10. // Salida: Numero vale: 3 y su direccion de memoria ORIGINAL es: 0x1
  11.  
  12. int *p_numero = &numero; // pongamos que <p_numero> se guarda en 0x5 y dentro de 0x5 guarda la direccion de <numero> 0x1
  13. // Pasamos un puntero por valor, entonces estamos haciendo una copia de su contenido pero su contenido ya es la direccion de memoria de <numero> 0x1
  14. void incrementar(int *p_numero){ // a la funcion llega 0x1 y se guarda en una copia del puntero en 0x13 por ejemplo
  15.    ++(*p_numero);
  16.    cout << "Numero vale: " << *p_numero << " y su direccion de memoria ORIGINAL es " << p_numero << endl;
  17.    cout << "La direccion de memoria del puntero es: " << &p_numero << endl;
  18. }
  19. // Salida: Numero vale: 4 y su direccion de memoria ORIGINAL es: 0x1
  20. //         La direccion de memoria del puntero es: 0x13 // Aqui se ve la direccion de la copia, no 0x5
  21.  
  22. // Pasamos el puntero por referencia, entonces estamos pasando la direccion de memoria EN LA QUE ESTA EL PUNTERO (0x5), no a la que apunta (<numero>)
  23. void incrementar(int *&p_numero){ // a la funcion llega 0x5 que sigue apuntando a 0x1
  24.    ++(*p_numero);
  25.    cout << "Numero vale: " << *p_numero << " y su direccion de memoria ORIGINAL es " << p_numero << endl;
  26.    cout << "La direccion de memoria del puntero ORIGINAL es: " << &p_numero << endl;
  27. }
  28. // Salida: Numero vale: 5 y su direccion de memoria ORIGINAL es: 0x1
  29. //          La direccion de memoria del puntero ORIGINAL es: 0x5
  30. }

Una vez visto esto, el tema es que los operadores <new> y <delete> no actúan en la dirección a la que apunta el puntero, sino en la dirección en la que está el puntero. Por eso si quisieramos hacer <new> o <delete> en el ejemplo anterior tendríamos que hacerlo sobre la dirección de memoria 0x5. Si el puntero lo pasamos por valor, estamos haciendo un <new> sobre 0x13, pero la dirección 0x5 no se ha enterado de lo que le han hecho a 0x13.
Por eso en ese caso hay que pasar el puntero por referencia.

Citar
PD2: Donde aprendiste a programar por cierto?
Me metieron en este mundo en el instituto, me gustó y me quedé. Si quieres un consejo: no te quedes con que tu programa funciona después de cambiar tal cosa, investiga por qué funciona después de ese cambio. No hacen falta programas enormes para aprender, hasta el programa más tonto como el código que he puesto arriba sirve para ver cómo funcionan las direcciones de memoria. Después de 2 años de Ingeniería Informática te puedo asegurar que es mucho mejor aprender por libre. Existen recursos como internet de sobra para poder hacerlo y cada uno tiene su ritmo de aprendizaje, si te metes a aprender en un sistema estandarizado no vas a profundizar en nada y no te va a dar tiempo a practicar todo lo que veas y la programación se aprende programando, no leyendo libros y códigos ya hechos una y otra vez.
En línea

Código
  1. cout << "Todos tenemos un defecto, un error en nuestro código" << endl;
98Fran

Desconectado Desconectado

Mensajes: 35


Ver Perfil
Re: Problema con los punteros C++
« Respuesta #15 en: 27 Agosto 2019, 19:54 pm »

Gracias por el consejo, cuando hago algo me gusta saber por qué lo hago y como funciona ese algo para poder entenderlo, ya que si no lo entiendo simplemente estaría copiando y pegando y seria perder el tiempo.

PD: Si lo he entendido bien esto:
Código
  1. void funcion(int**& p_m) // usando new
  2. //seria equivalente a:
  3. void funcion(int m[][100]

La diferencia radicaría en que en la primera se usa para crear una matriz dinámica y así ahorrar espacio en la memoria y en la segunda ya tienes el espacio reservado, no?

PD2: las variables dinámicas no tienes nombre? o solo se les puede llamar a través del puntero del que se crean?
« Última modificación: 27 Agosto 2019, 19:57 pm por 98Fran » En línea

K-YreX
Moderador
***
Desconectado Desconectado

Mensajes: 918



Ver Perfil
Re: Problema con los punteros C++
« Respuesta #16 en: 27 Agosto 2019, 21:23 pm »

Citar
PD: Si lo he entendido bien esto:
Código
  1. void funcion(int**& p_m) // usando new
  2. //seria equivalente a:
  3. void funcion(int m[][100]
La diferencia radicaría en que en la primera se usa para crear una matriz dinámica y así ahorrar espacio en la memoria y en la segunda ya tienes el espacio reservado, no?
Respecto a esto, más que para qué se usa, es qué estoy haciendo con cada cosa. La primera cosa a tener en cuenta es, dicho de una forma poco exacta es que unos corchetes se pueden sustituir por un asterisco y un asterisco por unos corchetes (hablando de arrays como parámetros). Entonces tenemos estas opciones principalmente:
Código
  1. void funcion1(int **matriz); // pasamos la direccion de memoria del elemento [0][0]
  2. void funcion2(int **&matriz); // pasamos la direccion de memoria que apunta a la direccion de memoria del elemento [0][0]
  3. void funcion3(int matriz[][TAM]); // igual que funcion1() pero necesitamos indicar todas las dimensiones excepto la primera
  4. void funcion4(int &matriz[][TAM]); // igual que funcion2() pero indicando las dimensiones como en la funcion3()
Luego claro está que podemos mezclar asteriscos y corchetes y decir "pues quito un par de corchetes y pongo un asterisco" o al revés. Recalco: lo de intercambiar asteriscos y corchetes es para arrays. Si queremos pasar un puntero que no es un array no podemos usar corchetes.
No puedo explicarte mucho más de esto ya que el tema de los arrays estáticos ha ido evolucionando mucho y no estoy muy puesto en ello pero ahora por ejemplo se permite crear un array estático indicando su tamaño en una variable cosa que en versiones anteriores no se podía y de ahí lo de declarar los tamaños usando <#define> (sobre todo en C) o usando una constante global al comienzo del programa <const int> (en C++).

Citar
PD2: las variables dinámicas no tienes nombre? o solo se les puede llamar a través del puntero del que se crean?
Claro que tienen nombre. El puntero. Lo puedes entender como si al hacer:
Código
  1. int miArray[5];
El compilador por dentro hiciese:
Código
  1. int *miArray = new int[5];
En el primer caso el nombre del array está claro. Y en el segundo? Pues es lo mismo, el nombre es el del puntero que lo está apuntando. Ya que con memoria dinámica se pueden hacer cosas como:
Código
  1. int *miArray = new int[10];
  2. int *otroArray = new int[5];
  3. // Queremos intercambiarlos pero en cuanto asignemos algo a uno de esos punteros, perderemos el array entonces:
  4. int *auxiliar = miArray; // Ahora el primer array tiene dos nombres: <auxiliar> y <miArray>
  5. miArray = otroArray; // Ahora hacemos que el puntero <miArray> apunte al mismo sitio que <otroArray>
  6. otroArray = auxiliar; // Y ahora <otroArray> apunta al mismo sitio que <auxiliar> que era el array original al que apuntaba <miArray>
Otra duda típica en estos casos es: ¿y hago algún <delete> por ejemplo a <auxiliar>? Pues no. El delete no borra el puntero, borra la memoria dinámica a la que apunta ese puntero. Entonces si hacemos por ejemplo:
Código
  1. delete [] auxiliar;
<auxiliar> a dónde estaba apuntando? Al mismo array que <otroArray>. Pues entonces <otroArray> ya sólo es un puntero ya que el array que habíamos reservado, nos lo hemos cargado con ese <delete>.
En línea

Código
  1. cout << "Todos tenemos un defecto, un error en nuestro código" << endl;
98Fran

Desconectado Desconectado

Mensajes: 35


Ver Perfil
Re: Problema con los punteros C++
« Respuesta #17 en: 27 Agosto 2019, 22:15 pm »

Bueno saberlo  ;-) ;-) ;-). Creo que ya he visto todo de los punteros creo. No se si hay punteros de funciones (juraría haber visto algo como: void *funcion() en alguna parte, pero no le encuentro sentido ponerle un puntero a una función a no ser que sea un puntero a un valor que devuelva. Supongo que cuando llegue a la parte de POO haré otro post lleno de preguntas xD, a ver si el profe del curso de udemy se pone las pilas y explica un poco como tu y seguro que no vuelvo a poner ningún post más  :xD :xD :xD.

PD: que sería un mensaje sin PD  ;-) ;-) ;-) :silbar:, lo bueno del post es que si cuando empiece la uni se me olvida alguna cosita de los puntero me releo el post y ya estaría  :rolleyes: :rolleyes:  :rolleyes:.
« Última modificación: 27 Agosto 2019, 22:19 pm por 98Fran » En línea

K-YreX
Moderador
***
Desconectado Desconectado

Mensajes: 918



Ver Perfil
Re: Problema con los punteros C++
« Respuesta #18 en: 27 Agosto 2019, 23:14 pm »

Citar
Creo que ya he visto todo de los punteros creo
Claro que no :xD :xD. Para trabajar a un nivel básico o incluso un poco avanzado ya tienes pero los punteros no son sólo lo que has visto. Como bien dices aunque un poco mezclado tienes por una parte los punteros de tipo <void> y por otra parte los punteros a funciones.

Los punteros de tipo <void> se usan para apuntar a un dato sin especificar el tipo de dato y así mediante estos punteros podemos pasar diferentes tipos de datos a una misma función. Esto da mucha libertad a la hora de trabajar con ello (pero también hay que saber cuándo de verdad compensa usarlos, de momento es mejor que no los uses). A la vez que da libertad también la quita ya que no podemos desreferenciar el puntero (mediante *) para trabajar con su valor sin antes hacer un <cast>.
Código
  1. void incrementar(void *puntero, int size){
  2.    if(size == sizeof(char)){
  3.        char *p_char = (char*)puntero;
  4.        ++(*p_char);
  5.    }
  6.    if(size == sizeof(int)){
  7.        char *p_int = (int*)puntero;
  8.        ++(*p_int);
  9.    }
  10. }
  11.  
  12. int main(){
  13.    char letra = 'a';
  14.    int numero = 1;
  15.    incrementar(&letra, sizeof(letra));
  16.    incrementar(&numero, sizeof(numero));
  17.    cout << letra << " - " << numero << endl;
  18. }
Código:
Salida: b - 2

Por otro lado están los punteros a funciones. Esto sirve para pasarle a una función, otra función.
Código
  1. int sumar(int a, int b){
  2.    return a + b;
  3. }
  4.  
  5. int restar(int a, int b){
  6.    return a - b;
  7. }
  8.  
  9. int realizarOperacion(int (*operacion)(int,int), int a, int b){
  10.    int resultado = (*operacion)(a,b);
  11.    return resultado;
  12. }
  13.  
  14. int main(){
  15.    int a = 4, b = 1;
  16.    int (*realizarResta)(int,int) = restar;
  17.    int resultadoSuma = realizarOperacion(sumar, a, b);
  18.    int resultadoResta = realizarOperacion(realizarResta, resultadoSuma, b);
  19. }
Este es un ejemplo típico de punteros a funciones. Está claro que no parece necesario usarlos pero pueden darse casos en los que sí y entonces pues ahí está la opción de hacerlo así.

Podía haber hecho un último mensaje corto pero eso no es lo mío. Dejo un ejemplo de cada uno de estos y así podríamos decir que este tema del foro queda bastante completo en cuanto a punteros se refiere.
PD: Te recomiendo para tenerlo más a mano hacerte un programa (por ejemplo punteros.cpp o punterosExplicaciones.cpp) y ponerte ahí todo lo que has ido viendo que se puede o no se puede hacer y con algunos comentarios. Y en caso de que necesites recordar algo más en profundidad entonces ya puedes volver aquí y buscar este tema. Suerte :-X
En línea

Código
  1. cout << "Todos tenemos un defecto, un error en nuestro código" << endl;
98Fran

Desconectado Desconectado

Mensajes: 35


Ver Perfil
Re: Problema con los punteros C++
« Respuesta #19 en: 28 Agosto 2019, 00:30 am »

Esto es la biblia de los punteros ya xD, lo tengo guardado en la barra de herramientas para tenerlo a la vista entro al chrome y ya le doy a abrir jajaja.

PD: por lo que he visto en el curso no se da más sobre punteros, ya pasa a pilas, a ver que tal jajaja. Acabo de hacer un programa donde podría usar un puntero de una función no?:
Código
  1. #include <iostream>
  2.  
  3. using namespace std;
  4.  
  5. void pedirDatos(int**&,int**&,int&,int&,int&,int&);
  6. void multiplicarMatrices(int**,int**,int**&,int,int,int);
  7. int multi(int**,int**,int,int,int);
  8. void mostrarMatriz(int**,int,int);
  9.  
  10. int main(){
  11. int **m1,**m2,c1,f1,c2,f2;
  12. int **mMultiplicacion;
  13.  
  14. pedirDatos(m1,m2,f1,c1,f2,c2);
  15. multiplicarMatrices(m1,m2,mMultiplicacion,f1,c2,c1); //c1 == f2 == c_f;
  16. mostrarMatriz(mMultiplicacion,f1,c2);
  17.  
  18.  
  19.  
  20. cin.get();
  21. return 0;
  22. }
  23.  
  24. void pedirDatos(int**& m1, int**& m2, int& f1, int& c1, int& f2, int& c2){
  25.  
  26. //Repetir proceso hasta que las dimensiones de las matrices sean multiplicables;
  27. do{
  28. //Definir filas y columnas M[1];
  29. cout<<"Digite numero de filas de M[1]: "; cin>>f1;
  30. cout<<"Digite numero de columnas de M[1]: "; cin>>c1;
  31.  
  32. //Definir filas y columnas M[2];
  33. cout<<"\nDigite numero de filas de M[2]: "; cin>>f2;
  34. cout<<"Digite numero de columnas de M[2]: "; cin>>c2;
  35.  
  36. cout<<"\n\n";}
  37. while(c1 != f2);
  38. //M[f1][c1] * T[f2][c2] |([c1] == [f2])| ---> = R[f1][c2];
  39.  
  40. //Reservar memoria para matriz puntero m1;
  41. m1 = new int*[f1];
  42. for(int i=0;i<f1;i++){
  43. m1[i] = new int[c1];
  44. }
  45.  
  46. m2 = new int*[f2];
  47. for(int i=0;i<f2;i++){
  48. m2[i] = new int[c2];
  49. }
  50.  
  51. //Declarar variables matriz 1;
  52. for(int i=0;i<f1;i++){
  53. for(int j=0;j<c1;j++){
  54. cout<<"Digite valor de M1["<<i<<"]["<<j<<"]: ";
  55. cin>>m1[i][j]; //es lo mismo que *(*(m1+i)+j);
  56. }
  57. }
  58. cout<<endl;
  59.  
  60. //Declarar variables matriz 2;
  61. for(int i=0;i<f2;i++){
  62. for(int j=0;j<c2;j++){
  63. cout<<"Digite valor de M2["<<i<<"]["<<j<<"]: ";
  64. cin>>m2[i][j];
  65. }
  66. }
  67. cout<<endl;
  68. }
  69.  
  70. void multiplicarMatrices(int** m1,int** m2,int**& mT,int f,int c, int f_c){
  71.  
  72. //Reservar memoria mT;
  73. mT = new int*[f];
  74. for(int i=0;i<f;i++){
  75. mT[i] = new int[c];
  76. }
  77.  
  78. //Empezar multiplicación;
  79. for(int i=0;i<f;i++){
  80. for(int j=0;j<c;j++){
  81. mT[i][j] = multi(m1,m2,f_c,i,j);
  82. }
  83. }
  84.  
  85. }
  86.  
  87. int multi(int** m1,int** m2,int f_c, int x, int y){
  88. int total=0;
  89.  
  90. //Multiplica filas M[1] x columnas M[2]. Maximo de multiplicaciones: c1 == f2 == f_c == c2_f1. Si es 2x3 * 3x3 --> multiplica máximo 3 veces --> MTotal = 2x3;
  91. for(int i=0;i<f_c;i++){
  92. total += (m1[x][i] * m2[i][y]);
  93. }
  94.  
  95.  
  96. return total;
  97. }
  98.  
  99. void mostrarMatriz(int** m,int f,int c){
  100.  
  101. //Mostrar Matriz Total
  102. cout<<"\n-----------------------------------------\n";
  103. cout<<"La Matriz total es:\n";
  104. for(int i=0;i<f;i++){
  105. for(int j=0;j<c;j++){
  106. cout<<m[i][j]<<" ";
  107. }
  108. cout<<endl;
  109. }
  110. }

Podría usar un puntero de la funcion multi al usarla en multiplicarMatrices, aun que como tu dices, a mi me parece lo mismo xD.
En línea

Páginas: 1 [2] 3 Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Problema con Punteros en C
Programación C/C++
aaronas 8 2,734 Último mensaje 2 Abril 2012, 00:12 am
por david_BS
Problema con punteros.
Programación C/C++
vazquinhos 4 1,791 Último mensaje 20 Septiembre 2012, 18:35 pm
por do-while
Problema con punteros
Programación C/C++
NEGRO_PABLO 3 1,918 Último mensaje 30 Noviembre 2012, 18:41 pm
por twins
Problema con punteros.
Programación C/C++
maxim_o 2 839 Último mensaje 24 Junio 2016, 23:29 pm
por class_OpenGL
Representación visual de punteros y punteros a punteros.. « 1 2 »
Programación C/C++
digimikeh 13 1,966 Último mensaje 4 Mayo 2019, 01:54 am
por RayR
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines