<div dir="ltr">Hola Antonio,<div class="gmail_extra"><br><div class="gmail_quote">2013/5/20 Antonio Arjona <span dir="ltr"><<a href="mailto:antonio.arjona.melches@gmail.com" target="_blank">antonio.arjona.melches@gmail.com</a>></span><br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
  
    
  
  <div bgcolor="#FFFFFF" text="#000000">
    Hola a todos.<br>
    <br>
    Mi principal duda es la siguiente: <br>
        A falta de conocer alguna biblioteca dedicada a esto, estoy
    creando una clase que me permita navegar entre directorios, y el
    caso es que para las opciones de configuración me gustaria utilizar
    banderas pero no tengo muy claro como funcionan los operadores de
    bits...<br></div></blockquote><div><br></div><div style>Sugiero que leas el capítulo 18 de nuestro curso de C++: <a href="http://c.conclase.net/curso/index.php?cap=018#inicio">http://c.conclase.net/curso/index.php?cap=018#inicio</a> que trata sobre los operadores a nivel de bits.</div>
<div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div bgcolor="#FFFFFF" text="#000000">
    Estoy aprendiendo por mi cuenta, por tanto perdonadme si meto tanto
    código, si alguien desea ver todo el código tan solo pedírmelo y lo
    subo a <a href="http://github.com" target="_blank">github.com</a>, muchas gracias de antemano...<br>
    <br>
    De momento lo que tengo es lo siguiente:<br>
    <br>
    <font color="#9999ff">// tengo declaradas unas pocas constantes</font><br>
    <br>
    <font color="#009900">#define MOSTRAR_OCULTOS     0<br>
      #define INVERTIR_ORDEN         1<br>
      #define ORDENA_TAMAÑO        2<br>
      #define ORDENA_EXTENSION   3<br>
      //__etc.__</font><br>
    <br></div></blockquote><div><br></div><div style>En C++, no sugiero usar constantes simbólicas del preprocesador. En su lugar, define constantes (variables); esto es,</div><div style><br></div><div style>const int MOSTRAR_OCULTOS = 0;</div>
<div style>const int INVERTIR_ORDEN = 1;<br></div><div style>...</div><div style><br></div><div style>O incluso, un tipo enumerado:<br><br>enum banderin_t { MOSTRAR_OCULTOS = 0, INVERTIR_ORDEN, ... };</div><div><br></div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div bgcolor="#FFFFFF" text="#000000">
    <font color="#9999ff">// y dentro de mi clase he creado un struct
      tal que asi:</font><br>
    <br>
    <font color="#000099">struct</font> conf<br>
            {                                 <font color="#9999ff">/**<
      ls = comando de consola Linux (muestra contenido directorio) */</font><br>
                <font color="#000099">bool</font> archOcultos;   <font color="#9999ff">/**< ls -all muestra todos los archivos,
      incluidos los ocultos */</font><br>
                <font color="#000099">bool</font> invertir;           <font color="#9999ff">/**< ls -r ordena el resultado en orden inverso
      */</font><br>
                <font color="#000099">bool</font> tamano;          <font color="#9999ff">/**< ls -S ordena el resultado por tamaño */</font><br>
                <font color="#000099">bool</font> extension;       <font color="#9999ff">/**< ls -X ordena por extension */</font><br>
                <font color="#9999ff">// etc.</font><br>
                <br>
                <font color="#000099">void</font> cambia(<font color="#000099">int</font> opcion);   /<br>
            }conf;<br>
    <br></div></blockquote><div><br></div><div style>No sugiero usar el mismo nombre para el tipo y variable.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div bgcolor="#FFFFFF" text="#000000">
    <br>
    <font color="#000099">void</font> FileManager::conf::cambia(int
    opcion)<br>
    {<br>
            <font color="#000099">if</font> (opcion = MOSTRAR_OCULTOS)<br></div></blockquote><div><br></div><div style>Esto no es lo que quieres. Te interesa el operador ==, para comparar.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div bgcolor="#FFFFFF" text="#000000">
            {<br>
                    <font color="#000099">if</font> ( archOcultos == <font color="#000099">false</font>) archOcultos = <font color="#000099">true</font>;<br>
                    <font color="#000099">else</font> archOcultos = <font color="#000099">false</font>;<br>
                    <br></div></blockquote><div><br></div><div style>Esta forma de expresarse no es necesaria. En su lugar, escribe:<br><br>archOcultos = !archOcultos;</div><div style><br></div><div style>Sin embargo, por la lógica de tu diseño, esto no refleja tus intenciones. Lo que te interesa hacer es dejar constancia de que quieres "mostrar ficheros y directorios ocultos. Por lo tanto, te interesa que el booleano sea verdadero; es decir,</div>
<div style><br></div><div style>if( MOSTRAR_OCULTOS == opcion )<br>  archOcultos = true;</div><div style><br></div><div style>O incluso podríamos reescribir lo anterior así:<br><br>archOcultos = MOSTRAR_OCULTOS == opcion;<br>
</div><div style><br></div><div style>Así no tenemos que hacer pruebas, simplemente guardamos la verdad en una variable booleana.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div bgcolor="#FFFFFF" text="#000000">
            }<br>
            <font color="#9999ff">// etc.</font><br>
    }<br>
    <br>
    Tras investigar por mi cuenta, mas o menos creo que seria tal que
    así:<br>
    <br>
    <font color="#9999ff">// los #defines de las banderas<br>
    </font><br>
    <font color="#009900">#define MOSTRAR_OCULTOS     0x00000001<br>
      #define INVERTIR_ORDEN         0x00000010<br>
      #define ORDENA_TAMAÑO        0x00000100<br>
      #define ORDENA_EXTENSION   0x00001000</font><br>
    <font color="#9999ff">// etc.</font><br>
    <br>
    <font color="#9999ff">// y pretendo usar las banderas
      miclase::conf::cambia(MOSTRAR_OCULTOS | INVERTIR_ORDEN |  etc...)</font><br>
    <br></div></blockquote><div><br></div><div style>Vas por buen camino, pero date cuenta que esos unos están en hexadecimal. Esto implica que 1 dígito hexadecimal involucra 4 bits (dígitos binarios). Lo más seguro es que no requieras tantos lugares para indicar cada concepto; con 1 bit es suficiente.</div>
<div style><br></div><div style>Sugiero hacer esto:<br><br><div>const int MOSTRAR_OCULTOS = 0x01;  // 0001</div><div>const int INVERTIR_ORDEN = 0x02;        // 0010<br></div><div>const int ORDENA_TAMANNO = 0x04;    // 0100</div>
<div>const int ORDENA_EXTENSION = 0x08;  // 1000<br></div><div>...</div><div><br></div><div style>Esto implica que podemos combinar estos bits en una sola secuencia sin que haya solapamiento de valores. Por ejemplo,</div>
<div style><br></div><div style>MOSTRAR_OCULTOS | INVERTIR_ORDEN | ORDENA_TAMANNO</div><div style><br></div><div style>significa que obtenemos un valor de: 0111.</div><div style><br></div><div style><br>Ahora bien, puede haber un problema con los demás banderines. Por ejemplo, 'ORDENA_TAMANNO' y 'ORDENA_EXTENSION' conceptualmente son métodos mutuamente exclusivos. Es decir, no podemos ordenar por tamaño Y por extensión simultáneamente. Esto implica que no podemos usar dos bits diferentes, porque no tiene sentido interpretar la secuencia binaria: 1100. En este caso, necesitamos dos bits para representar estos valores e interpretar esa pareja de bits correctamente. Por ejemplo,</div>
<div style><br></div><div style><div>const int ORDENA_TAMANNO = 0x00;    // 0000</div><div>const int ORDENA_EXTENSION = 0x0C;  // 1100</div><div><br></div><div style>Claro está, podríamos interpretar las secuencias de bits para aceptar o rechazarlas; o sea, alguna forma de validación.</div>
<div style><br></div><div style>En general, deberías diseñar el formato de la secuencia de bits creando una correspondencia entre lugares de bits y los conceptos de cada banderín. Por ejemplo,</div><div style><br>criterio de ordenación</div>
<div style> |  |  sentido de ordenación</div><div style> |  |  |  mostrar ocultos</div><div> |  |  |  |</div><div style>3 2 1 0</div></div></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div bgcolor="#FFFFFF" text="#000000">
    void FileManager::conf::cambia(Uint32 opcion)<br>
    {<br>
            <font color="#9999ff">// mostrar archivos ocultos</font><br>
            <font color="#000099">if</font> ((opcion >> 0)
    &0xf  == 0x1)<br>
            {<br>
                    <font color="#000099">if</font> ( archOcultos == <font color="#000099">false</font>) archOcultos = <font color="#000099">true</font>;<br>
                    <font color="#000099">else</font> archOcultos = <font color="#000099">false</font>;<br>
                    <br>
            }<br>
    <br>
            <font color="#9999ff">// invertir el orden de aparición </font><br>
            <font color="#000099">if</font> ((opcion >> 4)
    &0xf == 0x1)<br>
            {<br>
                    <font color="#000099">if</font> ( invertir == <font color="#000099">false</font>) invertir = <font color="#000099">true</font>;<br>
                    <font color="#000099">else</font> invertir = <font color="#000099">false</font>;<br>
                    <br>
            }<br>
            <font color="#9999ff">// etc.</font><br>
    }<br>
    <br>
    Esto seria correcto?<br></div></blockquote><div><br></div><div style>Podrías hacer esto, pero creo que es más fácil crear la máscara AND exacta para consultar cada bit que te interesa. Afortunadamente, ya las creaste:<br>
<br>if( opcion & MOSTRAR_OCULTOS )<br>{<br>  ...<br>}</div><div style><br></div><div style>if( opcion & INVERTIR_ORDEN )<br>{</div><div style>  ...<br>}<br><br></div><div style>y así sucesivamente. Además, esto es mucho más legible que andar con valores hexadecimales.</div>
<div style><br></div><div style><br></div><div style>Quiero agregar que no estoy convencido de que necesites tantas variables booleanas. De hecho, dejaría el valor de los banderines en un solo campo de tipo entero (sin signo). Así no tienes que estar convirtiendo los banderines a booleanos. Lo que sí te puedo aconsejar - si quieres - es que crees varias funciones miembro; por ejemplo,<br>
</div><div style><br></div><div style>bool mostrarOcultos() const  { return opcion & MOSTRAR_OCULTOS; }</div><div style>bool invertirOrden() const  { return opcion & INVERTIR_ORDEN; }<br></div><div style>...</div>
<div style><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div bgcolor="#FFFFFF" text="#000000">

    ...............................<br>
    <br>
    La otra cuestión es la manera que estoy usando para desplazarme
    entre directorios, aunque me funciona perfectamente con Linux,
    quisiera saber si es una manera correcta de hacer esto y si hay
    alternativas mejores, mi intención es que en un futuro sea multi
    plataforma.<br>
    Lo que hago es:<br>
    <br></div></blockquote><div><br></div><div style>Creo que deberías separar tu representación de ficheros, directorios, y rutas de la representación de Linux, Microsoft, MacOS, etc.. De esta forma, usas una interfaz común para todas las plataformas, que trae menos quebraderos de cabeza a la hora de usar directorios y ficheros dentro de otros programas. De hecho, esto es un claro ejemplo del uso de clases en C++; específicamente, polimorfismo. Por ejemplo,</div>
<div style><br></div><div style>class SistemaFicheros {...};</div><div style><br></div><div style><div><div>class SistemaFicheros_Microsoft : public SistemaFicheros {...};</div></div><div><div><div>class SistemaFicheros_MacOS : public SistemaFicheros {...};</div>
<div></div><div>class SistemaFicheros_Linux : public SistemaFicheros {...};</div><div></div></div></div></div><div>...</div><div><br></div><div style> Y luego, haríamos algo así:<br><br>SistemaFicheros *psf = new SistemaFicheros_Microsoft;<br>
</div><div style><br></div><div style><div style><br>Si de verdad quieres algo multiplataforma, entonces puedes usar la biblioteca Boost, que ahora pertenece al estándar de C++. Así te quitas de encima tener que crear toda esta parafernalia.</div>
</div><div><br></div><div><br></div><div style>Espero que todo esto te oriente.</div><div><br></div><div style>Steven</div><div style><br></div></div></div></div>