[C con Clase] necesito ayuda con este código

Steven R. Davidson vze266ft en verizon.net
Mar Feb 12 07:02:28 CET 2008


Hola Leonel,

Leonel Florín Sellés wrote:
> mira, estoy programando hace rato ya en C, estoy aprendiendo, y
> depeus paso para C++, no se preocupen.
> 
> la cuestión es que, estoy haciendo un ejercicio, donde se tiene que
> insertar una lista de letras o palabras, en mi caso, letras, en dos
> listas enlazadas diferentes, son listas enlazadas nada mas, sin
> complicaciones, y luego tengo que unir estas dos lista en una, pero
> el problema radica en, cuando voy a llenar la lista 2, cuando se
> llena la lista 1 no da problema alguno, pero cuando voy para la dos,
> cuando trato de insertar el segundo elemento me dice que violación
> de acceso, y estoy utilizando una misma function para insertar
> elementos en ambas listas, con una me da error y con la otra no.
> depurando he podido dar con alguna cosa pero no lo entiendo, miren.
> 
> cuando paso el primer elemento no hay problemas, pero cuando paso el
> segundo, le mando a la funtion un apuntador de apuntado, una doble
> indirección, y le paso el elemento que va a ser insertado, pero
> parece que no recibe la dirección de el apuntador que contiene el
> inicio de la segunda linea, y se detiene en el ciclo que es el que
> va a recorrer la lista.
> 
> no se alarmen cuando vean que inserto un carácter dentro de una
> variable arreglo de tipo char con un solo elemento, el problema por
> el que hago esto es que cuando la función scanf me va a pedir un
> elemento char con el control de formato %c, scanf("%c", &letra); ,
> es como si no me hiera caso y lo pasa por alto, por eso es que tuve
> que tomar esta alternativa.
> 

Pues me temo que éste es el problema. Escribes,

nodoPtr inicio_lista1_Ptr = NULL;
nodoPtr inicio_lista_Ptr2 = NULL;
char letra[1], opcion;

Cuando usas 'letra' para leer y guardar una cadena de caracteres, no 
tienes en cuenta que todas las cadenas terminan en el carácter nulo. La 
función 'scanf()' agrega el carácter nulo después de guardar el carácter 
leído. Como tu array es de un solo elemento, ese carácter nulo es 
guardado posteriormente en memoria.

Lo más seguro es que tu compilador organiza las variables en una pila, 
por lo que la memoria posterior a 'letra' es ocupada por la variable 
'inicio_lista_Ptr2'. Esto implica que 'scanf()' agregará el carácter 
nulo en la memoria de 'inicio_lista_Ptr2' corrompiéndola.

La solución sería crear una cadena de más caracteres. Por ejemplo,

char letra[2];

También podrías agregar la restricción de la cantidad de caracteres al 
leer con 'scanf()'. Por ejemplo,

scanf( "%1s", letra );


Dicho lo anterior, podemos pasar al otro "problema" que estabas teniendo 
con el comportamiento de aparentemente hacer caso omiso a la lectura y 
saltándola al pedir el siguiente carácter con el especificador %c. El 
problema realmente proviene de una lectura previa del número entero para 
la opción. Escribes:

scanf( "%d", &opcion );

En este caso, esta lectura y conversión continúa hasta que se encuentre 
el carácter '\n'. Por ejemplo, el usuario escribe:

2[ENTER]

En el búfer del teclado, obtendremos,

"2\n"

Cuando llega la lectura de 'scanf()', obtendremos lo siguiente:

búfer del teclado <-- "\n"
opcion <-- 2

Como puedes ver, queda un carácter en el búfer. Cuando lleguemos a la 
segunda lectura de 'scanf()' ésta se encontrará con el carácter '\n'. 
Este carácter es extraído y guardado:

búfer del teclado <-- ""
letra <-- '\n'

Y pasará a la siguiente sentencia. Por esta razón, el programa aparenta 
saltarse la lectura.

Lo que puedes hacer es extraer ese carácter después de leer el número 
para la opcidn del menú. Por ejemplo,

char letra, opcion;

menu();
scanf( "%d", &opcion );
getchar();  // Extraemos '\n' del búfer del teclado

while( opcion != 5 )
{
   switch( opcion )
   {
     ...
     case 2:
       printf( "\nEntre la letra para la Segunda Lista:\n?." );
       scanf( "%c", &letra );
       getchar();  // Extraemos '\n' del búfer del teclado
     ...
   }
}


También tienes un error en el programa. Creas memoria dinámicamente, 
pero no la liberas. Debes usar 'free()' tantas veces como invocaste 
'malloc()'.


Aparte de los problemas anteriores, he visto un problema de diseño. En 
algunas funciones, pasas un puntero a 'nodoPtr', lo cual no lo 
necesitas. Recuerda que 'nodoPtr' ya es un puntero. En la función 
'insertar()', necesitas un puntero a 'nodoPtr', pero no en 
'mostrar_lista()'. En 'unir()', es posible que también necesites un 
'nodoPtr *'. Además, en 'mostrar_lista()' deberías acepta un 'const 
nodoPtr', porque no tiene intención alguna de modificar el contenido de 
la estructura apuntada.


Espero que todo esto te ayude.

Steven






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