Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Clase para manejo de ini - Julio Gorgé

Iniciado por ethernet, 16 de Febrero de 2003, 05:04:59 PM

« anterior - próximo »

ethernet



    Autor:  Julio Gorgé
    Web:           http://zsgames.cjb.net
    Código fuente: http://www.alu.ua.es/j/jgf8/code/inifile.zip

      Este COTW es una clase para trabajar con ficheros .ini. Permite consultar y modificar su contenido, siguiendo siempre el estándar de los ficheros de Windows:



               [seccion]

               clave=valor

               clave2=valor2



               [seccion2]

               clave=valor

               ...



    Los ficheros .ini son útiles en la programación de juegos porque pueden ser modificados por personas sin conocimientos de programación con un editor de textos cualquiera. Unreal Tournament 2003 y NFS:Hot Pursuit 2 son dos de los juegos más recientes que usan este tipo de archivos para su configuración.



    La API de Windows proporciona funciones como GetPrivateProfileString o WriteProfileString, que simplifican el manejo de ficheros .ini. La clase que he creado utiliza internamente estas funciones, pero ahorra código a la hora de acceder a numerosas claves.



    En el ejemplo que se incluye junto con el código fuente de la clase, podeis ver qué fácil es usar la clase IniFile:




    #include <windows.h>



    #include "inifile.h"











    void main()



    {



          IniFile* pIni = new IniFile("settings.ini");



         



          if(pIni)



          {



                 // Get [graphics]



                 //            mode=...



               



                 char szGraphicMode[32];



               



                 pIni->GetKey((char*)szGraphicMode,"graphics","mode");



                 MessageBox(NULL,szGraphicMode,"Selected mode",MB_OK);



               



                 // Set [graphics]



                 //            bpp=16



               



                 pIni->SetKey("16","graphics","bpp");



               



                 // Check [sound]



                 //            3d=true



               



                 if(pIni->IsKeyTrue("sound","3d"))



                        MessageBox(NULL,"3d sound enabled","Status",MB_OK);



               



               



                 delete pIni;



          }



         



    }





    Aquí hemos supuesto que tenemos un fichero de texto en el mismo directorio del programa llamado "settings.ini" donde tenemos guardada la configuración de nuestro juego.



    Primero consultamos una clave, luego modificamos una, y finalmente comprobamos que una de las claves tiene como valor "true". Hacer todo esto sin la ayuda de una clase genera mucho código.



    Si probais a dar valor a una clave que no existe, comprobaréis que automáticamente se crea la sección necesaria(si no existía ya) y la clave con el nombre adecuado.



    Ahora os toca a vosotros enviar los bugs que encontréis(que los tiene) y proponer posibles mejoras.



    Julio Gorgé, ZS Games

    Éste código fue enviado por Julio Gorgé aka ZaelsiuS el 6 de febrero del 2003

    Si quieres enviar tu propio código hazlo a  eth_cotd@lycos.es

    ethernet

    Hay q agradecer q ZaelsiuS ha subido el codigo por su cuenta y ha enviado  comentario bastante completo y util,  tal cual lo veis aqui.

    gracias ;**

    CordayUK

                                    mola esta muy bien!                                

    ethernet

    Nadie dice nada ? habra q meter un poco de caña XDD

    m_szFilename = new char[strlen(szFilename) +3];
    strcpy(m_szFilename,".");
    strcat(m_szFilename,szFilename);

    q pasaria ahi si resulta q le pasamos un string sin tener un al final ? puede llegar a pasar si miras el codigo

    por q no compruebas si m_szFileName es != NULL para usar las funciones

    q pasaria aqui :

    return WritePrivateProfileString(szSection,szKey,szBuffer,m_szFilename);

    si resulta q no se ha iniciado bien la clase pero seguimos usandola ?

    yo pondria un assert(m_szFileName); para chequear eso en debug o usar un if(m_zsFileNmae) { resto de la funcion}


    otra cosa, es necesario poner un "."  antes del fichero? asi no podras usar inis de fuera de la carpeta del exe a no ser q cambies de directorio :(


    La verdad q son estupideces pero nadie hablaba xDDD por lo demas me parece un buen codigo, util y limpio.

    saludos

    CordayUK

                                    de paso voy y pregunto yo algo....

    el tipico fichero .ini guardas cadenas y booleanos, genial que tengamos un GetKey () y un IsTrue () etc... pero tambien podemos tener valores float por ejemplo, molaria ampliar la clase con un GetFlaot () en lugar de tener que convertir el texto a mano despues.
    Yo en mis ficheros ini tambien guardo DWORD por ejemplo

    [FOG]
    FogColor=0xccffaa22
    FogMaxZ=50.0

    molaria tambien tener un GetDW () entonces.
    lo que yo hago es parsear cada numero de la cadena 0xccff... y crear un dword a mano y devolverlo.  es un poco tedioso la verdad. Si alguien conoce algun metodo para hacerlo de forma elegante que lo postee aqui!! :)                                

    ethernet

    corday cabron, no jodas el COTW de la semana proxima XDD

    CordayUK

                                    era una mierda de COTW de todas formas XDDDDDDDDDDD                                

    Zaelsius

    Gracias por comentar un poco el COTW!!

    Pues me apunto los bugs y sugerencias, y respecto a lo de incluir . en la clase... sólo se que no me iba bien si no lo ponía delante(no estoy seguro ahora mismo si es por alguna movida del debug working directory del VC++), así que si alguien lo prueba pues mejor.

    No lo intenté probar yo pq como se supone que los .ini van dentro de la carpeta del exe(aunque alguien querría poner exe en /bin y .ini's en /config por ejemplo).

    Ethernet: cuando en el constructor pongo "szFilename", indico al programador que se trata de una cadena acabada con mediante
    el sufijo sz(intento seguir la notación húngara de MS :D ).

    También añadiré la posibilidad de leer DWORD's y alguna cosilla más.
    Cuando revise la clase ya lo postearé por aquí. Y mejor aun, si alguien se anima a hacerlo, que me envie la clase y la reemplazo en mi web.

    ethernet

    comentaba lo del . por q algunos programas guardan sus configuraciones en c:windows o similar pero es un detalle sin importancia.

    Con el cotw de corday q esta por llegar se puede mejorar tu clase para lo q comentaba corday...mañana lo veremos :DD

    saludos

    Zaelsius

     Rebuscando entre el código de Emule y xMule, he encontrado la clase dedicada a manejo de ficheros .ini y (aparte de ser la misma en los dos programas) es similar a la que puse en este cotw, aunque está algo más completa.

    En el caso de xMule, creo que en las plataformas no windows deben utilizar algun otro mecanismo, pq la clase se basa en las funciones de la API win32 - como writeprivateprofilestring(), etc...-  creo(aun no lo he comprobado) que dichos casos echan mano de la librería wxWindows(puede que hayan clonado estas funciones).

    ethernet

     mira los fuentes del unreal, hay una solucion completamente portable. Yo por otra parte hice la mia propia un dia q la necesitaba para alguna chorrada:


    namespace conf
    {
       typedef  std::string st;
       typedef  st::size_type sz_t;
       typedef  std::map<st,st> Vars;
       typedef  std::map<st,Vars> ini_t;
       typedef  const st c_st;
       typedef  char const * const ccc;
       
       enum { BUFF = 256 , CTAG = ';'};  

       class IniFile: public ini_t
       {  
               typedef  std::vector<st> ArgList;        
               bool isws (char c,ccc wstr){return strchr(wstr,c)!=0;}
               st trim(c_st &s,sz_t &idx,ccc ws= " "){
                   sz_t i = s.find_first_not_of(ws,idx);
                   sz_t j = idx = s.find_first_of(ws,i);
                   return st(s.substr(i,j-i));
                 
               }
               void stk (ArgList &l,c_st &s,ccc ws = " \r\t\n"){
                   sz_t i = 0;l.clear();
                   while (i<s.size())l.push_back(trim(s,i,ws));  
               }
           public:
               IniFile(ccc f= 0){ if(f)readvars(f); }
               bool readvars(c_st& file)
               {
                   char b[BUFF];
                   st secc;
                   ArgList a;
                   ifstream f(file.c_str(),ios::in|ios::nocreate);
                   f.getline(b,BUFF);        
                   while(f.good())
                   {              
                       stk(a,b," \t\r\n=");
                       if(a.size() && a[0][0]!=CTAG)
                            if(a[0][0]=='[') secc=a[0].substr(1,a[0].size()-2);              
                            else   (*this)[secc][a[0]]=a[1];      
                       f.getline(b,BUFF);        
                   }
                   return f.bad();
               }
       };
    };
    int main(int argc, char* argv[])
    {
       conf::IniFile a("1.ini");
       
       cout << a["holas"]["hola"].c_str() << endl;
       cout << a["juego"]["var"].c_str() << endl;
       
    return 0;
    }

    Zaelsius

     Yo tb estaba haciendo una implementación portable ahora... XD    ¡marikita el resto!  :lol:  

    DraKKaR

     Ei, si haceis una implementacion completamente portable avisad (que no dependa de nada)! Yo tambien uso ficheros ini para nuestro juego, y me estaba preguntando si tendria ke reescribir las funciones de tratamiento de ficheros ini a pelo para que furulara en linux.

    Zaelsius

     La implementación que estoy haciendo es totalmente portable, pq la necesitamos para linux/windows. Aparte de algunas optimizaciones y tal, hay soporte para leer directamente booleanos, dwords, y alguna cosilla más.  Supongo que para mediados de septiembre la tendré lista, pq ahora no puedo avanzar demasiado con los estudios y movidas varias.

    PD. la sobrecarga del operador [] de la implementación de Unreal mola!
    PDD. la implementación de Quake III es ininteligible XD, sólo hay comentarios al respecto de posibles bugs o mejoras... y como lo hacen todo sin clases, con C a pelo, no hay quien entienda nada mirándola por encima

    ethernet

     uh? donde esta la sobrecarga del operador [] en el codigo del unreal? no sera la del Map ?  






    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.