Benvenuto! Per postare e godere delle funzionalità del forum registrati, occorrono pochi secondi ed è gratis!

C++ scrivere e leggere files di testo (settaggi)
(Questo messaggio è stato modificato l'ultima volta il: 04/12/2013, 1:01 da digger.)

Il criceto mannaro
Messaggi: 3,536
Discussioni: 201
Registrato: 03-2011
Reputazione:
106

Mix: 3,737
Ciao a tutti,
qualcuno mi chiedeva come fare a scrivere e leggere un file di testo al fine di salvare dei settaggi per poi poterli ricaricare all'esecuzione successiva.

Premesso che si può fare in mille modi come al solito, qui di seguito riporto un esempio di come si potrebbe procedere.
Sicuramente il codice non è il massimo, l'ho buttato giu un po' di corsa però penso che dia già l'idea e qualche spunto su cui lavorare. Occhio quindi che non ci sono molti controlli e non prevedo errori vari nel formato del file etc, quindi nel caso provvedete voi a migliorarlo.
Nel codice ho usato anche il "map" della STL, trovavo che questa fosse una buona occasione per tirare in ballo la STL e far vedere qualcosa di utile.

    C++ Programming
  1. #include <iostream>
  2. #include <fstream>
  3. #include <string>
  4. #include <map>
  5.  
  6. using namespace std;
  7.  
  8. typedef map<string, string> settingsMap;
  9.  
  10. void scrivi_settaggi(const char* filename)
  11. {
  12. // questa funzione ci serve solo per creare un file di settaggi
  13. // per le nostre prove
  14.  
  15. int width = 800;
  16. int height = 600;
  17.  
  18. ofstream settings_file(filename);
  19. if (!settings_file.bad())
  20. {
  21. settings_file << "width=" << width << endl;
  22. settings_file << "height=" << height << endl;
  23. settings_file.close();
  24. }
  25. }
  26.  
  27. void leggi_settaggi(const char* filename, settingsMap& sets)
  28. {
  29. // questa funzione legge qualsiasi file di testo in cui i settaggi
  30. // si trovino uno per linea nella forma token=valore
  31. // esempio:
  32. // width=800
  33. // height=600
  34.  
  35. size_t found;
  36. string line;
  37. string token;
  38. string value;
  39.  
  40. ifstream settings_file(filename);
  41. while (settings_file.good())
  42. {
  43. getline(settings_file,line);
  44. if (line.length()>0)
  45. {
  46. found = line.find("=");
  47. token= line.substr(0,found);
  48. value= line.substr(found+1,line.length()-found);
  49. sets[token]=value;
  50. }
  51. }
  52. settings_file.close();
  53. }
  54.  
  55. int main ()
  56. {
  57. const char* filename="settings.txt";
  58.  
  59. scrivi_settaggi(filename);
  60.  
  61. settingsMap settings;
  62. leggi_settaggi(filename,settings);
  63.  
  64. cout << "WIDTH : " << settings["width"] << endl;
  65. cout << "HEIGHT: " << settings["height"] << endl;
  66.  
  67. system("pause");
  68.  
  69. return 0;
  70. }



Il codice dovrebbe capirsi abbastanza facilmente credo.
Nel caso posso commentare le varie parti, ma non stasera perchè sono cotto e me ne vado a dormire.

Spiego solo a grandi linee cosa fa il programma.
Nel main vengono chiamate 2 funzioni,
la prima, "scrivi_settaggi" serve a creare un file dei settaggi.
Da qui si può vedere quindi come nel nostro fantomatico programma possiamo salvare il valore di alcune variabili (qui width e height) direttamente su un file di testo nel formato:

width=800
height=600

Poi chiamiamo subito dopo una funzione "leggi_settaggi".
Questa si occupa di leggere un file di testo riga per riga,
e in ogni riga letta va a cercare una coppia token=valore
dove token sarebbe il parametro del caso e valore è chiaramente il valore a cui era settato quando lo abbiamo salvato.

Ad esempio in un videogioco potremmo salvare una cosa cosi:

width=800
height=600
health=100
ammo=150
lives=3
...

chiaro no? abbiamo salvato la risoluzione attuale dello schermo,
la quantità di vita del giocatore, le munizioni e le vite etc etc

Cosi possiamo chiudere il gioco e poi riaprirlo e andare a caricare questi valori dal file e riprendere da li a giocare.

Alla funzione leggi_settaggi, oltre che il nome del file dobbiamo passare anche la "map", questo è un contenitore associativo che troviamo nella STL del C++
E' molto utile, ci permette di creare una specie di array dove però gli elementi non vengono letti e scritti usando un indice numerico ma piuttosto usando una chiave.
esempio:

map <string,string> settings;

settings["width"]=800;
settings["height"]=600;

quello che succede è che associamo alla chiave "width" il valore 800 e alla chiave "height" il valore 600
E questo perchè ci torna utile? perchè leggendo un file di testo che chiunque può aver modificato non sappiamo cosa ci possiamo trovare dentro, in questo modo creiamo tutta una serie di associazioni chiave=valore, che possono contenere anche cose che noi non conociamo e di cui non sappiamo il significato e nemmeno ci interessano, alla fine tanto noi faremo cosi

int width = settings["width"];
int height = settings["height"];

tralasciando tutti gli altri parametri che qualcuno potrebbe aver messo nel file a nostra insaputa.
Oppure un giorno in cui vogliamo usare quei parametri in piu ci basterà aggiungere le relative righe:

int altro = settings["altro"];

insomma mi pareva un sistema pulito ed elegante per leggere i parametri dal file senza usare montagne di if e switch .

Inoltre il map ha un'altra utilità, ovvero quella di eliminare le ripetizioni. Se nel file ci sono piu volte gli stessi parametri il programma non entra in crisi, semplicemente tiene buono l'ultimo che vede. Esempio

width=800
height=600
altro=10
width=850

in questo caso c'è 2 volte width ,bene il programma alla fine della lettura del file avrà width=850 perchè la seconda volta in cui trova width va a sovrascrivere quanto trovato in precedenza.

Va bene, spero che sia tutto chiaro, altrimenti spiegherò la prossima volta quello che non è chiaro

ciao!
Digger


digger
04/12/2013, 0:59
#1
Cerca
(Questo messaggio è stato modificato l'ultima volta il: 06/12/2013, 14:59 da Cyanstack.)

Iscritto
Messaggi: 270
Discussioni: 40
Registrato: 10-2013
Reputazione:
0

Mix: 0
Può servire anche per le hacks, per salvare le funzioni attive Happywide , comunque se ho capito bene, questo map ci permette, in questo caso di creare una parola chiave che identifica cio che è scritto nel file di testo settings.txt?

__ edit

Digger sto provando a fare una cosa, ovvero fare sì che se quello che è scritto nel file di testo settings.txt è un numero, una variabile int prende quel numero, ho scritto così, ovviamente mi da un errore di compilatore perché non posso convertire una stringa a int, come posso fare ?! D:

    C++ Programming
  1. bool esiste_numero ( string x )
  2. {
  3. if ( x >= "0" && x <= "999999" )
  4. {
  5. return true;
  6. }
  7. return false;
  8. }
  9.  
  10. int main ()
  11. {
  12. const char* filename="settings.txt";
  13. settingsMap settings;
  14. leggi_settaggi(filename,settings);
  15. string x = settings["user"];
  16. int b;
  17. if ( esiste_numero(x) == true )
  18. {
  19. b = x;// non so come fare qua..
  20. }
  21.  
  22.  
  23. cout << "ID : " << b << endl;
  24. system("pause");
  25. return 0;
  26. }



04/12/2013, 12:40
#2
Cerca

1 Life, 1 Avatar &lt;3
Messaggi: 9,074
Discussioni: 271
Registrato: 08-2011
Reputazione:
77

Mix: 0
adesso faccio il nabbo.
Bisogna usare i templates o come si scrive? Happywide
Grazie mille diggeh, appena posso mi impegno per metterlo nel mio giuoco, sarà fantastico :3

06/12/2013, 17:00
#3
Cerca

Il criceto mannaro
Messaggi: 3,536
Discussioni: 201
Registrato: 03-2011
Reputazione:
106

Mix: 3,737
uno dei modi (come al solito) per fare quello che dici è questo :
    C++ Programming
  1. #include <stdlib.h>
  2. ...
  3. ...
  4. b = atoi(x.c_str());



nota inoltre che c'è un errore anche nella funzione "esiste_numero" in quanto la comparazione che stai facendo con x>="0" e x<="999999" la stai facendo tra stringhe e non tra numeri quindi non ti tornerà il risultato sperato, ad esempio per lui 9 è > 10 tanto per dire!

quindi ti conviene convertire subito x in intero e quindi fare tutti i ragionamenti con l'intero e quindi anche la funzione esiste_numero farla in modo che si aspetti un intero


digger
06/12/2013, 17:14
#4
Cerca
(Questo messaggio è stato modificato l'ultima volta il: 06/12/2013, 17:41 da Cyanstack.)

Iscritto
Messaggi: 270
Discussioni: 40
Registrato: 10-2013
Reputazione:
0

Mix: 0
(06/12/2013, 17:14)digger Ha scritto:

[Per vedere i link devi REGISTRARTI.]

uno dei modi (come al solito) per fare quello che dici è questo :
    C++ Programming
  1. #include <stdlib.h>
  2. ...
  3. ...
  4. b = atoi(x.c_str());



nota inoltre che c'è un errore anche nella funzione "esiste_numero" in quanto la comparazione che stai facendo con x>="0" e x<="999999" la stai facendo tra stringhe e non tra numeri quindi non ti tornerà il risultato sperato, ad esempio per lui 9 è > 10 tanto per dire!

quindi ti conviene convertire subito x in intero e quindi fare tutti i ragionamenti con l'intero e quindi anche la funzione esiste_numero farla in modo che si aspetti un intero

x non me lo fa convertire in int,
se faccio così :
    C++ Programming
  1. int x = settings["user"];


mi fa errore

1>c:\documents and settings\user\documenti\visual studio 2010\projects\thanks 1\thanks 1\main.cpp(57): error C2440: 'inizializzazione': impossibile convertire da 'std::basic_string<_Elem,_Traits,_Ax>' a 'int'


__ EDIT

Ho risolto Happywide grazie, ho fatto così :
    C++ Programming
  1. bool esiste_numero ( int x )
  2. {
  3. if ( x >= 0 && x <= 999999 )
  4. {
  5. return true;
  6. }
  7. return false;
  8. }
  9.  
  10. int main ()
  11. {
  12. const char* filename="settings.txt";
  13. settingsMap settings;
  14. leggi_settaggi(filename,settings);
  15. string x = settings["user"];
  16. int b = atoi ( x.c_str() );
  17. if ( esiste_numero(b) == true)
  18. {
  19. cout << "ID : " << b << endl;
  20. }
  21. else
  22. {
  23. cout << "L'ID non puo' contenere piu' di 999999 numeri e non puo' avere lettere" << endl;
  24. }
  25. system("pause");
  26. return 0;
  27. }



06/12/2013, 17:25
#5
Cerca

Il criceto mannaro
Messaggi: 3,536
Discussioni: 201
Registrato: 03-2011
Reputazione:
106

Mix: 3,737
bravo! era quello che intendevo Smile


digger
06/12/2013, 20:10
#6
Cerca

1 Life, 1 Avatar &lt;3
Messaggi: 9,074
Discussioni: 271
Registrato: 08-2011
Reputazione:
77

Mix: 0
Lunedì e martedi sera mi impegnero a mettere gli upgrade nel mio giochino

07/12/2013, 21:49
#7
Cerca


Discussioni simili
Discussione Autore Risposte Letto Ultimo messaggio
  [Guida] C++ scrivere e leggere file di testo(settaggi) via WEB Cyanstack 4 1,176 05/06/2014, 21:58
Ultimo messaggio: Cyanstack
  [VB.NET] Scrivere nel Registro di Sistema Cato97 11 3,531 16/12/2012, 20:51
Ultimo messaggio: pauldomy
  [Tutorial After Effects CS5] Testo animato Cato97 11 1,231 05/09/2012, 11:49
Ultimo messaggio: Pocciox



Utenti che stanno guardando questa discussione: 1 Ospite(i)