Uhr, Winkel zwischen Zeigern

Odin

Grünschnabel
Hallo,
ich habe eine Aufgabe bei deren Lösung ich etwas Hilfe benötigen könnte.
Kurz zur allgemeinen Aufgabe:
Ich soll ein Programm schreiben, das zu einer bestimmten Uhrzeit im (24-Stunden-Takt) berechnen soll, wie groß der kleinste Winkel zwischen dem Stunden- und dem Minutenzeiger ist. Uhrzeit soll über Kommandozeile eingegeben werden.
Das Habe ich auch alles hinbekommen, Programm leuft einwandfrei:

C++:
#include <iostream>
#include <cmath>

using namespace std;

int s;
int m;

int main () {
    cout << "Uhrzeit eingeben:" << endl;
    cout << "Stunden: ";
    cin >> s;
    cout << "Minuten: ";
    cin >> m;
       
    int i = 360;
    int ws;
    int wm;
    int winkel;
    
    ws = (s * 30 + m * 1/2);
    wm = m * 6;
    winkel = ws - wm;   
    
    cout << "Der Winkel zwischen den Zeigern betraegt: " << winkel << " " << "Grad";
}

Wie gesagt, funktioniert einwandfrei. Es gibt allerdings ein kleines Problem: Das Programm funktioniert NUR, wenn ich die Uhrzeiten im 12-Stunden-Takt angebe (urzeit 0 - 12, anstatt 0 - 24). Gebe ich z.B. 20:18 ein, kommt das falsche Ergebnis raus, bei 8:18 das Richtige.

Meine Frage:
Wie mache ich das das auch mit den uhrzeiten von 13 - 24 uhr geht? Ist ja schließlich die Aufgabenstellung! Ich habe mir gedacht, man könnte dem Programm vllt sagen, das wenn die eingegebene Zahl größer als 12 ist, das der dann die Zahlen ersetzen soll, also 13 mit 1, 14 mit 2 ersetzen usw....
Wenn ich das mit lauter if-Schleifen mache, berechnet der das Ergebnis falsch! Auserdem sieht es sehr unschön aus:

C++:
#include <iostream>
#include <cmath>

using namespace std;

int s;
int m;

int main () {
    cout << "Uhrzeit eingeben:" << endl;
    cout << "Stunden: ";
    cin >> s;
    cout << "Minuten: ";
    cin >> m;
    
    if (s==13);
    s = 1;
    
    if (s==14);
    s = 2;
    
    if (s==15);
    s = 3;
    
    if (s==16);
    s = 4;
    
    if (s==17);
    s = 5;
    
    if (s==18);
    s = 6;
    
    if (s==19);
    s = 7;
    
    if (s==20);
    s = 8;
    
    if (s==21);
    s = 9;
    
    if (s==22);
    s = 10;
    
    if (s==23);
    s = 11;
    
    if (s==24);
    s = 12;
    
    int i = 360;
    int ws;
    int wm;
    int winkel;
    
    ws = (s * 30 + m * 1/2);
    wm = m * 6;
    winkel = ws - wm;   
    
    cout << "Der Winkel zwischen den Zeigern betraegt: " << winkel << " " << "Grad";
}

Wenn ich 8:18 Uhr eingebe, muss normalerweise der Winkel 141 rauskommen, es kommt aber (wenn die ifschleifen dabei sind) 261 raus,

Weis jemand wie man dieses Problem besser und vorallem richtig lösen könnte?
Danke schonmal.

Gruß
 
So auf Anhieb kann ich nicht erkennen, warum ein falscher Winkel rauskommt, aber:

Die zwölf if sind wirklich unnötig
Schau mal:
C++:
while(s>=12)
    s-=12;
Wenn s größer gleich 12 ist, wird von s 12 abgezogen...
Das while statt dem if sorgt auch dafür, dass 24:00 zu 0:00 wird.

Übrigens: if ist keine Schleife, sondern eine Bedingung. Schleifen wiederholen sich. while, do-while, for.
 
So auf Anhieb kann ich nicht erkennen, warum ein falscher Winkel rauskommt, aber:

Das ; hinter jedem if (); dürfte diese Fehler verursachen (würde ich mal ohne testen behaupten!).

Die zwölf if sind wirklich unnötig
Schau mal:
C++:
while(s>=12)
    s-=12;
Wenn s größer gleich 12 ist, wird von s 12 abgezogen...
Das while statt dem if sorgt auch dafür, dass 24:00 zu 0:00 wird.

Aber auch, dass es keine 12 Uhr geben kann :D Deswegen würde ich hier die if-Variante nehmen

Code:
if (s > 12)
   s -= 12;

Gruß
Rudolf
 
Das ; hinter jedem if (); dürfte diese Fehler verursachen (würde ich mal ohne testen behaupten!).
Hehe...das hab ich übersehen :D

Aber auch, dass es keine 12 Uhr geben kann :D Deswegen würde ich hier die if-Variante nehmen
Dann würde s*30 aber 360 ergeben, damit nicht gerade den kleinsten Winkel...

Hier wäre zumindest eine funktionierende Variante (ja um Mitternacht ist mir immer langweilig :D )
C++:
#include <stdio.h>

int main()
{
	int s,m;long double w;
	printf("Uhrzeit (hh:mm) eingeben:\n");
	scanf("%d:%d",&s,&m);
	if(!((s==24&&m==0)||(s>=0&&s<24&&m>=0&&m<60)))
	{
		printf("Falsche Eingabe.\n");
		return 1;
	}
	s=(s%12)*30-m*6;
	w=((long double)m)/2+(long double)s;
	printf("%.2lf Grad.\n",(w<0)?(-w):w);
	return 0;
}

edit:Oder so :D :D
C++:
#include <stdio.h>
int main(){int s,m;scanf("%d:%d",&s,&m);s=(s%12)*30-m*6;long double w;=((long double)m)/2+(long double)s;printf("%.2lf",(w<0)?(-w):w);}

Gruß
 
Zuletzt bearbeitet:
Dann würde s*30 aber 360 ergeben, damit nicht gerade den kleinsten Winkel...

Stimmt, hast Recht da macht das mit der while-Schleife mehr sinn :D (obwohl das Resultat, wenn es gezeichnet werden soll, das gleiche währe :D)


Hier wäre zumindest eine funktionierende Variante (ja um Mitternacht ist mir immer langweilig :D )
C++:
#include <stdio.h>

int main()
{
	int s,m;long double w;
	printf("Uhrzeit (hh:mm) eingeben:\n");
	scanf("%d:%d",&s,&m);
	if(!((s==24&&m==0)||(s>=0&&s<24&&m>=0&&m<60)))
	{
		printf("Falsche Eingabe.\n");
		return 1;
	}
	s=(s%12)*30-m*6;
	w=((long double)m)/2+(long double)s;
	printf("%.2lf Grad.\n",(w<0)?(-w):w);
	return 0;
}

Wenn der Odin das jetzt auch noch versteht (besonders die ?:- if-Notation) dann passt jetzt alles :D

Gruß
RudolfG
 
Vielen Dank für die schnelle und kompetente Hilfe!
An das
C++:
if (s > 12)
hatte ich auch schon gedacht, nur war ich mir nicht sicher, was ich dadrunter schreiben soll. Jetzt wo ichs sehe ist das eigentlich klar. Dankeschön.

Aber ihr habt recht, dann bekommt man nicht immer den kleinsten Winkel raus. Dummerweise sind bei dem Code von sheel einige Befehle, die wir noch nicht in der Vorlesung hatten, wodurch ich mich da erstmal kurz versuchen muss reinzudenken um zu schauen ob ichs denn verstehe. Auserdem weis ich nicht in wie fern der Prof die Lösung akzeptiert, wenn da ganz andere Befehle drin stehen, wie er uns beigebracht hat.

Gruß
Odin
 
Zuletzt bearbeitet:
Ok, da ich den Code nur zum Teil verstanden habe, habe ich mich an einer eigenen Verbesserung versucht. Jetzt scheint alles zu klappen, nur mit ein paar einzelnen Uhrzeiten hat das Programm noch Probleme. z.b. kann es nicht sein, das bei 11:00 Uhr 150 Grad raus kommen!
Hier mein Abgeänderter Code:
C++:
#include <iostream>
#include <cmath>

using namespace std;

int s;
int m;

int main () {
    cout << "Uhrzeit eingeben:" << endl;
    cout << "Stunden: ";
    cin >> s;
    cout << "Minuten: ";
    cin >> m;
    
    if (s > 12)
    s -= 12;
    
    int i = 360;
    int ws;
    int wm;
    int winkel;
    
    if(s == 12 || s == 24) {
        cout << "Falsche Eingabe." << endl;
        return 1;
    }
    else {

    
    ws = (s * 30 + m * 1/2);
    wm = m * 6;
    winkel = ws - wm;
    
    if (winkel > 180)
    winkel -= 180;
    
    if (winkel < 0)
    winkel = winkel *(-1);
    
    cout << "Der Winkel zwischen den Zeigern betraegt: " << winkel << " " << "Grad";
    return 0;
    }

}

Da bei einigen Rechnungen mit 0 Uhr minus Zahlen raus kamen, hab ich diese einfach in Positive Zahlen umgewandelt.
C++:
    if (winkel < 0)
    winkel = winkel *(-1);
Das mit dem, das nur die kleinen Winkel genommen werden sollen, hab ich versucht so ähnlich zu lösen, wie das Problem mit dem 12- und 24-Stunden-Takt.
C++:
    if (winkel > 180)
    winkel -= 180;
Auserdem habe ich versucht das Problem mit 12 und 24 Uhr zu lösen.
C++:
    if(s == 12 || s == 24) {
        cout << "Falsche Eingabe." << endl;
        return 1;
    }
    else {
    ....
    }

Auserdem @ sheel:
Ich habe deinen Code mal ausprobiert, der gehtn icht. Da kommt, egal was man eintippt, -0,00 Grad heraus.

Gruß
Odin
 
Zuletzt bearbeitet:
Welchen Compiler/Betriebssystem verwendest du denn?
Bei mir funktioniert mein Code einwandfrei.

Zu deinem:
1) Bei dir wäre 12 Uhr eine ungültige Eingabe.
12 ist nicht >12, also wird das erste if nichtgemacht, und dann sgast du bei 12 oder 24 Ungültig. Warum das?

2) Die Prüfung auf die ungültige Eingabe solltest du vor dem minus-12-rechnen machen.
Und nur prüfen, ob die Minuten zwischen 0 und 60 und die Stunden von 0 bis 24 sind.
Nicht 12 als ungültig erklären.

3) Du hast ein int i (=360). Warum? Du verwendest es nie.

4) Wenn du die vorigen Beiträge gelesen hättest, wüsstest du, dass statt
C++:
if(s>12) s-=12;
das hingehört:
C++:
while(s>=12) s-=12;
Das >=, weil 12 den gleichen Winkel wie 0 ergibt und deshalb 12 auch auf 0 hintergerechnet werden sollte.
Ist für die Winkelberechnung nur hilfreich.
Und das while, damit auch 24 nicht nur auf 12, sondern auch auf 0 zurückgerechnet wird.
Und statt dem Teil könntest du auch einfach
C++:
s%=12;
machen.
% (Modulo) macht praktisch eine Division (hier durch 12), nimmt aber nicht das Ergebnis sondern den Rest.
Also bleibt auch nur irgendwas von 0 bis 11 übrig.

5) ie Reiehnfolge der letzten beiden ifs ändern.

7) Statt
C++:
winkel=winkel*(-1)
würde das auch reichen:
C++:
winkel=-winkel

8) Beim >180... solltest du eher
winkel=360-winkel rechnen

Gruß
 
Zuletzt bearbeitet:
Zurück