[C con Clase] tengo unas dudas con bibliotek

Steven Davidson steven en conclase.net
Lun Feb 12 21:47:35 CET 2007


Hola Luis,

El pasado 2007-02-09 23:20:39, Luis escribió:

L> >
L> >
L> >
L> > En cuanto a este programa en particular, "bibliotek", contiene 3 errores
L> > semánticos que son los siguientes:
L> >
L> > - En 'eliminar()', escribe:
L> por favor podrias explicarme cual es la diferencia entre estas 2 y por que
L> con el tuyo funciona, bueno ami parecer el primero esta bien.
L> Dudas:
L>    1. solo que la variable "i" va a tener alcanse en este "for".
L>    2. ¿Porque ";" no se supone que deberia ir "{ }"?.
L>    3. y por que && se que "&" se lee direción de, ¿pero &&?.
L> // for(int i=0;i<tam&&AUX!=bib[i]->cod;i++);
L> int i=0;
L> for( ;i<tam&&AUX!=bib[i]->cod;i++);

1. El problema no está en que la variable 'i' se declare en el bucle 'for'. El problema es que se intenta usar la variable 'i' fuera del bucle. El código es el siguiente:

for( int i=0; i<tam&&AUX!=bib[i]->cod; i++ );

if( i==tam )  { g(4,20); puts("NO EXISTE EL CODIGO;"); getch(); clrscr(); }
else
{
  bib[i]=NULL; g(4,20); puts("LIBRO ELIMINADO"); getch();
  ...
}

Como puedes ver, otras funciones posteriores al bucle 'for' intentan usar la variable 'i'. Sin embargo, su declaración queda comprendida en el ámbito del bucle 'for' y por tanto podemos decir que 'i' sólo pertenece a 'for'.

2. No hace falta poner {} si sólo se trata de una sola sentencia. En este caso, se trata de una sentencia nula o vacía; es decir, "no hace nada" o en el caso de un bucle 'for': "no existe cuerpo".

La sintaxis del bucle 'for' es la siguiente:

for ( [<expresión_1>] ; [<expresión_2>] ; [<expresión_3>] ) <sentencia>

Las expresiones son optativas. Para <sentencia>, tenemos la siguiente definición o sintaxis:

<sentencia> <-- <sentencia_única> | <bloque_de_sentencias>

Por lo tanto, podemos tener una sola sentencia o un bloque de sentencias que por definición empieza por { y termina por }.

Te pongo un ejemplo parecido,

for( int n=1; n<=20; n++ )
  cout << n << endl;

El cuerpo del bucle 'for' consiste solamente de una sentencia: cout. Por lo tanto, no es necesario poner las llaves. Si quieres, puedes hacerlo,

for( int n=1; n<=20; n++ )
{
  cout << n << endl;
}

Sin embargo, para casos sencillos, las llaves puede ser un estorbo para la legibilidad del programa.

3. Los símbolos & y && representan tres operadores diferentes y un declarador. En el caso del operador &, éste tiene una cierta dualidad ya que puede ser un operador unitario o binario. El símbolo & también sirve de declarador; es decir, a la hora de declarar una variable. Brevemente explicaré las operaciones:

& (unitario) : consigue la dirección de memoria de una variable.
& (binario)  : realiza la operación AND a nivel de bits.
&&           : realiza la operación AND booleana o condicional.

El declarador & sirve para declarar una referencia.

Si quieres, te pongo unos ejemplos de cada,

void func( long double * &p, long double  datos[], unsigned long int nCant,
           bool bMostrarPositivos );

int main()
{
  long double lista[100];
  long double *ptr = lista;
  ...
  func( ptr, lista, 100, true );
  ...
}

void func( long double * &p, long double  datos[], unsigned long int nCant,
           bool bMostrarPositivos )
{
  for( int i=0; i<nCant; i++ )
  {
    if( 0 == datos[i] )  p = &datos[i];
    if( bMostrarPositivos && datos[i] >= 0 )
      cout << datos[i];
  }
}

Para el otro "uso" del operador &, los ejemplos son algo más esotéricos, ya que se manipulan los bits de un valor. Por ejemplo,

// Modos para ficheros
const unsigned char LECTURA   = 0x01;  // 00000001
const unsigned char ESCRITURA = 0x02;  // 00000010
const unsigned char TEXTO     = 0x04;  // 00000100
const unsigned char NUEVO     = 0x08;  // 00001000
const unsigned char EXISTE    = 0x08;  // 00001000
...
fichero fi = AbrirFichero( "datos.dat", LECTURA | ESCRITURA | BINARIO | NUEVO );
...
func( fi );
...

void func( const fichero &fi )
{
  unsigned char modo = ConseguirModo( fi );

  // ¿El fichero es binario?
  if( modo & BINARIO )  EscribirBinario(...);
  else  EscribirTexto(...);

  // ¿El fichero es para lectura?
  if( modo & LECTURA )  ...

  // ¿El fichero es para escritura?
  if( modo & ESCRITURA )  ...

  // ¿El fichero es para lectura y escritura simultáneamente?
  if( modo & (LECTURA | ESCRITURA) )  ...

  // ¿El fichero tuvo que ser creado (sólo en modo escritura)?
  if( modo & (ESCRITURA | NUEVO) )  ...

  // ¿El fichero existió previamente (sólo en modo lectura)?
  if( modo & (LECTURA | NUEVO) )  ...
  ...
}

L> si pudes responderme a estos errores sino no hya problema buscare otro
L> código.
L> ademas me vas a disculpar lo molestoso, pero igual no me funciona hice lo
L> que dijistes, pero ahora presenta los siguientes erroes, al parecer le falta
L> inplementar una funcion daley?, este es el mensaje que me presenta.

Te recuerdo que el programa fue diseñado para compiladores de Borland. En particular, compiladores antiguos de Borland para MS-DOS como pueden ser: Turbo C++ o Borland C++. No estoy seguro si compilará bajo Builder C++, aunque creo que sí.

Si no tienes uno de estos compiladores, entonces lo más seguro es que no te funcione debido a las funciones no estándares como 'delay()', 'clrscr()', 'gotoxy()', etc..

Veamos los mensajes que te dio el compilador.

L> C++ Warning] PruebBiblioteca.cpp(76): W8071 Conversion may lose significant
L> digits.

Esto tiene que ver con la sentencia:

op = getch();

La función 'getch()' retorna un 'int', pero 'op' fue declarada como 'char'. Por lo tanto, es posible que no se pueda guardar toda la información.

L> [C++ Warning] PruebBiblioteca.cpp(221): W8080 'i' is declared but never
L> used.

Esto es cosa del análisis del compilador, que piensa que la variable 'i' no tuvo gran impacto en el comportamiento del programa o función.

L> [C++ Warning] PruebBiblioteca.cpp(256): W8071 Conversion may lose
L> significant digits.

Igual que el primer aviso.

L> [C++ Warning] PruebBiblioteca.cpp(297): W8013 Possible use of 'tecla' before
L> definition.

Aquí, se declara 'tecla', pero no contiene un valor determinado, pero inmediatamente es usada para una comprobación. La sentencia en cuestión es:

while( tecla!=13 )

Podemos inicializar la variable 'tecla' previamente para que no tengamos sorpresas. Por ejemplo,

unsigned char tecla = 0;

while( tecla!=13 )

L> [C++ Warning] PruebBiblioteca.cpp(298): W8071 Conversion may lose
L> significant digits.

Lo mismo que antes.

L> [C++ Warning] PruebBiblioteca.cpp(337): W8075 Suspicious pointer conversion.

Esto se debe a un error al retornar un array. Se escribe:

char *capturar( int longitud, int tipo )
{
  char aux[81], i=0;
  ...
  return aux;
}

Las variables locales son creadas al comenzar el bloque o ámbito "local" y son destruidas al terminar su ámbito. Por lo tanto, el contenido de 'aux' puede o no existir al regresar desde la función 'capturar()'.


Todos estos mensajes son solamente avisos y no errores gramaticales.

L> [C++ Error] PruebBiblioteca.cpp(352): E2268 Call to undefined function
L> 'delay'.

Esto posiblemente aparece porque el compilador o mejor dicho el producto de desarrollo que estás usando ya no declara ni define la función 'delay()'. Posiblemente estés usando Builder C++. Podrías probar con la función '_sleep()'. Sugiero crear una macro para ello. Por ejemplo,

#define delay _sleep
...

Así no tienes que ir en busca de todas las apariciones de 'delay'.


Espero que esto te ayude.

Steven


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