Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: z3nth10n en 19 Septiembre 2013, 20:13 pm



Título: Hacer array de 2D a través del split de una string con un delimitador
Publicado por: z3nth10n en 19 Septiembre 2013, 20:13 pm
Hola bueno, esta va a ser la primera pregunta que haga de C++ en el foro...

Y bueno, pues yo creo que es de nivel...
xD

Código
  1. #include <iostream>
  2. #include <string>
  3.  
  4. int main()
  5. {
  6. std::string s = "0,0,0,1,1,1,0,0,1";
  7. std::string delimiter = ",";
  8.  
  9. int x = 0;
  10. std::string mapa[9];
  11.  
  12. size_t pos = 0;
  13. std::string token;
  14. while ((pos = s.find(delimiter)) != std::string::npos) {
  15.    token = s.substr(0, pos);
  16.    std::cout << token << std::endl;
  17.    s.erase(0, pos + delimiter.length());
  18.  
  19.    mapa[x] = token;
  20.    x++;
  21. }
  22. std::cout << s << std::endl;
  23. cin.get();
  24. }

Básicamente esto obtiene la dimensión X de la array, pero ahora necesito la segunda que básicamente sería la Y, con otro delimitador...

Tengo 2 problema 1 es que no se como hacerlo y 2 es que:

Código
  1. std::cout << s << std::endl;

Esto obtiene el último string que sería un 1:

Citar
"0,0,0,1,1,1,0,0,1"

Como haría para que mostrase todo sin tener que hacer cosas raras... ?

Y por si queréis el archivo de texto del que extraigo todo el mejunje:

Citar
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1

Gracias a todo aquel que me quiera guiar y/o hacer el code!
Un saludo. ;D

Me han dicho que use vectores, pero no tengo ni la mas mínima idea de como se usan... xD


Título: Re: Hacer array de 2D a través del split de una string con un delimitador
Publicado por: 0xDani en 19 Septiembre 2013, 20:56 pm
A ver si lo he entendido: tienes una entrada, que es la que muestras en el archivo; y quieres generar una salida, que es un array bidimensional de caracteres, de forma que el array contenga en los índices x e y lo mismo que hay en esas coordenadas en el archivo.

Lo que veo es que puedes tener un array:

Código
  1. char myArray[MAX_ROWS][MAX_COLUMNS];

También te lo puedes hacer dinámico pero eso ya es cosa tuya.

Entonces lo que haces es que lees un carácter del archivo, y si es distinto de un salto de línea lo guardas en el array, en la posición de la fila actual, y en la de la columna anterior más 1. Si es un salto de línea, entonces sumas uno a la fila actual y pones la columna a cero otra vez.

Código
  1. size_t row=0, column=0;
  2. std::string s;
  3. while(getline(file, s))
  4. {
  5.    size_t i=0;
  6.    while(s[i]!='\n')
  7.    {
  8.         myArray[row][column++] = s[i];
  9.    }
  10.    row++;
  11.    column = 0;
  12. }
  13.  


Título: Re: Hacer array de 2D a través del split de una string con un delimitador
Publicado por: z3nth10n en 20 Septiembre 2013, 15:06 pm
Me resulta bastante curioso tu code, ya que encontre este:

Código
  1. fstream fstr;
  2. fstr.open("file.txt",ios::in);
  3. string str;
  4. int yDimension = 0;
  5. while(getline(fstr,str)
  6. {
  7.    yDimension++;   //do appropriate thing with the y dimension
  8.    std::string token;
  9.    while ((pos = str.find(delimiter)) != std::string::npos) {
  10.        token = str.substr(0, pos);
  11.        std::cout << token << std::endl;
  12.        str.erase(0, pos + delimiter.length());
  13.        mapa[x] = token;
  14.        x++;
  15.    }
  16. }

Que por cierto está mal hecho... (El code de arriba ^^)

He estado probando, y por alguna extraña razon tu code:

Código
  1. #include <iostream>
  2. #include <string>
  3. #include <fstream>
  4.  
  5.  
  6. using namespace std;
  7.  
  8. fstream myfile;
  9. size_t row=0, column=0;
  10. std::string s;
  11. int myArray[30][10];
  12.  
  13. int main() {
  14.  
  15. myfile.open("mapa.txt");
  16.  
  17. while(getline(myfile, s))
  18. {
  19.    size_t i=0;
  20.    while(s[i]!='\n')
  21.    {
  22.         myArray[row][column] = s[i];
  23.         std::cout << myArray[row][column];
  24.         column++;
  25.    }
  26.    row++;
  27.    column = 0;
  28. }
  29.  
  30. std::cout << myArray[3][1] << std::endl;
  31. std::cin.get();
  32.  
  33. return 0;
  34. }

(Editado un poco) Hace una cosa rarisima, xD Muestra 48 en la consola y cuando lleva 4 lineas crashea xD Eso en un milisegundo y me resulta curioso no se porque... :P



Me he tomado la molestía y con la ayuda de Skatewinner he hecho esto:

Código
  1. #include <iostream>
  2. #include <string>
  3. #include <fstream>
  4.  
  5. using namespace std;
  6.  
  7. int main()
  8. {
  9.  
  10. fstream fstr;
  11. fstr.open("mapa.txt");
  12.  
  13. int mapa[31][9], x = 0, y = 0;
  14. char c;
  15. while(fstr.good())
  16. {
  17.    c = fstr.get();
  18.    if (c!= ',') {
  19.        mapa[x][y] = c;
  20.        x++;
  21.    }
  22.    if (c=='\n')
  23.    {
  24.        x = 0;
  25.        y++;
  26.    }
  27. }
  28.  
  29. fstr.close();
  30. cin.get();
  31.  
  32. }

Es lo más sencillo que lo he podido hacer.. :P
Y sin embargo sigo teniendo el mismo problema del 48... :/

(http://gyazo.com/30b4ea2999c9d0e4be6681ccccb166af.png)



Ya se a que se debe, se debe a que el array lo almacena todo en ascii y si le digo que lo muestre en entero pues va a mostrar el entero del ascii xd


Título: Re: Hacer array de 2D a través del split de una string con un delimitador
Publicado por: 0xDani en 22 Septiembre 2013, 15:02 pm
Umm, claro, en mi code no he tenido en cuenta las comas. De todas formas, el que crashee depende del tamaño que le hayas puesto al array.


Título: Re: Hacer array de 2D a través del split de una string con un delimitador
Publicado por: z3nth10n en 22 Septiembre 2013, 16:49 pm
Bueno tio, gracias por las molestias que te tomas, pero ya hace 1 día que termine todo el cacharrerio con ayuda de skatewinner y en esto se quedo la función:

Código
  1. std::ifstream ifile("mapa.txt");
  2. if (ifile) {
  3. fstr.open("mapa.txt");
  4.  
  5. char mapa[worldWidth][worldHeight];
  6. int x = 0, y = 0;
  7. char c;
  8. while(fstr.good())
  9. {
  10.    c = fstr.get();
  11.    if (int(c) != -1 && c!= ',' && c!= '\n') {
  12.        mapa[x][y] = c;
  13.        x++;
  14.    }
  15.    if (c=='\n')
  16.    {
  17.        x = 0;
  18.        y++;
  19.    }
  20. }
  21.  
  22.        for (int x = 0; x<worldWidth; x++) {
  23.            for (int y = 0; y<worldHeight; y++) {
  24.                sf::Texture texture;
  25.                if (!texture.loadFromFile("images/blocks/" + ruta(mapa[x][y]) + ".png"))
  26.                return -1;
  27.  
  28.                sf::RectangleShape rectCaja(sf::Vector2f(16, 16));
  29.                rectCaja.setPosition(sf::Vector2f(x*16, y*16));
  30.                //rectCaja.setFillColor(sf::Color::Black);
  31.                rectCaja.setTexture(&texture);
  32.                window.draw(rectCaja);
  33.            }
  34.        }
  35. }

Un saludo.


Título: Re: Hacer array de 2D a través del split de una string con un delimitador
Publicado por: rir3760 en 22 Septiembre 2013, 18:18 pm
Si todos lo campos tienen la misma longitud no es necesario el separador (la coma), si se elimina el contenido del archivo seria:
Código:
000000000000000000000000000000
000000000000000000000000000000
000000000000000000000000000000
000000000000000000000000000000
000000000000000000000000000000
111111111111111111111111111111
111111111111111111111111111111
111111111111111111111111111111
111111111111111111111111111111
111111111111111111111111111111
Y la lectura del archivo se podría realizar utilizando un vector y un bucle:
Código
  1. ifstream in;
  2. vector<string> linea;
  3. string aux;
  4.  
  5. // Apertura del archivo
  6.  
  7. while (getline(in, aux))
  8.   linea.push_back(aux);
  9. in.close();

Y si se debe almacenar la información en un array de arrays de caracteres la lectura que haces:
Código
  1. char mapa[worldWidth][worldHeight];
  2. int x = 0, y = 0;
  3. char c;
  4.  
  5. while(fstr.good())
  6. {
  7.   c = fstr.get();
  8.   if (int(c) != -1 && c!= ',' && c!= '\n') {
  9.       mapa[x][y] = c;
  10.       x++;
  11.   }
  12.   if (c=='\n')
  13.   {
  14.       x = 0;
  15.       y++;
  16.   }
  17. }
Tiene dos errores: almacenar el valor de retorno de get en una variable de tipo char cuando debería ser de tipo int y asumir que el valor de EOF es -1 (lo usual pero no esta garantizado).

Seria mejor cambiar ese fragmento utilizando otra versión de la función get:
Código
  1. char mapa[worldWidth][worldHeight];
  2. int x = 0, y = 0;
  3. char c;
  4.  
  5. while (fstr.get(c))
  6.   if (c == '\n'){
  7.      x = 0;
  8.      y++;
  9.   }else if (c != ','){
  10.      mapa[x][y] = c;
  11.      x++;
  12.   }

Un saludo


Título: Re: Hacer array de 2D a través del split de una string con un delimitador
Publicado por: z3nth10n en 22 Septiembre 2013, 18:26 pm
Muchisimas gracias rir... xD Está bastante simplificado el code.. :D