Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





C++ Por qué no funciona?

Iniciado por J_F_NASH, 22 de Enero de 2014, 09:44:46 PM

« anterior - próximo »

J_F_NASH

Trato de hacer un arreglo de cadenas.
Luego escribir una cadena he insertarla en una posicion de memoria.

Qué estoy haciendo mal?


char *tabla[6][10];

tabla[0][0] = "xxx1";
tabla[1][0] = "xxx2";
tabla[2][0] = "xxx3";
tabla[3][0] = "xxx4";
tabla[4][0] = "xxx5";

cin >> tabla[0][0]; //Aqui da error cuando introduzco una cadena de caracteres y presiono enter

El error es:
"Intento de leer o escribir en la memoria protegida. A menudo, esto indica que hay otra memoria dañada."

Cómo deberia hacerlo?

Gracias.

Darago_malaga

Posiblemente este metiendo la pata porque tengo muy oxidado mi c++...pero tabla[0][0] es un caracter no??? Si intentas meter un string te petara.... No seria:

string *tabla[6][10];

o

cin >> tabla[0];

Gallo

#2
tabla[0][0] es un puntero a char, el cual inicializas apuntando a una región estática osea const char* a la cual no se puede escribir, y cosa que ademas está deprecated. Tienes dos opciones, o bien prealojas memória dinámica en esa tabla, por ejemplo de esta forma:

tabla[0][0] = new char[6];

o con un malloc si es en C, con lo cual podrías escribir cadenas de hasta 6 caracteres, 5 si contamos que el último deberia ser 0. O bien delcaras un vector de chars para escribir con el en cin y luego apuntas con los punteros de la tabla a esa memoria.

char cosa[9];
cin >> cosa;
tabla[1][0] = cosa;
cout << tabla[1][0];


Pero ten en cuenta que "cosa" solo existe hasta que sales de la actual función, con lo que si la tabla está fuera, apuntará a un sector de memoria que se usará para otras cosas, cosa que no pasaría con la memoria alojada dinámicamente.

Ambas cosas las puedes hacer utilizando clases de la c++ standard library, por ejemplo así:

    std::vector<std::vector<std::string>> tabla(5);
    tabla[0] = std::vector<std::string>(1);
    tabla[1] = std::vector<std::string>(1);
    tabla[2] = std::vector<std::string>(1);
    tabla[3] = std::vector<std::string>(1);
    tabla[4] = std::vector<std::string>(1);
   
    std::cin >> tabla[0][0];
    std::cout << tabla[0][0];

   

Manu343726

#3
Cita de: Gallo en 23 de Enero de 2014, 12:49:48 AM
Ambas cosas las puedes hacer utilizando clases de la c++ standard library, por ejemplo así:

    std::vector<std::vector<std::string>> tabla(5);
    tabla[0] = std::vector<std::string>(1);
    tabla[1] = std::vector<std::string>(1);
    tabla[2] = std::vector<std::string>(1);
    tabla[3] = std::vector<std::string>(1);
    tabla[4] = std::vector<std::string>(1);
   
    std::cin >> tabla[0][0];
    std::cout << tabla[0][0];

   

Ten cuidado al hacer asignaciones del estilo lvalue = llamada al constructor (En plan Java, vamos). Incluso en C++11 con move semantics, el rendimiento de ese tipoc de cosas es horrible. El compilador no es capaz de hacer RVOs (O el tipo de copy elision que se aplique en este caso) con ese tipo de cosas. Así que en el mejor de los casos (C++11 move semantics) tienes ésto:


Constructor call
Move assigment
Destructor call


Es decir, ese absurdo rvalue temporal no te lo quitas de encima.

Lo mejor es que uses construcción in-place. En el caso de std::vector, usando emplace_back():

   

constexpr std::size_t filas = 5;
constexpr std::size_t columnas = 5; //Por ejemplo

std::vector<std::vector<std::string>> tabla;

for( std::size_t i = 0 ; i < filas ; ++i )
    tabla.emplace_back( columnas );
   
    std::cin >> tabla[0][0];
    std::cout << tabla[0][0];




Aunque lo hicieras de la otra manera, piensa que no tiene mucho sentido: Has usado el constructor que inicializa el vector a n elementos (5 en tu caso), y luego creas instancias sueltas que asignas a dichos elementos. Éstas son el tipo de cosas que se hacen en java porque cambiar referencias es gratis y pedir memoria a la JVM es también gratis (No es lo mismo un new/malloc() que un new de Java/C#). Pero en C++ son horribles, ya que utiliza semántica de valor, no de referencia. Incluso con move semantics (Move es menos trabajo que copiar, pero es trabajo).






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.