[C] Aiuto con char contenenti spazi

MikC1
Salve a tutti .. Ho questo problema su questo programma abbastanza complesso ( almeno per me :))..
In ogni caso leggendo il forum ho visto di altri con la mia stessa domanda come fare a inserire stringhe contenenti spazi. Ora nel mio programma le stl non funzionano e mi complicano solamente la vita visto che dovrei fare con esse funzioni di ricerca e di ordinamento che ho già preparato considerando le stringhe come array di caratteri. Quindi considerando in tal modo le stringhe c'è un modo in cui io posso inserire degli array con gli spazi? Ho già provato con la fgets:

struct coefficenti
{char materiale[SIZE_MAX_STRING];
int K;
}P;
fgets(P.materiale,SIZE_MAX_STRING, stdin);

ma in esecuzione il programma salta l'inserimento o comunque non riesce a prendere ciò che io scrivo. Grazie in anticipo per l'aiuto e i suggerimenti spero di essere stato chiaro nel problema :D

Risposte
apatriarca
Mi stupisce che il compilatore non abbia nulla da ridire nella seguente riga.
 cin.getline(P.materiale,30) cin.ignore(30,'\n'); 

Ma a parte la mancanza di un punto e virgola, cin.ignore va inserito PRIMA di cin.getline e non nell'ordine da te seguito. Il codice corretto è quindi il seguente (il valore passato a cin.ignore è quello massimo possibile per una riga e non c'è alcun bisogno di limitarsi a 30..).
 
cin.ignore(10000, '\n');
cin.getline(P.materiale,30);

Il problema di questo metodo è che non è possibile (da quanto ne so) stabilire se cin.getline o cin.ignore sono usciti perché la dimensione massima è stata raggiunta o perché è stato trovato il carattere di a capo. La soluzione più semplice che mi viene in mente è quella di usare un buffer un po' più grande della dimensione massima stabilita per una riga e verificare se il numero di caratteri letti è superiore a questo limite.

Ho poi notato che in alcune funzioni stai scrivendo e leggendo sul file usando la modalità testuale invece di quella binaria. In alcuni sistemi operativi non c'è differenza, ma è opportuno usare la modalità corretta (e quindi aggiungere una b a tutte le stringhe che descrivono la modalità di apertura dei file).

Immagino ci siano altri errori, ma per via di conio.h al momento non posso compilare il tuo codice.

MikC1
Ok non so come ma mettendo fflush(stdin) e poi prendere la stringa con una gets(p.materiale) ho risolto e prende la stringa( yeaaaaaaaaaaaaah) ora rimane solamente il problema del 0.21 ..

sorto un altro problema li visualizza correttamente ma nella ricerca binaria trova solamente quelli composti di una sola parola e non quelli con spazi.

vict85
Ribadisco il concetto: fflush(stdin) è qualcosa che non dovrebbe mai essere inserito in un codice; inserirlo compromette la stabilità e la portabilità del codice. Chiunque te lo abbia insegnato non è degno di insegnare il C/C++ e qualsiasi testo lo proponga nel suo codice ha senso usarlo solo per accendere il camino durante l’inverno.

Detto questo, la mia opinione su chi ti abbia insegnato ‘conio.h’ non è più gentile.

Una sola curiosità: dove stai usando quelle tre liste? Dovresti proprio iniziare ad usare variabili locali.

apatriarca
@MikC: Ma hai provato a seguire i miei suggerimenti del post precedente? Il fatto che la soluzione che hai scritto abbia funzionato in un caso (spero tralaltro che la seconda funzione da te usata fosse fgets e non gets) non vuol dire che sia corretta o che continuerà a funzionare in futuro. In particolare, non è detto funzionerà anche sul computer del tuo professore quando andrà a correggere il tuo esercizio. Ti abbiamo già indicato il metodo corretto per leggere tali stringhe. Se non funziona è perché stai facendo qualcosa di sbagliato e non perché il metodo indicato sia in qualche modo errato. Invece di fare delle modifiche a caso sperando che una di queste porti alla soluzione corretta, sarebbe opportuno affrontare il problema in modo più scientifico e ordinato. Facendo quindi ad esempio un debug del codice per comprendere dove si trova l'errore. Usare variabili locali invece di quelli globali è inoltre spesso molto utile per limitare e circoscrivere i danni ad una sola parte del programma.

MikC1
Le uniche variabili globali sono legate alla ricerca che attualmente funziona solo per le stringhe senza spazi.. Comunque applicando quello che mi avete detto anche mettendo prima cin.ignore e poi cin.getline non prende comunque.. Per quanto riguarda la conio.h mi è stato detto di usarla quando si usano le getch() . Ora rimane da risolvere questi due problemi della ricerca che non trova le stringhe con gli spazi anche se vengono visualizzate correttamente e dello 0.21. L'attuale codice è questo.
#include <string.h>
#include <conio.h>
#include <iostream>
#include <list>
#define Z 30
using namespace std;
void Carica();
void CalcoloQ();
float Calcolo();
void Visualizza();
void Ordina();
void Ricerca();
int FileSize();
void Menu();
FILE *f;
bool fine;
list<int> l;
list<int> g;
list<int> r;
char K[30]; int  C;
bool trovato;
float G=0;
struct Coefficenti
{char materiale[30];
 float V;
}P;


void Carica()
{f=fopen("F:/MICHELE LUNATI 4a As/coefficenti.dat","a");
 int N, i=0; 
 cout<<"Quanti contatti vuoi inserire?="; cin>>N;
 do{cout<<"Inserisci materiale:"; 
  fflush(stdin); gets(P.materiale); 
    cout<<"Coefficente di "<<P.materiale<<"="; 
    cin>>P.V; 
    fwrite(&P,sizeof(P),1,f);
    i++;
    }
 while(i<N);
fclose(f);
Ordina();
}


void Menu()
{cout<<"\nMenu della rubrica...\n";
     cout<<"1) Carica altri coefficenti\n";
     cout<<"2) Ricerca coefficente\n";
    cout<<"3) Visualizza coefficenti di conduttanza\n";
    cout<<"4) Calcolo lamda equivalente\n";
     cout<<"5) Calcolo calore\n"; 
     cout<<"6) Esci\n"; 
}


void Visualizza()
{Ordina();
 f=fopen("F:/MICHELE LUNATI 4a As/coefficenti.dat","rb");
 while(fread(&P,sizeof(P),1,f))
{cout<<"\nCoefficente di "<<P.materiale<<"= "<<P.V; printf("\n");
}
fclose(f);
}



void Ricerca()
{system("CLS");
 f=fopen("F:/MICHELE LUNATI 4a As/coefficenti.dat","rb");
 cout<<"\nNome del materiale da ricercare:"; 
 cin>>K;
 int Inf=0, Sup=FileSize()-1;
 trovato=false;
 while (Inf<=Sup && !trovato)
       {C=(Inf+Sup)/2;
        fseek(f,C*sizeof(P),SEEK_SET);
        fread(&P,sizeof(P),1,f);
        if(strcmp(K,P.materiale)>0) Inf=C+1;
        else {if(strcmp(K,P.materiale)<0) Sup=C-1;
              else trovato=true;
             }
       }
 if(trovato){ cout<<"\nCoefficente di "<<P.materiale<<"= "<<P.V; printf("\n"); getch();}
 else cout<<"Non presente"; getch();
fclose(f);
}





void Ordina()
{system("CLS");
 f=fopen("F:/MICHELE LUNATI 4a As/coefficenti.dat","r+");
 int Sup=FileSize();
 bool Scambio;
 Coefficenti S, T;
 do{Sup--;
    Scambio=false;
    for(int i=0; i<Sup; i++)
         {fseek(f,i*sizeof(T),SEEK_SET);
          fread(&T,sizeof(T),1,f);
          fseek(f,(i+1)*sizeof(S),SEEK_SET);
          fread(&S,sizeof(S),1,f);
          if(strcmp(T.materiale,S.materiale)>0)
             {fseek(f,i*sizeof(S),SEEK_SET);
              fwrite(&S,sizeof(S),1,f);
              fseek(f,(i+1)*sizeof(T),SEEK_SET);
              fwrite(&T,sizeof(T),1,f);
              Scambio=true;
              }
          }
    }
 while(Scambio);
 fclose(f);
 system("CLS");
}


int FileSize()
{fseek(f,0,SEEK_END); 
 int N=ftell(f);
 return N/sizeof(P);
}


float Calcolo()
{int i=0, S;
f=fopen("F:/MICHELE LUNATI 4a As/coefficenti.dat","r");
 cout<<"Inserire di quanti materiali è composto il muro:"; 
 cin>>S;
  float coefficente[Z], spessore[Z], x;
 
 while(i<S)
 {Ricerca(); 
  if(trovato){fseek(f,C*sizeof(P),SEEK_SET);
              fread(&P,sizeof(P),1,f);
              coefficente[i]=P.V;
              cout<<"Inserisci spessore del"<<P.materiale<<"="; 
              cin>>x;
              spessore[i]=x;
              
              }
i++;
 }
fclose(f);
int J=0; float d=0;
while(J<S)
{float rapporto=spessore[J]/coefficente[J]; 
 d+=rapporto;
G+=spessore[J];
  J++;
}
float lambda=1/d; cout<<"lambda equivalente="<<lambda;
return lambda;
}
              


void CalcoloQ()
{ float B, H, T, d;
     cout<<"Inserisci base parete"; 
     cin>>B;
     cout<<"Inserisci base parete"; 
     cin>>H;
     
     float A=B*H;
    
     cout<<"Inserisci temperatura esterna="; 
     cin>>T;
     cout<<"Inserisci temperatura interna="; 
     cin>>d;
     float Q=(A/G)* Calcolo() * (T-d);
     cout<<"Calore="<<Q; 
     getch();
     }
     


int main()
{system("CLS");
 do {Menu();
     char c=getche();      
     switch(c)
          {case'1': Carica(); break;
           case'2': Ricerca(); break;
           case'3': Visualizza(); break;
           case'4': Calcolo(); break;
           case'5': CalcoloQ(); break;
           case'6': fine=true; break;
           default: printf("\nERROR\n");
          }
    }
 while(!fine);
}    
     
     
     
     
     

apatriarca
if(strcmp(K,P.materiale)>0) Inf=C+1;
        else {if(strcmp(K,P.materiale)<0) Sup=C-1;
              else trovato=true;

Non capisco cosa stai cercando di fare qui.. La funzione è quella di ricerca. Stai cercando di fare una specie di ricerca binaria? Se fosse così il codice è sbagliato. Posso consigliare per iniziare di evitare di ordinare le strutture nel file e usare una ricerca lineare?

Guardando comunque la funzione di ricerca noto anche un'altra cosa.. Stai leggendo il nome in un modo totalmente diverso da quello che usi negli altri casi!
cout<<"\nNome del materiale da ricercare:"; 
 cin>>K;

vict85
Ci sono delle scelte di design molto discutibili:


    [*:18ayc2fs] Stai usando variabili globali e le usi ‘localmente’ nel senso che sono ri-inizializzate tutte le volte (il file lo apri e chiudi sempre). Perciò o le definisci localmente oppure cerchi di sfruttare il fatto che sono globali.[/*:m:18ayc2fs]
    [*:18ayc2fs] Alcune variabili globali hanno scopi molto limitati e temporanei.[/*:m:18ayc2fs]
    [*:18ayc2fs] La lunghezza del file la ricalcoli tutte le volte anche se, una volta partito il programma, tu sai esattamente come muta questa lunghezza all’interno della esecuzione. Perciò avrebbe senso memorizzarla da qualche parte.[/*:m:18ayc2fs]
    [*:18ayc2fs] Riordini prima di visualizzare anche se hai già riordinato dopo aver introdotto gli elementi.[/*:m:18ayc2fs]
    [*:18ayc2fs] Il tuo design prevede l’uso di operazioni costosissime e al contempo pretende di essere efficiente. Sinceramente finora ogni scelta che hai fatto per l’efficienza penso che abbia rallentato tremendamente il programma. Quindi evita di cercare di fare ottimizzazione e pensa al modo più semplice per fare le cose.[/*:m:18ayc2fs]
    [*:18ayc2fs] Riordinare il file potrebbe essere più costoso del vantaggio che hai nella ricerca binaria rispetto a quella sequenziale.[/*:m:18ayc2fs]
    [*:18ayc2fs] Il metodo che usi per trovare la lunghezza del file potrebbe fallire nel caso in cui f sia aperto in modo testuale.[/*:m:18ayc2fs]
    [*:18ayc2fs] continui ad usare system("CLS") e fflush(stdin)[/*:m:18ayc2fs]
    [*:18ayc2fs] Ci sono variabili che non usi.[/*:m:18ayc2fs]
    [*:18ayc2fs] Per certi versi ti potrebbe convenire, caricare tutto il file all’inizio e riscriverlo alla fine. Lavorando su una qualche struttura dati nel mezzo. Ovviamente dipende da quanti dati possiedi. La struttura dati dipende un po’ da che operazione vuoi potenziare.[/*:m:18ayc2fs]
    [*:18ayc2fs] Carichi il file in modo troppo “fisso”. Sarebbe opportuno usare un indirizzo relativo al programma. Rende pressoché impossibile compilare il tuo programma per altri.[/*:m:18ayc2fs][/list:u:18ayc2fs]

    In generale il mio consiglio è mettere da parte il programma e ripensare le operazioni base: devi semplificare il tutto.

MikC1
Grazie mille a tutti e due per i preziosi consigli. apatriarca grazie a te sono riuscito a risolvere il problema della ricerca infatti inserivo la key da ricercare nello stesso modo in cui inserivo prima il materiale. Per quanto riguarda le fflush stdin le utilizzo solo in due casi e le systemcls credo di averle rimosse del tutto. Rimane ora da risolvere il problema del 0.21 che manda in crisi il programma.
Attuale codice:
#include <string.h>
#include <conio.h>
#include <iostream>
#include <list>
#define Z 30
using namespace std;
void Carica();
void CalcoloQ();
float Calcolo();
void Visualizza();
void Ordina();
void Ricerca();
int FileSize();
void Menu();
FILE *f;
bool fine;
char K[30]; int  C;
bool trovato;
float G=0;
struct Coefficenti
{char materiale[30];
 float V;
}P;


void Carica()
{f=fopen("F:/MICHELE LUNATI 4a As/coefficenti.dat","a");
 int N, i=0; 
 cout<<"Quanti contatti vuoi inserire?="; cin>>N;
 do{cout<<"Inserisci materiale:"; 
  fflush(stdin); gets(P.materiale); 
    cout<<"Coefficente di "<<P.materiale<<"="; 
    cin>>P.V; 
    fwrite(&P,sizeof(P),1,f);
    i++;
    }
 while(i<N);
fclose(f);
Ordina();
}


void Menu()
{cout<<"\nMenu della rubrica...\n";
     cout<<"1) Carica altri coefficenti\n";
     cout<<"2) Ricerca coefficente\n";
    cout<<"3) Visualizza coefficenti di conduttanza\n";
    cout<<"4) Calcolo lamda equivalente\n";
     cout<<"5) Calcolo calore\n"; 
     cout<<"6) Esci\n"; 
}


void Visualizza()
{f=fopen("F:/MICHELE LUNATI 4a As/coefficenti.dat","rb");
 while(fread(&P,sizeof(P),1,f))
{cout<<"\nCoefficente di "<<P.materiale<<"= "<<P.V; printf("\n");
}
fclose(f);
}



void Ricerca()
{f=fopen("F:/MICHELE LUNATI 4a As/coefficenti.dat","rb");
 cout<<"\nNome del materiale da ricercare:"; 
 fflush(stdin); gets(K);
 int Inf=0, Sup=FileSize()-1;
 trovato=false;
 while (Inf<=Sup && !trovato)
       {C=(Inf+Sup)/2;
        fseek(f,C*sizeof(P),SEEK_SET);
        fread(&P,sizeof(P),1,f);
        if(strcmp(K,P.materiale)>0) Inf=C+1;
        else {if(strcmp(K,P.materiale)<0) Sup=C-1;
              else trovato=true;
             }
       }
 if(trovato){ cout<<"\nCoefficente di "<<P.materiale<<"= "<<P.V; printf("\n"); getch();}
 else cout<<"Non presente"; getch();
fclose(f);
}





void Ordina()
{f=fopen("F:/MICHELE LUNATI 4a As/coefficenti.dat","r+");
 int Sup=FileSize();
 bool Scambio;
 Coefficenti S, T;
 do{Sup--;
    Scambio=false;
    for(int i=0; i<Sup; i++)
         {fseek(f,i*sizeof(T),SEEK_SET);
          fread(&T,sizeof(T),1,f);
          fseek(f,(i+1)*sizeof(S),SEEK_SET);
          fread(&S,sizeof(S),1,f);
          if(strcmp(T.materiale,S.materiale)>0)
             {fseek(f,i*sizeof(S),SEEK_SET);
              fwrite(&S,sizeof(S),1,f);
              fseek(f,(i+1)*sizeof(T),SEEK_SET);
              fwrite(&T,sizeof(T),1,f);
              Scambio=true;
              }
          }
    }
 while(Scambio);
 fclose(f);
}


int FileSize()
{fseek(f,0,SEEK_END); 
 int N=ftell(f);
 return N/sizeof(P);
}


float Calcolo()
{int i=0, S;
f=fopen("F:/MICHELE LUNATI 4a As/coefficenti.dat","r");
 cout<<"Inserire di quanti materiali è composto il muro:"; 
 cin>>S;
  float coefficente[Z], spessore[Z], x;
  while(i<S)
 {Ricerca(); 
  if(trovato){fseek(f,C*sizeof(P),SEEK_SET);
              fread(&P,sizeof(P),1,f);
              coefficente[i]=P.V;
              cout<<"Inserisci spessore del"<<P.materiale<<"="; 
              cin>>x;
              spessore[i]=x;
              
              }
i++;
 }
fclose(f);
int J=0; float d=0;
while(J<S)
{float rapporto=spessore[J]/coefficente[J]; 
 d+=rapporto;
G+=spessore[J];
  J++;
}
float lambda=1/d; cout<<"lambda equivalente="<<lambda;
return lambda;
}
              


void CalcoloQ()
{ float B, H, T, d;
     cout<<"Inserisci base parete"; 
     cin>>B;
     cout<<"Inserisci base parete"; 
     cin>>H;
     float A=B*H;
     cout<<"Inserisci temperatura esterna="; 
     cin>>T;
     cout<<"Inserisci temperatura interna="; 
     cin>>d;
     float Q=(A/G)*Calcolo()*(T-d);
     cout<<"Calore="<<Q; 
     getch();
     }
     


int main()
{system("CLS");
 do {Menu();
     char c=getche();      
     switch(c)
          {case'1': Carica(); break;
           case'2': Ricerca(); break;
           case'3': Visualizza(); break;
           case'4': Calcolo(); break;
           case'5': CalcoloQ(); break;
           case'6': fine=true; break;
           default: printf("\nERROR\n");
          }
    }
 while(!fine);
}    

apatriarca
Sarebbe utile sapere come hai testato il tuo programma. Quali dati hai inserito e cosa hai cercato di ottenere. Tra le varie versioni hai inoltre cancellato e ricreato da zero il "database"?

vict85
Alcune correzioni veloci: In nero quelli relativamente piccoli e potenzialmente innocui, in rosso quelli proprio sbagliati.

Riga 27:
f=fopen("F:/MICHELE LUNATI 4a As/coefficenti.dat","a");
da sostituire con
f=fopen("F:/MICHELE LUNATI 4a As/coefficenti.dat","ab");


Riga 31:
fflush(stdin); gets(P.materiale);
da sostituire con
cin>>P.materiale;


Riga 57:
{cout<<"\nCoefficente di "<<P.materiale<<"= "<<P.V; printf("\n");
da sostituire con
{cout<<"\nCoefficente di "<<P.materiale<<"= "<<P.V<<"\n";
oppure con
{cout<<"\nCoefficente di "<<P.materiale<<"= "<<P.V<<endl;
Io in genere uso il secondo.

Riga 67: come la riga 31. Ma con K al posto di P.materiale.

Riga 79: come per la Riga 57.

Riga 79-80: Non capisco il senso dei due getch(); a cosa serve? A creare una pausa?

Riga 89:
f=fopen("F:/MICHELE LUNATI 4a As/coefficenti.dat","r+");
da sostituire con
f=fopen("F:/MICHELE LUNATI 4a As/coefficenti.dat","rb+");


Riga 123:
f=fopen("F:/MICHELE LUNATI 4a As/coefficenti.dat","r");
da sostituire con
f=fopen("F:/MICHELE LUNATI 4a As/coefficenti.dat","rb");


righe 123-138: Manca il test nel fatto che \(\displaystyle Scoefficente[i]=P.V; in riga 131 e
spessore[i]=x;
scriverebbero al di fuori degli array coefficiente e spessore.

Riga 128: In questa riga chiami Ricerca, che apre in lettura lo stesso file che hai già aperto per poi chiuderlo alla fine della funzione. In questo caso lavori su f sia in Calcolo che in Ricerca contemporaneamente. Questo vuol dire che dopo la riga 128 f è un file chiuso. Le operazioni nell'if non hanno quindi alcun senso per il pc. La correzione ‘toppa’ consiste nel cambiare, in riga 65
f=fopen("F:/MICHELE LUNATI 4a As/coefficenti.dat","rb"); 
con
FILE * f=fopen("F:/MICHELE LUNATI 4a As/coefficenti.dat","rb");
ma sarebbe opportuno mettere tutto locale e gestire le cose in modo diverso.

Riga 142: Stai dividendo per un valore che potrebbe essere 0 (nel programma si intende). Il valore 0 potrebbe infatti essere introdotto per sbaglio. Il controllo potrebbe essere anche fatto in Carica.

Riga 147: Stai dividendo per un valore che potrebbe essere 0 (nel programma si intende). L’utente potrebbe infatti inserire uno spesso di 0 per ogni elemento.\( \displaystyle S

MikC1
Allora apatriarca si ho rifatto il database anche se per ora non mi accingo a farlo completo ma solo una parte. Nonostante questi aggiustamenti rimane il problema del 0.21 inspiegabile.
Grazie a vict per il tempo perso ad aggiustare il mio programma. Credo di aver aggiustato tutti i punti da te elencati tranne l'acquisizione della stringa con la gets che risulta essere l'unico modo per acquisirla con gli spazi.

#include <string.h>
#include <conio.h>
#include <iostream>
#include <list>
#define Z 30
using namespace std;
void Carica();
void CalcoloQ();
float Calcolo();
void Visualizza();
void Ordina();
void Ricerca();
int FileSize();
void Menu();
FILE *f;
bool fine;
char K[30]; int  C;
bool trovato;
float G=0;


struct Coefficenti
{char materiale[30];
 float V;
}P;


void Carica()
{f=fopen("F:/MICHELE LUNATI 4a As/coefficenti.dat","ab");
 int N, i=0; 
 cout<<"Quanti contatti vuoi inserire?="; cin>>N;
 do{cout<<"Inserisci materiale:"; 
    fflush(stdin); gets(P.materiale); 
    cout<<"Coefficente di "<<P.materiale<<"(* inserire coefficente diverso da 0 )= "; 
    cin>>P.V; 
    if(P.V != 0) {fwrite(&P,sizeof(P),1,f);}
    i++;
    }
 while(i<N);
fclose(f);
Ordina();
}


void Menu()
{cout<<"\nMenu della rubrica...\n";
     cout<<"1) Carica altri coefficenti\n";
     cout<<"2) Ricerca coefficente\n";
    cout<<"3) Visualizza coefficenti di conduttanza\n";
    cout<<"4) Calcolo lamda equivalente\n";
     cout<<"5) Calcolo calore\n"; 
     cout<<"6) Esci\n"; 
}


void Visualizza()
{f=fopen("F:/MICHELE LUNATI 4a As/coefficenti.dat","rb");
 while(fread(&P,sizeof(P),1,f))
{cout<<"\nCoefficente di "<<P.materiale<<"= "<<P.V<<endl;
}
fclose(f);
}



void Ricerca()
{f=fopen("F:/MICHELE LUNATI 4a As/coefficenti.dat","rb");
 cout<<"\nNome del materiale da ricercare:"; 
 fflush(stdin); gets(K);
 int Inf=0, Sup=FileSize()-1;
 trovato=false;
 while (Inf<=Sup && !trovato)
       {C=(Inf+Sup)/2;
        fseek(f,C*sizeof(P),SEEK_SET);
        fread(&P,sizeof(P),1,f);
        if(strcmp(K,P.materiale)>0) Inf=C+1;
        else {if(strcmp(K,P.materiale)<0) Sup=C-1;
              else trovato=true;
             }
       }
 if(trovato){cout<<"\nCoefficente di "<<P.materiale<<"= "<<P.V<<endl;}
 else cout<<"Non presente"; 
 getch();
fclose(f);
}





void Ordina()
{f=fopen("F:/MICHELE LUNATI 4a As/coefficenti.dat","rb+");
 int Sup=FileSize();
 bool Scambio;
 Coefficenti S, T;
 do{Sup--;
    Scambio=false;
    for(int i=0; i<Sup; i++)
         {fseek(f,i*sizeof(T),SEEK_SET);
          fread(&T,sizeof(T),1,f);
          fseek(f,(i+1)*sizeof(S),SEEK_SET);
          fread(&S,sizeof(S),1,f);
          if(strcmp(T.materiale,S.materiale)>0)
             {fseek(f,i*sizeof(S),SEEK_SET);
              fwrite(&S,sizeof(S),1,f);
              fseek(f,(i+1)*sizeof(T),SEEK_SET);
              fwrite(&T,sizeof(T),1,f);
              Scambio=true;
              }
          }
    }
 while(Scambio);
 fclose(f);
}


int FileSize()
{fseek(f,0,SEEK_END); 
 int N=ftell(f);
 return N/sizeof(P);
}


float Calcolo()
{int i=0, S;
cout<<"Inserire di quanti materiali è composto il muro:"; 
 cin>>S;
  if(S > 0)
  {float coefficente[Z], spessore[Z], x;
   while(i<S)
    {Ricerca(); 
     if(trovato){f=fopen("F:/MICHELE LUNATI 4a As/coefficenti.dat","r");
                 fseek(f,C*sizeof(P),SEEK_SET);
                 fread(&P,sizeof(P),1,f);
                 coefficente[i]=P.V;
                 cout<<"Inserisci spessore del"<<P.materiale<<"(non nullo in metri) ="<<endl; 
                 cin>>x;
                 if(x > 0) {spessore[i]=x; 
                            i++;
                            cout<<"Spessore non valido"<<endl;
                            }
                 }
      }
fclose(f);
int J=0; float d=0;
while(J<S)
{float rapporto=spessore[J]/coefficente[J]; 
 d+=rapporto;
 G+=spessore[J];
  J++;
}
float lambda=1/d; cout<<"Lambda equivalente="<<lambda<<" [ m^2K/W ]"<<endl;
return lambda;
}
}

              


void CalcoloQ()
{ float B, H, T, d;
     cout<<"Inserisci base parete  (non nulla in metri) :"<<endl; 
     cin>>B;
     cout<<"Inserisci altezza parete  (non nulla in metri) :"<<endl;
     cin>>H;
     float A=B*H;
     
     cout<<"Inserisci temperatura esterna  (non nulla in gradi):"<<endl; 
     cin>>T;
     cout<<"Inserisci temperatura interna  (non nulla in gradi):"<<endl; 
     cin>>d;
     float Q=Calcolo()*(d-T)*(A/G);
     cout<<"Trasmittanza termica="<<Q<<" [ W/m^2K ]"<<endl;
     getch();
     }
     


int main()
{system("CLS");
 do {Menu();
     char c=getche();      
     switch(c)
          {case'1': Carica(); break;
           case'2': Ricerca(); break;
           case'3': Visualizza(); break;
           case'4': Calcolo(); break;
           case'5': CalcoloQ(); break;
           case'6': fine=true; break;
           default: printf("\nERROR\n");
          }
    }
 while(!fine);
}

vict85
Ho provato il tuo codice sul mio, con code::blocks e mingw, e mi funziona tutto. Quindi, a meno che l'utente non voglia mandare in crash volontariamente il tuo programma, direi che è giusto. A me mostra 0.21! Prova a ricancellare il file e riinserire i dati.

Nel codice che hai postato hai comunque dimenticato
#include <cstdio>
#include <cstring>
all'inizio (ma ti sarai dimenticato di copiarlo :roll: )

e poi c'é il simpatico ed innocuo errore di scrivere
if(x > 0)
{
  spessore[i]=x;
  i++;
  cout<<"Spessore non valido"<<endl;
}

invece di
if(x > 0)
{
     spessore[i]=x;
     i++;
}
else
{
   cout<<"Spessore non valido"<<endl;
}

claudio862
Bonus: lo stesso identico sorgente di due post sopra, più le modifiche suggerite da vict85 nell'ultimo post, ma formattato decentemente.
Segnalo inoltre che la funzione Calcolo() non restituisce niente se S <= 0 (manca proprio l'istruzione return).

Se vuoi che capiamo perché in alcuni casi non legga 0.21 devi metterci in condizione di vedere questo problema. Descrivici, partendo da un database vuoto, tutte le operazioni che fai fino ad avere il problema.

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <conio.h>
#include <iostream>
#include <list>

#define Z 30

using namespace std;

void Carica();
void CalcoloQ();
float Calcolo();
void Visualizza();
void Ordina();
void Ricerca();
int FileSize();
void Menu();

FILE *f;
bool fine;
char K[30];
int  C;
bool trovato;
float G = 0;


struct Coefficenti {
    char materiale[30];
    float V;
} P;


void Carica() {
    f = fopen("F:/MICHELE LUNATI 4a As/coefficenti.dat", "ab");
    int N, i = 0;
    cout << "Quanti contatti vuoi inserire?=";
    cin >> N;
    do {
        cout << "Inserisci materiale:";
        fflush(stdin);
        gets(P.materiale);
        cout << "Coefficente di " << P.materiale << "(* inserire coefficente diverso da 0 )= ";
        cin >> P.V;
        if (P.V != 0) {
            fwrite(&P, sizeof(P), 1, f);
        }
        i++;
    } while (i < N);
    fclose(f);
    Ordina();
}


void Menu() {
    cout << "\nMenu della rubrica...\n";
    cout << "1) Carica altri coefficenti\n";
    cout << "2) Ricerca coefficente\n";
    cout << "3) Visualizza coefficenti di conduttanza\n";
    cout << "4) Calcolo lamda equivalente\n";
    cout << "5) Calcolo calore\n";
    cout << "6) Esci\n";
}


void Visualizza() {
    f = fopen("F:/MICHELE LUNATI 4a As/coefficenti.dat", "rb");
    while (fread(&P, sizeof(P), 1, f)) {
        cout << "\nCoefficente di " << P.materiale << "= " << P.V << endl;
    }
    fclose(f);
}


void Ricerca() {
    f = fopen("F:/MICHELE LUNATI 4a As/coefficenti.dat", "rb");
    cout << "\nNome del materiale da ricercare:";
    fflush(stdin);
    gets(K);
    int Inf = 0, Sup = FileSize() - 1;
    trovato = false;
    while (Inf <= Sup && !trovato) {
        C = (Inf + Sup) / 2;
        fseek(f, C * sizeof(P), SEEK_SET);
        fread(&P, sizeof(P), 1, f);
        if (strcmp(K, P.materiale) > 0) Inf = C + 1;
        else {
            if (strcmp(K, P.materiale) < 0) Sup = C - 1;
            else trovato = true;
        }
    }
    if (trovato) {
        cout << "\nCoefficente di " << P.materiale << "= " << P.V << endl;
    } else cout << "Non presente";
    getch();
    fclose(f);
}



void Ordina() {
    f = fopen("F:/MICHELE LUNATI 4a As/coefficenti.dat", "rb+");
    int Sup = FileSize();
    bool Scambio;
    Coefficenti S, T;
    do {
        Sup--;
        Scambio = false;
        for (int i = 0; i < Sup; i++) {
            fseek(f, i * sizeof(T), SEEK_SET);
            fread(&T, sizeof(T), 1, f);
            fseek(f, (i + 1)*sizeof(S), SEEK_SET);
            fread(&S, sizeof(S), 1, f);
            if (strcmp(T.materiale, S.materiale) > 0) {
                fseek(f, i * sizeof(S), SEEK_SET);
                fwrite(&S, sizeof(S), 1, f);
                fseek(f, (i + 1)*sizeof(T), SEEK_SET);
                fwrite(&T, sizeof(T), 1, f);
                Scambio = true;
            }
        }
    } while (Scambio);
    fclose(f);
}


int FileSize() {
    fseek(f, 0, SEEK_END);
    int N = ftell(f);
    return N / sizeof(P);
}


float Calcolo() {
    int i = 0, S;
    cout << "Inserire di quanti materiali è composto il muro:";
    cin >> S;
    if (S > 0) {
        float coefficente[Z], spessore[Z], x;
        while (i < S) {
            Ricerca();
            if (trovato) {
                f = fopen("F:/MICHELE LUNATI 4a As/coefficenti.dat", "r");
                fseek(f, C * sizeof(P), SEEK_SET);
                fread(&P, sizeof(P), 1, f);
                coefficente[i] = P.V;
                cout << "Inserisci spessore del" << P.materiale << "(non nullo in metri) =" << endl;
                cin >> x;
                if (x > 0) {
                    spessore[i] = x;
                    i++;
                } else {
                    cout << "Spessore non valido" << endl;
                }
            }
        }
        fclose(f);
        int J = 0;
        float d = 0;
        while (J < S) {
            float rapporto = spessore[J] / coefficente[J];
            d += rapporto;
            G += spessore[J];
            J++;
        }
        float lambda = 1 / d;
        cout << "Lambda equivalente=" << lambda << " [ m^2K/W ]" << endl;
        return lambda;
    }
}




void CalcoloQ() {
    float B, H, T, d;
    cout << "Inserisci base parete  (non nulla in metri) :" << endl;
    cin >> B;
    cout << "Inserisci altezza parete  (non nulla in metri) :" << endl;
    cin >> H;
    float A = B * H;

    cout << "Inserisci temperatura esterna  (non nulla in gradi):" << endl;
    cin >> T;
    cout << "Inserisci temperatura interna  (non nulla in gradi):" << endl;
    cin >> d;
    float Q = Calcolo() * (d - T) * (A / G);
    cout << "Trasmittanza termica=" << Q << " [ W/m^2K ]" << endl;
    getch();
}



int main() {
    system("CLS");
    do {
        Menu();
        char c = getche();
        switch (c) {
        case'1':
            Carica();
            break;
        case'2':
            Ricerca();
            break;
        case'3':
            Visualizza();
            break;
        case'4':
            Calcolo();
            break;
        case'5':
            CalcoloQ();
            break;
        case'6':
            fine = true;
            break;
        default:
            printf("\nERROR\n");
        }
    } while (!fine);
}

MikC1
Ok non so come saranno state le preghiere , o le bestemmie, che ho fatto ma il programma funziona.
Ringrazio di cuore tutti ma proprio tutti quelli che mi hanno dato una mano spero che mi aiuterete anche con i programmi successivi.

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.