Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - Problema codice C per lavoro sui files
Forum - C/C++ - Problema codice C per lavoro sui files

Avatar
()
Newbie


Messaggi:
Iscritto:

Segnala al moderatore
Postato alle 1:00
Giovedì, 01/01/1970
Buongiorno :)
Stamattina ho deciso di provare a risolvere il problema n°8 di ProjectEuler ( https://projecteuler.net/problem=8 ). Ho dunque scritto l'algoritmo e l'ho tradotto in linguaggio C, ottenendo questo codice:

Codice sorgente - presumibilmente C++

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdbool.h>
  4.  
  5.  
  6. /*dichiarazione variabili globali contenenti il massimo prodotto, i 13 numeri da moltiplicare, un interruttore per sapere se il processo
  7. è avvenuto correttamente  e tutte le cifre su cui lavorare*/
  8. long int max_prod = 0;
  9. int val[13];
  10. bool completo = true;
  11. char string[] = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869
  12. 47885184385861560789112949495459501737958331952853208805511125406987471585238630507156932909
  13. 63295227443043557668966489504452445231617318564030987111217223831136222989342338030813533627
  14. 66142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998
  15. 79790879227492190169972088809377665727333001053367881220235421809751254540594752243525849077
  16. 11670556013604839586446706324415722155397536978179778461740649551492908625693219784686224828
  17. 39722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758
  18. 86668811642717147992444292823086346567481391912316282458617866458359124566529476545682848912
  19. 88314260769004224219022671055626321111109370544217506941658960408071984038509624554443629812
  20. 30987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507
  21. 754100225698315520005593572972571636269561882670428252483600823257530420752963450";
  22.  
  23. /*dichiarazione delle funzioni necessarie*/
  24. long int lettura(char[], long int);
  25. long int moltiplica(int[]);
  26. long int confronta(long int, long int);
  27.  
  28.  
  29. int main()
  30. {
  31.         /*definizione dell'indice dei valori letti dal file, e scrittura del file*/
  32.         long int indice = 0;
  33.         FILE* numeri = fopen("file.dat", "w");
  34.         fprintf(numeri, "%s", string);
  35.         fclose(numeri);
  36.  
  37.         /*Inizio della computazione: introduzione dell'utente nel programma e inizio lettura del file*/
  38.         printf("Inizio del calcolo: apertura del file... \n");
  39.         long int prodotto = lettura("file.dat", indice);
  40.  
  41.         /*confronto del prodotto appena ottenuto con il massimo prodotto ottenuto fin'ora*/
  42.         if (prodotto != 0)
  43.         {
  44.                 max_prod = confronta(prodotto, max_prod);
  45.                 prodotto = lettura("file.dat", indice);
  46.         }
  47.         /*se tutti i prodotti sono già stati calcolati e confrontati, il massimo di loro viene stampato*/
  48.         else if (prodotto == 0)
  49.         {
  50.                 printf("Fine del file. \n Il massimo prodotto possibile è %u", max_prod);
  51.                 printf("\n Premere un qualsiasi tasto per uscire.");
  52.                 getchar();
  53.                 return 0;
  54.         }
  55. }
  56.  
  57. long int lettura(char nome[],long int indice)
  58. {
  59.         /*il file viene aperto*/
  60.         FILE* numeri = fopen(nome, "r");
  61.  
  62.         /*i numeri vengono letti*/
  63.         for (int i = 0; i <= 12; i++)
  64.         {
  65.                 /*si imposta la posizione da cui cominciare la lettura*/
  66.                 fseek(numeri, indice, SEEK_SET);
  67.                
  68.                 /*se il file è già stato letto tutto, il ciclo si può interrompere*/
  69.                 if (ftell(numeri) == EOF)
  70.                 {
  71.                         completo = false;
  72.                         break;
  73.                 }
  74.                 /*se viene letto uno zero, il prodotto sarà nullo, quindi è inutile proseguire: meglio andare oltre lo zero*/
  75.                 else if (fscanf(numeri, "%d", &val[i]) == 0)
  76.                 {
  77.                         i = 0;
  78.                         indice = ftell(numeri) + 1;
  79.                 }
  80.                 /*se il valore letto non è uno zero, esso può essere memorizzato nell'array*/
  81.                 else
  82.                 {
  83.                         fscanf(numeri, "%d", &val[i]);
  84.                         printf("Numero letto: %d \n", val[i]);
  85.                         i++;
  86.                         indice++;
  87.                 }
  88.         }
  89.  
  90.         /*se la lettura è completa, i numeri rilevati devono essere moltiplicati tra loro*/
  91.         if (completo == true)
  92.         {
  93.                 int prodotto = moltiplica(val);
  94.                 fclose(numeri);
  95.                 return prodotto;
  96.         }
  97.         /*se il file è finito, la lettura non deve più continuare*/
  98.         else if (completo == false)
  99.         {
  100.                 fclose(numeri);
  101.                 return 0;
  102.         }
  103. }
  104.  
  105. long int moltiplica(int val[])
  106. {
  107.         /*si inizializa il prodotto assegnandogli il primo valore letto dal file*/
  108.         int prodotto = val[0];
  109.  
  110.         /*si effettua la moltiplicazione e si stampa il risultato*/
  111.         for (int i = 1; i <= 12; i++) prodotto *= val[i];
  112.         printf("Prodotto ottenuto: %s", prodotto);
  113.  
  114.         /*il valore finale viene inviato*/
  115.         return prodotto;
  116. }
  117.  
  118. long int confronta(long int prod1, long int prod2)
  119. {
  120.         /*se il prodotto appena ottenuto è minore del massimo ottenuto fin'ora, il valore massimo rimane uguale*/
  121.         if (prod1 <= prod2) return prod2;
  122.         /*altrimenti, un nuovo massimo è stato trovato, ed occorre memorizzarlo*/
  123.         else if (prod1 > prod2) return prod1;
  124. }



L'idea di base dell'algoritmo è quella di trascrivere le cifre assegnate in un file, e da lì leggerle a gruppi di 13 per poterci poi lavorare.

Quando vado ad eseguire il codice, però, esso non funziona, e ottengo il risultato che potete vedere nell'immagine allegata.

Secondo voi, dove ho sbagliato?


ha allegato un file: Immagine.png (17100 bytes)
Clicca qui per guardare l'immagine

Ultima modifica effettuata da il 07/03/2015 alle 15:56
PM Quote
Avatar
nessuno (Normal User)
Guru^2


Messaggi: 6402
Iscritto: 03/01/2010

Segnala al moderatore
Postato alle 15:43
Sabato, 07/03/2015
Non ho controllato tutto il codice quindi potranno esserci tanti problemi ma quello che salta all'occhio è

if(completo = true)

ovviamente sbagliato



Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti ( uno dei padri fondatori del moderno Calcolo delle probabilità ) chiamava il gioco del Lotto Tassa sulla stupidità.
PM Quote
Avatar
()
Newbie


Messaggi:
Iscritto:

Segnala al moderatore
Postato alle 15:49
Sabato, 07/03/2015
Hai ragione (che errore del cavolo 8-|)...
Comunque, il codice continua a non funzionare... ora ci sto lavorando (probabilmente ho usato qualche funzione nel modo sbagliato), ma non riesco a trovare il problema :d

PM Quote
Avatar
nessuno (Normal User)
Guru^2


Messaggi: 6402
Iscritto: 03/01/2010

Segnala al moderatore
Postato alle 15:56
Sabato, 07/03/2015
Infatti, non ti ho detto che quello fosse la causa del problema ,,,

Quello che non capisco è questo

/*se viene letto uno zero, il prodotto sarà nullo, quindi è inutile proseguire: meglio andare oltre lo zero*/
else if (fscanf(numeri, "%d", &val[ i ]) == 0)

Cosa vorresti fare con questa linea? Perché confronti il valore restituito da fscanf con 0?

Tieni presente che il valore restituito da fscanf NON è quello che viene letto dalla fscanf ...
E poi, scusa, cosa ti aspetti che ci sia in val[ i ] dopo la lettura ? Sai che %d legge un intero non una cifra ...?

Ma poi, scusa, perché mai stai scrivendo e leggendo da file i dati?

Se li hai nel vettore, lavora con il vettore in memoria.

L'esercizio non parla di file.

Ultima modifica effettuata da nessuno il 07/03/2015 alle 16:03


Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti ( uno dei padri fondatori del moderno Calcolo delle probabilità ) chiamava il gioco del Lotto Tassa sulla stupidità.
PM Quote
Avatar
()
Newbie


Messaggi:
Iscritto:

Segnala al moderatore
Postato alle 16:16
Sabato, 07/03/2015
Infatti sto riscrivendo tutto senza lavorare con il file... ma continuo a non ottenere niente, quindi mi sa che il mio errore è anche concettuale...

Ora il codice è così:

Codice sorgente - presumibilmente C++

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdbool.h>
  4.  
  5.  
  6. /*dichiarazione variabili globali contenenti il massimo prodotto, i 13 numeri da moltiplicare e tutte le cifre su cui lavorare*/
  7. long int max_prod = 0;
  8. int val[13];
  9. char string[] = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869
  10. 47885184385861560789112949495459501737958331952853208805511125406987471585238630507156932909
  11. 63295227443043557668966489504452445231617318564030987111217223831136222989342338030813533627
  12. 66142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998
  13. 79790879227492190169972088809377665727333001053367881220235421809751254540594752243525849077
  14. 11670556013604839586446706324415722155397536978179778461740649551492908625693219784686224828
  15. 39722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758
  16. 86668811642717147992444292823086346567481391912316282458617866458359124566529476545682848912
  17. 88314260769004224219022671055626321111109370544217506941658960408071984038509624554443629812
  18. 30987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507
  19. 754100225698315520005593572972571636269561882670428252483600823257530420752963450";
  20.  
  21. /*dichiarazione delle funzioni necessarie*/
  22. long int lettura(long int);
  23. long int moltiplica(int[]);
  24. long int confronta(long int, long int);
  25.  
  26.  
  27. int main()
  28. {
  29.         /*definizione dell'indice dei valori letti dalla stringa*/
  30.         long int indice = 0;
  31.  
  32.         /*Inizio della computazione: introduzione dell'utente nel programma e inizio lettura*/
  33.         printf("Inizio del calcolo... \n");
  34.         long int prodotto = lettura(indice);
  35.  
  36.         /*confronto del prodotto appena ottenuto con il massimo prodotto ottenuto fin'ora*/
  37.         if (prodotto != 0)
  38.         {
  39.                 max_prod = confronta(prodotto, max_prod);
  40.                 prodotto = lettura(indice);
  41.         }
  42.         /*se tutti i prodotti sono già stati calcolati e confrontati, il massimo di loro viene stampato*/
  43.         else if (prodotto == 0)
  44.         {
  45.                 printf("Fine. \n Il massimo prodotto possibile è %d", max_prod);
  46.                 printf("\n Premere un qualsiasi tasto per uscire.");
  47.                 getchar();
  48.                 return EXIT_SUCCESS;
  49.         }
  50. }
  51.  
  52. long int lettura(long int indice)
  53. {
  54.                 /*i numeri vengono letti*/
  55.                 for (int i = 0; i <= 12; i++)
  56.                 {
  57.                         if (indice < 1000)
  58.                         {
  59.                                 /*se viene letto uno zero, il prodotto sarà nullo, quindi è inutile proseguire: meglio andare oltre lo zero*/
  60.                                 if (string[indice] == '0')
  61.                                 {
  62.                                         i = 0;
  63.                                         indice++;
  64.                                 }
  65.                                 /*se il valore letto non è uno zero, esso può essere memorizzato nell'array*/
  66.                                 else
  67.                                 {
  68.                                         val[i] = string[indice] - '0';
  69.                                         printf("Numero letto: %d \n", val[i]);
  70.                                         indice++;
  71.                                 }
  72.                         }
  73.                         else return 0;
  74.                 }
  75.  
  76.                 /*a lettura completa, i numeri rilevati devono essere moltiplicati tra loro*/
  77.                 int prodotto = moltiplica(val);
  78.                 return prodotto;
  79.         }
  80.  
  81. long int moltiplica(int val[])
  82. {
  83.         /*si inizializza il prodotto assegnandogli il primo valore letto*/
  84.         int prodotto = val[0];
  85.  
  86.         /*si effettua la moltiplicazione e si stampa il risultato*/
  87.         for (int i = 1; i <= 12; i++) prodotto *= val[i];
  88.         printf("\n Prodotto ottenuto: %d", prodotto);
  89.  
  90.         /*il valore finale viene inviato*/
  91.         return prodotto;
  92. }
  93.  
  94. long int confronta(long int prod1, long int prod2)
  95. {
  96.         /*se il prodotto appena ottenuto è minore del massimo ottenuto fin'ora, il valore massimo rimane uguale*/
  97.         if (prod1 <= prod2) return prod2;
  98.         /*altrimenti, un nuovo massimo è stato trovato, ed occorre memorizzarlo*/
  99.         else return prod1;
  100. }



E ogni volta che lo compilo, la console si chiude senza darmi il tempo di leggere... ho provato a usare system("pause") e roba del genere per bloccarla, ma niente...

Ultima modifica effettuata da il 07/03/2015 alle 16:19
PM Quote
Avatar
nessuno (Normal User)
Guru^2


Messaggi: 6402
Iscritto: 03/01/2010

Segnala al moderatore
Postato alle 16:28
Sabato, 07/03/2015
In effetti non capisco la logica che ti guida. Probabilmente ti complichi la vita inutilmente.

Ad esempio, che logica segui nel main ? Non capisco ...

Prova a realizzare tutto SENZA funzioni, tutto nel main e, quando funziona, si vede se usarle e dove.

Una raccomandazione ... quando usi le if..else non ripetere le if se non necessarie. Se controlli che qualcosa sia uguale a zero scriverai

if(qualcosa == 0)
...
else
...

e nell'else non serve ripetere la if se diverso da zero ... ok?


Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti ( uno dei padri fondatori del moderno Calcolo delle probabilità ) chiamava il gioco del Lotto Tassa sulla stupidità.
PM Quote
Avatar
()
Newbie


Messaggi:
Iscritto:

Segnala al moderatore
Postato alle 17:18
Sabato, 07/03/2015
Ho provato a riscrivere l'algoritmo secondo le tue direttive... traducendolo in codice, ho ottenuto questo (che non funziona, perchè il risultato che mi da è sbagliato):

Codice sorgente - presumibilmente C++

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <inttypes.h>
  4.  
  5. int main()
  6. {
  7.         char string[] = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869
  8. 47885184385861560789112949495459501737958331952853208805511125406987471585238630507156932909
  9. 63295227443043557668966489504452445231617318564030987111217223831136222989342338030813533627
  10. 66142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998
  11. 79790879227492190169972088809377665727333001053367881220235421809751254540594752243525849077
  12. 11670556013604839586446706324415722155397536978179778461740649551492908625693219784686224828
  13. 39722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758
  14. 86668811642717147992444292823086346567481391912316282458617866458359124566529476545682848912
  15. 88314260769004224219022671055626321111109370544217506941658960408071984038509624554443629812
  16. 30987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507
  17. 754100225698315520005593572972571636269561882670428252483600823257530420752963450";
  18.         uint64_t max_prod = 0;
  19.         int indice = 0;
  20.         uint64_t prodotto = 1;
  21.         int cifre[1000];
  22.  
  23.         for (int j = 0; j < 1000; j++)
  24.         {
  25.                 cifre[j] = string[j] - '0';
  26.         }
  27.  
  28.         while (indice < 1000)
  29.         {
  30.                 int i = 0;
  31.  
  32.                 for (i = 0; i < 13; i++)
  33.                 {
  34.                         if (cifre[indice] == 0)
  35.                         {
  36.                                 i = 0;
  37.                                 indice++;
  38.                                 prodotto = 1;
  39.                         }
  40.                         else if (indice == 1000) break;
  41.                         else
  42.                         {
  43.                                 prodotto *= cifre[indice];
  44.                                 indice++;
  45.                         }
  46.                 }
  47.  
  48.                 printf("\n Prodotto ottenuto:" "%" PRIu64 "\n", prodotto);
  49.  
  50.                 if (prodotto > max_prod) max_prod = prodotto;
  51.  
  52.                 printf("\n Massimo prodotto finora:" "%" PRIu64 "\n", max_prod);
  53.                 prodotto = 1;
  54.         }
  55.  
  56.         printf("\n Massimo prodotto totale:" "%" PRIu64 "\n", max_prod);
  57.         printf("\n Premere un tasto per uscire.");
  58.         getchar();
  59.         return EXIT_SUCCESS;
  60. }



Che dici? Come scrittura, al di là degli errori (che ci sono, altrimenti il codice funzionerebbe) sono sulla strada giusta?

Ultima modifica effettuata da il 07/03/2015 alle 17:19
PM Quote
Avatar
()
Newbie


Messaggi:
Iscritto:

Segnala al moderatore
Postato alle 18:27
Sabato, 07/03/2015
Aggiornamento: ragionandoci e cercando di semplificare al massimo il codice, ho risolto il quesito :asd:

Codice sorgente - presumibilmente C++

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <inttypes.h>
  4.  
  5. int main()
  6. {
  7.         char string[] = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869
  8. 47885184385861560789112949495459501737958331952853208805511125406987471585238630507156932909
  9. 63295227443043557668966489504452445231617318564030987111217223831136222989342338030813533627
  10. 66142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998
  11. 79790879227492190169972088809377665727333001053367881220235421809751254540594752243525849077
  12. 11670556013604839586446706324415722155397536978179778461740649551492908625693219784686224828
  13. 39722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758
  14. 86668811642717147992444292823086346567481391912316282458617866458359124566529476545682848912
  15. 88314260769004224219022671055626321111109370544217506941658960408071984038509624554443629812
  16. 30987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507
  17. 754100225698315520005593572972571636269561882670428252483600823257530420752963450";
  18.         uint64_t max_prod = 1;
  19.         int indice = 0;
  20.         int numcifre = 1;
  21.         uint64_t prodotto = 1;
  22.         int cifre[13];
  23.  
  24.         for (indice = 0; indice + 12 < 1000; indice++)
  25.         {
  26.                 for (int j = 0; j < 13; j++)
  27.                 {
  28.                         cifre[j] = (int)string[indice+j] - 48;
  29.                         prodotto *= cifre[j];
  30.                 }
  31.                 if (prodotto > max_prod) max_prod = prodotto;
  32.                 prodotto = 1;
  33.                 printf("\n Prodotto massimo finora: " "%" PRIu64 "\n", max_prod);
  34.         }
  35.  
  36.         printf("\n\n Massimo prodotto totale:""%" PRIu64 "\n", max_prod);
  37.         printf("\n Premere un tasto per uscire.");
  38.         getchar();
  39.         return EXIT_SUCCESS;
  40. }



Partendo da questo codice, ho poi cercato di re-inserire il controllo delle cifre (così da evitare di calcolare e verificare prodotti nulli) e rendere il programma più logico (per esempio, quale programma notificherebbe all'utente ogni prodotto calcolato od ogni confronto tra esso e il massimo fin'allora ottenuto?), e ho ottenuto quest'altro codice (funzionante :D ), che rispetto al precedente ottiene il risultato finale con circa 1/3 dei calcoli:

Codice sorgente - presumibilmente C++

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <inttypes.h>
  4.  
  5. int main()
  6. {
  7.         /*dichiarazione della stringa data, delle variabili che conterranno il prodotto massimo provvisorio e l'ultimo prodotto calcolato, di un
  8.         array che conterrà i gruppi di 13 cifre da trattare e di un indice che sarà utile per copiare gli elementi dalla stringa a tale array*/
  9.         char string[] = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869
  10. 47885184385861560789112949495459501737958331952853208805511125406987471585238630507156932909
  11. 63295227443043557668966489504452445231617318564030987111217223831136222989342338030813533627
  12. 66142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998
  13. 79790879227492190169972088809377665727333001053367881220235421809751254540594752243525849077
  14. 11670556013604839586446706324415722155397536978179778461740649551492908625693219784686224828
  15. 39722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758
  16. 86668811642717147992444292823086346567481391912316282458617866458359124566529476545682848912
  17. 88314260769004224219022671055626321111109370544217506941658960408071984038509624554443629812
  18. 30987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507
  19. 754100225698315520005593572972571636269561882670428252483600823257530420752963450";
  20.         uint64_t max_prod = 1;
  21.         uint64_t prodotto = 1;
  22.         int cifre[13];
  23.         int indice = 0;
  24.  
  25.         /*viene notificato all'utente l'inizio dei calcoli*/
  26.         printf("Inizio dei calcoli...\n");
  27.  
  28.         /*il ciclo principale del programma ha inizio*/
  29.         for (indice = 0; indice + 12 < 1000; indice++)
  30.         {
  31.                 /*in questo loop, 13 valori non nulli vengono inseriti nell'array e moltiplicati tra loro*/
  32.                 for (int j = 0; j < 13; j++)
  33.                 {
  34.                         cifre[j] = (int)string[indice+j] - 48;
  35.                         if (cifre[j] != 0) prodotto *= cifre[j];
  36.                         /*se tra i valori letti ce n'è uno nullo, non ha senso continuare il prodotto: occorre passare oltre, ricominciando l'analisi dal primo
  37.                         elemento successio allo zero*/
  38.                         else
  39.                         {
  40.                                 prodotto = 1;
  41.                                 indice += j;
  42.                                 break;
  43.                         }
  44.                 }
  45.  
  46.                 /*se il prodotto appena determinato è maggiore del massimo prodotto fino ad ora ottenuto, il massimo va ridefinito*/
  47.                 if (prodotto > max_prod) max_prod = prodotto;
  48.                 /*la "variabile ponte" va nuovamente inizializzata, così da poter essere utilizzata per un altro prodotto*/
  49.                 prodotto = 1;
  50.         }
  51.         /*terminati i calcoli, viene reso noto all'utente il massimo prodotto effettivamente ottenibile*/
  52.         printf("\nMassimo prodotto totale:""%" PRIu64 "\n", max_prod);
  53.         printf("\nPremere un tasto per uscire.");
  54.         getchar();
  55.         return EXIT_SUCCESS;
  56. }


Ultima modifica effettuata da il 07/03/2015 alle 18:47
PM Quote