[C con Clase] fatal error LNK1136: invalid or corrupt file

Steven Davidson srd4121 en njit.edu
Sab Abr 16 10:46:47 CEST 2011


Hola Wolverine,

On 4/16/2011 1:23 AM, wolverine wrote:
> hola steven cuanto tiempo bueno pues adaptandolo al ejemplo dela
> pagina mi destructor quedaria algo asi usando el cab:
>
>
> 	  util* aux;
>
> 	while(cab!=NULL) {
> 		aux = cab;
> 		cab = cab->sgte;
> 		delete aux;
>     }
> 	ultimo = NULL;
>

Esta última asignación no es necesaria, ya que este objeto de la clase 
'listautil' y sus datos serán liberados y dejarán de existir en memoria. 
Por lo tanto, es irrelevante qué información guardan, ya que se va a 
perder en cuanto se termine de ejectuar esta función - el destructor.

>        if(cab==NULL)
> 	  cout<<"\n        no hay utiles en la lista";
> 	  else
> 	  cout<<"\n\n Lista de utiles  borrada.";
>
>       getch();
>
>
> ...bueno al menos ya se soluciono lo del "general protection
> exception" cuando ingreso la opcion salir, lo unico es que la ventana
> se queda inactiva y alli se queda bueno eso no me preocupa tanto, lo
> que pasa esque esta lista forma parte de un programa mas grande al
> cual envio  a esta lista como parametro a otra  lista de utiles
> comprados . Esta ultima es una lista que sirve parallevar el registro
> de los utiles comprados que por cierto ya no es una lista enlazada
> sino una dinamica empleando un vector
>

No estoy seguro de la implementación exacta que has hecho, pero sugiero 
mantener o bien un vector (array) de punteros a los útiles, o incluso 
punteros a los nodos que contienen los útiles, o bien una lista 
dinámciamente enlazada de punteros a los útiles. Por ejemplo,

util **pListaUtilesCompradas;
int nCant;

Ahora puedes crear un vector (array) dinámico de punteros a 'util'. Por 
ejemplo,

pListaUtilesCompradas = new util *[nCant];

Y luego, puedes ir agregando útiles existentes al vector. Obtenemos 
estos punteros a 'util' de la lista dinámicamente enlazada que ya creaste.

De esta manera, no tienes que mantener información duplicada. Puedes 
pensar que es como una mini-base de datos.

>
> //CLASE QUE REGISTRA LOS UITLES COMPRADOS
>
> class compra
> {
>    char codutil[10];
>    int cantidad;
>    float subtotal;  //precio*cantidad
>

Si 'subtotal' es calculada, entonces no aconsejo guardarla como miembro, 
sino que sea calculada y dada a través de una función miembro.

>    public:
>
>     compra();
>
>     void llenar(listautil);
>    void presenta();
>    char* getcodutil(){return codutil;}
>    void setcodutil(char* cod){strcpy(codutil,cod);}
>    float getsubtotal(){return subtotal;}

No retornes el valor, sino calcúlalo en el momento.

>
>
>
> };
>
>
> //////////////////////////funciones cLAse compra//////////////////////
>   compra::compra(){
>     codutil[0]=NULL;

Usa el carácter nulo, '\0'.

>
>    cantidad=0;
>     subtotal=0.0;
>
>   }
>
> void compra::llenar(listautil LU){

En sí, esto no es un problema, pero según el diseño actual de 
'listautil', sí los vas a tener.

Aquí estás pasando el objeto por copia (o por valor). Esto significa que 
se instancia un objeto local, 'LU', que será una copia del objeto 
original que pasas a esta función miembro.

El problema es que tu diseño de 'listautil' no implementa un constructor 
copia. Por lo tanto, se usa el constructor copia por defecto, que 
simplemente copia la información de un objeto a otro. En tu caso, esto 
es problemático porque estás copiando punteros; o sea, copias 
direcciones de memoria. Esto se llama: una copia superficial.

La solución es hacer una copia profunda. Implementa un constructor copia 
para 'listautil' para crear memoria dinámicamente para cada nodo de la 
lista y copiar cada nodo a los nuevos. Esto es,

listautil::listautil( const listautil &ref )
{
   // Crea cada nodo y
   //   copia cada nodo de 'ref' a cada nodo de este objeto
   ...
}

Ahora bien, en el caso de 'llenar()', recomiendo pasar el objeto 
original por referencia, pero tratado como un objeto constante. Esto es,

void compra::llenar( const listautil &LU )

Así nos ahorramos memoria al pasar el objeto como parámetro y además no 
instanciamos un objeto local.

>
> 	util* posx;
> 	char cod1[10];
> 		posx=new util();
>
>   cout<<"\n  Registro de nuevo compra: \n" ;
>
> SD>//AQUI ES EL PROBLEMA SOLO ME DEJA COMPRAR UN UTIL ESCOLAR
> SD>//Y SI QUIERO SEGUIR COMPRANDO ES COMO SI LA LISTA DE UTILES SE HUBIESE SD>//BORRADO Y POR LO TANTO EL DO-WHILE YANO ME DEJA AVANZAR
>

He dado la explicación anterior acerca del problema.

[CORTE]

> Es ovio que para saber que utiles quiero "comprar" debo saber que
> utiles existen, por eso mismo es que en cada elemento de las Lista de
> utiles comprados debo tener adentro de esta ala Lista de Utiles, creo
> que ahi parte el nuevo problema...meter una lista enlazada dentro de
> "algo"...creo que los punteros lo complican todo pero tengo que
> hacerlo exclusivamente asi lamentablemente.
>

Creo que he explicado la solución a esto. Piensa que creas una base de 
datos, que es la lista de útiles existentes. En la lista de compras, 
creas otra lista de punteros a estos útiles los cuales existen en esa 
base de datos. Así no tienes que copiar útiles, sino que apuntas a 
ellos. Seguramente necesitarás esa lista de útiles como miembro a esta 
lista de compras.

Por otro lado, también es cierto que cada útil tiene su código, que me 
imagino que es a modo de identificación. Por lo tanto, podrías crear una 
lista de códigos los cuales representan los útiles. Esta técnica es 
buena para relacionar información, como en una base de datos, pero como 
tenemos punteros en C++, creo que éstos nos sirve mejor que los códigos.

> Y esta lista de utiles comprados(listacompras) es un miembro dato de
> class venta que forma parte de una Listaventas pero ya no quiero
> complicar mas las cosas tampoco se sime deje entender bueno las
> disculpas del caso sinome supe expresar de todos modos se agradece la
> ayuda o comentarios
>

Nuevamente, estamos ante el mismo problema de antes. La información - 
los útiles - sigue siendo la misma. Por consiguiente, creamos listas o 
vectores de punteros o de códigos para acceder a esa información 
indirectamente.

Sugiero que dediques más tiempo al diseño, antes de lanzarte a escribir 
código fuente. Piensa en las soluciones que te he dado; quizá te 
interesen más.


Espero que todo esto te ayude.

Steven





Más información sobre la lista de distribución Cconclase