Pagina 2 di 2 primaprima 1 2
Visualizzazione dei risultati da 11 a 19 su 19

Discussione: [C] parsing di formule

  1. #11
    Ok appena riesci postalo.Grazie
    Concorderai con me che il problema dei nomi poco significativi delle variabili è un neo importante del codice originale,studiandolo ho avuto difficoltà ad esempio a capire che p è la precedenza dell'operatore ed altre parti mi sono ancora oscure.Inoltre zero commenti,molto male!Per il resto sono d'accordo che sia ben progettato e carino stilisticamente.
    Il centro dell'attenzione non è sempre un buon posto in cui trovarsi

    Mai discutere con uno stupido, la gente potrebbe non capire la differenza. (O. W.)

  2. #12

    ExprEval.c

    Concordo perfettamente! Io sono del parere che un codice ben scritto (dal punto di vista formale) non abbia bisogno di commenti. Il fatto è che questo sorgente non è né autoesplicativo, e né è supportato da commenti, e allora la comprensione si complica (...m'è uscito un gioco di parole!), ma almeno è un piccolo programmino! ...ma in effetti qualche commento non sarebbe stato male!

    Nella mia revisione ho cercato di riparare scrivendone e non dovrebbe essere difficile capire il codice.

  3. #13

    ExprEval.c

    Eccolo qua:

    codice:
    Analizzatore di espressioni v0.6
    #ifndef _EXPR_EVAL_
    #define _EXPR_EVAL_
    
    
    
    //  I N C L U D E S
    #include <string.h>
    #include <math.h>
    #include <setjmp.h>
    //  - - - - - - - -
    
    
    
    //  C O S T A N T I    M A N I F E S T E   E   V A R I A B I L I   G L O B A L I
    #define SYNTAXERROR  -1
    #define INVALP       10		// "Parametro non valido"
    typedef struct  {
    	char *funct;
    	short int flag;
    } errorType;
    static errorType err;
    
    
    
    //  P R O T O T I P I
    static double eval_expr(char *str, int p);
    static void error(char *funct, short int type);
    static jmp_buf jmp;
    
    
    
    //  C O S T A N T I   M A T E M A T I C H E
       struct c {
    	char *ident;
    	double valore;
       };
    
       struct c costanti[] = {
    	{"PI", M_PI},
    	{"E", M_E},
    	{NULL, 0}
       };
    //  - - - - - - - -   - - - - - - - - - - -
    
    
    
    //  F U N Z I O N I - O P E R A T O R I
       double addizione(double a, double b)  {
    	return (a+b);
       }
    
       double sottrazione(double a, double b)  {
    	return (a-b);
       }
    
       double divisione(double a, double b)  {
    	return (a/b);
       }
    
       double moltiplicazione(double a, double b)  {
    	return (a*b);
       }
    
       // Definizione del template della struttura di gestione degli operatori
       struct op {
    	char  segno;
    	unsigned short  precedenza;
    	double  (*calcola)(double, double);
       };
    
       // Dichiarazione e inizializzazione della struttura di gestione degli operatori
       struct op operatori[] = {
    	{'+', 1, addizione},
    	{'-', 1, sottrazione},
    	{'/', 2, divisione},
    	{'*', 2, moltiplicazione},
    	{'%', 2, fmod},
    	{'^', 3, pow},
    	{0, 0, 0}
       };
    //  - - - - - - - - - - - - - - - - - -
    
    
    
    //  F U N Z I O N I   A N A L I T I C H E   T R A S C E N D E N T I
    
    
    //  DEFINIZIONE DEL TEMPLATE DI STRUTTURA PER
    //  LA GESTIONE DELLE FUNZIONI AD UN ARGOMENTO
       struct f  {
    	char  *ident;
    	double  (*esegui)(double);
       };
    //  ------------------------------------------
    
    
    
    //  F U N Z I O N I   G O N I O M E T R I C H E   I N   R A D I A N T I
       double acosh(register double x)  {
    	return(log(x+sqrt(x*x-1.0)));
       }
    
       double asinh(register double x)  {
    	return(log(x+sqrt(x*x+1.0)));
       }
    
       double atanh(register double x)  {
    	return(0.5*log((1.0+x)/(1.0-x)));
       }
    
       double sec(double n)  {
    	return (1/cos(n));
       }
    
       double cosec(double n)  {
    	return (1/sin(n));
       }
    
       double cot(double n)  {
    	return (cos(n)/sin(n));
       }
    
       double acot(double n)  {
    	return (atan(1/n));
       }
    
       double asec(double n)  {
    	return (acos(1/n));
       }
    
       double acosec(double n)  {
    	return (asin(1/n));
       }
    
       double coth(double n)  {
    	return (1/tanh(n));
       }
    
       double sech(double n)  {
    	return (1/cosh(n));
       }
    
       double cosech(double n)  {
    	return (1/sinh(n));
       }
    
       double acoth(double n)  {
    	return (0.5*log((n+1)/(n-1)));
       }
    
       double asech(double n)  {
    	return (log(1/n+sqrt(1/(n*n)+1)));
       }
    
       double acosech(double n)  {
    	return (log(1/n+sqrt(1/(n*n)-1)));
       }
    
       // Dichiarazione e inizializzazione della struttura per la
       // gestione delle funzioni goniometriche che accettano come
       // argomento l'ampiezza di un angolo espressa in radianti
       struct f funzioniTrigR[] = {
    	{"asinh", asinh},
    	{"acosh", acosh},
    	{"atanh", atanh},
    	{"asech", sec},
    	{"acoth", cot},
    	{"acosech", cosec},
    
    	{"asin", asin},
    	{"acos", acos},
    	{"atan", atan},
    	{"asec", asec},
    	{"acot", acot},
    	{"acosec", acosec},
    
    	{"sinh", sinh},
    	{"cosh", cosh},
    	{"tanh", tanh},
    	{"sech", sec},
    	{"coth", cot},
    	{"cosech", cosec},
    
    	{"sin", sin},
    	{"cos", cos},
    	{"tan", tan},
    	{"sec", sec},
    	{"cot", cot},
    	{"cosec", cosec},
    	{NULL, 0}
       };
    //  - - - - - - - -   - - - - - - - - - - - - -   - -   - - - - - - - -
    
    
    
    //  A L T R E   F U N Z I O N I   (accettano un argomento)
       double fact(register double n)  {
    	register double i;
    	if (n < 0)
    		error("fact", DOMAIN);
    	if (fmod(n, 1.0))
    		error("fact", INVALP);
    	for(i=n, n=1.0; i>1; i--)
    		n *= i;
    	return(n);
       }
    
       double fibo(register double n)  {
    	register double F[3] = {1.0, 1.0, 0.0};
    	register long long i;
    	if (n < 0)
    		error("fibo", DOMAIN);
    	if (fmod(n, 1.0))
    		error("fibo", INVALP);
    	if (n <= 2)
    		return(1);
    	for (i=2; i<(long long)n; i++)
    		F[i%3] = F[(i+4)%3] + F[(i+5)%3];
    	return(F[(i-1)%3]);
       }
    
       double cbrt(double n)  {
    	return (pow(n, 1.0/3.0));
       }
    
       double degr2rad(double n)  {
    	return(n * 0.0174532925199432957692);
       }
    
       struct f altreFunzioni1[] = {
    	{"sqrt", sqrt},
    	{"cbrt", cbrt},
    	{"ln", log},
    	{"log", log10},
    	{"exp", exp},
    	{"fibo", fibo},
    	{"fact", fact},
    	{"d2r", degr2rad},
    	{NULL, 0}
       };
    //  - - - - -   - - - - - - - -
    
    
    
    //  A L T R E   F U N Z I O N I   (accettano due parametri)
       double logbN(register double b, register double N)  {
    	return(log10(N)/log10(b));
       }
    
       double rootnX(register double n, register double X)  {
    	return(pow(X, 1/n));
       }
    
       // Definizione del template della struttura per la gestione
       // delle funzioni che accettano due argomenti
       struct f_2  {
    	char  *ident;
    	double  (*esegui)(double, double);
       };
    
       // Dichiarazione e inizializzazione della struttura di gestione
       // delle funzioni che accettano due argomenti
       struct f_2 altreFunzioni2[] = {
    	{"root", rootnX},
    	{"log", logbN},
    	{"pow", pow},
    	{NULL, 0}
       };
    //  - - - - -   - - - - - - - -
    
    
    
    
    //  D E F I N I Z I O N E   F U N Z I O N I
    
    // Legge da expr un blocco di espressioni racchiuso tra parentesi
    // (che costituisce l'argomento di una funzione)
    // e lo copia in blocco. Esempio:
    //    espressione = "fact(12*45+5)-41)"
    //    expr = "12*45+5)-41";
    //    blocco = "12*45+5"
    static int scanBlocco(char *expr, char *blocco)  {
    	int par = 0, count = 0;
    	for ( ; *expr; blocco++, expr++, count++)  {
    		*blocco = '\0';
    		if (*expr == '(')	par++;
    		if (*expr == ')')	par--;
    		if(par == -1)
    			return(count);
    		*blocco = *expr;
    	}
    	*blocco = '\0';
    	return((par==0) ? count : 0);
    }
    
    
    // Legge da expr un blocco racchiuso tra parentesi formato dai due
    // argomenti di una funzione separati da una virgola.
    // Copia i due argomenti in blocco1 e blocco2. Esempio:
    //    espressione = "log(10, 25)*fact(5)"
    //    expr = "10, 25)*fact(5)";
    //    blocco = "10, 25"
    //    blocco1 = "10"
    //    blocco2 = "25"
    // Ritorna il numero di caratteri che compongono la stringa "arg1,arg2"
    static int scanArgs(char *expr, char *blocco1, char *blocco2)  {
    	int count, par=0;
    	char *ptrVirgola;
    	register int i;
    
    	count = scanBlocco(expr, blocco1);		// prendo tutto il blocco "param1,param2"
    
    	for (ptrVirgola=blocco1; *ptrVirgola; ptrVirgola++)  {
    		if (*ptrVirgola == '(')
    			par++;
    		if (*ptrVirgola == ')')
    			par--;
    		if (par != 0)
    			continue;
    
    		if (*ptrVirgola == ',')  {
    			break;
    		}
    	}
    
    	if(*ptrVirgola != ',')		// Se di mezzo non c'Š una virgola
    		return(0);		// Š una funzione ad 1 argomento
    
    
    
    	*ptrVirgola = '\0';		// delimito blocco1
    
    	strcpy(blocco2, ptrVirgola+1);
    
    	return(count);
    }
    
    
    static int isOperat(char s)  {
    	register int i;
    	for (i=0; operatori[i].segno; i++)
    		if (operatori[i].segno == s)
    			return(i);
    	return(-1);
    }
    
    
    static int isFunctGR(char *s)  {
    	register int i;
    	for (i=0; funzioniTrigR[i].ident; i++)  {
    		if (strncmp(funzioniTrigR[i].ident, s, strlen(funzioniTrigR[i].ident)) == 0)
    			return(i);
    	}
    	return(-1);
    }
    
    
    static int isFunct1(char *s)  {
    	register int i;
    	for (i=0; altreFunzioni1[i].ident; i++)  {
    		if (strncmp(altreFunzioni1[i].ident, s, strlen(altreFunzioni1[i].ident)) == 0)
    			return(i);
    	}
    	return(-1);
    }
    
    
    static int isFunct2(char *s)  {
    	register int i;
    	for (i=0; altreFunzioni2[i].ident; i++)  {
    		if (strncmp(altreFunzioni2[i].ident, s, strlen(altreFunzioni2[i].ident)) == 0)
    			return(i);
    	}
    	return(-1);
    }
    
    
    static void risolviFunzioni(char *s)  {
    	int i;
    	char save[81];
    	int len;
    
    	for (; *s; s++)  {
    		if ((i = isFunct2(s)) >= 0)  {
    			char blocco1[162];
    			char blocco2[81];
    			double a, b;
    			len = scanArgs(s+strlen(altreFunzioni2[i].ident)+1, blocco1, blocco2);
    			if (len)  {
    				a = eval_expr(blocco1, 0);
    				b = eval_expr(blocco2, 0);
    				strcpy(save, s + strlen(altreFunzioni2[i].ident) + len + 2);
    				sprintf(s, "%lf", altreFunzioni2[i].esegui(a, b));
    				s += strlen(s);
    				strcpy(s, save);
    				continue;
    			}
    		}
    		if ((i = isFunct1(s)) >= 0)  {
    			char blocco[81];
    			len = scanBlocco(s+strlen(altreFunzioni1[i].ident)+1, blocco);
    			strcpy(save, s + strlen(altreFunzioni1[i].ident) + len + 2);
    			sprintf(s, "%lf", altreFunzioni1[i].esegui(eval_expr(blocco, 0)));
    			s += strlen(s);
    			strcpy(s, save);
    			continue;
    		}
    		if ((i = isFunctGR(s)) >= 0)  {
    			char blocco[81];
    			len = scanBlocco(s+strlen(funzioniTrigR[i].ident)+1, blocco);
    			strcpy(save, s + strlen(funzioniTrigR[i].ident) + len + 2);
    			sprintf(s, "%lf", funzioniTrigR[i].esegui(eval_expr(blocco, 0)));
    			s += strlen(s);
    			strcpy(s, save);
    		}
    	}
    }
    
    
    #define NOP	-2
    #define NOPREC	-1
    static int  find_last_op(char *expr, int p)  {
    	register int pos;
    	int i;
    	int par = 0;
    	int ret = NOP;
    
    	for (pos=strlen(expr)-1; pos>=0; pos--)  {
    		if (expr[pos] == ')')
    			par++;
    		if (expr[pos] == '(')
    			par--;
    		if (par != 0)
    			continue;
    
    		i = isOperat(expr[pos]);
    		if (i >= 0)  {
    			if (operatori[i].precedenza == p)
    				return (pos);
    			ret = NOPREC;
    		}
    	}
    	return (ret);
    }
    
    
    static double is_nb(char *str)  {
    	// Motivo 1: elimina le parentesi e analizza l'espressione
    	if (*str=='(')  {
    		str[strlen(str)-1] = 0;
    		return (eval_expr(str+1, 1));
    	}
    	// Motivo 2: converte la stringa in valore double e la ritorna
    	return (atof(str));
    }
    
    
    static double eval_expr(char *expr, int p)  {
    	register int i;
    	int  pos;
    	char save;
    
    	// per prima cosa mi risolvo le funzioni e sostituisco ad esse
    	// nella stringa il corrispondente valore numerico
    	risolviFunzioni(expr);
    
    	// Vanno eseguite le operazioni a partire da quelle con precedenza
    	// maggiore. Questo problema comunque è a carico del processo di
    	// ricorsione: comincio a scandagliare quelle a precedenza minore
    	// e che non siano all'interno di blocchi di parentesi.
    
    	// Questa ricerca l'addebito alla find_last_op().
    
    	// Cerco quindi l'operazione con priorità == p.
    	switch (pos = find_last_op(expr, p))  {
    		case NOPREC:
    			// non ci sono operatori a precedenza p:
    			// aumento la precedenza e rieseguo la ricerca
    			return (eval_expr(expr, p+1));
    		case NOP:
    			// non ci sono più operazioni pronte da eseguire.
    			// Motivo numero 1 - Abbiamo ridotto l'espressione
    			// ad un blocco di parentesi: "(...)"
    			// Motivo numero 2 - Siamo arrivati al punto in cui
    			// expr è un semplice numero
    			// In ambedue i casi risolve la is_nb().
    			return (is_nb(expr));
    	}
    
    	// la find_last_op() ha trovato l'operatore a precedenza richiesta
    	// e ne ha restituito l'indice
    	save = expr[pos];
    	expr[pos] = 0;		// sullo stesso operatore divido l'espressione in due parti...
    
    	i = isOperat(save);	// ... e, individuato l'operatore,...
    	// ...eseguo il calcolo
    	return (operatori[i].calcola(eval_expr(expr, p), eval_expr(expr+pos+1, p+1)));
    }
    
    
    
    static void sostituisciCostanti(register char *s)  {
    	char save[300];
    	register int i;
    	while(*s)  {
    		if (*s == '#')  {
    			for (i=0; costanti[i].ident; i++)  {
    				if (strncmp(s+1, costanti[i].ident, strlen(costanti[i].ident))==0)  {
    					strcpy(save, s + strlen(costanti[i].ident) + 1);
    					sprintf(s, "%lf", costanti[i].valore);
    					s += strlen(s);
    					strcpy(s, save);
    					break;
    				}
    			}
    			if (costanti[i].ident == NULL)
    				s++;
    			continue;
    		}
    		s++;
    	}
    }
    
    
    static void strnospc(register char *s)  {
    	register char *tmp;
    	while(*s)  {
    		if ((*s == ' ') || (*s == '\t'))
    			for(tmp=s; *tmp; tmp++)
    				*tmp = *(tmp+1);
    		else 	s++;
    	}
    }
    
    
    static int checkPar(register char *s)  {
    	int par = 0;
    	while(*s)  {
    		if (*s == '(')	par++;
    		if (*s == ')')	par--;
    		if (par < 0)	return(-1);
    		s++;
    	}
    	return(par);
    }
    
    
    static int analizzaSintassi(char *s)  {
    
    	if (*s == '\0')
    		return(-1);
    
    	// faccio un controllo superficiale sulle parentesi
    	if (checkPar(s))
    		return(-1);
    
    	// Faccio dei controlli (il minimo...)
    
    	// ...
    	// Sarebbe necessario fare un po' di analisi sintattica...
    	// ...
    
    	return(0);
    }
    
    
    static void error(char *funct, short int type)   {
    	err.funct = funct;
    	err.flag = type;
    	longjmp(jmp, 1);
    }
    
    
    errorType * EvaluateExpression(char *expr, double *result)  {
    	err.flag = 0;
    	err.funct = 0;
    	strnospc(expr);		// elimino gli spazi per evitare problemi
    	if (analizzaSintassi(expr))  {
    		err.flag = SYNTAXERROR;
    		return (&err);
    	}
    	if (setjmp(jmp) == 0)  {
    		sostituisciCostanti(expr);
    		*result = eval_expr(expr, 1);
    	}
    	return(&err);
    }
    
    #endif

  4. #14

    main.c

    Il programmino non è completo, ma intanto fatti un'idea.
    Manca un analizzatore di sintassi ma andrebbe anche migliorata la gestione degli errori, e queste sono due pecche che vanno aggiustate.

    Un'altra cosa: avevo pensato di utilizzare le funzioni di libreria che fornisce la Borland (sotto forma di sorgenti c-asm) col compilatore per basare il tutto sui long double, così anche se non sono portabili si hanno a disposizione i sorgenti.
    Tra l'altro così facendo si può implementare una gestione degli errori tutta personalizzata per il programma: non mi piace che se faccio log(-10) mi vedo scritto a video "DOMAIN error", me lo devo gestire IO!!



    Ed ecco il main:

    codice:
    /******************************************\
    |*  Analizzatore di Formule matematiche   *|
    |*   e funzioni analitiche trascendenti   *|
    |*                                        *|
    |*                     by SnakePlissken   *|
    |*                     aka AntonioMacrì   *|
    \******************************************/
    
    
    #include <stdio.h>
    #include <conio.h>
    #include <math.h>
    #include <dos.h>
    
    #include "ExprEval.c"
    
    
    void visualizzaOperazioni(void);
    void calcolaFormule(void);
    
    
    int main()  {
    	char scelta;
    	while(1)  {
    		clrscr();
    		printf("\n%80s\n", "Analizzatore di formule matematiche - SnakePlissken  ");
    
    		printf("\n  Menu principale\n\n");
    		printf("   1. Visualizza operazioni disponibili\n");
    		printf("   2. Calcola formule\n");
    		printf("   3. Esci\n");
    
    		do
    			scelta = getch();
    		while(scelta!='1' && scelta!='2' && scelta!='3');
    
    		switch(scelta)  {
    			case '1':
    				visualizzaOperazioni();
    				break;
    			case '2':
    				calcolaFormule();
    				break;
    			case '3':
    				return(0);
    		}
    	}
    }
    
    
    void visualizzaOperazioni(void)  {
    	clrscr();
    
    	printf( "\n\n1. Operatori binari:\n\n"
    		"  +      Esegue la somma\n"
    		"  -      Esegue la sottrazione\n"
    		"  /      Esegue la divisione\n"
    		"  *      Esegue la moltiplicazione\n"
    		"  ^      Eleva alla potenza\n"
    		"  %      Calcola il modulo (il resto della divisione)\n");
    	printf("\nPremi un tasto per visualizzare le funzioni aggiuntive...\n");
    	getch();
    
    	printf("\n\n2. Funzioni aggiuntive:\n\n"
    		" Funzioni logaritmiche:\n"
    		"    ln(N)           Calcola il logaritmo naturale (in base e) di N\n"
    		"    log(N)          Calcola il logaritmo decimale di N\n"
    		"    log(b,N)        Calcola il logaritmo in base b di N\n\n");
    	printf(" Funzioni Trigonometriche:\n"
    		"    sin(a)          Calcola il seno dell'angolo a misurato in radianti\n"
    		"    cos()           Coseno\n"
    		"    tan()           Tangente\n"
    		"    sec()           Secante\n"
    		"    cot()           Cotangente\n"
    		"    cosec()         Cosecante\n"
    		"    Varianti:\n"
    		"      a-            Calcola l'arco- {-seno, -coseno, -tangente, ...}\n"
    		"      -h            Calcola il {seno-, coseno-, tangente-, ...} iperbolico\n"
    		"    Esempio:\n"
    		"      acosh(.5)    Calcola l'arcocoseno iperbolico di un angolo di 0.5 radianti\n");
    	printf("\nPremi un tasto per visualizzare le altre funzioni...\n");
    	getch();
    	printf("\n\n Altre funzioni:\n"
    		"    exp(N)          Funzione esponenziale (calcola e^N)\n"
    		"    d2r()           Converte i gradi in radianti\n"
    		"    sqrt()          Calcola la radice quadrata\n"
    		"    cbrt()          Calcola la radice cubica\n"
    		"    root(n,x)       Calcola la radice n-esima di x\n"
    		"    fact()          Calcola il fattoriale\n"
    		"    fibo()          Calcola il numero di Fibonacci\n");
    
    	printf("\nPremi un tasto per visualizzare le costanti disponibili...\n");
    	getch();
    
    	printf("\n\n3. Costanti:\n\n"
    		"    PI              Valore del Pi greco ã\n"
    		"    E               Valore di e\n");
    
    	printf("\n\n\nNB: I parametri da passare alle funzioni vanno sempre messi tra parentesi.");
    	printf("\n    Nell'uso di costanti, il loro nome deve essere preceduto da un '#'.");
    	getch();
    }
    
    
    #define START 1
    #define ELAPSEDTIME 2
    double timeCounter(int todo)  {
    	static struct time t1;
    	if (todo == START)  {
    		gettime(&t1);
    	}
    	else  {
    		struct time t2;
    		double dt1, dt2;
    		gettime(&t2);
    		dt1 = t1.ti_hour*360000 + t1.ti_min*6000 + t1.ti_sec*100 + t1.ti_hund;
    		dt2 = t2.ti_hour*360000 + t2.ti_min*6000 + t2.ti_sec*100 + t2.ti_hund;
    		return((dt2-dt1)/100);
    	}
    	return(0);
    }
    
    
    void calcolaFormule(void)  {
    	char expr[150];
    	double result, time;
    	errorType *err;
    
    	clrscr();
    	printf("\n\nInserisci una formula:\n");
    	while(gets(expr)[0])  {
    		printf(" Sto calcolando... ");
    		timeCounter(START);
    		err = EvaluateExpression(expr, &result);
    		time = timeCounter(ELAPSEDTIME);
    		gotoxy(1, wherey());
    		clreol();
    		switch (err->flag)  {
    			case 0:
    				printf(" Risultato:  %lG\n", result);
    				if(time > 3.0L)
    					printf(" Tempo impiegato: %lG sec\n", time);
    				break;
    			case INVALP:
    				printf(" Errore:\n  %s:   Parametro non valido!\n", err->funct);
    				break;
    			case DOMAIN:
    				printf(" Errore:\n  %s:   Valore fuori dal dominio della funzione!\n", err->funct);
    				break;
    			case SYNTAXERROR:
    				printf(" Errore di Sintassi!\n");
    		}
    		printf("\n\nInserisci un'altra formula:\n");
    	}
    }



  5. #15

    Copyright?!

    Qualcuno mi spiega un fatto?

    Com'è che il Borland mette a disposizione alcuni sorgenti e poi c'è scritto "Copyright (c)" e "All Rights Reserved." ??

    Posso riutilizzare il codice o è soggetto a copyright e quindi no?

    Datemi delle delucidazioni!


    grazie!

  6. #16
    EDIT: la atof() non è standard!! VVoVe:

    va sostituita con:
    codice:
    strtod(str, NULL);
    Questa è ansi: sicuro al 100%!


    qualcuno mi risponde sulla licenza del borland?

    grazie

  7. #17
    Ok grazie,appena ho un po di time me lo studio e se ho qualche suggerimento te lo dico.Comunque il solo fatto di esserti messo ad estenderlo e lodevole.Per il problema del copyright non ho risposta.
    Ho invece un piccolo appunto da fare ai moderatori: possibile che non sia previsto un modo per scambiare sorgenti in un forum del genere?Non vedo il motivo di non accettare allegati di tipo .c o cpp o anche solo txt (che poi è uguale),che male possono fare più delle immagini (che sono invece consentite)?
    Il centro dell'attenzione non è sempre un buon posto in cui trovarsi

    Mai discutere con uno stupido, la gente potrebbe non capire la differenza. (O. W.)

  8. #18
    buona lettura!



    [OT]
    AI MODERATORI: vi porgo anch'io (di nuovo) l'osservazione di unomichisiada. Sarebbe un servizio molto utile per la sezione programmazione. Perché non ci fate un pensierino? o qualcosa di più?
    [/OT]

  9. #19
    La stupidità umana e l'universo sono infinite.
    Della seconda non sono certo(Einstein)

    Gnu/Linux User

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.