Entwickler-Ecke
C# - Die Sprache - Jahrestage
ThomAlex - Do 22.04.10 20:36
Titel: Jahrestage
Hallo,
ich habe ein kleines Programm geschrieben, dass die Eingabe von Jahr, Monat und Tag mit einem Algorithmus verarbeitet, der mir ausspuckt, welcher Tag im Jahr das ist. Miteinbezogen sind Schaltjahre, diese haben 366 Tage und um die grogorianische Schaltregel mal einfachheitshalber außen vor zu lassen, ist jedes vierte Jahr ein Schaltjahr (also das Jahr geteilt durch 4 darf keinen Rest aufweisen). Es klappt, nur ich möchte versuchen den Code von der Menge soweit zu kürzen, wie es nur geht, habt ihr Ideen, wie ich den verkürzen kann? Hier der Code:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59:
| int result, userday, usermonth, useryear; int[] monthdays = new int[12];
private void button1_Click(object sender, EventArgs e) { userday = 0; usermonth = 0; useryear = 0;
if (int.Parse(txtDays.Text) > 0 && int.Parse(txtDays.Text) <= 31) userday = int.Parse(txtDays.Text); else { MessageBox.Show("Ungültige Eingabe für den Tag!"); txtDays.Text = ""; return; }
if (int.Parse(txtMonth.Text) <= 12 && int.Parse(txtMonth.Text) >= 1) usermonth = int.Parse(txtMonth.Text); else { MessageBox.Show("Ungültige Eingabe für den Monat!"); txtMonth.Text = ""; return; } try { useryear = int.Parse(txtYear.Text); } catch { MessageBox.Show("Ungültige Eingabe!"); txtYear.Text = ""; return; }
result = 0;
for (int i = 0; i < 12; i++) { if (i == 0 || i == 2 || i == 4 || i == 6 || i == 7 || i == 9 || i == 11) monthdays[i] = 31; else if (i == 1 && useryear % 4 == 0) monthdays[i] = 29; else if (i == 1 && useryear % 4 != 0) monthdays[i] = 28; else monthdays[i] = 30; } for (int i = 0; i < usermonth - 1; i++) result += monthdays[i]; result += userday;
lblAusgabe.Text = result + ". Tag im Jahr " + useryear; lblAusgabe.Visible = true; } |
Danke fürs Gedanken machen
Moderiert von
Kha: Topic aus WinForms verschoben am Do 22.04.2010 um 21:20
Ralf Jansen - Do 22.04.10 20:55
Laß das ganze doch das Framework selber rechnen. Ist kompakter und das Schaltjahr Handling ist auch geschenkt.
C#-Quelltext
1:
| result = new DateTime(useryear, usermonth, userday).Subtract(new DateTime(useryear - 1, 12, 31)).Days; |
JüTho - Do 22.04.10 21:03
Ich empfehle DayOfYear. Jürgen
ThomAlex - Do 22.04.10 21:17
Ja danke für die Methoden, allerdings gehts mir um eine Optimierung meines Codes. Sinn der Sache ist nicht fertigen Code zu benutzen, sondern ihn selber in Kurzform zu programmieren. Kann jemand meinen Code kürzen? Danke
Kha - Do 22.04.10 21:30
ThomAlex hat folgendes geschrieben : |
| Es klappt, nur ich möchte versuchen den Code von der Menge soweit zu kürzen, wie es nur geht, habt ihr Ideen, wie ich den verkürzen kann? |
Der Code ist von der Logik schon ziemlich direkt, da lässt sich wenig rütteln. Aber zwei Anmerkungen: Warum sind die Variablen außerhalb der Methode deklariert? Die meisten
= 0 Initialisierungen kannst du dir auch sparen. Und wozu erst
monthdays füllen und dann direkt zusammenrechnen? Die zwei Schritte könntest du gleichzeitig ausführen und dir so das Array sparen. Oder du ersetzt die Schleife durch Folgendes, imo ein wenig hübscher:
C#-Quelltext
1:
| int[] monthDays = { 31, userYear % 4 == 0 ? 29 : 28, 31, 30, ... }; |
Und wenn du LINQ magst, kannst du dann mit
C#-Quelltext
1:
| int result = monthDays.Take(userMonth - 1).Sum() + userDay; |
weitermachen.
/edit: Und noch eine Idee: Das Einlesen der drei Datumsteile in eine Methode
bool Validate(TextBox box, string name, int min, int max, out int value) auslagern.
Ralf Jansen - Do 22.04.10 21:32
| Zitat: |
| Sinn der Sache ist nicht fertigen Code zu benutzen, sondern ihn selber in Kurzform zu programmieren. Kann jemand meinen Code kürzen |
Der Ausspruch ist jetzt aber reichlich Paradox :gruebel:
danielf - Do 22.04.10 21:35
Okay, dann mache ich mich mal an den Code :)
Zu aller erst könntest du ein NumericUpDown verwenden für die Datum eingabe. Dann brauchst du das Parsen nicht.
Oder eine MaskedTextBoxed, dann kannst du ungültige Eingaben abfangen.
Wenn es aber eine Textbox sein "muss" dann denke ich, dass dir TryParse weiter hilft:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43:
| private void button1_Click(object sender, EventArgs e) { int userday, usermonth, useryear;
if (!int.TryParse(textDays.Text, out userday) || userday > 31 || userday < 0) { throw new Exception("Ungültige Tag eingabe"); } if (!int.TryParse(textMonth.Text, out usermonth) || usermonth > 12 || usermonth < 1) { throw new Exception("Ungültige Monat eingabe"); } if (!int.TryParse(textYear.Text, out useryear)) { throw new Exception("Ungültige Jahr eingabe"); }
int[] monthdays = new int[12]; int sumOfDays; for (int i = 0; i < 12; i++) { switch(i) { case 0: case 2: case 4: case 6: case 7: case 9: case 11: monthdays[i]= 31; break; case 1: monthdays[i]= useryear % 4 ? 28 : 29; break; default: monthdays[i]= 30; } sumOfDays += monthdays[i]; } lblAusgabe.Text = string.Format("Das Jahr {0} hat {1} Tage.", useryear, sumOfDays); } |
Ich denke das ist selbsterklärend :)
Wenn du fragen hast .. schieß los
Gruß
ThomAlex - Fr 23.04.10 00:07
Vielen Dank, aus allem hab ich etwas genommen.
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43:
| private void button1_Click(object sender, EventArgs e) { int userday, usermonth, useryear; if (!InitializeData(out userday, out usermonth, out useryear)) return;
int[] monthdays = { 31, useryear % 4 == 0 ? 28 : 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; int sumOfDays = 0; for (int i = 0; i < usermonth - 1; i++) sumOfDays += monthdays[i]; sumOfDays += userday;
lblAusgabe.Text = "Der " + userday.ToString() + "." + usermonth.ToString() + " ist der " + sumOfDays.ToString() + ". Tag im Jahr " + useryear.ToString(); lblAusgabe.Visible = true; } private bool InitializeData(out int userday, out int usermonth, out int useryear) { bool Converted = true; if (!int.TryParse(txtDays.Text, out userday) || userday < 1 || userday > 31) { MessageBox.Show("Ungültiger Tag!"); txtDays.Text = ""; Converted = false; } if (!int.TryParse(txtMonth.Text, out usermonth) || usermonth < 1 || usermonth > 12) { MessageBox.Show("Ungültiger Monat!"); txtMonth.Text = ""; Converted = false; } if (!int.TryParse(txtYear.Text, out useryear)) { MessageBox.Show("Ungültiges Jahr!"); txtYear.Text = ""; Converted = false; } if (!Converted) lblAusgabe.Text = ""; return Converted; } |
Nemag - Fr 23.04.10 07:35
Servus
zum Code an sich will ich jetzt mal nichts sagen, nur zur Schaltjahrberechnung (hab mir jetzt nicht alles durch gelesen - vielleicht hat es ja auch schon jemand geschrieben)
Schaltjahre sind alle Jahre die restlos durch 4 geteilt werden können ohne die, die durch 100 teilbar aber nicht durch 400 teilbar sind.
quasi 1900 war keins, 2000 war eins und 2100 wird wieder keins.
aber das nur am Rande.
ThomAlex - Mo 26.04.10 18:51
@Nemag:
| Zitat: |
Schaltjahre sind alle Jahre die restlos durch 4 geteilt werden können ohne die, die durch 100 teilbar aber nicht durch 400 teilbar sind.
|
C#-Quelltext
1:
| int[] monthdays = { 31, useryear % 4 == 0 ? 28 : 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; |
Im zweiten Element, dem Februar, ist deine Anmerkung längst erfüllt worden.
JüTho - Mo 26.04.10 19:29
ThomAlex hat folgendes geschrieben : |
C#-Quelltext 1:
| int[] monthdays = { 31, useryear % 4 == 0 ? 28 : 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; |
Im zweiten Element, dem Februar, ist deine Anmerkung längst erfüllt worden. |
Wie bitte?
* Bei useryear = 1900 ist mod4 gleich 0, dann also 28 Tage. Korrekt.
* Bei useryear = 1901 ist mod4 gleich 1, dann also 29 Tage. Falsch.
* Bei useryear = 1902 ist mod4 gleich 2, dann also 29 Tage. Falsch.
* Bei useryear = 1903 ist mod4 gleich 3, dann also 29 Tage. Falsch.
* Bei useryear = 1904 ist mod4 gleich 0, dann also 28 Tage. Falsch.
Du müsstest also zumindest 28 und 29 vertauschen. Aber auch dann fehlen die Bedingungen mod 100 und mod 400.
Jürgen
ThomAlex - Mi 28.04.10 22:37
Wenn mans genau nimmt schon, aber die Gregorianische Regel gilt nur bis 1582 und diese wollte ich weglassen und simpel einfach die julianische Regel, die nur besagt Ein Jahr ist ein Schaltjahr, wenn die Division durch 4 keinen Rest ergibt, weiter nichts, nehmen.
Nemag - Do 29.04.10 09:47
ThomAlex hat folgendes geschrieben : |
| Wenn mans genau nimmt schon, aber die Gregorianische Regel gilt nur bis 1582 und diese wollte ich weglassen und simpel einfach die julianische Regel, die nur besagt Ein Jahr ist ein Schaltjahr, wenn die Division durch 4 keinen Rest ergibt, weiter nichts, nehmen. |
Also wenn man es schon genau nimmt gilt die Gregorianische Regel ab 1582 und nicht bis. Übrigens gibt es dafür diverse Normen ISO 8601 (die deutsche dazu weiß ich spontan nicht und war jetzt zu faul zu googln).
Ich hoffe du hast den von Jürgen beschriebenen Fehler beim Zuweisungoperator wenigstens getauscht ;-)
JüTho - Do 29.04.10 17:18
Nemag hat folgendes geschrieben : |
| Normen ISO 8601 (die deutsche dazu weiß ich spontan nicht |
Ganz einfach: EN 28601 (und europäische Normen sind auch deutsche Normen). Jürgen
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!