Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Tastiera gaming MSI GK600 TKL: switch hot-swap, display LCD e tre modalità wireless
Tastiera gaming MSI GK600 TKL: switch hot-swap, display LCD e tre modalità wireless
MSI FORGE GK600 TKL WIRELESS: switch lineari hot-swap, tripla connettività, display LCD e 5 strati di fonoassorbimento. Ottima in gaming, a 79,99 euro
DJI Osmo Pocket 4: la gimbal camera tascabile cresce e ha nuovi controlli fisici
DJI Osmo Pocket 4: la gimbal camera tascabile cresce e ha nuovi controlli fisici
DJI porta un importante aggiornamento alla sua linea di gimbal camera tascabili con Osmo Pocket 4: sensore CMOS da 1 pollice rinnovato, gamma dinamica a 14 stop, profilo colore D-Log a 10 bit, slow motion a 4K/240fps e 107 GB di archiviazione integrata. Un prodotto pensato per i creator avanzati, ma che convince anche per l'uso quotidiano
Sony INZONE H6 Air: il primo headset open-back di Sony per giocatori
Sony INZONE H6 Air: il primo headset open-back di Sony per giocatori
Il primo headset open-back della linea INZONE arriva a 200 euro con driver derivati dalle cuffie da studio MDR-MV1 e un peso record di soli 199 grammi
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 26-01-2012, 09:23   #1
vendettaaaaa
Senior Member
 
L'Avatar di vendettaaaaa
 
Iscritto dal: Jan 2012
Messaggi: 1267
[C++] Perchè evitare "goto" a tutti i costi?

Perchè leggo dappertutto che il goto va sempre evitato?
L'unica ragione plausibile è: dato che goto punta ad una parola che non è una variabile, quando il codice diventa lungo si potrebbe per sbaglio chiamare una variabile come l'etichetta del goto. Ad esempio:
Codice:
play:
    [codice del gioco]
    cout << "Play again?"; cin >> again;
    if (again == 'y') goto play;
    [...tante linee di codice...]
    int play;
E' per questo? Altri motivi non me ne vengono.
In realtà, mi rendo conto che saltare fuori da un ciclo può essere pericoloso, ma quando non si è in un ciclo goto mi pare più efficiente (dal punto di vista della quantità di linee di codice richieste) di altri conditional statement. In particolare quando controllo l'input dell'utente: lo si può fare in 3 modi:
Codice:
cin >> n;
while (condizione su n) cin >> n;
Codice:
do {
    cin >> n;
    } while (condizione su n);
Codice:
input:
    cin >> n;
    if (condizione su n) goto input
Trovo la 3° opzione molto comoda in certi casi, ma mi sono sempre costretto ad usare la 1° per evitare appunto un "bad habit" però raddoppiando il numero di righe dedicate a cout e cin...

Quindi che ha che non va il goto? Siate convincenti
vendettaaaaa è offline   Rispondi citando il messaggio o parte di esso
Old 26-01-2012, 09:32   #2
banryu79
Senior Member
 
L'Avatar di banryu79
 
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
Davvero usi i goto? Pussa via!
Scherzi a parte, eccoti una vecchia discussione in cui se ne parlò.

Se al termine di quella lettura non ne hai abbastanza, il web è pieno.
Un rant contro il GOTO che fa parte della "letteratura" è quello famosissimo di Dijkstra (cerca qualcosa tipo "goto considererd harmful", o roba del genere)
__________________

As long as you are basically literate in programming, you should be able to express any logical relationship you understand.
If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it.
(Chris Crawford)
banryu79 è offline   Rispondi citando il messaggio o parte di esso
Old 26-01-2012, 09:50   #3
!fazz
Moderatore
 
L'Avatar di !fazz
 
Iscritto dal: Nov 2006
Messaggi: 22068
perchè fortunatamente il c++ include tutta una serie di istruzioni, che rendono l'uso del goto non necessario semplificando di molto la chiarezza del codice e il debug

personalmente trovo il goto assolutamente inutile e "pericoloso"con tutti i linguaggi di alto livello
__________________
"WS" (p280,cx750m,4790k+212evo,z97pro,4x8GB ddr3 1600c11,GTX760-DC2OC,MZ-7TE500, WD20EFRX)
Desktop (three hundred,650gq,3800x+nh-u14s ,x570 arous elite,2x16GB ddr4 3200c16, rx5600xt pulse P5 1TB)+NB: Lenovo p53 i7-9750H,64GB DDR4,2x1TB SSD, T1000
!fazz è offline   Rispondi citando il messaggio o parte di esso
Old 26-01-2012, 10:52   #4
vendettaaaaa
Senior Member
 
L'Avatar di vendettaaaaa
 
Iscritto dal: Jan 2012
Messaggi: 1267
Ho dato un'occhio al vecchio topic sul goto che però è da subito stato oggetto di discussioni "di alto livello", fuori dalla mia completa comprensione (ad esempio non ho ancora studiato le eccezioni).
L'idea che mi sono fatto è...la stessa che avevo prima: eviterò di inserire goto in cicli eccetera, ma nel mio giochino memory lo tengo implementato per giocare ancora: label e goto sono all'esterno di tutto il codice, non c'è alcun rischio di saltare fuori da cicli che incasinano il valore di iteratori o altro, e mi risparmio di indentare quello che è il corpo principale del programma il che, oltre ad essere più leggibile, lo trovo anche più logico.
Torvalds sarà un cazzaro, oppure no, non so, però quello che ha scritto mi pare ragionevole: "gotos are fine in the case that the code is not naturally indented".
Cercherò di limitarmi, ragionandoci bene ogni volta, piuttosto che mettere automaticamente un while o altro.
Perlomeno fino a quando non cambierò idea
vendettaaaaa è offline   Rispondi citando il messaggio o parte di esso
Old 26-01-2012, 11:05   #5
banryu79
Senior Member
 
L'Avatar di banryu79
 
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
Quote:
Originariamente inviato da vendettaaaaa Guarda i messaggi
Cercherò di limitarmi, ragionandoci bene ogni volta, piuttosto che mettere automaticamente un while o altro.
Perlomeno fino a quando non cambierò idea
Ecco bravo, la cosa migliore è fare esperienza diretta, riesaminarla e formarsi una propria circostanziata opinione.
Comunque GOTO IS EVIL
__________________

As long as you are basically literate in programming, you should be able to express any logical relationship you understand.
If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it.
(Chris Crawford)
banryu79 è offline   Rispondi citando il messaggio o parte di esso
Old 26-01-2012, 11:07   #6
vendettaaaaa
Senior Member
 
L'Avatar di vendettaaaaa
 
Iscritto dal: Jan 2012
Messaggi: 1267
Quote:
Originariamente inviato da banryu79 Guarda i messaggi
Ecco bravo, la cosa migliore è fare esperienza diretta, riesaminarla e formarsi una propria circostanziata opinione.
Comunque GOTO IS EVIL
Esatto, devo sbatterci la testa per capire cosa non va nel goto (sempre che ci sia qualcosa ).
vendettaaaaa è offline   Rispondi citando il messaggio o parte di esso
Old 26-01-2012, 11:14   #7
WarDuck
Senior Member
 
L'Avatar di WarDuck
 
Iscritto dal: May 2001
Messaggi: 12966
L'unica ragione per cui sarebbe utile, e forse anche consigliato usare goto, è in linguaggi come C, in cui magari ti trovi di fronte a gestire una situazione di errore e devi fare un cleanup di alcune aree di memoria in diversi punti del codice dove può accadere l'errore.

In questo caso può essere utile usare goto, per non replicare il codice che gestisce l'errore (e quindi rischiare di introdurne altri), ed evitare di introdurre gli overhead dovuti ad una eventuale chiamata a funzione (anche se con le funzioni inline l'overhead viene annullato, ma comunque dovresti creare una funzione di cleanup per ciascuna funzione che fa allocazioni e quant'altro, diventerebbe complicato).

In C++ con la gestione delle eccezioni non dovrebbe essere necessario.

In tutti gli altri casi non c'è alcuna ragione per cui usare goto, che ti fa perdere il flusso logico del codice.

A livello puramente teorico, l'ideale sarebbe avere un codice senza alcun salto.

Ultima modifica di WarDuck : 26-01-2012 alle 11:22.
WarDuck è offline   Rispondi citando il messaggio o parte di esso
Old 26-01-2012, 11:15   #8
!fazz
Moderatore
 
L'Avatar di !fazz
 
Iscritto dal: Nov 2006
Messaggi: 22068
Quote:
Originariamente inviato da vendettaaaaa Guarda i messaggi
Ho dato un'occhio al vecchio topic sul goto che però è da subito stato oggetto di discussioni "di alto livello", fuori dalla mia completa comprensione (ad esempio non ho ancora studiato le eccezioni).
L'idea che mi sono fatto è...la stessa che avevo prima: eviterò di inserire goto in cicli eccetera, ma nel mio giochino memory lo tengo implementato per giocare ancora: label e goto sono all'esterno di tutto il codice, non c'è alcun rischio di saltare fuori da cicli che incasinano il valore di iteratori o altro, e mi risparmio di indentare quello che è il corpo principale del programma il che, oltre ad essere più leggibile, lo trovo anche più logico.
Torvalds sarà un cazzaro, oppure no, non so, però quello che ha scritto mi pare ragionevole: "gotos are fine in the case that the code is not naturally indented".
Cercherò di limitarmi, ragionandoci bene ogni volta, piuttosto che mettere automaticamente un while o altro.
Perlomeno fino a quando non cambierò idea
prendilo come esercizio

modifica il tuo memory in maniera da non usare goto e vedrai che il codice sarà sicuramente più comprensibile e di migliore qualità

giusto per capire, dove lo trovi così indispensabile il goto nel tuo programma?

trovo towalds un "pazzo visionario" sicuramente un genio ma di solito quello che funziona per un genio (o comunque una persona parecchio skillata) non sempre è sinonimo di buone regole anche per chi inizia.

es. io uso tantissimo il ? per avere un codice più compatto ma non lo consiglio minimamente ad un principiante.
__________________
"WS" (p280,cx750m,4790k+212evo,z97pro,4x8GB ddr3 1600c11,GTX760-DC2OC,MZ-7TE500, WD20EFRX)
Desktop (three hundred,650gq,3800x+nh-u14s ,x570 arous elite,2x16GB ddr4 3200c16, rx5600xt pulse P5 1TB)+NB: Lenovo p53 i7-9750H,64GB DDR4,2x1TB SSD, T1000

Ultima modifica di !fazz : 26-01-2012 alle 11:18.
!fazz è offline   Rispondi citando il messaggio o parte di esso
Old 26-01-2012, 11:19   #9
nico159
Senior Member
 
Iscritto dal: Aug 2003
Città: Barletta (BA)
Messaggi: 939
Come dannoso?

Ma se l'hanno aggiunto in PHP 5.3 per modernizzare il linguaggio
http://php.net/manual/en/control-structures.goto.php
__________________
In a world without fences, who needs Gates?
Power by: Fedora 8 - Mac OS X 10.4.11

Ultima modifica di nico159 : 26-01-2012 alle 11:22.
nico159 è offline   Rispondi citando il messaggio o parte di esso
Old 26-01-2012, 11:26   #10
Tommo
Senior Member
 
L'Avatar di Tommo
 
Iscritto dal: Feb 2006
Messaggi: 1304
Quote:
Originariamente inviato da !fazz Guarda i messaggi
es. io uso tantissimo il ? per avere un codice più compatto ma non lo consiglio minimamente ad un principiante.
Un'altro estimatore di ?

goto non lo uso perchè non serve se si programma OOP... uso la necessità del goto proprio come un campanello d'allarme: ogni funzione dovrebbe svolgere un preciso compito, ma se serve un goto la mia funzione ne sta svolgendo più di uno.
Basta spostare ogni "feature" nella sua funzione e magicamente il goto non serve più
Si, questo spawna un bel pò di funzioni da 4 o 5 righe, ma trovo che sia meglio da tutti i punti di vista.
__________________
*ToMmO*

devlog | twitter

Ultima modifica di Tommo : 26-01-2012 alle 11:32.
Tommo è offline   Rispondi citando il messaggio o parte di esso
Old 26-01-2012, 11:29   #11
cdimauro
Senior Member
 
L'Avatar di cdimauro
 
Iscritto dal: Jan 2002
Città: Germania
Messaggi: 26110
Quote:
Originariamente inviato da vendettaaaaa Guarda i messaggi
Torvalds sarà un cazzaro, oppure no, non so, però quello che ha scritto mi pare ragionevole: "gotos are fine in the case that the code is not naturally indented".
Con questo hai appena trasformato il "sarà" in "è".

Comunque il goto è talmente bello come costrutto sintattico, che ci sono linguaggi che nemmeno lo prevedono.
Quote:
Originariamente inviato da nico159 Guarda i messaggi
Come dannoso?

Ma se l'hanno aggiunto in PHP 5.3 per modernizzare il linguaggio
http://php.net/manual/en/control-structures.goto.php
Ma LOL.

Chissà cosa ne pensa Guido...
__________________
Per iniziare a programmare c'è solo Python con questo o quest'altro (più avanzato) libro
@LinkedIn Non parlo in alcun modo a nome dell'azienda per la quale lavoro
Ho poco tempo per frequentare il forum; eventualmente, contattatemi in PVT o nel mio sito. Fanboys
cdimauro è offline   Rispondi citando il messaggio o parte di esso
Old 26-01-2012, 11:34   #12
vendettaaaaa
Senior Member
 
L'Avatar di vendettaaaaa
 
Iscritto dal: Jan 2012
Messaggi: 1267
Visto che ci tenete, vi posto il codice sorgente del mio gioco, ma promettete di non usarlo per arricchirvi
Vi evidenzio in rosso il primo punto dove lo uso, ed in blu il secondo, così non dovete spippettarvelo tutto:
Codice:
#include "Classes.h"
#include <iostream>
#include <string>

using namespace std;

bool IsInputInteger(string& line);

int main()
{
	string control;
	int difficulty;
	char again;
	string go;
	int n, m;
	Memory* myGrid;

	cout << "Exercise 5.1: have a game at Memory!\n" << endl;

play:
	cout << "Select the difficulty:" << endl;
	cout << "1) Easy" << endl;
	cout << "2) Medium" << endl;
	cout << "3) Hard" << endl;
	cout << "4) Custom: choose the grid dimension yourself (max 10x10)" << endl;
	cin >> control;
	while (!IsInputInteger(control)) {
		cout << "You should enter a number between 1 and 4..." << endl;
		cout << "1) Easy" << endl;
		cout << "2) Medium" << endl;
		cout << "3) Hard" << endl;
		cout << "4) Custom: choose the grid dimension yourself (max 10x10)" << endl;
		cin >> control;
	}
	difficulty = atoi(control.c_str());

	switch (difficulty) {
	case 1:
		n = 4;
		m = 4;
		break;
	case 2:
		n = 6;
		m = 6;
		break;
	case 3:
		n = 8;
		m = 8;
		break;
	case 4:
		do {
			cout << "Enter the number of rows and columns of the grid (at least one of two numbers must be an even):" << endl;
			cout << "Rows = "; cin >> n; cout << "Columns = "; cin >> m; cout << endl << endl;
		} while (n % 2 != 0 && m % 2 != 0);
		break;
	default:
		cout << "If entering a number between 1 and 4 is so hard for you, this game might not be your cup of tea." << endl << endl;
		return 0;
	}

	// Initialize and display the scrambled grid
	myGrid = new Memory(n, m);
	// myGrid -> SetGrid(n, m);
	cout << "This is the scrambled grid: memorize it" << endl;
	myGrid -> OrderedGrid();
	myGrid -> ScrambleGrid();
	myGrid -> PrintGrid(cout, myGrid);
	cout << endl << "Type GO! when you're ready to start playing: ";
	do {cin >> go;} while (go != "GO!");
	system("cls");

	// Start solving the grid
	string c;
	int n1, m1, n2, m2;
	int realAttempts = 0;
	int idealAttempts = (n*m)/2;
	do {
		cout << "Now enter the indeces of the 2 elements you think form a couple:" << endl;
elements:		
		cout << "Element 1 - row "; cin >> control;
		while (!IsInputInteger(control)) {
			cout << "Element 1 - row ";
			cin >> control;
		}
		n1 = atoi(control.c_str());

		cout << "Element 1 - column "; cin >> control;
		while (!IsInputInteger(control)) {
			cout << "Element 1 - column ";
			cin >> control;
		}
		m1 = atoi(control.c_str());

		cout << "Element 2 - row "; cin >> control;
		while (!IsInputInteger(control)) {
			cout << "Element 2 - row ";
			cin >> control;
		}
		n2 = atoi(control.c_str());

		cout << "Element 2 - column "; cin >> control;
		while (!IsInputInteger(control)) {
			cout << "Element 2 - column ";
			cin >> control;
		}
		m2 = atoi(control.c_str());
		
		if (n1 == n2 && m1 == m2) {
			cout << "Enter 2 distinct elements!! Dumbass" << endl;
			goto elements;
		}		
		myGrid -> GuessCouple(n1, m1, n2, m2, cout);
		++realAttempts;
	} while (!myGrid -> IsSolved());
	
	cout << "Congratulations, you have solved the grid! Like a boss!" << endl;
	cout << "It took you " << realAttempts - idealAttempts << " attempt(s) more than you should have!" << endl << endl;
	delete myGrid;

	// Option to play again
	cout << "Want to play again? (y/n)" << endl;
	do {cin >> again;} while (again != 'y' && again != 'n');
	if (again == 'y') {
		system("cls");
		goto play;
	}

	return 0;
}

bool IsInputInteger(string& line)
{
	for (int i = 0; i < line.size(); ++i) {
		if (!isdigit(line[i])) return false;
	}

	return true;
}
Nel caso di play again mi pare totalmente innocuo. Distruggo la matrice memory appena l'utente la risolve, prima del "play again", quindi non c'è rischio di memory leak. Se non usassi goto, dovrei indentare tutto quanto in un
Codice:
do {gioca} while (again == 'y');
e non mi va di spostare tutto a destra di 4 spazi, non ho uno schermo panoramico!

Anche nel secondo caso dovrei usare un
Codice:
do {inserisci n1, m1, n2, m2} while (n1 == n2 && m1 == m2);
ma di nuovo, vorrei non indentare troppo. Inoltre, dato che se l'user viola la condizione lo insulto, la seconda volta il messaggio di testo è diverso e per ottenere ciò dovrei usare non più un do while, bensì un while:
Codice:
cout << "Inserisci ...";
while (n1 == n2 && m1 == m2) {
    cout << "Idiota! Inserisci 2 elementi diversi!!";
    cin >> ...;
ripetendo ben 2 volte i 4 blocchi di acquisizione di n1, m1, n2 ed m2.
Il goto mi sembra comunque innocuo oltre che risparmioso, perchè non salto fuori da nessun loop.

A voi la palla
vendettaaaaa è offline   Rispondi citando il messaggio o parte di esso
Old 26-01-2012, 11:51   #13
banryu79
Senior Member
 
L'Avatar di banryu79
 
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
Quote:
Originariamente inviato da Tommo Guarda i messaggi
goto non lo uso perchè non serve se si programma OOP...
Sì, infatti, bisogna un'attimo circostanziare il discorso.
__________________

As long as you are basically literate in programming, you should be able to express any logical relationship you understand.
If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it.
(Chris Crawford)
banryu79 è offline   Rispondi citando il messaggio o parte di esso
Old 26-01-2012, 11:54   #14
Tommo
Senior Member
 
L'Avatar di Tommo
 
Iscritto dal: Feb 2006
Messaggi: 1304
@vendetta: quel codice tutto contenuto nel main è un'ottima prova per il mio discorso, andava spezzato almeno in 4 o 5 funzioni. Lo credo bene che non sai come gestire il flusso senza goto se schiaffi tutto nel main

Ad esempio, da "play:" fino alla fine della logica di gioco doveva stare tutto dentro una funzione play() che viene chiamata in un ciclo.
Praticamente ogni corpo di ogni ciclo potevi smembrarlo allo stesso modo.
In pratica stai programmando come chi programma assembly ora come ora, riuso del codice = 0.

In sostanza goto è male perchè se ti serve goto la struttura del tuo programma è sbagliata. Non è che goto è sbagliato di suo.
__________________
*ToMmO*

devlog | twitter

Ultima modifica di Tommo : 26-01-2012 alle 11:56.
Tommo è offline   Rispondi citando il messaggio o parte di esso
Old 26-01-2012, 12:00   #15
banryu79
Senior Member
 
L'Avatar di banryu79
 
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
Sì quel codice chiama un po' vendetta, anzi... vendettaaaaa! (), è in astinenza di refactoring.
Ad esempio, questa duplicazione è un sintomo:
Codice:
while (!IsInputInteger(control)) {
    cout << "Element 2 - column ";
    cin >> control;
}
Quote:
In sostanza goto è male perchè se ti serve goto la struttura del tuo programma è sbagliata. Non è che goto è sbagliato di suo.
Non è sbagliata: è aspaghettata.
__________________

As long as you are basically literate in programming, you should be able to express any logical relationship you understand.
If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it.
(Chris Crawford)
banryu79 è offline   Rispondi citando il messaggio o parte di esso
Old 26-01-2012, 12:02   #16
vendettaaaaa
Senior Member
 
L'Avatar di vendettaaaaa
 
Iscritto dal: Jan 2012
Messaggi: 1267
Quote:
Originariamente inviato da Tommo Guarda i messaggi
@vendetta: quel codice tutto contenuto nel main è un'ottima prova per il mio discorso, andava spezzato almeno in 4 o 5 funzioni. Lo credo bene che non sai come gestire il flusso senza goto se schiaffi tutto nel main

Ad esempio, da "play:" fino alla fine della logica di gioco doveva stare tutto dentro una funzione play() che viene chiamata in un ciclo.
Praticamente ogni corpo di ogni ciclo potevi smembrarlo allo stesso modo.
In pratica stai programmando come chi programma assembly ora come ora, riuso del codice = 0.

In sostanza goto è male perchè se ti serve goto la struttura del tuo programma è sbagliata. Non è che goto è sbagliato di suo.
Essendo un programmino del menga non sono stato a creare una funzione nella classe Memory per ogni "funzione logica" che serve, certo che se faccio myGrid.play() posso tranquillamente metterci un do while!
Cmq sia, detto alla tua maniera suona già meglio...
vendettaaaaa è offline   Rispondi citando il messaggio o parte di esso
Old 26-01-2012, 12:03   #17
shinya
Senior Member
 
L'Avatar di shinya
 
Iscritto dal: Jul 2005
Città: Bologna
Messaggi: 1130
Ogni 'if' è un 'goto'.

(flaming expected in 3..2..1..)
shinya è offline   Rispondi citando il messaggio o parte di esso
Old 26-01-2012, 12:06   #18
banryu79
Senior Member
 
L'Avatar di banryu79
 
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
Quote:
Originariamente inviato da shinya Guarda i messaggi
Ogni 'if' è un 'goto'.

(flaming expected in 3..2..1..)
A suo tempo se ne era straparlato.
Se vuoi scatenare un flame secondo me devi impegnarti di più, caro il mio guerrafondaio
__________________

As long as you are basically literate in programming, you should be able to express any logical relationship you understand.
If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it.
(Chris Crawford)
banryu79 è offline   Rispondi citando il messaggio o parte di esso
Old 26-01-2012, 12:08   #19
vendettaaaaa
Senior Member
 
L'Avatar di vendettaaaaa
 
Iscritto dal: Jan 2012
Messaggi: 1267
Cmq in realtà la mia mente è già al lavoro per capire come riutilizzare varie linee di codice, che mi trovo a scrivere ora, in futuro.
L'esempio portato da banryu è palese, e rimanda ad un altro problema che mi son posto qua (se volete darci un'occhio vi ringrazio ): ho tutta l'intenzione di farmi una classe derivata da cin che sappia capire se in input riceve un int, un char o che altro, così da evitarmi 7-8 LOC ogni volta che voglio controllare che un utente digiti un numero se è richiesto un numero, e non un carattere.
Per intenderci, sto entrando nell'ottica OOP ma per comodità, e perchè voglio far le cose fatte bene e il più generiche possibili, non sto a creare oggetti o funzioni per ogni programmino didattico che sto facendo
vendettaaaaa è offline   Rispondi citando il messaggio o parte di esso
Old 26-01-2012, 12:18   #20
banryu79
Senior Member
 
L'Avatar di banryu79
 
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
Quote:
Originariamente inviato da vendettaaaaa Guarda i messaggi
Cmq in realtà la mia mente è già al lavoro per capire come riutilizzare varie linee di codice, che mi trovo a scrivere ora, in futuro.
L'esempio portato da banryu è palese, e rimanda ad un altro problema che mi son posto qua (se volete darci un'occhio vi ringrazio ): ho tutta l'intenzione di farmi una classe derivata da cin che sappia capire se in input riceve un int, un char o che altro, così da evitarmi 7-8 LOC ogni volta che voglio controllare che un utente digiti un numero se è richiesto un numero, e non un carattere.
Per intenderci, sto entrando nell'ottica OOP ma per comodità, e perchè voglio far le cose fatte bene e il più generiche possibili, non sto a creare oggetti o funzioni per ogni programmino didattico che sto facendo
Io ho scritto una fesseria (in Java), per piccolissimi programmini senza interfaccia grafica, che stampano tutto in consolle. Lo scopo era ridurre il codice ridondante da scrivere per la validazione degli argomenti passati da riga di comando e arrivare a scrivere delle robe così:

Esempio 1:
Codice:
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

/**
 * Input: a JPEG image path and a Rectangle
 * Output: a new JPEG file as a subimage of the input specified by the Rectangle.
 *
 * Testing production of subimages from JPEG files.
 *
 * @author Francesco Baro
 */
public class Test {

    public static void main(String... args) {
        String path = 
            "\"C:/Documents and Settings/Francesco/Documenti/Immagini/" +
            "00143_grapeleaf_1280x800.jpg\"";
        String msg =
            "Devi specifiare 5 argomenti:\n" +
            "1) il path di un'immagine JPEG.\n" +
            "2) la coordinata X per la porzione di immagine da tagliare.\n" +
            "3) la coordinata Y per la porzione di immagine da tagliare.\n" +
            "4) la coordinata WIDTH per la porzione di immagine da tagliare.\n" +
            "5) la coordinata HEIGHT per la porzione di immagine da tagliare.\n" +
            "Ad esempio:\n" +
            "java Test " + path + " 0 0 150 200";
        // Data input & start processing
        new ApplicationImpl()
                .withUsageMessage(msg)
                .withArguments(args)
                .start();
    }

    // Validation & Execution logic implementation
    static class ApplicationImpl extends ConsolleApp {

        @Override protected boolean validateArguments() {
            return checkArgsCount(5)
                && checkFilePathAt(0)
                && checkIntAt(1)
                && checkIntAt(2)
                && checkIntAt(3)
                && checkIntAt(4);
        }

        @Override protected void execute() {
            final String path = getArg(0);
            final int x = Integer.parseInt(getArg(1));
            final int y = Integer.parseInt(getArg(2));
            final int width = Integer.parseInt(getArg(3));
            final int height = Integer.parseInt(getArg(4));

            File file = new File(path);
            try {
                BufferedImage jpeg = ImageIO.read(file);
                BufferedImage portion = jpeg.getSubimage(x, y, width, height);
                File dest = new File(file.getParentFile(), "sub_" + file.getName());
                ImageIO.write(portion, "JPEG", dest);
            } catch (IOException ex) {
                System.err.println("IO error reading/writing specified image file: " + file);
            }

            System.out.println("Work on " + path + " done.");
        }
    }
}
Esempio 2:
Codice:
/**
 * Input: a JPEG image path
 * Output: two new JPEG files as a subimages: the left half and the right half
 *
 * Testing vertical half cut of a JPEG image
 *
 * @author Francesco Baro
 */
public class TestVerticalHalf {

    public static void main(String... args) {
        String path =
            "\"C:/Documents and Settings/Francesco/Documenti/Immagini/" +
            "00143_grapeleaf_1280x800.jpg\"";
        String msg =
            "Devi specifiare il path di un'immagine JPEG.\n" +
            "Ad esempio:\n" +
            "java TestVerticalHalf " + path;
        // Data input & start processing
        new ApplicationImpl()
                .withUsageMessage(msg)
                .withArguments(args)
                .start();
    }

    // Validation & Execution logic implementation
    static class ApplicationImpl extends ConsolleApp {
        
        @Override protected boolean validateArguments() {
            return checkArgsCount(1)
                && checkFilePathAt(0);
        }

        @Override protected void execute() {
            final String path = getArg(0);
            File file = new File(path);

            BufferedImage jpeg = null;
            try {
                jpeg = ImageIO.read(file);
            } catch (IOException ex) {
                System.err.println("IO error reading the image file: " + file);
            }

            BufferedImage left = leftHalf(jpeg);
            BufferedImage right = rightHalf(jpeg);
            
            try {
                File dest = new File(file.getParentFile(), "left_" + file.getName());
                ImageIO.write(left, "JPEG", dest);
                dest = new File(file.getParentFile(), "right_" + file.getName());
                ImageIO.write(right, "JPEG", dest);
            } catch (IOException ex) {
                System.err.println("IO error writing image file: " + file);
            }

            System.out.println("Work on " + path + " done.");
        }
    }

    /**
     * Get the left half of the given in-memory buffered image.
     * @param image the buffered image
     * @return the left half of the image
     */
    public static BufferedImage leftHalf(BufferedImage image) {
        int w = image.getWidth() / 2;
        int h = image.getHeight();
        return image.getSubimage(0, 0, w, h);
    }

    /**
     * Get the right half of the given in-memory buffered image.
     * @param image the buffered image
     * @return the right half of the image
     */
    public static BufferedImage rightHalf(BufferedImage image) {
        int x = image.getWidth() / 2;
        int w = image.getWidth() - x;
        int h = image.getHeight();
        return image.getSubimage(x, 0, w, h);
    }
    
}
ConsolleApp:
Codice:
/**
 * Abstract away consolle arguments validation and execution.
 *
 * @author Francesco Baro
 */
public abstract class ConsolleApp {

    /** The "show usage" message */
    private String usageMessage = "";

    /** The application runtime arguments */
    private String[] args = new String[] {};
    
//
// ----- Public Interface
//

    /**
     * Set this application usage message
     * @param message the application "show usage" message
     */
    final public ConsolleApp withUsageMessage(String message) {
        usageMessage = message;
        return this;
    }

    /**
     * Set this application arguments
     * @param args the application arguments
     */
    final public ConsolleApp withArguments(String... args) {
        this.args = args;
        return this;
    }

    /**
     * Launch this consolle application
     */
    final public void start() {
        if (validateArguments()) execute();
        else System.out.println(usageMessage);
    }

    /**
     * Get the argument at index
     * @param index the index of the argument in the argument list
     * @return the argument value
     */
    final public String getArg(int index) {
        return args[index];
    }


//
// ----- Helper methods for validation
//

    /**
     * Validate the number of arguments passed in
     * @param count minimum number of arguments required
     * @return true on validation, false otherwise
     */
    final protected boolean checkArgsCount(int count) {
        if (args.length != count) {
            String error = "Errato numero di argomenti passati.";
            System.out.println(error);
            return false;
        }

        return true;
    }

    /**
     * Verify that the indexed arguments is a valid file path (must exists)
     * @param index argument index
     * @return true on validation, false otherwise
     */
    final protected boolean checkFilePathAt(int index) {
        File file = new File(args[index].trim());

        if (! file.exists()) {
            String error = "args[" + index + "] - file inesistente: " + file;
            System.out.println(error);
            return false;
        }

        if (! file.isFile()) {
            String error = "args[" + index + "] - percorso non valido: " + file;
            System.out.println(error);
            return false;
        }

        return true;
    }

    /**
     * Verify that the indexed arguments is a valid integer
     * @param index argument index
     * @return true on validation, false otherwise
     */
    final protected boolean checkIntAt(int index) {
        try {
            Integer.parseInt(args[index]);
            return true;
        } catch (NumberFormatException managed) {
            String error = "args[" + index + "] - il valore non è un intero: " + args[index];
            System.out.println(error);
            return false;
        }
    }

//
// ----- Abstract part
//

    /**
     * Validate the arguments passed to this consolle app.
     * Implemetors should define validation logic here.
     * @return true on correct validation, false otherwise
     */
    protected abstract boolean validateArguments();

    /**
     * Execute this consolle app, called on successfull arguments
     * validation. Implementors should define application logic here,
     * and could use getArg to access the arguments.
     */
    protected abstract void execute();
}
Se dovesse servirmi tenterei un'approccio del genere anche per l'acquisizione dell'input utente.
__________________

As long as you are basically literate in programming, you should be able to express any logical relationship you understand.
If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it.
(Chris Crawford)
banryu79 è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


Tastiera gaming MSI GK600 TKL: switch hot-swap, display LCD e tre modalità wireless Tastiera gaming MSI GK600 TKL: switch hot-swap, ...
DJI Osmo Pocket 4: la gimbal camera tascabile cresce e ha nuovi controlli fisici DJI Osmo Pocket 4: la gimbal camera tascabile cr...
Sony INZONE H6 Air: il primo headset open-back di Sony per giocatori Sony INZONE H6 Air: il primo headset open-back d...
Nutanix cambia pelle: dall’iperconvergenza alla piattaforma full stack per cloud ibrido e IA Nutanix cambia pelle: dall’iperconvergenza alla ...
Recensione Xiaomi Pad 8 Pro: potenza bruta e HyperOS 3 per sfidare la fascia alta Recensione Xiaomi Pad 8 Pro: potenza bruta e Hyp...
Spento lo strumento LECP della sonda spa...
Voyager Technologies ha siglato un accor...
GoPro annuncia la linea MISSION 1 con tr...
Alcune varianti dei futuri Samsung Galax...
Il ridimensionamento di OnePlus in Europ...
Il cofondatore di Netflix ha lasciato l'...
ASUS porta in Italia il nuovo Zenbook Du...
Assassin's Creed: Black Flag Resynced, s...
Xbox Game Pass cambierà: tra le n...
I nuovi Surface Pro e Laptop sono vicini...
OnePlus ci riprova con la fascia bassa: ...
La Top 10 delle offerte Amazon del weeke...
XGIMI MoGo 2 Pro a 339€: Google TV con N...
Forum IT & Intelligence 2026: dall'A...
iPhone 16e per la prima volta a meno di ...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 04:44.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Served by www3v