2010-07-12 15 views
6

Ho creato un piccolo programma che calcola la media di 15 numeri o meno. Ci sono 15 caselle di testo, il cui valore predefinito è '0'. Il programma sa di ottenere la somma di tutti i numeri digitati e di dividerli per numeri di caselle di testo che non restituiscono '0'. Ma se l'utente cancella erroneamente uno degli "0" in una delle caselle di testo .. errore di runtime.Come trasformare null a 0

Inizialmente ho risolto questo problam scrivendo questo "if" 15 volte (una per ogni casella di testo):

if (t1.Text == "") { tr1 = 0; } 
else 
{ 
    tr1 = Double.Parse(t1.Text); 
} 

controlla questo codice se non c'è una cosa in casella di testo (per esempio, chiamato t1), se è vero, il programma sta dando il doppio 'tr1' (non confondere con 't1'), il valore di '0', se falso, il codice dà il doppio ' tr1 'il testo di' t1 '.

ho dovuto scrivere questo 'se' 15 volte. volevo sapere se posso scrivere lo stesso codice con matrici e un ciclo for, e come?

qui è l'intero codice (mi dispiace per i nomi var non sono simili a l'uso di var.):

private void goyouidiot_Click(object sender, EventArgs e) 
{ 
    double tr1; 
    double tr2; 
    double tr3; 
    double tr4; 
    double tr5; 
    double tr6; 
    double tr7; 
    double tr8; 
    double tr9; 
    double tr10; 
    double tr11; 
    double tr12; 
    double tr13; 
    double tr14; 
    double tr15; 
    if (t1.Text == "") { tr1 = 0; } 
    else 
    { 
     tr1 = Double.Parse(t1.Text); 
    } 
    if (t2.Text == "") { tr2 = 0; } 
    else 
    { 
     tr2 = Double.Parse(t2.Text); 
    } 

    if (t3.Text == "") { tr3 = 0; } 
    else 
    { 
     tr3 = Double.Parse(t3.Text); 
    } 


    if (t4.Text == "") { tr4 = 0; } 
    else 
    { 
     tr4 = Double.Parse(t4.Text); 
    } 


    if (t5.Text == "") { tr5 = 0; } 
    else 
    { 
     tr5 = Double.Parse(t5.Text); 
    } 

    if (t6.Text == "") { tr6 = 0; } 
    else 
    { 
     tr6 = Double.Parse(t6.Text); 
    } 


    if (t7.Text == "") { tr7 = 0; } 
    else 
    { 
     tr7 = Double.Parse(t7.Text); 
    } 


    if (t8.Text == "") { tr8 = 0; } 
    else 
    { 
     tr8 = Double.Parse(t8.Text); 
    } 

    if (t9.Text == "") { tr9 = 0; } 
    else 
    { 
     tr9 = Double.Parse(t9.Text); 
    } 


    if (t10.Text == "") { tr10 = 0; } 
    else 
    { 
     tr10 = Double.Parse(t10.Text); 
    } 


    if (t11.Text == "") { tr11 = 0; } 
    else 
    { 
     tr11 = Double.Parse(t11.Text); 
    } 


    if (t12.Text == "") { tr12 = 0; } 
    else 
    { 
     tr12 = Double.Parse(t12.Text); 
    } 

    if (t13.Text == "") { tr13 = 0; } 
    else 
    { 
     tr13 = Double.Parse(t13.Text); 
    } 


    if (t14.Text == "") { tr14 = 0; } 
    else 
    { 
     tr14 = Double.Parse(t14.Text); 
    } 


    if (t15.Text == "") { tr15 = 0; } 
    else 
    { 
     tr15 = Double.Parse(t15.Text); 
    } 
    double[] sch = { tr1, tr2, tr3, tr4, tr5, tr6, tr7, tr8, tr9, tr10, tr11, tr12, tr13, tr14, tr15 }; 
    double total = 0; 
    double sorf = 0; 
    for (int i = 0; i != 14; i++) 
    { 

     sorf = sorf + sch[i]; 

     if (sch[i] > 0) 
     { total++; } 

    } 

    double totalic = sorf/total; 
    string glass = totalic.ToString(); 
    result.Text = ("your score: " + glass); 
} 
+0

Cosa succede se l'utente inserisce uno Zero in una delle caselle? Non finiresti per calcolare la media sbagliata? – Shravan

+0

Vorrei usare try/catch al posto di quelli if/else. Questo perché, l'utente può anche inserire del testo, che causerà un'eccezione, quando provi a Double.Parse (tx.Text) ;. – Biroka

+7

Holy copia/incolla codice, Batman! – cHao

risposta

10
Double.TryParse(t1.Text.Trim(), out tr1); 

imposterà TR1 al valore numerico della casella di testo, o 0,0 se non è riuscito a convertirlo per qualche motivo. Restituisce anche true se la conversione è riuscita o falsa se non è riuscita, ma non ti interessa il valore restituito se il valore predefinito è 0.0.

Bonus aggiuntivo: non genera un'eccezione se qualcuno decide di inserire "Questo non è un numero". in una casella di testo. Si vedrà solo il valore come 0.

Per fare questo in un array ...

TextBox t[] = { t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15 }; 
double tr[] = new double[t.Length]; 

for (int i = 0; i < t.Length; ++i) 
{ 
    Double.TryParse(t[i].Text.Trim(), out tr[i]); 
} 

UPDATE:

Nota, è perfettamente ragionevole aspettarsi di essere in grado di calcolare una media di numeri che include 0. per fare questo:

TextBox t[] = { t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15 }; 
double tr[] = new double[t.Length]; 
int valid_count = 0; 

for (int i = 0; i < t.Length; ++i) 
{ 
    if (Double.TryParse(t[i].Text.Trim(), out tr[i])) ++valid_count; 
} 

Impostare valori di default le vostre caselle di testo a vuoto (''), e poi saprete quanti erano legittimamente 0 del immesso dall'utente e quantierano vuoti Dividere la somma per valid_count per ottenere una media accurata. (Ma essere sicuri valid_count > 0, o è probabile ottenere un'eccezione di divisione per zero.)

0

mettere un .Trim() durante il recupero i valori dal TextBox

TR3 = Doppio .Parse (t3.Text.Trim());

+0

come posso usarlo per risolvere il mio problema? what.trim() fa comunque? c'è un errore in fase di runtime come ho provato a trasformare null in 0 –

7

Certo, creare un double tr[15] e una matrice corrispondente di campi di testo.

poi basta usare:

for (int i = 0; i < 15; i++) { 
    if (t[i].Text == "") { 
     tr[i] = 0; 
    } else { 
     tr[i] = Double.Parse(t[i].Text); 
    } 
} 
3

Se è solo la grande quantità di codice sorgente preso con i tuoi if dichiarazioni, si potrebbe optare per qualcosa di simile:

tr1 = (t1.Text == "") ? 0 : Double.Parse(t1.Text); 
tr2 = (t2.Text == "") ? 0 : Double.Parse(t2.Text); 
: 
tr15 = (t15.Text == "") ? 0 : Double.Parse(t15.Text); 

Questo è bello e pulito , non occupa molto spazio sullo schermo ed è abbastanza facile vedere l'intento.

O, meglio ancora, qualcosa di simile a:

tr1 = 0; try { tr1 = Double.Parse(t1.Text); } catch (Exception e) {}; 
tr2 = 0; try { tr2 = Double.Parse(t2.Text); } catch (Exception e) {}; 
: 
tr15 = 0; try { tr15 = Double.Parse(t15.Text); } catch (Exception e) {}; 

perché i campi potrebbero essere validi e non vuota.

È può fare la stessa cosa con gli array e un ciclo for se strutturare i dati e controlli in modo diverso, ma non può essere necessario per soli quindici elementi. Certamente, se dovessi aggiungere altro, prenderei seriamente in considerazione questa opzione.

E si consiglia di caricare i valori direttamente in un array in modo che non hai bisogno di sch:

double tr[15]; 
: 
tr[ 0] = 0; try { tr[ 0] = Double.Parse(t1.Text); } catch (Exception e) {}; 
tr[ 1] = 0; try { tr[ 1] = Double.Parse(t2.Text); } catch (Exception e) {}; 
: 
tr[14] = 0; try { tr[14] = Double.Parse(t15.Text); } catch (Exception e) {}; 
: 
double total = 0; 
double sorf = 0; 
for (int i = 0; i < 15; i++) { 
    if (tr[i] > 0) { 
     sorf = sorf + tr[i]; 
     total++; 
    } 
} 
: 

Per una soluzione codice minimo , è anche possibile creare un array di caselle di testo da cui stai tirando le informazioni.Qualcosa di simile (non testata):

TextBox t[] = {t1, t2, t3, ..., t15}; 
double tr[t.length]; 
: 
for (int i = 0; i < t.length; i++) { 
    tr[i] = 0; try { tr[i] = Double.Parse(t[i].Text); } catch (Exception e) {}; 
} 
: 
double total = 0; 
double sorf = 0; 
for (int i = 0; i < tr.length; i++) { 
    if (tr[i] > 0) { 
     sorf = sorf + tr[i]; 
     total++; 
    } 
} 
: 
+1

Hai un rep di 90k e non ti viene mai in mente di fare una funzione 'ParseDoubleOrZero'? – Gabe

+1

Ho un rappresentante da 90K ma sono un nuovo arrivato relativamente al C# :-) Ma il tuo punto è preso, anche se mi chiedo quanto sia vantaggioso. Certamente nessuno in termini di dimensioni del codice sorgente. Probabilmente meno codice oggetto e più leggibile dal momento che è possibile utilizzare un nome di funzione decente. – paxdiablo

+0

E vorrei usare double.TryParse invece perché le eccezioni si presentano regolarmente se si tratta di un utente che immette un numero. –

2

scrivere una funzione che converte un valore casella di testo per un doppio, qualcosa come:

private static double ConvertTextboxValueToDouble(string value) 
{ 
    double result; 
    Double.TryParse(value, out result); 

    return result; 
} 

Quindi creare un matrice da vostre caselle di testo, convertendo i loro valori a doppi:

double[] values = 
    { 
     ConvertTextboxValueToDouble(t1.text), 
     ConvertTextboxValueToDouble(t2.text), 
     ConvertTextboxValueToDouble(t3.text), 
... 
     ConvertTextboxValueToDouble(t15.text) 
    } 
1

avete considerato di utilizzare un NumericUpDown invece di un TextBox?

Inoltre, invece di scrivere qualcosa quindici volte si dovrebbe davvero refactoring del codice e provare uno dei seguenti modi:

  • Registrati per tutte le vostre caselle di immissione di un evento, dove tutto utilizzando lo stesso codice

    public void ValueChanged(Object sender, EventArgs e) 
    { 
        var numericUpDown = sender as NumericUpDown; 
        if(numericUpDown == null) 
         return; 
        //ToDo: Put some check code here 
    } 
    
  • Usa alcuni List<T> dove mettete tutte le vostre scatole dentro e scorrere su di esso per controllare tutte le impostazioni

    var myList = new List<NumericUpDown>(); 
    //ToDo: Put all your boxes into it 
    myList.Add(numericUpDown1); 
    myList.Add(numericUpDown2); 
    //or get the list from somewhere else 
    myList.AddRange(this.Controls.OfType<NumericUpDown>()) 
    
    //OnButtonClick 
    foreach(var numericUpDown in myList) 
    { 
        //ToDo: Do some checking 
    } 
    
+0

numricupdown non è d'aiuto in caso di possesso dei numeri 100, 97, 34. l'utente otterrà semplicemente il numero di trovare il numero. –

+0

non capisco il tuo commento. Un NumericUpDown è un TextBox che accetta solo i numeri più due pulsanti per/diminuire il valore. Quindi l'utente può usare questi pulsanti, ma può anche inserire direttamente questi valori come in un TextBox. – Oliver

+0

Quindi non vedo perché dovrei usare NumricUpDown. –

0

Per queste situazioni e pensando di portare a termine il lavoro in una piccola porzione di codice, uso un piccolo trucco: posizionare i controlli in un pannello.

Se il pannello è che contiene solo i comandi desiderati (in questo caso, caselle di testo), questo sarà sufficiente per memorizzare i valori in un elenco dei doppi:

private void button1_Click(object sender, EventArgs e) 
    { 
     List<double> doubleList = new List<double>(); 

     foreach (TextBox t in panel1.Controls) 
      doubleList.Add(this.checkTextBox(t)); 
    } 

    private double checkTextBox(TextBox t) 
    { 
     return (t.Text != string.Empty) ? Double.Parse(t.Text.Trim()) : 0; 
    } 

Se non si può avere solo un pannello per caselle di testo e la forza di progettazione di mixare i controlli in, si dovrà fare un ulteriore controllo/conversione:

private void button1_Click(object sender, EventArgs e) 
    { 
     List<double> doubleList = new List<double>(); 

     foreach (Control t in panel1.Controls) 
      if(t is TextBox) 
       doubleList.Add(this.checkTextBox((TextBox)t)); 
    } 

    private double checkTextBox(TextBox t) 
    { 
     return (t.Text != string.Empty) ? Double.Parse(t.Text.Trim()) : 0; 
    } 

Saluti!

Problemi correlati