Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: Shout en 1 Noviembre 2012, 18:23 pm



Título: El programa se cierra al usar string[]
Publicado por: Shout en 1 Noviembre 2012, 18:23 pm
Hola!

Tengo este código:
Código
  1. #include <iostream>
  2. #include <cmath>
  3.  
  4. using namespace std;
  5.  
  6. string _sqrt(string num);
  7. string chunk_split(string source, int length = 2);
  8. string substr(string source, int start, int end);
  9. int chrpos(char s, char *str);
  10.  
  11. int main(){
  12. string s;
  13.  
  14. cout << "Insert a number:\n> ";
  15. cin >> s;
  16.  
  17. _sqrt(s);
  18.  
  19. cin.get();
  20. cin.get();
  21. return 0;
  22. }
  23.  
  24. int chrpos(char s, char *str){
  25. for(int i=0,c=(int)strlen(str);i<c;i++){
  26. if(str[i] == s) return i;
  27. }
  28. return -1;
  29. }
  30.  
  31. string chunk_split(string source, int length){
  32. int j = 0, t = (int)ceil((int)source.length()/2);
  33. string r[t];
  34. for(int i=0;i<source.length();i+=length){
  35. r[j] = substr(source, i, length);
  36. ++j;
  37. }
  38. return *r;
  39. }
  40.  
  41. string substr(string source, int start, int end){
  42. string r = "";
  43. for(int i=start,c=start+end;i<c;i++){
  44. r += source[i];
  45. }
  46. return r;
  47. }
  48.  
  49. string _sqrt(string num){
  50. // const int l = (int)ceil((int)num.length()/2);
  51. string arr[1024] = chunk_split(substr(num, 1, num.length() - 3), 2);
  52. for(int i=0;i<1024;i++){
  53. cout << "arr[" << i << "] = " << arr[i] << endl;
  54. }
  55. // cout << substr(num, 4, 4);
  56. }
  57.  

El problema es que, si le pongo de input "1234567", en el for de _sqrt SIEMPRE sale "23", en todos los 1024 elementos. Deberían estar vacíos los que van después del [2], pero no, todos son 23.

Alguien sabe a qué se debe?
Estoy intentando sacar la raíz cuadrada de un número en string, pero la función la haré más tarde, ya que no puedo seguir antes de solucionar esto.

Resumiendo: arr[] ha de contener los números de un string separados de 2 en 2.


Título: Re: El programa se cierra al usar string[]
Publicado por: lapras en 2 Noviembre 2012, 03:30 am
Un problema es la asignación de strings:
Código
  1. string arr[1024] = chunk_split(substr(num, 1, num.length() - 3), 2);
Con esto lo que haces es meter en todos los elementos de el array lo mismo.

Con este ejemplo se ve claro:

Código
  1. #include<stdio.h>
  2. #include<iostream>
  3. #include<string.h>
  4. #include<cmath>
  5. using namespace std;
  6.  
  7. int main(){
  8. string hole[5]="hole";
  9. hole[1]="hole";
  10. cout<<hole[3]<<endl;
  11. }
Esto imprime "hole"

Otro problema es que pretendes devolver muchas strings pero el tipo de retorno es string(solo una). Para ello se deben usar arrays de string.

Otro problema es que en el ceil haces casting a int dentro primero y así redondeas al más bajo cuando ceil se supone que debe redondear al más alto. Pero de todas maneras esto se puede solucionar sumando 1.

He modificado un poco tu código:
Código
  1. #include <iostream>
  2. #include <cmath>
  3. #include <string.h>
  4.  
  5. using namespace std;
  6.  
  7. string* _sqrt(string num);
  8. string* chunk_split(string source, int length = 2);
  9. string substr(string source, int start, int end);
  10. int chrpos(char s, char *str);
  11.  
  12. int main(){
  13. string s;
  14.  
  15. cout << "Insert a number:\n> ";
  16. cin >> s;
  17.  
  18. _sqrt(s);
  19.  
  20. //cin.get();
  21. cin.get();
  22. return 0;
  23. }
  24.  
  25. int chrpos(char s, char *str){
  26. for(int i=0,c=(int)strlen(str);i<c;i++){
  27. if(str[i] == s) return i;
  28. }
  29. return -1;
  30. }
  31.  
  32. string* chunk_split(string source, int length){
  33. int j = 0, t = (int)ceil((int)source.length()/2);
  34. string* r= new string[t+1]; //remember to delete
  35. for(int i=0;i<source.length();i+=length){
  36. r[j] = substr(source, i, ((source.length()-i==1)?(i+length-2):(i+length-1)));
  37. ++j;
  38. }
  39. return r;
  40. }
  41.  
  42. string substr(string source, int start, int end){
  43. string r = "";
  44. for(int i=start,c=end;i<=c;i++){
  45. r += source[i];
  46. }
  47. return r;
  48. }
  49.  
  50. string* _sqrt(string num){
  51. const int l = (int)ceil((int)num.length()/2);
  52. string* arr = chunk_split(substr(num, 0, num.length()-1 ), 2);
  53. for(int i=0;i<l+1;i++){
  54. cout << "arr[" << i << "] = " << arr[i] << endl;
  55. }
  56.  
  57. // cout << substr(num, 4, 4);
  58. return arr;
  59. }

Ah, y un error que me ha sorprendido por que daba segmentation fault es que la función _sqrt() no devuelve nada.

Supongo que quieres hacer la raíz cuadrada por el método manual que se enseña en el colegio. Me parece una gran idea. Si tienes más problemas puedes escribir aquí, estaré encantado de ayudarte.
Por si te interesa hay otros métodos de hacer raíces que se suelen usar en computación como el método babilónico (http://es.wikipedia.org/wiki/C%C3%A1lculo_de_la_ra%C3%ADz_cuadrada#Algoritmo_babil.C3.B3nico).


Título: Re: El programa se cierra al usar string[]
Publicado por: Shout en 2 Noviembre 2012, 11:57 am
Muchas gracias @tuket por la explicación tan completa! No se me había ocurrido usar *arr :P

Ahora pruebo y te digo si funciona.

Citar
Otro problema es que en el ceil haces casting a int dentro primero y así redondeas al más bajo cuando ceil se supone que debe redondear al más alto. Pero de todas maneras esto se puede solucionar sumando 1.
Pero lo hago después del ceil, así 7.123 se convertiría en 8 y luego lo convierto a int para que no tire error al iniciar la variable (creo que devolvía float o double el ceil).
Si me equivoco corrígeme.

PD: Sí, estoy intentando sacar la raíz cuadrada, pero no es exactamente para el colegio  :silbar: se me ocurrió sacar la raíz cuadrada de un número de 132 números (¡estoy loco! :P) y como ningún tipo de datos, ya sea double, long long ni parecidos lograba guardarlo, pues nada, a usar strings! :P Y para practicar me puse la condición de nada de sqrt(), pero eso se soluciona fácil creando una función sqrt2() creada por mi, como el método babilónico que me has dejado.

Gracias!

=== Edito: ===
Lo he probado y funciona, pero al final tira error:
Segmentation fault (core dumped)
Process returned 139 (0x8B)

Estoy usando Linux Mint Maya versión MATE


Título: Re: El programa se cierra al usar string[]
Publicado por: lapras en 3 Noviembre 2012, 01:44 am
(int)ceil((int)num.length()/2)
En este segmento de código lo que pasa es que si por ejemplo num.length() es 7 -> num.length()/2=3.5-->(int)num.length()/2=3 -->ceil(3.0)==3

No quería decir que eso sea para el colegio, sino que ese método de hacer raíces manualmente se suele enseñar en el colegio(al menos a mi me lo enseñaron en el cole).

Citar
Y para practicar me puse la condición de nada de sqrt(), pero eso se soluciona fácil creando una función sqrt2() creada por mi, como el método babilónico que me has dejado.
¿ Podrías explicar esta frase? Es que no la entiendo. xD

Sobre lo de que te da segmentation fault... ¿Podrías decirme para que numero lo has probado? Es que con los números que yo he introducido no me da ese error.


Título: Re: El programa se cierra al usar string[]
Publicado por: Shout en 3 Noviembre 2012, 14:44 pm
Sí, pero lo que pasa es que el (int) (creo) que se aplica a source.length() y no a la división, por eso está ahí, ya que .length() antes tiraba error de conversión.

Lo de sqrt() es que si usase la función sqrt() me sería fácil, y esto era para practicar algo más "dificilillo" :D

Y el número que he probado es "1212".


Título: Re: El programa se cierra al usar string[]
Publicado por: lapras en 3 Noviembre 2012, 23:32 pm
Claro que si hombre, tiene que ser difícil. xD
Pues no se, a mi si que me funciona con "1212".
A lo mejor es que el código que he puesto no es el que me quedó al final.
A ver si es este:
Código
  1. #include <iostream>
  2. #include <cmath>
  3. #include <string.h>
  4.  
  5. using namespace std;
  6.  
  7. string* _sqrt(string num);
  8. string* chunk_split(string source, int length = 2);
  9. string substr(string source, int start, int end);
  10. int chrpos(char s, char *str);
  11.  
  12. int main(){
  13. string s;
  14.  
  15. cout << "Insert a number:\n> ";
  16. cin >> s;
  17.  
  18. _sqrt(s);
  19.  
  20. //cin.get();
  21. cin.get();
  22. return 0;
  23. }
  24.  
  25. int chrpos(char s, char *str){
  26. for(int i=0,c=(int)strlen(str);i<c;i++){
  27. if(str[i] == s) return i;
  28. }
  29. return -1;
  30. }
  31.  
  32. string* chunk_split(string source, int length){
  33. int j = 0, t = (int)ceil((int)source.length()/2);
  34. string* r= new string[t+1]; //remember to delete
  35. for(int i=0;i<source.length();i+=length){
  36. r[j] = substr(source, i, ((source.length()-i==1)?(i+length-2):(i+length-1)));
  37. ++j;
  38. }
  39. return r;
  40. }
  41.  
  42. string substr(string source, int start, int end){
  43. string r = "";
  44. for(int i=start,c=end;i<=c;i++){
  45. r += source[i];
  46. }
  47. return r;
  48. }
  49.  
  50. string* _sqrt(string num){
  51. const int l = (int)ceil((int)num.length()/2);
  52. string* arr = chunk_split(substr(num, 0, num.length()-1 ), 2);
  53. for(int i=0;i<l+1;i++){
  54. cout << "arr[" << i << "] = " << arr[i] << endl;
  55. }
  56.  
  57. // cout << substr(num, 4, 4);
  58. return arr;
  59. }

De todos modos revisaré el código.