Forum - C/C++
- ottimizzare il codice? scomposizione in fattori primi
Pagine: [ 1 2 ]
|
darkannet (Normal User)
Newbie
Messaggi: 4
Iscritto: 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++
#include<conio.h>
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>
#include<limits>
#include<iostream>
using namespace std;
int boolean;
void ne( ) {
if ( boolean== 0)
printf ( "-" ) ;
}
int legge( ) {
int numero;
while ( ! ( cin >> numero) ) {
cout << "Questo non e' un numero!\n inserisci un numero da scomporre:" ;
cin .clear ( ) ;
cin .ignore ( numeric_limits< streamsize> :: max ( ) , '\n ' ) ; }
return numero;
}
int aspetto( int n,int risultato,int divisore) {
int num,costante;
num= log10 ( n) + 1 ;
costante= log10 ( risultato) ;
ne( ) ;
printf ( "%d" ,n) ;
for ( int contatore= num; contatore<= costante; contatore++ )
printf ( " " ) ;
printf ( "|" ) ;
printf ( "%d\n " ,divisore) ;
}
int * azzeramento( int arr[ ] ,int z)
{
for ( int i= 0 ; i< z; i++ ) {
arr[ i] = 0 ;
}
return arr;
}
int main( ) {
char scelta;
int time ;
while ( scelta! = 'N' ) {
system ( "CLS" ) ; system ( "color 0c" ) ;
int n= 0,z= 0,divisore= 1,p= 0,y= 0 ;
int upgrade= 0,u= 0,num= 0 ;
int contatore= 1 ;
do {
printf ( "inserisci un numero da scomporre: " ) ;
n= legge( ) ;
if ( n== 0)
printf ( "il numero non puo' essere 0!\n " ) ;
} while ( n== 0) ;
if ( n< 0)
{
boolean= 0 ;
n= n*- 1 ;
}
else
boolean= 1 ;
int scambio= n;
int risultato= n;
{
divisore= 1 ;
z= 0 ;
do {
divisore++ ;
if ( n% divisore== 0) {
aspetto( n,risultato,divisore) ;
n= n/ divisore;
z++ ;
divisore= 1 ;
}
} while ( n> divisore) ;
ne( ) ;
printf ( "%d\n " ,n) ;
}
//dichiarazione variabili
int val[ z] ;
int err[ z] ;
int col[ z] ;
int zc= 0 ;
contatore= 1 ;
//fine dichiarazione variabili
while ( scambio> 1)
{
contatore++ ;
if ( scambio% contatore== 0)
{
val[ zc] = contatore;
zc++ ;
scambio/ = contatore;
contatore= 1 ;
}
}
azzeramento( err,z) ;
for ( int xx= 0 ; xx< z; xx++ ) {
y= 0 ;
for ( int yy= 0 ; yy< z; yy++ )
{
if ( val[ xx] ! = err[ yy] ) {
y++ ;
}
}
if ( y== z)
err[ xx] = val[ xx] ;
}
for ( int xx= 0 ; xx< z; xx++ )
{
if ( err[ xx] ! = 0)
{
col[ num] = err[ xx] ;
num++ ;
}
}
int numerisingoli[ num] ;
int potenza[ num] ;
azzeramento( potenza,num) ;
for ( int yy= 0 ; yy< num; yy++ )
{
numerisingoli[ yy] = col[ yy] ;
}
for ( int xx= 0 ; xx< num; xx++ )
{
for ( int yy= 0 ; yy< z; yy++ )
{
if ( numerisingoli[ xx] == val[ yy] )
{
potenza[ xx] ++ ;
}
}
}
printf ( "\n " ) ;
if ( boolean== 0)
printf ( "-(" ) ;
for ( int stamp= 0 ; stamp< num; stamp++ )
{
printf ( "%d" ,numerisingoli[ stamp] ) ;
if ( potenza[ stamp] ! = 1)
printf ( "^%d" ,potenza[ stamp] ) ;
if ( stamp< num- 1)
printf ( "*" ) ;
}
if ( boolean== 0)
printf ( ")" ) ;
printf ( " =" ) ;
ne( ) ;
printf ( "%d" ,risultato) ;
fflush ( stdin ) ;
printf ( "\n vuoi inserire un altro numero?(S/N)" ) ;
scelta= getchar ( ) ;
scelta= toupper ( scelta) ;
}
system ( "PAUSE" ) ;
}
Ultima modifica effettuata da darkannet il 04/01/2017 alle 18:37
AldoBaldo (Member )
Guru
Messaggi: 700
Iscritto: 08/01/2015
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)
1. main.c
Codice sorgente - presumibilmente C#
#include <stdio.h>
#include <string.h>
#include "interfaccia.h"
// ===> MACRO/COSTANTI/STRINGHE <===============================================
#define MAX_FATTORI 36 // in effetti, unsigned long puo' contenere un valore
// massimo di 2^32-1, per cui nella scomposizione non
// ci possono essere piu' di 32 fattori primi
const char * kStrPres[ ] = {
"SCOMPOSIZIONE IN FATTORI PRIMI" ,
"questo programma scompone in fattori primi valori interi compresi" ,
"tra 2 e 4294967295, presentando il risultato sia in forma di" ,
"calcolo in colonna, sia come formula riassuntiva in linea"
} ;
// ===> PROTOTIPI DI FUNZIONI <=================================================
void scomponi( unsigned long n, unsigned long * fattori ) ;
// ===> FUNZIONE D'ACCESSO AL PROGRAMMA <=======================================
int main( ) {
unsigned long n, fattori[ MAX_FATTORI] ;
presenta_in_console( kStrPres, kNStrPres ) ;
do {
memset
( fattori, 0,
sizeof ( * fattori
) * MAX_FATTORI
) ;
n = chiedi_numero_da_scomporre( ) ;
scomponi( n, fattori ) ;
scrivi_tabella_scomposizione( n, fattori ) ;
scrivi_scomposizione_in_linea( n, fattori ) ;
} while ( chiedi_se_continuare( ) ) ;
return 0 ;
}
// ===> FUNZIONE DI SCOMPOSIZIONE IN FATTORI PRIMI <============================
void scomponi( unsigned long n, unsigned long * fattori ) {
if ( n > 1 ) {
unsigned long d, max;
int nf; // la quantita' dei fattori trovati
for ( d= 2, nf= 0 ; n% d== 0 ; ++ nf ) {
fattori[ nf] = d;
n /= d;
}
if ( n == 1 ) return;
for ( max= n, d= 3 ; d<= max; ) {
if ( n% d ) { d+= 2 ; continue; }
fattori[ nf++ ] = d;
if ( ( n/= d) == 1 ) break;
max = n;
}
}
else {
if ( n == 0 )
printf( "Lo zero non e' scomponibile.\n \n " ) ;
else printf( "L'unita' non e' scomponibile.\n \n " ) ;
}
}
2. interfaccia.h
Codice sorgente - presumibilmente C++
#ifndef INTERFACCIA_H_INCLUDED
#define INTERFACCIA_H_INCLUDED
void presenta_in_console( const char * s[ ] , int ns ) ;
unsigned long chiedi_numero_da_scomporre( void ) ;
void scrivi_tabella_scomposizione( unsigned long n, unsigned long * fattori ) ;
void scrivi_scomposizione_in_linea( unsigned long n, unsigned long * fattori ) ;
int chiedi_se_continuare( void ) ;
#endif // INTERFACCIA_H_INCLUDED
3. interfaccia.c
Codice sorgente - presumibilmente C++
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "interfaccia.h"
// ===> MACRO/COSTANTI <========================================================
#define LARGHEZZA_CONSOLE 80 // specificare la larghezza della console
#define A_CAPO printf("\n")
// ===> PROTOTIPI DI FUNZIONI <=================================================
int leggi_riga_da_console( char ** riga, size_t * dim_riga ) ;
int stringa_in_numero_intero( const char * s, unsigned long * n ) ;
void centra_in_console( const char * s ) ;
void traccia_riga_in_console( int c, int nc ) ;
void mostra_errore_in_console( const char * msg ) ;
void attendi_invio_da_console( void ) ;
void svuota_console( void ) ;
/*==============================================================================
Chiede all'utente di immettere il numero che intende scomporre. Verifica il dato
immesso per assicurarsi che sia effettivamente un numero intero. La verifica
avviene tramite la funzione standard strtoul(). La richiesta viene iterata fino
a che viene immesso un valore accettabile.
==============================================================================*/
unsigned long chiedi_numero_da_scomporre( void ) {
unsigned long numero;
char * riga = NULL ;
int err = 1 ;
do {
svuota_console( ) ;
printf ( "\n Inserisci un numero da scomporre: " ) ;
if ( leggi_riga_da_console( & riga,NULL ) == 0 ) {
if ( stringa_in_numero_intero( riga,& numero) == 0 ) {
err = 0 ;
} else mostra_errore_in_console( "l'input non e' un numero intero" ) ;
free ( riga ) ; riga = NULL ;
} else mostra_errore_in_console( "impossibile allocare" ) ;
} while ( err ! = 0 ) ;
svuota_console( ) ;
printf ( "\n " ) ;
return numero;
}
/*==============================================================================
Legge una riga di testo di lunghezza arbitraria dalla console. La riga letta
viene collocata in uno spazio di memoria allocato dinamicamente il cui puntatore
viene immesso in *riga. Se dim_riga non e' NULL, le dimensioni della stringa
risultante sono collocate in *dim_riga (escluso il carattere terminatore).
Spetta al chiamante liberare con free() la memoria allocata.
Valori di ritorno:
0 tutto bene
1 parametri non validi (puntatori NULL)
4 impossibile allocare dinamicamente la memoria necessaria
==============================================================================*/
int leggi_riga_da_console( char ** riga, size_t * dim_riga ) {
const size_t inc = 16 ; // procede per blocchi d'allocazione di inc byte
size_t dr, dm; // dr = dimensioni riga; dm = dimensioni memoria
char * tmp, * aux;
int c;
if ( dim_riga ) * dim_riga = 0 ;
if ( riga ) * riga = NULL ; else return 1 ;
// alloca un primo blocco di memoria dinamica
dm = inc;
tmp = malloc ( dm+ 1 ) ;
if ( ! tmp ) return 4 ;
// legge i dati nella memoria dinamica, ridimensionandola se necessario
for ( dr= 0, c= fgetc ( stdin ) ; c! = '\n ' && c! = EOF ; ++ dr, c= fgetc ( stdin ) ) {
if ( dr < ( dm- 1) ) {
tmp[ dr] = c;
}
else {
aux = tmp; // caso mai realloc fallisse (vedi else)
if ( ( tmp= realloc ( tmp,dm+ inc) ) ) {
dm + = inc;
tmp[ dr] = c;
}
else {
free ( aux ) ;
return 4 ;
}
}
}
* riga = tmp;
( * riga) [ dr] = '\0 ' ; // termina la stringa
if ( dim_riga ) * dim_riga = dr;
return 0 ;
}
/*==============================================================================
Tramile la funzione standard strtoul() tenta di verificare la validita' della
stringa immessa dall'utente. Restituisce in *n il numero intero senza segno
rappresentato dalla stringa s. Se tutto va bene, il valore di ritorno e' 0; in
caso contrario e' diverso da 0.
==============================================================================*/
int stringa_in_numero_intero( const char * s, unsigned long * n ) {
char * fine = NULL ;
* n = strtoul ( s, & fine, 10 ) ;
return s == fine;
}
/*==============================================================================
Scrive, centrandole nella console, una serie di ns stringhe ricavandole
dall'array s[]. Al termine della scrittura si pone in attesa della pressione del
tasto "invio" da parte dell'utente. Quando l'utente preme "invio", svuota la
console e ritorna.
==============================================================================*/
void presenta_in_console( const char * s[ ] , int ns ) {
if ( s ) {
int i;
traccia_riga_in_console( '=' , LARGHEZZA_CONSOLE- 1 ) ; A_CAPO;
for ( i= 0 ; i< ns; ++ i ) { centra_in_console( s[ i] ) ; A_CAPO; }
traccia_riga_in_console( '=' , LARGHEZZA_CONSOLE- 1 ) ; A_CAPO; A_CAPO;
attendi_invio_da_console( ) ;
svuota_console( ) ;
}
}
/*==============================================================================
Scrive nella console la stringa s, facendola precedere dalla quantità di spazi
necessari per centrarla.
==============================================================================*/
void centra_in_console( const char * s ) {
if ( s ) {
char buff[ LARGHEZZA_CONSOLE/ 2+ 4] ;
int l = ( LARGHEZZA_CONSOLE- strlen ( s) ) / 2 ;
memset ( buff, ' ' , l ) ; buff[ l] = '\0 ' ;
printf ( "%s%s" , buff, s ) ;
}
}
/*==============================================================================
Scrive nella console una serie di nc caratteri c. Se nc e' maggiore di
LARGHEZZA_CONSOLE la funzione scrive comunque un massimo di LARGHEZZA_CONSOLE
caratteri.
==============================================================================*/
void traccia_riga_in_console( int c, int nc ) {
if ( nc > 0 ) {
char buff[ LARGHEZZA_CONSOLE+ 4] ;
nc = nc<= LARGHEZZA_CONSOLE ? nc : LARGHEZZA_CONSOLE;
memset ( buff, c, nc ) ; buff[ nc] = '\0 ' ;
printf ( "%s" , buff ) ;
}
}
/*==============================================================================
Scrive nella console la stringa msg, preceduta da una breve intestazione
d'errore. Emette un "bip" d'avviso sonoro. Al termine della scrittura si pone in
attesa della pressione del tasto "invio" da parte dell'utente. Quando l'utente
preme "invio", ritorna.
==============================================================================*/
void mostra_errore_in_console( const char * msg ) {
if ( msg ) {
printf ( "\a \n ===> ERRORE <===\n %s\n \n " , msg ) ;
attendi_invio_da_console( ) ;
}
}
/*==============================================================================
Si pone in attesa della pressione del tasto "invio" da parte dell'utente. Quando
l'utente preme "invio", svuota lo stream di input e ritorna.
==============================================================================*/
void attendi_invio_da_console( void ) {
printf ( "Premi \" invio\" per continuare... " ) ;
while ( getchar ( ) ! = '\n ' ) ;
}
/*==============================================================================
Usa system() per richiedere lo svuotamento della console.
==============================================================================*/
void svuota_console( void ) {
system ( "cls" ) ;
}
/*==============================================================================
Scrive nella console una tabella che raffigura il procedimento di scomposizione
in fattori primi del numero n, secondo i dati immagazzinati nell'array fattori.
==============================================================================*/
void scrivi_tabella_scomposizione( unsigned long n, unsigned long * fattori ) {
int i;
for ( i= 0 ; n! = 1 ; ++ i ) {
printf ( "%12lu | %lu\n " , n, fattori[ i] ) ;
n / = fattori[ i] ;
}
printf ( "%12lu | \n \n " , n ) ;
}
/*==============================================================================
Scrive nella console una formula che descrive la scomposizione in fattori del
numero n, secondo i dati immagazzinati nell'array fattori.
==============================================================================*/
void scrivi_scomposizione_in_linea( unsigned long n, unsigned long * fattori ) {
unsigned long fc = 0 ; // fc = fattore corrente
int ec; // ec = esponente corrente
int tf; // tf = totale fattori
int i;
for ( tf= 0 ; fattori[ tf] ! = 0 ; ++ tf ) ;
if ( tf == 0 ) return ;
printf ( " %lu = " , n ) ;
for ( i= tf- 1, fc= fattori[ i] , ec= 0 ; i>= 0 ; -- i ) {
if ( fc ! = fattori[ i] ) {
printf ( "%lu" , fc ) ;
if ( ec ! = 1 ) printf ( "^%d" , ec ) ;
printf ( " * " ) ;
fc = fattori[ i] ;
ec = 1 ;
}
else {
++ ec;
}
}
printf ( "%lu" , fc ) ;
if ( ec ! = 1 ) printf ( "^%d" , ec ) ;
printf ( "\n " ) ;
}
/*==============================================================================
Chiede all'utente se intende continuare con un'ulteriore scomposizione o uscire
dal programma.
==============================================================================*/
int chiedi_se_continuare( void ) {
char * riga = NULL ;
int esito = 0xFFFF ;
do {
printf ( "\n Vuoi scomporre un altro numero? (S/N) " ) ;
if ( leggi_riga_da_console( & riga,NULL ) == 0 ) {
switch ( toupper ( * riga) ) {
case 'S' : esito = 1 ; break ;
case 'N' : esito = 0 ; break ;
default : mostra_errore_in_console( "input non valido" ) ;
}
free ( riga ) ; riga = NULL ;
} else mostra_errore_in_console( "impossibile allocare" ) ;
} while ( esito == 0xFFFF ) ;
return esito;
}
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.
Goblin (Member )
Expert
Messaggi: 375
Iscritto: 02/02/2011
Postato originariamente da AldoBaldo :
...[cut].... preso dal fuoco sacro del giocare a fingere d'essere un programmatore della madonna! (che non è vero)
Ultima modifica effettuata da Goblin il 05/01/2017 alle 15:04
Ibis redibis non morieris in bello
TheDarkJuster (Member )
Guru^2
Messaggi: 1620
Iscritto: 27/09/2013
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.
lumo (Member )
Expert
Messaggi: 449
Iscritto: 18/04/2010
Una linked list non ha senso qui.
Altra cosa, per controllare i divisori basta arrivare a sqrt(n).
AldoBaldo (Member )
Guru
Messaggi: 700
Iscritto: 08/01/2015
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).
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!
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.
darkannet (Normal User)
Newbie
Messaggi: 4
Iscritto: 04/01/2017
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) 1. main.c
Codice sorgente - presumibilmente C++
#include <stdio.h>
#include <string.h>
#include "interfaccia.h"
// ===> MACRO/COSTANTI/STRINGHE <===============================================
#define MAX_FATTORI 36 // in effetti, unsigned long puo' contenere un valore
// massimo di 2^32-1, per cui nella scomposizione non
// ci possono essere piu' di 32 fattori primi
const char * kStrPres[ ] = {
"SCOMPOSIZIONE IN FATTORI PRIMI" ,
"questo programma scompone in fattori primi valori interi compresi" ,
"tra 2 e 4294967295, presentando il risultato sia in forma di" ,
"calcolo in colonna, sia come formula riassuntiva in linea"
} ;
const int kNStrPres = sizeof ( kStrPres) / sizeof ( * kStrPres) ;
// ===> PROTOTIPI DI FUNZIONI <=================================================
void scomponi( unsigned long n, unsigned long * fattori ) ;
// ===> FUNZIONE D'ACCESSO AL PROGRAMMA <=======================================
int main( ) {
unsigned long n, fattori[ MAX_FATTORI] ;
presenta_in_console( kStrPres, kNStrPres ) ;
do {
memset ( fattori, 0, sizeof ( * fattori) * MAX_FATTORI ) ;
n = chiedi_numero_da_scomporre( ) ;
scomponi( n, fattori ) ;
scrivi_tabella_scomposizione( n, fattori ) ;
scrivi_scomposizione_in_linea( n, fattori ) ;
} while ( chiedi_se_continuare( ) ) ;
return 0 ;
}
// ===> FUNZIONE DI SCOMPOSIZIONE IN FATTORI PRIMI <============================
void scomponi( unsigned long n, unsigned long * fattori ) {
if ( n > 1 ) {
unsigned long d, max;
int nf; // la quantita' dei fattori trovati
for ( d= 2, nf= 0 ; n% d== 0 ; ++ nf ) {
fattori[ nf] = d;
n / = d;
}
if ( n == 1 ) return ;
for ( max= n, d= 3 ; d<= max; ) {
if ( n% d ) { d+ = 2 ; continue ; }
fattori[ nf++ ] = d;
if ( ( n/ = d) == 1 ) break ;
max = n;
}
}
else {
if ( n == 0 )
printf ( "Lo zero non e' scomponibile.\n \n " ) ;
else printf ( "L'unita' non e' scomponibile.\n \n " ) ;
}
}
2. interfaccia.h
Codice sorgente - presumibilmente C++
#ifndef INTERFACCIA_H_INCLUDED
#define INTERFACCIA_H_INCLUDED
void presenta_in_console( const char * s[ ] , int ns ) ;
unsigned long chiedi_numero_da_scomporre( void ) ;
void scrivi_tabella_scomposizione( unsigned long n, unsigned long * fattori ) ;
void scrivi_scomposizione_in_linea( unsigned long n, unsigned long * fattori ) ;
int chiedi_se_continuare( void ) ;
#endif // INTERFACCIA_H_INCLUDED
3. interfaccia.c
Codice sorgente - presumibilmente C++
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "interfaccia.h"
// ===> MACRO/COSTANTI <========================================================
#define LARGHEZZA_CONSOLE 80 // specificare la larghezza della console
#define A_CAPO printf("\n")
// ===> PROTOTIPI DI FUNZIONI <=================================================
int leggi_riga_da_console( char ** riga, size_t * dim_riga ) ;
int stringa_in_numero_intero( const char * s, unsigned long * n ) ;
void centra_in_console( const char * s ) ;
void traccia_riga_in_console( int c, int nc ) ;
void mostra_errore_in_console( const char * msg ) ;
void attendi_invio_da_console( void ) ;
void svuota_console( void ) ;
/*==============================================================================
Chiede all'utente di immettere il numero che intende scomporre. Verifica il dato
immesso per assicurarsi che sia effettivamente un numero intero. La verifica
avviene tramite la funzione standard strtoul(). La richiesta viene iterata fino
a che viene immesso un valore accettabile.
==============================================================================*/
unsigned long chiedi_numero_da_scomporre( void ) {
unsigned long numero;
char * riga = NULL ;
int err = 1 ;
do {
svuota_console( ) ;
printf ( "\n Inserisci un numero da scomporre: " ) ;
if ( leggi_riga_da_console( & riga,NULL ) == 0 ) {
if ( stringa_in_numero_intero( riga,& numero) == 0 ) {
err = 0 ;
} else mostra_errore_in_console( "l'input non e' un numero intero" ) ;
free ( riga ) ; riga = NULL ;
} else mostra_errore_in_console( "impossibile allocare" ) ;
} while ( err ! = 0 ) ;
svuota_console( ) ;
printf ( "\n " ) ;
return numero;
}
/*==============================================================================
Legge una riga di testo di lunghezza arbitraria dalla console. La riga letta
viene collocata in uno spazio di memoria allocato dinamicamente il cui puntatore
viene immesso in *riga. Se dim_riga non e' NULL, le dimensioni della stringa
risultante sono collocate in *dim_riga (escluso il carattere terminatore).
Spetta al chiamante liberare con free() la memoria allocata.
Valori di ritorno:
0 tutto bene
1 parametri non validi (puntatori NULL)
4 impossibile allocare dinamicamente la memoria necessaria
==============================================================================*/
int leggi_riga_da_console( char ** riga, size_t * dim_riga ) {
const size_t inc = 16 ; // procede per blocchi d'allocazione di inc byte
size_t dr, dm; // dr = dimensioni riga; dm = dimensioni memoria
char * tmp, * aux;
int c;
if ( dim_riga ) * dim_riga = 0 ;
if ( riga ) * riga = NULL ; else return 1 ;
// alloca un primo blocco di memoria dinamica
dm = inc;
tmp = malloc ( dm+ 1 ) ;
if ( ! tmp ) return 4 ;
// legge i dati nella memoria dinamica, ridimensionandola se necessario
for ( dr= 0, c= fgetc ( stdin ) ; c! = '\n ' && c! = EOF ; ++ dr, c= fgetc ( stdin ) ) {
if ( dr < ( dm- 1) ) {
tmp[ dr] = c;
}
else {
aux = tmp; // caso mai realloc fallisse (vedi else)
if ( ( tmp= realloc ( tmp,dm+ inc) ) ) {
dm + = inc;
tmp[ dr] = c;
}
else {
free ( aux ) ;
return 4 ;
}
}
}
* riga = tmp;
( * riga) [ dr] = '\0 ' ; // termina la stringa
if ( dim_riga ) * dim_riga = dr;
return 0 ;
}
/*==============================================================================
Tramile la funzione standard strtoul() tenta di verificare la validita' della
stringa immessa dall'utente. Restituisce in *n il numero intero senza segno
rappresentato dalla stringa s. Se tutto va bene, il valore di ritorno e' 0; in
caso contrario e' diverso da 0.
==============================================================================*/
int stringa_in_numero_intero( const char * s, unsigned long * n ) {
char * fine = NULL ;
* n = strtoul ( s, & fine, 10 ) ;
return s == fine;
}
/*==============================================================================
Scrive, centrandole nella console, una serie di ns stringhe ricavandole
dall'array s[]. Al termine della scrittura si pone in attesa della pressione del
tasto "invio" da parte dell'utente. Quando l'utente preme "invio", svuota la
console e ritorna.
==============================================================================*/
void presenta_in_console( const char * s[ ] , int ns ) {
if ( s ) {
int i;
traccia_riga_in_console( '=' , LARGHEZZA_CONSOLE- 1 ) ; A_CAPO;
for ( i= 0 ; i< ns; ++ i ) { centra_in_console( s[ i] ) ; A_CAPO; }
traccia_riga_in_console( '=' , LARGHEZZA_CONSOLE- 1 ) ; A_CAPO; A_CAPO;
attendi_invio_da_console( ) ;
svuota_console( ) ;
}
}
/*==============================================================================
Scrive nella console la stringa s, facendola precedere dalla quantità di spazi
necessari per centrarla.
==============================================================================*/
void centra_in_console( const char * s ) {
if ( s ) {
char buff[ LARGHEZZA_CONSOLE/ 2+ 4] ;
int l = ( LARGHEZZA_CONSOLE- strlen ( s) ) / 2 ;
memset ( buff, ' ' , l ) ; buff[ l] = '\0 ' ;
printf ( "%s%s" , buff, s ) ;
}
}
/*==============================================================================
Scrive nella console una serie di nc caratteri c. Se nc e' maggiore di
LARGHEZZA_CONSOLE la funzione scrive comunque un massimo di LARGHEZZA_CONSOLE
caratteri.
==============================================================================*/
void traccia_riga_in_console( int c, int nc ) {
if ( nc > 0 ) {
char buff[ LARGHEZZA_CONSOLE+ 4] ;
nc = nc<= LARGHEZZA_CONSOLE ? nc : LARGHEZZA_CONSOLE;
memset ( buff, c, nc ) ; buff[ nc] = '\0 ' ;
printf ( "%s" , buff ) ;
}
}
/*==============================================================================
Scrive nella console la stringa msg, preceduta da una breve intestazione
d'errore. Emette un "bip" d'avviso sonoro. Al termine della scrittura si pone in
attesa della pressione del tasto "invio" da parte dell'utente. Quando l'utente
preme "invio", ritorna.
==============================================================================*/
void mostra_errore_in_console( const char * msg ) {
if ( msg ) {
printf ( "\a \n ===> ERRORE <===\n %s\n \n " , msg ) ;
attendi_invio_da_console( ) ;
}
}
/*==============================================================================
Si pone in attesa della pressione del tasto "invio" da parte dell'utente. Quando
l'utente preme "invio", svuota lo stream di input e ritorna.
==============================================================================*/
void attendi_invio_da_console( void ) {
printf ( "Premi \" invio\" per continuare... " ) ;
while ( getchar ( ) ! = '\n ' ) ;
}
/*==============================================================================
Usa system() per richiedere lo svuotamento della console.
==============================================================================*/
void svuota_console( void ) {
system ( "cls" ) ;
}
/*==============================================================================
Scrive nella console una tabella che raffigura il procedimento di scomposizione
in fattori primi del numero n, secondo i dati immagazzinati nell'array fattori.
==============================================================================*/
void scrivi_tabella_scomposizione( unsigned long n, unsigned long * fattori ) {
int i;
for ( i= 0 ; n! = 1 ; ++ i ) {
printf ( "%12lu | %lu\n " , n, fattori[ i] ) ;
n / = fattori[ i] ;
}
printf ( "%12lu | \n \n " , n ) ;
}
/*==============================================================================
Scrive nella console una formula che descrive la scomposizione in fattori del
numero n, secondo i dati immagazzinati nell'array fattori.
==============================================================================*/
void scrivi_scomposizione_in_linea( unsigned long n, unsigned long * fattori ) {
unsigned long fc = 0 ; // fc = fattore corrente
int ec; // ec = esponente corrente
int tf; // tf = totale fattori
int i;
for ( tf= 0 ; fattori[ tf] ! = 0 ; ++ tf ) ;
if ( tf == 0 ) return ;
printf ( " %lu = " , n ) ;
for ( i= tf- 1, fc= fattori[ i] , ec= 0 ; i>= 0 ; -- i ) {
if ( fc ! = fattori[ i] ) {
printf ( "%lu" , fc ) ;
if ( ec ! = 1 ) printf ( "^%d" , ec ) ;
printf ( " * " ) ;
fc = fattori[ i] ;
ec = 1 ;
}
else {
++ ec;
}
}
printf ( "%lu" , fc ) ;
if ( ec ! = 1 ) printf ( "^%d" , ec ) ;
printf ( "\n " ) ;
}
/*==============================================================================
Chiede all'utente se intende continuare con un'ulteriore scomposizione o uscire
dal programma.
==============================================================================*/
int chiedi_se_continuare( void ) {
char * riga = NULL ;
int esito = 0xFFFF ;
do {
printf ( "\n Vuoi scomporre un altro numero? (S/N) " ) ;
if ( leggi_riga_da_console( & riga,NULL ) == 0 ) {
switch ( toupper ( * riga) ) {
case 'S' : esito = 1 ; break ;
case 'N' : esito = 0 ; break ;
default : mostra_errore_in_console( "input non valido" ) ;
}
free ( riga ) ; riga = NULL ;
} else mostra_errore_in_console( "impossibile allocare" ) ;
} while ( esito == 0xFFFF ) ;
return esito;
}
Non è che ci abbia capito tanto, comunque dopo me lo studio un po'
darkannet (Normal User)
Newbie
Messaggi: 4
Iscritto: 04/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
darkannet (Normal User)
Newbie
Messaggi: 4
Iscritto: 04/01/2017
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