Oppure

Loading
04/01/17 15:12
darkannet
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!
#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!\ninserisci 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("\nvuoi inserire un altro numero?(S/N)");
scelta=getchar();
scelta=toupper(scelta);
}
system("PAUSE");
}

Ultima modifica effettuata da darkannet 04/01/17 17:37
aaa
05/01/17 2:05
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

#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

#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

#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( "\nInserisci 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] = '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

#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

#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

#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( "\nInserisci 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] = '{parsed_message}'; // 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] = '{parsed_message}';
        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] = '{parsed_message}';
        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( "\nVuoi 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;
}
'; // 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] = '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

#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

#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

#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( "\nInserisci 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] = '{parsed_message}'; // 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] = '{parsed_message}';
        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] = '{parsed_message}';
        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( "\nVuoi 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;
}
'; 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] = '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

#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

#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

#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( "\nInserisci 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] = '{parsed_message}'; // 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] = '{parsed_message}';
        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] = '{parsed_message}';
        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( "\nVuoi 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;
}
'; 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( "\nVuoi 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 05/01/17 17: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.
05/01/17 14:02
Goblin
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 05/01/17 14:04
Ibis redibis non morieris in bello
05/01/17 16:57
TheDarkJuster
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.
aaa
05/01/17 17:07
lumo
Una linked list non ha senso qui.
Altra cosa, per controllare i divisori basta arrivare a sqrt(n).
aaa
05/01/17 17:18
AldoBaldo
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! :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.
05/01/17 19:51
darkannet
Postato originariamente da AldoBaldo:
Dubito che sia possibile parlare di &quot;ottimizzazione&quot;, 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

#include <stdio.h>
#include <string.h>
#include &quot;interfaccia.h&quot;

// ===> 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[] = {
&quot;SCOMPOSIZIONE IN FATTORI PRIMI&quot;,
&quot;questo programma scompone in fattori primi valori interi compresi&quot;,
&quot;tra 2 e 4294967295, presentando il risultato sia in forma di&quot;,
&quot;calcolo in colonna, sia come formula riassuntiva in linea&quot;
};

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( &quot;Lo zero non e' scomponibile.\n\n&quot; );
        else printf( &quot;L'unita' non e' scomponibile.\n\n&quot; );
    }
}

2. interfaccia.h

#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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include &quot;interfaccia.h&quot;

// ===> MACRO/COSTANTI <========================================================

#define LARGHEZZA_CONSOLE 80 // specificare la larghezza della console
#define A_CAPO printf(&quot;\n&quot;)

// ===> 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( &quot;\nInserisci un numero da scomporre: &quot; );

        if( leggi_riga_da_console(&amp;riga,NULL) == 0 ) {
            if( stringa_in_numero_intero(riga,&amp;numero) == 0 ) {
                err = 0;
            } else mostra_errore_in_console( &quot;l'input non e' un numero intero&quot; );

            free( riga );  riga = NULL;
        } else mostra_errore_in_console( &quot;impossibile allocare&quot; );
    } while( err != 0 );

    svuota_console();
    printf( &quot;\n&quot; );

    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' &amp;&amp; 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] = '
Postato originariamente da AldoBaldo:
Dubito che sia possibile parlare di &quot;ottimizzazione&quot;, 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

#include <stdio.h>
#include <string.h>
#include &quot;interfaccia.h&quot;

// ===> 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[] = {
&quot;SCOMPOSIZIONE IN FATTORI PRIMI&quot;,
&quot;questo programma scompone in fattori primi valori interi compresi&quot;,
&quot;tra 2 e 4294967295, presentando il risultato sia in forma di&quot;,
&quot;calcolo in colonna, sia come formula riassuntiva in linea&quot;
};

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( &quot;Lo zero non e' scomponibile.\n\n&quot; );
        else printf( &quot;L'unita' non e' scomponibile.\n\n&quot; );
    }
}

2. interfaccia.h

#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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include &quot;interfaccia.h&quot;

// ===> MACRO/COSTANTI <========================================================

#define LARGHEZZA_CONSOLE 80 // specificare la larghezza della console
#define A_CAPO printf(&quot;\n&quot;)

// ===> 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( &quot;\nInserisci un numero da scomporre: &quot; );

        if( leggi_riga_da_console(&amp;riga,NULL) == 0 ) {
            if( stringa_in_numero_intero(riga,&amp;numero) == 0 ) {
                err = 0;
            } else mostra_errore_in_console( &quot;l'input non e' un numero intero&quot; );

            free( riga );  riga = NULL;
        } else mostra_errore_in_console( &quot;impossibile allocare&quot; );
    } while( err != 0 );

    svuota_console();
    printf( &quot;\n&quot; );

    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' &amp;&amp; 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] = '{parsed_message}'; // 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, &amp;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 &quot;invio&quot; da parte dell'utente. Quando l'utente preme &quot;invio&quot;, 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] = '{parsed_message}';
        printf( &quot;%s%s&quot;, 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] = '{parsed_message}';
        printf( &quot;%s&quot;, buff );
    }
}

/*==============================================================================
Scrive nella console la stringa msg, preceduta da una breve intestazione
d'errore. Emette un &quot;bip&quot; d'avviso sonoro. Al termine della scrittura si pone in
attesa della pressione del tasto &quot;invio&quot; da parte dell'utente. Quando l'utente
preme &quot;invio&quot;, ritorna.
==============================================================================*/

void mostra_errore_in_console( const char *msg ) {
    if( msg ) {
        printf( &quot;\a\n===> ERRORE <===\n%s\n\n&quot;, msg );
        attendi_invio_da_console();
    }
}

/*==============================================================================
Si pone in attesa della pressione del tasto &quot;invio&quot; da parte dell'utente. Quando
l'utente preme &quot;invio&quot;, svuota lo stream di input e ritorna.
==============================================================================*/

void attendi_invio_da_console( void ) {
    printf( &quot;Premi \&quot;invio\&quot; per continuare... &quot; );
    while( getchar() != '\n' );
}

/*==============================================================================
Usa system() per richiedere lo svuotamento della console.
==============================================================================*/

void svuota_console( void ) {
    system( &quot;cls&quot; );
}

/*==============================================================================
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( &quot;%12lu | %lu\n&quot;, n, fattori[i] );
        n /= fattori[i];
    }

    printf( &quot;%12lu | \n\n&quot;, 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( &quot; %lu = &quot;, n );

    for( i=tf-1, fc=fattori[i], ec=0; i>=0; --i ) {
        if( fc != fattori[i] ) {
            printf( &quot;%lu&quot;, fc );
            if( ec != 1 ) printf( &quot;^%d&quot;, ec );
            printf( &quot; * &quot; );

            fc = fattori[i];
            ec = 1;
        }
        else {
            ++ec;
        }
    }

    printf( &quot;%lu&quot;, fc );
    if( ec != 1 ) printf( &quot;^%d&quot;, ec );
    printf( &quot;\n&quot; );
}

/*==============================================================================
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( &quot;\nVuoi scomporre un altro numero? (S/N) &quot; );

        if( leggi_riga_da_console(&amp;riga,NULL) == 0 ) {
            switch( toupper(*riga) ) {
                case 'S': esito = 1; break;
                case 'N': esito = 0; break;
                default: mostra_errore_in_console( &quot;input non valido&quot; );
            }

            free( riga );  riga = NULL;
        } else mostra_errore_in_console( &quot;impossibile allocare&quot; );
    } while( esito == 0xFFFF );

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

'; // 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, &amp;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 &quot;invio&quot; da parte dell'utente. Quando l'utente preme &quot;invio&quot;, 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] = '
Postato originariamente da AldoBaldo:
Dubito che sia possibile parlare di &quot;ottimizzazione&quot;, 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

#include <stdio.h>
#include <string.h>
#include &quot;interfaccia.h&quot;

// ===> 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[] = {
&quot;SCOMPOSIZIONE IN FATTORI PRIMI&quot;,
&quot;questo programma scompone in fattori primi valori interi compresi&quot;,
&quot;tra 2 e 4294967295, presentando il risultato sia in forma di&quot;,
&quot;calcolo in colonna, sia come formula riassuntiva in linea&quot;
};

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( &quot;Lo zero non e' scomponibile.\n\n&quot; );
        else printf( &quot;L'unita' non e' scomponibile.\n\n&quot; );
    }
}

2. interfaccia.h

#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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include &quot;interfaccia.h&quot;

// ===> MACRO/COSTANTI <========================================================

#define LARGHEZZA_CONSOLE 80 // specificare la larghezza della console
#define A_CAPO printf(&quot;\n&quot;)

// ===> 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( &quot;\nInserisci un numero da scomporre: &quot; );

        if( leggi_riga_da_console(&amp;riga,NULL) == 0 ) {
            if( stringa_in_numero_intero(riga,&amp;numero) == 0 ) {
                err = 0;
            } else mostra_errore_in_console( &quot;l'input non e' un numero intero&quot; );

            free( riga );  riga = NULL;
        } else mostra_errore_in_console( &quot;impossibile allocare&quot; );
    } while( err != 0 );

    svuota_console();
    printf( &quot;\n&quot; );

    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' &amp;&amp; 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] = '{parsed_message}'; // 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, &amp;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 &quot;invio&quot; da parte dell'utente. Quando l'utente preme &quot;invio&quot;, 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] = '{parsed_message}';
        printf( &quot;%s%s&quot;, 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] = '{parsed_message}';
        printf( &quot;%s&quot;, buff );
    }
}

/*==============================================================================
Scrive nella console la stringa msg, preceduta da una breve intestazione
d'errore. Emette un &quot;bip&quot; d'avviso sonoro. Al termine della scrittura si pone in
attesa della pressione del tasto &quot;invio&quot; da parte dell'utente. Quando l'utente
preme &quot;invio&quot;, ritorna.
==============================================================================*/

void mostra_errore_in_console( const char *msg ) {
    if( msg ) {
        printf( &quot;\a\n===> ERRORE <===\n%s\n\n&quot;, msg );
        attendi_invio_da_console();
    }
}

/*==============================================================================
Si pone in attesa della pressione del tasto &quot;invio&quot; da parte dell'utente. Quando
l'utente preme &quot;invio&quot;, svuota lo stream di input e ritorna.
==============================================================================*/

void attendi_invio_da_console( void ) {
    printf( &quot;Premi \&quot;invio\&quot; per continuare... &quot; );
    while( getchar() != '\n' );
}

/*==============================================================================
Usa system() per richiedere lo svuotamento della console.
==============================================================================*/

void svuota_console( void ) {
    system( &quot;cls&quot; );
}

/*==============================================================================
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( &quot;%12lu | %lu\n&quot;, n, fattori[i] );
        n /= fattori[i];
    }

    printf( &quot;%12lu | \n\n&quot;, 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( &quot; %lu = &quot;, n );

    for( i=tf-1, fc=fattori[i], ec=0; i>=0; --i ) {
        if( fc != fattori[i] ) {
            printf( &quot;%lu&quot;, fc );
            if( ec != 1 ) printf( &quot;^%d&quot;, ec );
            printf( &quot; * &quot; );

            fc = fattori[i];
            ec = 1;
        }
        else {
            ++ec;
        }
    }

    printf( &quot;%lu&quot;, fc );
    if( ec != 1 ) printf( &quot;^%d&quot;, ec );
    printf( &quot;\n&quot; );
}

/*==============================================================================
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( &quot;\nVuoi scomporre un altro numero? (S/N) &quot; );

        if( leggi_riga_da_console(&amp;riga,NULL) == 0 ) {
            switch( toupper(*riga) ) {
                case 'S': esito = 1; break;
                case 'N': esito = 0; break;
                default: mostra_errore_in_console( &quot;input non valido&quot; );
            }

            free( riga );  riga = NULL;
        } else mostra_errore_in_console( &quot;impossibile allocare&quot; );
    } while( esito == 0xFFFF );

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

'; printf( &quot;%s%s&quot;, 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] = '
Postato originariamente da AldoBaldo:
Dubito che sia possibile parlare di &quot;ottimizzazione&quot;, 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

#include <stdio.h>
#include <string.h>
#include &quot;interfaccia.h&quot;

// ===> 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[] = {
&quot;SCOMPOSIZIONE IN FATTORI PRIMI&quot;,
&quot;questo programma scompone in fattori primi valori interi compresi&quot;,
&quot;tra 2 e 4294967295, presentando il risultato sia in forma di&quot;,
&quot;calcolo in colonna, sia come formula riassuntiva in linea&quot;
};

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( &quot;Lo zero non e' scomponibile.\n\n&quot; );
        else printf( &quot;L'unita' non e' scomponibile.\n\n&quot; );
    }
}

2. interfaccia.h

#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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include &quot;interfaccia.h&quot;

// ===> MACRO/COSTANTI <========================================================

#define LARGHEZZA_CONSOLE 80 // specificare la larghezza della console
#define A_CAPO printf(&quot;\n&quot;)

// ===> 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( &quot;\nInserisci un numero da scomporre: &quot; );

        if( leggi_riga_da_console(&amp;riga,NULL) == 0 ) {
            if( stringa_in_numero_intero(riga,&amp;numero) == 0 ) {
                err = 0;
            } else mostra_errore_in_console( &quot;l'input non e' un numero intero&quot; );

            free( riga );  riga = NULL;
        } else mostra_errore_in_console( &quot;impossibile allocare&quot; );
    } while( err != 0 );

    svuota_console();
    printf( &quot;\n&quot; );

    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' &amp;&amp; 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] = '{parsed_message}'; // 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, &amp;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 &quot;invio&quot; da parte dell'utente. Quando l'utente preme &quot;invio&quot;, 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] = '{parsed_message}';
        printf( &quot;%s%s&quot;, 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] = '{parsed_message}';
        printf( &quot;%s&quot;, buff );
    }
}

/*==============================================================================
Scrive nella console la stringa msg, preceduta da una breve intestazione
d'errore. Emette un &quot;bip&quot; d'avviso sonoro. Al termine della scrittura si pone in
attesa della pressione del tasto &quot;invio&quot; da parte dell'utente. Quando l'utente
preme &quot;invio&quot;, ritorna.
==============================================================================*/

void mostra_errore_in_console( const char *msg ) {
    if( msg ) {
        printf( &quot;\a\n===> ERRORE <===\n%s\n\n&quot;, msg );
        attendi_invio_da_console();
    }
}

/*==============================================================================
Si pone in attesa della pressione del tasto &quot;invio&quot; da parte dell'utente. Quando
l'utente preme &quot;invio&quot;, svuota lo stream di input e ritorna.
==============================================================================*/

void attendi_invio_da_console( void ) {
    printf( &quot;Premi \&quot;invio\&quot; per continuare... &quot; );
    while( getchar() != '\n' );
}

/*==============================================================================
Usa system() per richiedere lo svuotamento della console.
==============================================================================*/

void svuota_console( void ) {
    system( &quot;cls&quot; );
}

/*==============================================================================
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( &quot;%12lu | %lu\n&quot;, n, fattori[i] );
        n /= fattori[i];
    }

    printf( &quot;%12lu | \n\n&quot;, 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( &quot; %lu = &quot;, n );

    for( i=tf-1, fc=fattori[i], ec=0; i>=0; --i ) {
        if( fc != fattori[i] ) {
            printf( &quot;%lu&quot;, fc );
            if( ec != 1 ) printf( &quot;^%d&quot;, ec );
            printf( &quot; * &quot; );

            fc = fattori[i];
            ec = 1;
        }
        else {
            ++ec;
        }
    }

    printf( &quot;%lu&quot;, fc );
    if( ec != 1 ) printf( &quot;^%d&quot;, ec );
    printf( &quot;\n&quot; );
}

/*==============================================================================
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( &quot;\nVuoi scomporre un altro numero? (S/N) &quot; );

        if( leggi_riga_da_console(&amp;riga,NULL) == 0 ) {
            switch( toupper(*riga) ) {
                case 'S': esito = 1; break;
                case 'N': esito = 0; break;
                default: mostra_errore_in_console( &quot;input non valido&quot; );
            }

            free( riga );  riga = NULL;
        } else mostra_errore_in_console( &quot;impossibile allocare&quot; );
    } while( esito == 0xFFFF );

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

'; printf( &quot;%s&quot;, buff ); } } /*============================================================================== Scrive nella console la stringa msg, preceduta da una breve intestazione d'errore. Emette un &quot;bip&quot; d'avviso sonoro. Al termine della scrittura si pone in attesa della pressione del tasto &quot;invio&quot; da parte dell'utente. Quando l'utente preme &quot;invio&quot;, ritorna. ==============================================================================*/ void mostra_errore_in_console( const char *msg ) { if( msg ) { printf( &quot;\a\n===> ERRORE <===\n%s\n\n&quot;, msg ); attendi_invio_da_console(); } } /*============================================================================== Si pone in attesa della pressione del tasto &quot;invio&quot; da parte dell'utente. Quando l'utente preme &quot;invio&quot;, svuota lo stream di input e ritorna. ==============================================================================*/ void attendi_invio_da_console( void ) { printf( &quot;Premi \&quot;invio\&quot; per continuare... &quot; ); while( getchar() != '\n' ); } /*============================================================================== Usa system() per richiedere lo svuotamento della console. ==============================================================================*/ void svuota_console( void ) { system( &quot;cls&quot; ); } /*============================================================================== 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( &quot;%12lu | %lu\n&quot;, n, fattori[i] ); n /= fattori[i]; } printf( &quot;%12lu | \n\n&quot;, 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( &quot; %lu = &quot;, n ); for( i=tf-1, fc=fattori[i], ec=0; i>=0; --i ) { if( fc != fattori[i] ) { printf( &quot;%lu&quot;, fc ); if( ec != 1 ) printf( &quot;^%d&quot;, ec ); printf( &quot; * &quot; ); fc = fattori[i]; ec = 1; } else { ++ec; } } printf( &quot;%lu&quot;, fc ); if( ec != 1 ) printf( &quot;^%d&quot;, ec ); printf( &quot;\n&quot; ); } /*============================================================================== 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( &quot;\nVuoi scomporre un altro numero? (S/N) &quot; ); if( leggi_riga_da_console(&amp;riga,NULL) == 0 ) { switch( toupper(*riga) ) { case 'S': esito = 1; break; case 'N': esito = 0; break; default: mostra_errore_in_console( &quot;input non valido&quot; ); } free( riga ); riga = NULL; } else mostra_errore_in_console( &quot;impossibile allocare&quot; ); } while( esito == 0xFFFF ); return esito; }
Non è che ci abbia capito tanto, comunque dopo me lo studio un po'

aaa
05/01/17 19:54
darkannet
Comunque la mia richiesta é dovuta soprattutto ai 3 passaggi per trovare i numeri che compaiono una sola volta.
Ultima modifica effettuata da darkannet 05/01/17 20:02
aaa