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++ - ottimizzare il codice? scomposizione in fattori primi
Forum - C/C++ - ottimizzare il codice? scomposizione in fattori primi

Pagine: [ 1 2 ] Precedente | Prossimo
Avatar
darkannet (Normal User)
Newbie


Messaggi: 4
Iscritto: 04/01/2017

Segnala al moderatore
Postato alle 16:12
Mercoledì, 04/01/2017
Ciao a tutti e buona sera, volevo chiedere consiglio su come ottimizzare il codice, a causa di ripetitivitá.
É un programma sulla scomposizione in fattori primi
Grazie in anticipo!
Codice sorgente - presumibilmente C++

  1. #include<conio.h>
  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. #include<math.h>
  5. #include<time.h>
  6. #include<limits>
  7. #include<iostream>
  8. using namespace std;
  9. int boolean;
  10. void ne(){
  11. if(boolean==0)
  12. printf("-");   
  13. }
  14.  
  15. int legge(){
  16. int numero;  
  17.  
  18. while(!(cin>>numero)) {  
  19.    cout<<"Questo non e' un numero!\ninserisci un numero da scomporre:";
  20.    cin.clear();  
  21.    cin.ignore(numeric_limits<streamsize>::max(), '\n'); }
  22.    return numero;
  23. }
  24.  
  25. int aspetto(int n,int risultato,int divisore){
  26.         int num,costante;
  27.         num=log10(n)+1;
  28.     costante=log10(risultato);
  29.     ne();
  30.         printf("%d",n);
  31.         for(int contatore=num; contatore<=costante;contatore++)
  32.         printf(" ");
  33.         printf("|");
  34.         printf("%d\n",divisore);       
  35. }
  36. int *azzeramento(int arr[],int z)
  37. {
  38. for(int i=0;i<z;i++){
  39. arr[i]=0;
  40. }
  41. return arr;
  42. }
  43. int main(){
  44. char scelta;
  45. int time;
  46. while(scelta!='N'){
  47.        
  48.         system("CLS"); system("color 0c");
  49.         int n=0,z=0,divisore=1,p=0,y=0;
  50.         int upgrade=0,u=0,num=0;
  51.        
  52. int contatore=1;       
  53. do{
  54. printf("inserisci un numero da scomporre: ");
  55. n=legge();
  56. if(n==0)
  57. printf("il numero non puo' essere 0!\n");
  58. }while(n==0);
  59. if(n<0)
  60. {
  61. boolean=0;
  62. n=n*-1;
  63. }
  64. else
  65. boolean=1;
  66. int scambio=n;
  67. int risultato=n;
  68.  
  69.  
  70. {
  71. divisore=1;
  72.         z=0;
  73. do{
  74. divisore++;
  75. if(n%divisore==0){
  76.  
  77. aspetto(n,risultato,divisore);
  78. n=n/divisore;
  79. z++;
  80. divisore=1;
  81. }
  82. }while(n>divisore);
  83. ne();
  84. printf("%d\n",n);
  85. }
  86. //dichiarazione variabili
  87. int val[z];
  88. int err[z];
  89. int col[z];
  90. int zc=0;
  91.  contatore=1;
  92. //fine dichiarazione variabili
  93. while(scambio>1)
  94. {
  95.         contatore++;
  96. if(scambio%contatore==0)
  97. {
  98. val[zc]=contatore;
  99. zc++;
  100. scambio/=contatore;
  101. contatore=1;
  102. }
  103.  
  104. }
  105. azzeramento(err,z);
  106. for(int xx=0;xx<z;xx++){
  107.         y=0;
  108.         for(int yy=0;yy<z;yy++)
  109.         {
  110.     if(val[xx]!=err[yy]){
  111.         y++;
  112.                         }
  113.     }
  114.     if(y==z)
  115.     err[xx]=val[xx];
  116. }
  117. for(int xx=0;xx<z;xx++)
  118. {
  119.         if(err[xx]!=0)
  120.         {
  121.         col[num]=err[xx];      
  122.         num++;
  123.         }
  124.  
  125. }
  126. int numerisingoli[num];
  127. int potenza[num];
  128. azzeramento(potenza,num);
  129. for(int yy=0;yy<num;yy++)
  130. {
  131.         numerisingoli[yy]=col[yy];
  132. }
  133. for(int xx=0;xx<num;xx++)
  134. {
  135.         for(int yy=0;yy<z;yy++)
  136.         {
  137.                
  138.                 if(numerisingoli[xx]==val[yy])
  139.                 {
  140.                        
  141.                         potenza[xx]++;
  142.                 }
  143.                
  144.         }
  145.        
  146. }
  147. printf("\n");
  148. if(boolean==0)
  149. printf("-(");
  150. for(int stamp=0;stamp<num;stamp++)
  151. {
  152.         printf("%d",numerisingoli[stamp]);
  153.         if(potenza[stamp]!=1)
  154.         printf("^%d",potenza[stamp]);
  155.         if(stamp<num-1)
  156.         printf("*");
  157. }
  158.  
  159. if(boolean==0)
  160. printf(")");
  161. printf(" =");
  162. ne();
  163. printf("%d",risultato);
  164.  
  165. fflush(stdin);
  166. printf("\nvuoi inserire un altro numero?(S/N)");
  167. scelta=getchar();
  168. scelta=toupper(scelta);
  169. }
  170. system("PAUSE");
  171. }


Ultima modifica effettuata da darkannet il 04/01/2017 alle 18:37
PM Quote
Avatar
AldoBaldo (Member)
Guru


Messaggi: 699
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 3:05
Giovedì, 05/01/2017
Dubito che sia possibile parlare di "ottimizzazione", però m'è preso il ghiribizzo di pasticciare un po' con la tua idea di un marchingegno per scomporre numeri in fattori primi. Ne è venuta fuori una roba, distribuita su tre file che credo sia in ANSI C. Il compilatore che uso (mingw) ha sputato fuori un eseguibile di 11 Kb in tutto, alla faccia del C++ che anche solo usando cin e cout s'avvicinava al Mb!

Sicuramente ci saranno ingenuità mostruose, sia perché le mie conoscenze matematiche sono quel che sono, sia perché ho fatto tutto un po' di getto, appiccicando funzioni su funzioni preso dal fuoco sacro del giocare a fingere d'essere un programmatore della madonna! (che non è vero) :D

1. main.c

Codice sorgente - presumibilmente C#

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include "interfaccia.h"
  4.  
  5. // ===> MACRO/COSTANTI/STRINGHE <===============================================
  6.  
  7. #define MAX_FATTORI 36 // in effetti, unsigned long puo' contenere un valore
  8.                        // massimo di 2^32-1, per cui nella scomposizione non
  9.                        // ci possono essere piu' di 32 fattori primi
  10.  
  11. const char *kStrPres[] = {
  12. "SCOMPOSIZIONE IN FATTORI PRIMI",
  13. "questo programma scompone in fattori primi valori interi compresi",
  14. "tra 2 e 4294967295, presentando il risultato sia in forma di",
  15. "calcolo in colonna, sia come formula riassuntiva in linea"
  16. };
  17.  
  18. const int kNStrPres = sizeof(kStrPres)/sizeof(*kStrPres);
  19.  
  20. // ===> PROTOTIPI DI FUNZIONI <=================================================
  21.  
  22. void scomponi( unsigned long n, unsigned long *fattori );
  23.  
  24. // ===> FUNZIONE D'ACCESSO AL PROGRAMMA <=======================================
  25.  
  26. int main() {
  27.     unsigned long n, fattori[MAX_FATTORI];
  28.  
  29.     presenta_in_console( kStrPres, kNStrPres );
  30.  
  31.     do {
  32.         memset( fattori, 0, sizeof(*fattori)*MAX_FATTORI );
  33.  
  34.         n = chiedi_numero_da_scomporre();
  35.  
  36.         scomponi( n, fattori );
  37.  
  38.         scrivi_tabella_scomposizione( n, fattori );
  39.         scrivi_scomposizione_in_linea( n, fattori );
  40.     } while( chiedi_se_continuare() );
  41.  
  42.     return 0;
  43. }
  44.  
  45. // ===> FUNZIONE DI SCOMPOSIZIONE IN FATTORI PRIMI <============================
  46.  
  47. void scomponi( unsigned long n, unsigned long *fattori ) {
  48.     if( n > 1 ) {
  49.         unsigned long d, max;
  50.         int nf; // la quantita' dei fattori trovati
  51.  
  52.         for( d=2, nf=0; n%d==0; ++nf ) {
  53.             fattori[nf] = d;
  54.             n /= d;
  55.         }
  56.  
  57.         if( n == 1 ) return;
  58.  
  59.         for( max=n, d=3; d<=max; ) {
  60.             if( n%d ) { d+=2; continue; }
  61.             fattori[nf++] = d;
  62.             if( (n/=d) == 1 ) break;
  63.             max = n;
  64.         }
  65.     }
  66.     else {
  67.         if( n == 0 )
  68.             printf( "Lo zero non e' scomponibile.\n\n" );
  69.         else printf( "L'unita' non e' scomponibile.\n\n" );
  70.     }
  71. }



2. interfaccia.h

Codice sorgente - presumibilmente C++

  1. #ifndef INTERFACCIA_H_INCLUDED
  2. #define INTERFACCIA_H_INCLUDED
  3.  
  4. void presenta_in_console( const char *s[], int ns );
  5. unsigned long chiedi_numero_da_scomporre( void );
  6. void scrivi_tabella_scomposizione( unsigned long n, unsigned long *fattori );
  7. void scrivi_scomposizione_in_linea( unsigned long n, unsigned long *fattori );
  8. int chiedi_se_continuare( void );
  9.  
  10. #endif // INTERFACCIA_H_INCLUDED



3. interfaccia.c

Codice sorgente - presumibilmente C++

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <ctype.h>
  5. #include "interfaccia.h"
  6.  
  7. // ===> MACRO/COSTANTI <========================================================
  8.  
  9. #define LARGHEZZA_CONSOLE 80 // specificare la larghezza della console
  10. #define A_CAPO printf("\n")
  11.  
  12. // ===> PROTOTIPI DI FUNZIONI <=================================================
  13.  
  14. int leggi_riga_da_console( char **riga, size_t *dim_riga );
  15. int stringa_in_numero_intero( const char *s, unsigned long *n );
  16. void centra_in_console( const char *s );
  17. void traccia_riga_in_console( int c, int nc );
  18. void mostra_errore_in_console( const char *msg );
  19. void attendi_invio_da_console( void );
  20. void svuota_console( void );
  21.  
  22. /*==============================================================================
  23. Chiede all'utente di immettere il numero che intende scomporre. Verifica il dato
  24. immesso per assicurarsi che sia effettivamente un numero intero. La verifica
  25. avviene tramite la funzione standard strtoul(). La richiesta viene iterata fino
  26. a che viene immesso un valore accettabile.
  27. ==============================================================================*/
  28.  
  29. unsigned long chiedi_numero_da_scomporre( void ) {
  30.     unsigned long numero;
  31.     char *riga = NULL;
  32.     int err = 1;
  33.  
  34.     do {
  35.         svuota_console();
  36.  
  37.         printf( "\nInserisci un numero da scomporre: " );
  38.  
  39.         if( leggi_riga_da_console(&riga,NULL) == 0 ) {
  40.             if( stringa_in_numero_intero(riga,&numero) == 0 ) {
  41.                 err = 0;
  42.             } else mostra_errore_in_console( "l'input non e' un numero intero" );
  43.  
  44.             free( riga );  riga = NULL;
  45.         } else mostra_errore_in_console( "impossibile allocare" );
  46.     } while( err != 0 );
  47.  
  48.     svuota_console();
  49.     printf( "\n" );
  50.  
  51.     return numero;
  52. }
  53.  
  54. /*==============================================================================
  55. Legge una riga di testo di lunghezza arbitraria dalla console. La riga letta
  56. viene collocata in uno spazio di memoria allocato dinamicamente il cui puntatore
  57. viene immesso in *riga. Se dim_riga non e' NULL, le dimensioni della stringa
  58. risultante sono collocate in *dim_riga (escluso il carattere terminatore).
  59. Spetta al chiamante liberare con free() la memoria allocata.
  60.  
  61. Valori di ritorno:
  62.  
  63.     0   tutto bene
  64.     1   parametri non validi (puntatori NULL)
  65.     4   impossibile allocare dinamicamente la memoria necessaria
  66. ==============================================================================*/
  67.  
  68. int leggi_riga_da_console( char **riga, size_t *dim_riga ) {
  69.     const size_t inc = 16; // procede per blocchi d'allocazione di inc byte
  70.     size_t dr, dm; // dr = dimensioni riga; dm = dimensioni memoria
  71.     char *tmp, *aux;
  72.     int c;
  73.  
  74.     if( dim_riga ) *dim_riga = 0;
  75.     if( riga ) *riga = NULL; else return 1;
  76.  
  77.     // alloca un primo blocco di memoria dinamica
  78.     dm = inc;
  79.     tmp = malloc( dm+1 );
  80.     if( !tmp ) return 4;
  81.  
  82.     // legge i dati nella memoria dinamica, ridimensionandola se necessario
  83.     for( dr=0, c=fgetc(stdin); c!='\n' && c!=EOF; ++dr, c=fgetc(stdin) ) {
  84.         if( dr < (dm-1) ) {
  85.             tmp[dr] = c;
  86.         }
  87.         else {
  88.             aux = tmp; // caso mai realloc fallisse (vedi else)
  89.  
  90.             if( (tmp=realloc(tmp,dm+inc)) ) {
  91.                 dm += inc;
  92.                 tmp[dr] = c;
  93.             }
  94.             else {
  95.                 free( aux );
  96.                 return 4;
  97.             }
  98.         }
  99.     }
  100.  
  101.     *riga = tmp;
  102.     (*riga)[dr] = '\0'; // termina la stringa
  103.     if( dim_riga ) *dim_riga = dr;
  104.     return 0;
  105. }
  106.  
  107. /*==============================================================================
  108. Tramile la funzione standard strtoul() tenta di verificare la validita' della
  109. stringa immessa dall'utente. Restituisce in *n il numero intero senza segno
  110. rappresentato dalla stringa s. Se tutto va bene, il valore di ritorno e' 0; in
  111. caso contrario e' diverso da 0.
  112. ==============================================================================*/
  113.  
  114. int stringa_in_numero_intero( const char *s, unsigned long *n ) {
  115.     char *fine = NULL;
  116.     *n = strtoul( s, &fine, 10 );
  117.     return s == fine;
  118. }
  119.  
  120. /*==============================================================================
  121. Scrive, centrandole nella console, una serie di ns stringhe ricavandole
  122. dall'array s[]. Al termine della scrittura si pone in attesa della pressione del
  123. tasto "invio" da parte dell'utente. Quando l'utente preme "invio", svuota la
  124. console e ritorna.
  125. ==============================================================================*/
  126.  
  127. void presenta_in_console( const char *s[], int ns ) {
  128.     if( s ) {
  129.         int i;
  130.         traccia_riga_in_console( '=', LARGHEZZA_CONSOLE-1 ); A_CAPO;
  131.         for( i=0; i<ns; ++i ) { centra_in_console( s[i] ); A_CAPO; }
  132.         traccia_riga_in_console( '=', LARGHEZZA_CONSOLE-1 ); A_CAPO; A_CAPO;
  133.         attendi_invio_da_console();
  134.         svuota_console();
  135.     }
  136. }
  137.  
  138. /*==============================================================================
  139. Scrive nella console la stringa s, facendola precedere dalla quantità di spazi
  140. necessari per centrarla.
  141. ==============================================================================*/
  142.  
  143. void centra_in_console( const char *s ) {
  144.     if( s ) {
  145.         char buff[LARGHEZZA_CONSOLE/2+4];
  146.         int l = (LARGHEZZA_CONSOLE-strlen(s))/2;
  147.         memset( buff, ' ', l ); buff[l] = '\0';
  148.         printf( "%s%s", buff, s );
  149.     }
  150. }
  151.  
  152. /*==============================================================================
  153. Scrive nella console una serie di nc caratteri c. Se nc e' maggiore di
  154. LARGHEZZA_CONSOLE la funzione scrive comunque un massimo di LARGHEZZA_CONSOLE
  155. caratteri.
  156. ==============================================================================*/
  157.  
  158. void traccia_riga_in_console( int c, int nc ) {
  159.     if( nc > 0 ) {
  160.         char buff[LARGHEZZA_CONSOLE+4];
  161.         nc = nc<=LARGHEZZA_CONSOLE ? nc : LARGHEZZA_CONSOLE;
  162.         memset( buff, c, nc ); buff[nc] = '\0';
  163.         printf( "%s", buff );
  164.     }
  165. }
  166.  
  167. /*==============================================================================
  168. Scrive nella console la stringa msg, preceduta da una breve intestazione
  169. d'errore. Emette un "bip" d'avviso sonoro. Al termine della scrittura si pone in
  170. attesa della pressione del tasto "invio" da parte dell'utente. Quando l'utente
  171. preme "invio", ritorna.
  172. ==============================================================================*/
  173.  
  174. void mostra_errore_in_console( const char *msg ) {
  175.     if( msg ) {
  176.         printf( "\a\n===> ERRORE <===\n%s\n\n", msg );
  177.         attendi_invio_da_console();
  178.     }
  179. }
  180.  
  181. /*==============================================================================
  182. Si pone in attesa della pressione del tasto "invio" da parte dell'utente. Quando
  183. l'utente preme "invio", svuota lo stream di input e ritorna.
  184. ==============================================================================*/
  185.  
  186. void attendi_invio_da_console( void ) {
  187.     printf( "Premi \"invio\" per continuare... " );
  188.     while( getchar() != '\n' );
  189. }
  190.  
  191. /*==============================================================================
  192. Usa system() per richiedere lo svuotamento della console.
  193. ==============================================================================*/
  194.  
  195. void svuota_console( void ) {
  196.     system( "cls" );
  197. }
  198.  
  199. /*==============================================================================
  200. Scrive nella console una tabella che raffigura il procedimento di scomposizione
  201. in fattori primi del numero n, secondo i dati immagazzinati nell'array fattori.
  202. ==============================================================================*/
  203.  
  204. void scrivi_tabella_scomposizione( unsigned long n, unsigned long *fattori ) {
  205.     int i;
  206.  
  207.     for( i=0; n!=1; ++i ) {
  208.         printf( "%12lu | %lu\n", n, fattori[i] );
  209.         n /= fattori[i];
  210.     }
  211.  
  212.     printf( "%12lu | \n\n", n );
  213. }
  214.  
  215. /*==============================================================================
  216. Scrive nella console una formula che descrive la scomposizione in fattori del
  217. numero n, secondo i dati immagazzinati nell'array fattori.
  218. ==============================================================================*/
  219.  
  220. void scrivi_scomposizione_in_linea( unsigned long n, unsigned long *fattori ) {
  221.     unsigned long fc = 0; // fc = fattore corrente
  222.     int ec;               // ec = esponente corrente
  223.     int tf;               // tf = totale fattori
  224.     int i;
  225.  
  226.     for( tf=0; fattori[tf]!=0; ++tf );
  227.     if( tf == 0 ) return;
  228.  
  229.     printf( " %lu = ", n );
  230.  
  231.     for( i=tf-1, fc=fattori[i], ec=0; i>=0; --i ) {
  232.         if( fc != fattori[i] ) {
  233.             printf( "%lu", fc );
  234.             if( ec != 1 ) printf( "^%d", ec );
  235.             printf( " * " );
  236.  
  237.             fc = fattori[i];
  238.             ec = 1;
  239.         }
  240.         else {
  241.             ++ec;
  242.         }
  243.     }
  244.  
  245.     printf( "%lu", fc );
  246.     if( ec != 1 ) printf( "^%d", ec );
  247.     printf( "\n" );
  248. }
  249.  
  250. /*==============================================================================
  251. Chiede all'utente se intende continuare con un'ulteriore scomposizione o uscire
  252. dal programma.
  253. ==============================================================================*/
  254.  
  255. int chiedi_se_continuare( void ) {
  256.     char *riga = NULL;
  257.     int esito = 0xFFFF;
  258.  
  259.     do {
  260.         printf( "\nVuoi scomporre un altro numero? (S/N) " );
  261.  
  262.         if( leggi_riga_da_console(&riga,NULL) == 0 ) {
  263.             switch( toupper(*riga) ) {
  264.                 case 'S': esito = 1; break;
  265.                 case 'N': esito = 0; break;
  266.                 default: mostra_errore_in_console( "input non valido" );
  267.             }
  268.  
  269.             free( riga );  riga = NULL;
  270.         } else mostra_errore_in_console( "impossibile allocare" );
  271.     } while( esito == 0xFFFF );
  272.  
  273.     return esito;
  274. }


Ultima modifica effettuata da AldoBaldo il 05/01/2017 alle 18:19


ATTENZIONE! Sono un hobbista e l'affidabilità delle mie conoscenze informatiche è molto limitata. Non prendere come esempio il codice che scrivo, perché non ho alcuna formazione accademica e rischieresti di apprendere pratiche controproducenti.
PM Quote
Avatar
Goblin (Member)
Expert


Messaggi: 375
Iscritto: 02/02/2011

Segnala al moderatore
Postato alle 15:02
Giovedì, 05/01/2017
Testo quotato

Postato originariamente da AldoBaldo:

...[cut].... preso dal fuoco sacro del giocare a fingere d'essere un programmatore della madonna! (che non è vero) :D




:rotfl::rotfl::rotfl::rotfl::rotfl::rotfl::rotfl:
Credo di essere allineato ... quando gioco a fare il "David Intersimone" di casa nostra.

PS: cmq passami una fiammellina .... è un gran bel fuoco :D:D

Ultima modifica effettuata da Goblin il 05/01/2017 alle 15:04


Ibis redibis non morieris in bello
PM Quote
Avatar
TheDarkJuster (Member)
Guru^2


Messaggi: 1620
Iscritto: 27/09/2013

Segnala al moderatore
Postato alle 17:57
Giovedì, 05/01/2017
Beh io prenderei una bella tabella di numeri primi (ricordo che 1 matematicamente non è primo) e proverei a dividere il numero per per ogni numero primo.

Se il resto della divisione è 0 si aggiunge il numero primo alla lista di divisori, e il numero per il quale cercare i divisori diventa il risultato della divisione di quel numero e il numero primo.

La scomposizione si ferma quando il numero di cui cercare i divisori è un numero primo (o 1 e si aggiunge alla fine 1 e il numero primo)

Per l'amor di dio usate le linked list, non array con un numero di posti fissi, oppure rendete l'array ingrandibile a runtime.
Non mettete menù all'interno del programma e prendetevi gli argomenti da char** argv.

PM Quote
Avatar
lumo (Member)
Expert


Messaggi: 449
Iscritto: 18/04/2010

Segnala al moderatore
Postato alle 18:07
Giovedì, 05/01/2017
Una linked list non ha senso qui.
Altra cosa, per controllare i divisori basta arrivare a sqrt(n).

PM Quote
Avatar
AldoBaldo (Member)
Guru


Messaggi: 699
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 18:18
Giovedì, 05/01/2017
Testo quotato

Postato originariamente da TheDarkJuster:Beh io prenderei una bella tabella di numeri primi ...



Tempo fa ne avevo fatto una versione del genere. Magari quando mi gira adatto la funzione scomponi(), qui sopra (ho conservato la tabella in un bel file di intestazione, mi basta un #include e poco altro).

Testo quotato

Postato originariamente da TheDarkJuster:Per l'amor di dio usate le linked list, non array con un numero di posti fissi, oppure rendete l'array ingrandibile a runtime.



Con l'array fisso c'est plus facile! :D


ATTENZIONE! Sono un hobbista e l'affidabilità delle mie conoscenze informatiche è molto limitata. Non prendere come esempio il codice che scrivo, perché non ho alcuna formazione accademica e rischieresti di apprendere pratiche controproducenti.
PM Quote
Avatar
darkannet (Normal User)
Newbie


Messaggi: 4
Iscritto: 04/01/2017

Segnala al moderatore
Postato alle 20:51
Giovedì, 05/01/2017
Testo quotato

Postato originariamente da AldoBaldo:
Dubito che sia possibile parlare di "ottimizzazione", però m'è preso il ghiribizzo di pasticciare un po' con la tua idea di un marchingegno per scomporre numeri in fattori primi. Ne è venuta fuori una roba, distribuita su tre file che credo sia in ANSI C. Il compilatore che uso (mingw) ha sputato fuori un eseguibile di 11 Kb in tutto, alla faccia del C++ che anche solo usando cin e cout s'avvicinava al Mb!

Sicuramente ci saranno ingenuità mostruose, sia perché le mie conoscenze matematiche sono quel che sono, sia perché ho fatto tutto un po' di getto, appiccicando funzioni su funzioni preso dal fuoco sacro del giocare a fingere d'essere un programmatore della madonna! (che non è vero) :D

1. main.c

Codice sorgente - presumibilmente C++

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include "interfaccia.h"
  4.  
  5. // ===> MACRO/COSTANTI/STRINGHE <===============================================
  6.  
  7. #define MAX_FATTORI 36 // in effetti, unsigned long puo' contenere un valore
  8.                        // massimo di 2^32-1, per cui nella scomposizione non
  9.                        // ci possono essere piu' di 32 fattori primi
  10.  
  11. const char *kStrPres[] = {
  12. "SCOMPOSIZIONE IN FATTORI PRIMI",
  13. "questo programma scompone in fattori primi valori interi compresi",
  14. "tra 2 e 4294967295, presentando il risultato sia in forma di",
  15. "calcolo in colonna, sia come formula riassuntiva in linea"
  16. };
  17.  
  18. const int kNStrPres = sizeof(kStrPres)/sizeof(*kStrPres);
  19.  
  20. // ===> PROTOTIPI DI FUNZIONI <=================================================
  21.  
  22. void scomponi( unsigned long n, unsigned long *fattori );
  23.  
  24. // ===> FUNZIONE D'ACCESSO AL PROGRAMMA <=======================================
  25.  
  26. int main() {
  27.     unsigned long n, fattori[MAX_FATTORI];
  28.  
  29.     presenta_in_console( kStrPres, kNStrPres );
  30.  
  31.     do {
  32.         memset( fattori, 0, sizeof(*fattori)*MAX_FATTORI );
  33.  
  34.         n = chiedi_numero_da_scomporre();
  35.  
  36.         scomponi( n, fattori );
  37.  
  38.         scrivi_tabella_scomposizione( n, fattori );
  39.         scrivi_scomposizione_in_linea( n, fattori );
  40.     } while( chiedi_se_continuare() );
  41.  
  42.     return 0;
  43. }
  44.  
  45. // ===> FUNZIONE DI SCOMPOSIZIONE IN FATTORI PRIMI <============================
  46.  
  47. void scomponi( unsigned long n, unsigned long *fattori ) {
  48.     if( n > 1 ) {
  49.         unsigned long d, max;
  50.         int nf; // la quantita' dei fattori trovati
  51.  
  52.         for( d=2, nf=0; n%d==0; ++nf ) {
  53.             fattori[nf] = d;
  54.             n /= d;
  55.         }
  56.  
  57.         if( n == 1 ) return;
  58.  
  59.         for( max=n, d=3; d<=max; ) {
  60.             if( n%d ) { d+=2; continue; }
  61.             fattori[nf++] = d;
  62.             if( (n/=d) == 1 ) break;
  63.             max = n;
  64.         }
  65.     }
  66.     else {
  67.         if( n == 0 )
  68.             printf( "Lo zero non e' scomponibile.\n\n" );
  69.         else printf( "L'unita' non e' scomponibile.\n\n" );
  70.     }
  71. }



2. interfaccia.h

Codice sorgente - presumibilmente C++

  1. #ifndef INTERFACCIA_H_INCLUDED
  2. #define INTERFACCIA_H_INCLUDED
  3.  
  4. void presenta_in_console( const char *s[], int ns );
  5. unsigned long chiedi_numero_da_scomporre( void );
  6. void scrivi_tabella_scomposizione( unsigned long n, unsigned long *fattori );
  7. void scrivi_scomposizione_in_linea( unsigned long n, unsigned long *fattori );
  8. int chiedi_se_continuare( void );
  9.  
  10. #endif // INTERFACCIA_H_INCLUDED



3. interfaccia.c

Codice sorgente - presumibilmente C++

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <ctype.h>
  5. #include "interfaccia.h"
  6.  
  7. // ===> MACRO/COSTANTI <========================================================
  8.  
  9. #define LARGHEZZA_CONSOLE 80 // specificare la larghezza della console
  10. #define A_CAPO printf("\n")
  11.  
  12. // ===> PROTOTIPI DI FUNZIONI <=================================================
  13.  
  14. int leggi_riga_da_console( char **riga, size_t *dim_riga );
  15. int stringa_in_numero_intero( const char *s, unsigned long *n );
  16. void centra_in_console( const char *s );
  17. void traccia_riga_in_console( int c, int nc );
  18. void mostra_errore_in_console( const char *msg );
  19. void attendi_invio_da_console( void );
  20. void svuota_console( void );
  21.  
  22. /*==============================================================================
  23. Chiede all'utente di immettere il numero che intende scomporre. Verifica il dato
  24. immesso per assicurarsi che sia effettivamente un numero intero. La verifica
  25. avviene tramite la funzione standard strtoul(). La richiesta viene iterata fino
  26. a che viene immesso un valore accettabile.
  27. ==============================================================================*/
  28.  
  29. unsigned long chiedi_numero_da_scomporre( void ) {
  30.     unsigned long numero;
  31.     char *riga = NULL;
  32.     int err = 1;
  33.  
  34.     do {
  35.         svuota_console();
  36.  
  37.         printf( "\nInserisci un numero da scomporre: " );
  38.  
  39.         if( leggi_riga_da_console(&riga,NULL) == 0 ) {
  40.             if( stringa_in_numero_intero(riga,&numero) == 0 ) {
  41.                 err = 0;
  42.             } else mostra_errore_in_console( "l'input non e' un numero intero" );
  43.  
  44.             free( riga );  riga = NULL;
  45.         } else mostra_errore_in_console( "impossibile allocare" );
  46.     } while( err != 0 );
  47.  
  48.     svuota_console();
  49.     printf( "\n" );
  50.  
  51.     return numero;
  52. }
  53.  
  54. /*==============================================================================
  55. Legge una riga di testo di lunghezza arbitraria dalla console. La riga letta
  56. viene collocata in uno spazio di memoria allocato dinamicamente il cui puntatore
  57. viene immesso in *riga. Se dim_riga non e' NULL, le dimensioni della stringa
  58. risultante sono collocate in *dim_riga (escluso il carattere terminatore).
  59. Spetta al chiamante liberare con free() la memoria allocata.
  60.  
  61. Valori di ritorno:
  62.  
  63.     0   tutto bene
  64.     1   parametri non validi (puntatori NULL)
  65.     4   impossibile allocare dinamicamente la memoria necessaria
  66. ==============================================================================*/
  67.  
  68. int leggi_riga_da_console( char **riga, size_t *dim_riga ) {
  69.     const size_t inc = 16; // procede per blocchi d'allocazione di inc byte
  70.     size_t dr, dm; // dr = dimensioni riga; dm = dimensioni memoria
  71.     char *tmp, *aux;
  72.     int c;
  73.  
  74.     if( dim_riga ) *dim_riga = 0;
  75.     if( riga ) *riga = NULL; else return 1;
  76.  
  77.     // alloca un primo blocco di memoria dinamica
  78.     dm = inc;
  79.     tmp = malloc( dm+1 );
  80.     if( !tmp ) return 4;
  81.  
  82.     // legge i dati nella memoria dinamica, ridimensionandola se necessario
  83.     for( dr=0, c=fgetc(stdin); c!='\n' && c!=EOF; ++dr, c=fgetc(stdin) ) {
  84.         if( dr < (dm-1) ) {
  85.             tmp[dr] = c;
  86.         }
  87.         else {
  88.             aux = tmp; // caso mai realloc fallisse (vedi else)
  89.  
  90.             if( (tmp=realloc(tmp,dm+inc)) ) {
  91.                 dm += inc;
  92.                 tmp[dr] = c;
  93.             }
  94.             else {
  95.                 free( aux );
  96.                 return 4;
  97.             }
  98.         }
  99.     }
  100.  
  101.     *riga = tmp;
  102.     (*riga)[dr] = '\0'; // termina la stringa
  103.     if( dim_riga ) *dim_riga = dr;
  104.     return 0;
  105. }
  106.  
  107. /*==============================================================================
  108. Tramile la funzione standard strtoul() tenta di verificare la validita' della
  109. stringa immessa dall'utente. Restituisce in *n il numero intero senza segno
  110. rappresentato dalla stringa s. Se tutto va bene, il valore di ritorno e' 0; in
  111. caso contrario e' diverso da 0.
  112. ==============================================================================*/
  113.  
  114. int stringa_in_numero_intero( const char *s, unsigned long *n ) {
  115.     char *fine = NULL;
  116.     *n = strtoul( s, &fine, 10 );
  117.     return s == fine;
  118. }
  119.  
  120. /*==============================================================================
  121. Scrive, centrandole nella console, una serie di ns stringhe ricavandole
  122. dall'array s[]. Al termine della scrittura si pone in attesa della pressione del
  123. tasto "invio" da parte dell'utente. Quando l'utente preme "invio", svuota la
  124. console e ritorna.
  125. ==============================================================================*/
  126.  
  127. void presenta_in_console( const char *s[], int ns ) {
  128.     if( s ) {
  129.         int i;
  130.         traccia_riga_in_console( '=', LARGHEZZA_CONSOLE-1 ); A_CAPO;
  131.         for( i=0; i<ns; ++i ) { centra_in_console( s[i] ); A_CAPO; }
  132.         traccia_riga_in_console( '=', LARGHEZZA_CONSOLE-1 ); A_CAPO; A_CAPO;
  133.         attendi_invio_da_console();
  134.         svuota_console();
  135.     }
  136. }
  137.  
  138. /*==============================================================================
  139. Scrive nella console la stringa s, facendola precedere dalla quantità di spazi
  140. necessari per centrarla.
  141. ==============================================================================*/
  142.  
  143. void centra_in_console( const char *s ) {
  144.     if( s ) {
  145.         char buff[LARGHEZZA_CONSOLE/2+4];
  146.         int l = (LARGHEZZA_CONSOLE-strlen(s))/2;
  147.         memset( buff, ' ', l ); buff[l] = '\0';
  148.         printf( "%s%s", buff, s );
  149.     }
  150. }
  151.  
  152. /*==============================================================================
  153. Scrive nella console una serie di nc caratteri c. Se nc e' maggiore di
  154. LARGHEZZA_CONSOLE la funzione scrive comunque un massimo di LARGHEZZA_CONSOLE
  155. caratteri.
  156. ==============================================================================*/
  157.  
  158. void traccia_riga_in_console( int c, int nc ) {
  159.     if( nc > 0 ) {
  160.         char buff[LARGHEZZA_CONSOLE+4];
  161.         nc = nc<=LARGHEZZA_CONSOLE ? nc : LARGHEZZA_CONSOLE;
  162.         memset( buff, c, nc ); buff[nc] = '\0';
  163.         printf( "%s", buff );
  164.     }
  165. }
  166.  
  167. /*==============================================================================
  168. Scrive nella console la stringa msg, preceduta da una breve intestazione
  169. d'errore. Emette un "bip" d'avviso sonoro. Al termine della scrittura si pone in
  170. attesa della pressione del tasto "invio" da parte dell'utente. Quando l'utente
  171. preme "invio", ritorna.
  172. ==============================================================================*/
  173.  
  174. void mostra_errore_in_console( const char *msg ) {
  175.     if( msg ) {
  176.         printf( "\a\n===> ERRORE <===\n%s\n\n", msg );
  177.         attendi_invio_da_console();
  178.     }
  179. }
  180.  
  181. /*==============================================================================
  182. Si pone in attesa della pressione del tasto "invio" da parte dell'utente. Quando
  183. l'utente preme "invio", svuota lo stream di input e ritorna.
  184. ==============================================================================*/
  185.  
  186. void attendi_invio_da_console( void ) {
  187.     printf( "Premi \"invio\" per continuare... " );
  188.     while( getchar() != '\n' );
  189. }
  190.  
  191. /*==============================================================================
  192. Usa system() per richiedere lo svuotamento della console.
  193. ==============================================================================*/
  194.  
  195. void svuota_console( void ) {
  196.     system( "cls" );
  197. }
  198.  
  199. /*==============================================================================
  200. Scrive nella console una tabella che raffigura il procedimento di scomposizione
  201. in fattori primi del numero n, secondo i dati immagazzinati nell'array fattori.
  202. ==============================================================================*/
  203.  
  204. void scrivi_tabella_scomposizione( unsigned long n, unsigned long *fattori ) {
  205.     int i;
  206.  
  207.     for( i=0; n!=1; ++i ) {
  208.         printf( "%12lu | %lu\n", n, fattori[i] );
  209.         n /= fattori[i];
  210.     }
  211.  
  212.     printf( "%12lu | \n\n", n );
  213. }
  214.  
  215. /*==============================================================================
  216. Scrive nella console una formula che descrive la scomposizione in fattori del
  217. numero n, secondo i dati immagazzinati nell'array fattori.
  218. ==============================================================================*/
  219.  
  220. void scrivi_scomposizione_in_linea( unsigned long n, unsigned long *fattori ) {
  221.     unsigned long fc = 0; // fc = fattore corrente
  222.     int ec;               // ec = esponente corrente
  223.     int tf;               // tf = totale fattori
  224.     int i;
  225.  
  226.     for( tf=0; fattori[tf]!=0; ++tf );
  227.     if( tf == 0 ) return;
  228.  
  229.     printf( " %lu = ", n );
  230.  
  231.     for( i=tf-1, fc=fattori[i], ec=0; i>=0; --i ) {
  232.         if( fc != fattori[i] ) {
  233.             printf( "%lu", fc );
  234.             if( ec != 1 ) printf( "^%d", ec );
  235.             printf( " * " );
  236.  
  237.             fc = fattori[i];
  238.             ec = 1;
  239.         }
  240.         else {
  241.             ++ec;
  242.         }
  243.     }
  244.  
  245.     printf( "%lu", fc );
  246.     if( ec != 1 ) printf( "^%d", ec );
  247.     printf( "\n" );
  248. }
  249.  
  250. /*==============================================================================
  251. Chiede all'utente se intende continuare con un'ulteriore scomposizione o uscire
  252. dal programma.
  253. ==============================================================================*/
  254.  
  255. int chiedi_se_continuare( void ) {
  256.     char *riga = NULL;
  257.     int esito = 0xFFFF;
  258.  
  259.     do {
  260.         printf( "\nVuoi scomporre un altro numero? (S/N) " );
  261.  
  262.         if( leggi_riga_da_console(&riga,NULL) == 0 ) {
  263.             switch( toupper(*riga) ) {
  264.                 case 'S': esito = 1; break;
  265.                 case 'N': esito = 0; break;
  266.                 default: mostra_errore_in_console( "input non valido" );
  267.             }
  268.  
  269.             free( riga );  riga = NULL;
  270.         } else mostra_errore_in_console( "impossibile allocare" );
  271.     } while( esito == 0xFFFF );
  272.  
  273.     return esito;
  274. }


Non è che ci abbia capito tanto, comunque dopo me lo studio un po'



PM Quote
Avatar
darkannet (Normal User)
Newbie


Messaggi: 4
Iscritto: 04/01/2017

Segnala al moderatore
Postato alle 20:54
Giovedì, 05/01/2017
Comunque la mia richiesta é dovuta soprattutto ai 3 passaggi per trovare i numeri che compaiono una sola volta.

Ultima modifica effettuata da darkannet il 05/01/2017 alle 21:02
PM Quote
Avatar
darkannet (Normal User)
Newbie


Messaggi: 4
Iscritto: 04/01/2017

Segnala al moderatore
Postato alle 20:58
Giovedì, 05/01/2017
Testo quotato

Postato originariamente da TheDarkJuster:

Per l'amor di dio usate le linked list, non array con un numero di posti fissi, oppure rendete l'array ingrandibile a runtime.
Non mettete menù all'interno del programma e prendetevi gli argomenti da char** argv.



Sinceramente non sapevo neanche dell'esistenza degli array ingrandibili, sono all'inizio

PM Quote
Pagine: [ 1 2 ] Precedente | Prossimo