Autor |
Beitrag |
ThomAlex
      
Beiträge: 58
Windows 7
C# (VS08) Games via XNA (privat) oder WinForms (Schule)
|
Verfasst: Do 22.04.10 20:36
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:
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
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: 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
      
Beiträge: 2021
Erhaltene Danke: 6
Win XP Prof
C# 2.0 (#D für NET 2.0, dazu Firebird); früher Delphi 5 und Delphi 2005 Pro
|
Verfasst: Do 22.04.10 21:03
Ich empfehle DayOfYear. Jürgen
|
|
ThomAlex 
      
Beiträge: 58
Windows 7
C# (VS08) Games via XNA (privat) oder WinForms (Schule)
|
Verfasst: 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
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: 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.
_________________ >λ=
Zuletzt bearbeitet von Kha am Do 22.04.10 21:36, insgesamt 2-mal bearbeitet
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: 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 
|
|
danielf
      
Beiträge: 1012
Erhaltene Danke: 24
Windows XP
C#, Visual Studio
|
Verfasst: 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:
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 
      
Beiträge: 58
Windows 7
C# (VS08) Games via XNA (privat) oder WinForms (Schule)
|
Verfasst: Fr 23.04.10 00:07
Vielen Dank, aus allem hab ich etwas genommen.
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
      
Beiträge: 132
Erhaltene Danke: 2
|
Verfasst: 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 
      
Beiträge: 58
Windows 7
C# (VS08) Games via XNA (privat) oder WinForms (Schule)
|
Verfasst: 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
      
Beiträge: 2021
Erhaltene Danke: 6
Win XP Prof
C# 2.0 (#D für NET 2.0, dazu Firebird); früher Delphi 5 und Delphi 2005 Pro
|
Verfasst: 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 
      
Beiträge: 58
Windows 7
C# (VS08) Games via XNA (privat) oder WinForms (Schule)
|
Verfasst: 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
      
Beiträge: 132
Erhaltene Danke: 2
|
Verfasst: 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
      
Beiträge: 2021
Erhaltene Danke: 6
Win XP Prof
C# 2.0 (#D für NET 2.0, dazu Firebird); früher Delphi 5 und Delphi 2005 Pro
|
Verfasst: 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
|
|
|