Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

Problema con esercizio in C

Linguaggi e sistemi

Moderatori: Foto UtentePaolino, Foto Utentefairyvilje

0
voti

[1] Problema con esercizio in C

Messaggioda Foto Utentegennyior » 18 gen 2014, 16:49

Salve a tutti , ho un problema con questo esercizio in C :

Si vuole realizzare una versione elettronica di un ricettario.
Il programma deve identificare queli sono le ricette cucinabili dato il conenuto del frigo.
Il programma accede a due file :
1) un file di testo (ricetta.txt) contenente tutti gli ingredienti per tutte le ricette secondo il seguente formato .
_ogni riga è nella forma : ricetta ingrediente quantita'
_ricetta è una stringa (max 20 caratteri)che indica il nome della ricetta
_ingrediente è una stringa (max 20 caratteri)che indica il nome dell ingrediente
_quantita' è un numero reale che indica la quantita' di tale ingrediente nella ricetta corrispondente
_sia ingrediente sia ricetta sono ripetuti piu' volte ma sempre in associazione a ricette o ingredienti diversi

2)un file di testo (frigo.txt) che rappresenta il contenuto del frigo in questo formato :
_ogni riga è nella forma : ingrediente quantita'
_ingrediente corrisponde ad uno degli ingredienti presenti nel file delle ricette
_quantita' è un numero che indica la quantita' di tale ingrediente nel frigo
_ogni ingrediente è presente una sola volta in questo file
_non è noto a priori il numero di righe del file né l ordine.
Il programma legge da tastiera il nome del file contenente la disponibilita' del frigorifero ed il nome di una ricetta e deve fornire in output l elenco degli ingredienti della ricetta (con l indicazione se è disponibile o meno e l indicazione finale se la ricetta puo' essere preparata.



La mia soluzione è questa qui , mi dite se per voi va bene o c è qualcosa che non va ?

Codice: Seleziona tutto
#include <stdio.h>
#include <string.h>
#define MAX 100

struct cucinare {
   char ricetta[20];
   char ingrediente[20];
   float quantita;
};

struct frigo {
   char ingrediente[20];
   float quantita;
};

struct cucinare cibo[MAX];
struct frigo dispensa[MAX];
FILE *file;

int  i;
char nomeFile[20];
char nomeRicetta[20];
int numRighe1=0;
int numRighe2=0;
int j;

int contaRighe(char *nomeFile, int *numRighe)
{
   FILE *file;
   int conta_righe=0;
   char c[200]; //stringa di appoggio

   file=fopen(nomeFile, "r");
   while(fgets(c, 200, file) != NULL)
      conta_righe++;
   fclose(file);
   *numRighe=conta_righe;
}

char vettore(char nomeRicetta[20])
{

   file=fopen("ricetta.txt", "r");
   contaRighe("ricetta.txt", &numRighe1);
   for(i=0;i<numRighe1;i++)
      fscanf(file, "%s %s %f", cibo[i].ricetta, cibo[i].ingrediente, &cibo[i].quantita);
   fclose(file);

   file=fopen("frigo.txt", "r");
   contaRighe("frigo.txt", &numRighe2);
   for(i=0; i<numRighe2;i++)
      fscanf(file, "%s %f", dispensa[i].ingrediente, &dispensa[i].quantita);
   fclose(file);

   for(i=0; i<numRighe1; i++) {
      if(strcmp(cibo[i].ricetta, nomeRicetta) == 0) {
         for(j=0; j<numRighe2; j++) {
            if(strcmp(dispensa[j].ingrediente, cibo[i].ingrediente) == 0) {
               if(dispensa[j].quantita>=cibo[i].quantita)
                  printf("-%s: OK\n", dispensa[j].ingrediente);
               else {
                  printf("-%s: richiesto %.1f, disponibile %.1f\n", dispensa[j].ingrediente, cibo[i].quantita, dispensa[j].quantita);
                  printf("Impossibile preparare la ricetta.\n");
               }
            }
         }
      }
   }
}

int main()
{
   printf("Inserisci il nome del file che contiene la disponibilità del frigo\n");
   printf("e il nome della ricetta che desideri preparare:\n");
   scanf("%s %s", nomeFile, nomeRicetta);
   printf("Per preparare \"%s\" servono i seguenti ingredienti:\n", nomeRicetta);
   vettore(nomeRicetta);
   return 0;
}



Grazie mille.

Schermata 2014-01-18 alle 15.46.25.png
Avatar utente
Foto Utentegennyior
145 1 6
Frequentatore
Frequentatore
 
Messaggi: 155
Iscritto il: 21 nov 2013, 20:26

0
voti

[2] Re: Problema con esercizio in C

Messaggioda Foto Utentegennyior » 18 gen 2014, 20:09

ho inserito nel file in allegato i dati relativi ai file richiesti.
Grazie ancora
Avatar utente
Foto Utentegennyior
145 1 6
Frequentatore
Frequentatore
 
Messaggi: 155
Iscritto il: 21 nov 2013, 20:26

0
voti

[3] Re: Problema con esercizio in C

Messaggioda Foto Utentegennyior » 19 gen 2014, 20:10

Qualche gentile anima pia che potesse consigliarmi ? non saprei come altro fare ?%
Avatar utente
Foto Utentegennyior
145 1 6
Frequentatore
Frequentatore
 
Messaggi: 155
Iscritto il: 21 nov 2013, 20:26

2
voti

[4] Re: Problema con esercizio in C

Messaggioda Foto UtentePepito » 19 gen 2014, 20:26

Ciao.
Non ho provato a compilare il tuo sorgente, quindi se hai dimenticato un punto e virgola non lo so.
Comunque concettualmente sembra poter funzionare, anche se certe cose mi sembrano veramente brutte.

La prima cosa che farei è innanzitutto evitare l'uso massiccio che hai fatto delle variabili globali (o statiche, essendo nello stesso modulo). Io passerei come parametro ciò che non sono strettamente costretto a lasciare accessibile a tutte le funzioni. Nella programmazione è buona norma non usare variabili globali o static se non si è costretti ad esempio dalla necessità, come ad esempio per variabili di stato e simili.

Poi l'uso che fai della struttura delle ricette è secondo me un po' "strano". Tu ti carichi tutta la struttura per cercare la ricetta. Questo può andare bene se nel tuo programma vuoi permettere più ricerche senza andare di nuovo ad accedere al file. Però in questo caso non ti serve aprire di nuovo il file per contarne le righe, lo fai mentre carichi i dati nella struttura. Idem per il file del frigo.

Poi quando fai la ricerca delle ricette, scorri tutta la struttura anche una volta che hai trovato la ricetta che cercavi. Questo è spreco di risorse.

Queste sono le prime cose che mi vengono in mente.
ciao

PSQ
_-^-_-^-_-^-_-^-_-^-_-^-_-^-_-^-_-^-_-^-_-^-_-^-_-^-_-^-_

Pepito Sbazzeguti
"gratta il Pepito e troverai il Pepone"
Avatar utente
Foto UtentePepito
1.759 6 12
Expert EY
Expert EY
 
Messaggi: 493
Iscritto il: 29 set 2012, 16:49

0
voti

[5] Re: Problema con esercizio in C

Messaggioda Foto Utentegennyior » 19 gen 2014, 20:39

Ti ringrazio innanzitutto per la disponibilita' .
Io ho studiato il C++ qualche anno fa per un esame all universita' , ora c è un amica al primo anno di matematica che è gia stata bocciata due volte ma loro programmano in C , mi ha chiesto una mano ma io piu' di cosi non riesco .
Ti andrebbe di mettere mano al mio codice per modificarmelo o chiedo troppo ?
Magari cosi' riesco a capire qual è il modo migliore per farlo e cerco di spiegarglielo alla meglio visto che è demoralizzatissima.

Grazie ancora
Avatar utente
Foto Utentegennyior
145 1 6
Frequentatore
Frequentatore
 
Messaggi: 155
Iscritto il: 21 nov 2013, 20:26

2
voti

[6] Re: Problema con esercizio in C

Messaggioda Foto Utenteobiuan » 19 gen 2014, 22:41

Ciao

Premesso che per un esercizio secondo me il codice non era pi così male, quantomeno sembrava funzionante, l'ho un po' rigirato per dargli una forma un po' più professionale. Non ho con me un compilatore C...in realtà sono in trasferta in medio oriente e pure stanco morto, quindi perdonami qualche errore sintattico sicuramente presente. Prendi il codice qui sotto in modo "generale", sono certo che qualche fesseria l'ho scritta e che quindi non compilerà, non al primo tentativo in ogni caso.

Gli errori, per così dire, erano:

- Utilizzo di variabili globali assolutamente inutili (i,j,numRighe1, numRighe2) che potevano essere semplicemente dichiarate all'interno della funzione Vettore.
- Utilizzo di array sovradimensionati per contenere quantità di dati ignote.
- Rilettura in diversi punti degli stessi file...una volta che li hai letti, tanto fa che li memorizzi.

Che mi pare in sostanza sia quanto ti è stato già fatto notare da Foto UtentePepito qui sopra.

comunque, ho spostato le globali facendole diventare locali, ed eliminando le inutili. Ho trasformato gli array in liste concatenate e usato il malloc per l'allocazione dinamica. Visto che il programma termina dopo l'esecuzione, non mi sono curato dei free relativi. Usando la lista, ho quindi eliminato la necessità di contare le righe, ottimizzando quindi il codice dal punto di vista prestazionale.

Ciao

Codice: Seleziona tutto
#include <stdio.h>
#include <string.h>

struct cucinare {
   char ricetta[20];
   char ingrediente[20];
   float quantita;
   struct cucinare* nextItem; // puntatore al prossimo elemento della lista concatenata
};

struct frigo {
   char ingrediente[20];
   float quantita;
   struct frigo* nextItem; // puntatore al prossimo elemento della lista concatenata
};

// solo puntatori globali
struct cucinare* cibo;    // puntatore "base" della lista cibo
struct frigo* dispensa;  // puntatore base della lista frigo
FILE *file;

int loadRicette()
{
   FILE *file;
   int conta_righe=0;
   char c[200]; //stringa di appoggio
   struct cucinare* runningPointer = cibo;
   file=fopen("ricetta.txt", "r");
   while(fgets(c, 200, file) != NULL) {
      if (conta_righe == 0)  // se è il primo elemento, crea la base della lista (puntata dalla variabile globale cibo")
          runningPointer = (struct cucinare*) malloc(sizeof(struct cucinare));         
      else {                 // altrimenti, aggiunge un elemento in coda e sposta il puntantore
          runningPointer.nextItem = (struct cucinare*) malloc(sizeof(struct cucinare));         
     runningPointer = runningPointer.nextItem;
      }
      runningPointer.nextItem = null;
      // legge da file e  memorizza nell'elemento della lista puntato al momento
      fscanf(file, "%s %s %f", *runningPointer.ricetta, *runningPointer.ingrediente, *runningPointer.quantita);
      conta_righe++;
   }
   fclose(file);
   return conta_righe;
}

int loadFrigo(char *nomeFile)
{
   FILE *file;
   int conta_righe=0;
   char c[200]; //stringa di appoggio
   struct frigo* runningPointer = dispensa;
   file=fopen("frigo.txt", "r");
   while(fgets(c, 200, file) != NULL) {
      if (conta_righe == 0)  // se è il primo elemento, crea la base della lista (puntata dalla variabile globale dispensa)
          runningPointer = (struct frigo*) malloc(sizeof(struct frigo)); 
      else {                 // altrimenti, aggiunge un elemento in coda e sposta il puntantore
          runningPointer.nextItem = (struct frigo*) malloc(sizeof(struct frigo));         
     runningPointer = runningPointer.nextItem;
      }
      runningPointer.nextItem = null;
      // legge da file e  memorizza nell'elemento della lista puntato al momento
      fscanf(file, "%s %s %f", *runningPointer.ricetta, *runningPointer.ingrediente, *runningPointer.quantita);
      conta_righe++;
   }
   fclose(file);
   return conta_righe;   
}

char vettore(char* nomeFile, char* nomeRicetta)
{
   int  i;   // queste andavano benissimo locali
   int j;    //
   struct frigo* runningFrigo = dispensa;
   struct cucinare* runningCibo = cibo;
   loadRicette(); // legge il file e carica  una lista concatenata (monodirezionale) con base &cibo
   loadFrigo(nomeFile);   // legge il file e carica una lista concatenata (monodirezionale) con base &dispensa

   while (runningCibo != null) {
      if(strcmp((runningCibo.ricetta, nomeRicetta) == 0) {
         while (runningFrigo != null) {
            if(strcmp(runningFrigo.ingrediente, runningCibo.ingrediente) == 0) {
               if(runningFrigo.quantita>=runningCibo.quantita)
                  printf("-%s: OK\n", runningFrigo.ingrediente);
               else {
                  printf("-%s: richiesto %.1f, disponibile %.1f\n", runningFrigo.ingrediente, runningCibo.quantita, runningFrigo.quantita);
                  printf("Impossibile preparare la ricetta.\n");
               }
            }
            runningFrigo = runningFrigo.nextItem;
         }
      }
      runningCibo = runningCibo.nextItem;
   }
}

int main()
{
   char nomeFile[20];
   char nomeRicetta[20];
   printf("Inserisci il nome del file che contiene la disponibilità del frigo\n");
   printf("e il nome della ricetta che desideri preparare:\n");
   scanf("%s %s", nomeFile, nomeRicetta);
   printf("Per preparare \"%s\" servono i seguenti ingredienti:\n", nomeRicetta);
   vettore(&nomeFile, &nomeRicetta);
   return 0;
}
_______________________________________________________
Gli oscillatori non oscillano mai, gli amplificatori invece sempre

Io HO i poteri della supermucca, e ne vado fiero!
Avatar utente
Foto Utenteobiuan
5.894 3 10 13
Master
Master
 
Messaggi: 980
Iscritto il: 23 set 2013, 23:45

2
voti

[7] Re: Problema con esercizio in C

Messaggioda Foto UtentePepito » 19 gen 2014, 23:48

Ciao.
Dunque, come diceva Foto Utenteobiuan il tuo codice non era "sbagliato". Semplicemente può essere migliorato. Ho pensato di fare una versione intermedia tra la tua e quella di obiuan, lasciando come globali le strutture ma riorganizzando un po' le funzioni.
Gli array li ho lasciati cos' (di dimensione fissa) per un motivo: non so se la tua amica ha studiato l'allocazione dinamica con malloc.
Comunque, per fare in modo che io e Foto Utenteobiuan non abbiamo solo fatto i compiti, sarebbe bello che magari ci chiedessi il perché di certe scelte nella scrittura del programma, magari coinvolgendo la tua amica che è poi la persona che dovrà fare l'esame... :D
ciao

PSQ

Codice:

Codice: Seleziona tutto
#include <stdio.h>
#include <string.h>

#define MAX_RICETTE_NUM 100
#define MAX_INGREDIENTI_NUM 100
#define MAX_NAME_LEN 20
#define MAX_RIGA_LEN 200

#define NOME_FILE_RICETTE "ricette.txt"

struct ricetta {
   char nome[MAX_NAME_LEN];
   char ingrediente[MAX_NAME_LEN];
   float quantita;
};

struct ingrediente {
   char nome[MAX_NAME_LEN];
   float quantita;
};

struct preparazione {
  char nome_ingrediente[MAX_NAME_LEN];
  float richiesta;
  float disponibilita;
};

struct ricetta Ricette[MAX_RICETTE_NUM];
struct ingrediente Frigo[MAX_INGREDIENTI_NUM];
struct preparazione Preparato[MAX_INGREDIENTI_NUM];

unsigned char NumeroRicette;
unsigned char NumeroIngredienti;
unsigned char ElementiComposizione;


unsigned char CaricaRicette(char *nomefile)
{
  FILE *file;
  unsigned char num_ric;
  char riga[MAX_RIGA_LEN];

  num_ric = 0;
  file = fopen(nomefile, "r");
  if(file != NULL)
  {
    while(fgets(riga, MAX_RIGA_LEN, file) != NULL)
    {
      sscanf(riga, "%s %s %f", Ricette[num_ric].nome, Ricette[num_ric].ingrediente, &Ricette[num_ric].quantita);
      num_ric++;
    }
    fclose(file);
  }
  return(num_ric);
}


unsigned char CaricaFrigo(char *nomefile)
{
  FILE *file;
  unsigned char num_ing;
  char riga[MAX_RIGA_LEN];

  num_ing = 0;
  file = fopen(nomefile, "r");
  if(file != NULL)
  {
    while(fgets(riga, MAX_RIGA_LEN, file) != NULL)
    {
      sscanf(riga, "%s %f", Frigo[num_ing].nome, &Frigo[num_ing].quantita);
      num_ing++;
    }
    fclose(file);
  }
  return(num_ing);
}


void ComponiPreparato(char *nome_ricetta)
{
  unsigned char i;
  unsigned char j;

  ElementiComposizione = 0;

  for(i = 0; i < NumeroRicette; i++)
  {
    if(strcmp(Ricette[i].nome, nome_ricetta) == 0)
    {
      strcpy(Preparato[ElementiComposizione].nome_ingrediente,Ricette[i].ingrediente);
      Preparato[ElementiComposizione].richiesta = Ricette[i].quantita;
      Preparato[ElementiComposizione].disponibilita = 0;
      for(j = 0; j < NumeroIngredienti; j++)
      {
        if(strcmp(Preparato[ElementiComposizione].nome_ingrediente,Frigo[j].nome) == 0)
        {
          Preparato[ElementiComposizione].disponibilita = Frigo[j].quantita;
        }
      }
      ElementiComposizione++;
    }
  }

}

int main()
{
  char nome_file_frigo[MAX_NAME_LEN];
  char nome_ricetta[MAX_NAME_LEN];
  char esito[MAX_NAME_LEN];
  unsigned char i;

  NumeroRicette = 0;
  NumeroIngredienti = 0;

  printf("Inserisci il nome del file che contiene la disponibilità del frigo\n");
  printf("e il nome della ricetta che desideri preparare:\n");

  scanf("%s %s", nome_file_frigo, nome_ricetta);

  NumeroRicette = CaricaRicette(NOME_FILE_RICETTE);
  NumeroIngredienti = CaricaFrigo(nome_file_frigo);
  ComponiPreparato(nome_ricetta);

  if(NumeroRicette != 0 && NumeroIngredienti != 0)
  {
    printf("Per preparare \"%s\" servono i seguenti ingredienti:\n", nome_ricetta);

    for(i = 0; i < ElementiComposizione; i++)
    {
      if(Preparato[i].richiesta <= Preparato[i].disponibilita)
      {
        strcpy(esito, "DISPONIBILE");
      }
      else
      {
        strcpy(esito, "MANCANTE");
      }
      printf("%s %f %s\n", Preparato[i].nome_ingrediente, Preparato[i].richiesta, esito);
    }
  }
  else
  {
    printf("Ricette o Frigorifero mancanti!\n");
  }

  return 0;
}

_-^-_-^-_-^-_-^-_-^-_-^-_-^-_-^-_-^-_-^-_-^-_-^-_-^-_-^-_

Pepito Sbazzeguti
"gratta il Pepito e troverai il Pepone"
Avatar utente
Foto UtentePepito
1.759 6 12
Expert EY
Expert EY
 
Messaggi: 493
Iscritto il: 29 set 2012, 16:49

0
voti

[8] Re: Problema con esercizio in C

Messaggioda Foto Utentegennyior » 24 gen 2014, 20:31

anzitutto grazie per la grande disponibilita' e mi scuso per il ritardo nella risposta dovuto ad impegni lavorativi, per quanto riguarda l'esercizio ho per sommi capi compreso il perché di tutto ma domani lo vedro' meglio insieme all'interessata e non esitero' in alcun modo a chiedere "il perché di alcune scelte" forte della disponibilità' che avete mostrato nell aiutarmi a compensare queste lacune.
Confermo inoltre il mancato studio dell'allocazione dinamica con malloc ma in verita' non è l unico neo mancante che probabilmente impedira' l'immediata comprensione totale del codice.
Ne approfitto per augurarvi una Buona serata O_/
Avatar utente
Foto Utentegennyior
145 1 6
Frequentatore
Frequentatore
 
Messaggi: 155
Iscritto il: 21 nov 2013, 20:26

0
voti

[9] Re: Problema con esercizio in C

Messaggioda Foto UtentePepito » 24 gen 2014, 21:43

Ciao.
Pensavo fossi sparito una volta avuta la soluzione (come fanno molti...) :D
comunque tranquillo, nella mia soluzione non c'è l'uso della malloc, anche se in C è una cosa che conviene studiarsi, indipendentemente dal fatto che il corso la tratti o meno (se non la tratta tanto valeva che le insegnassero matlab, scilab o simili...)
ciao

PSQ
_-^-_-^-_-^-_-^-_-^-_-^-_-^-_-^-_-^-_-^-_-^-_-^-_-^-_-^-_

Pepito Sbazzeguti
"gratta il Pepito e troverai il Pepone"
Avatar utente
Foto UtentePepito
1.759 6 12
Expert EY
Expert EY
 
Messaggi: 493
Iscritto il: 29 set 2012, 16:49

0
voti

[10] Re: Problema con esercizio in C

Messaggioda Foto Utentegennyior » 24 gen 2014, 22:49

ciao,
no figurati non sarei mai sparito, sono un assiduo frequentatore del forum ed apprezzo troppo la disponibilita' delle persone come te , per giunta quando non mi è chiara una cosa ( e obiuan puo' confermare) sono al quanto assillante. :lol:
comunque sia per quanto riguarda l'uso di malloc non saprei dirti di piu' , io per giunta ho dato un occhiata al C soltanto per essere utile in quanto non l ho mai studiato avendo soltanto avuto a che fare direttamente con il c++ .
Magari approfondisco e ti faccio sapere O_/
Avatar utente
Foto Utentegennyior
145 1 6
Frequentatore
Frequentatore
 
Messaggi: 155
Iscritto il: 21 nov 2013, 20:26


Torna a PC e informatica

Chi c’è in linea

Visitano il forum: Nessuno e 21 ospiti