Forum: PC-Programmierung C-Code Zwei Uhrzeiten, berechnung Differenz, falsche Werte


von Tobias Straub (Gast)


Lesenswert?

Ich grüße euch.
Ich habe gerade ein Programm in C geschrieben bei dem der Anwender zwei 
Uhrzeiten im Format hh:mm eingeben kann. Diese Zeiten werden als 
einzelne Arrays eingespeichert. Dann übergebe ich die Arrays an eine 
Funktion.
Hier rechne ich das Array erst einmal um, um die richtigen Zahlen zu 
erhalten. (Zwecks Ascii-Tabelle).
Danach rechne ich mit den Zeiten ein bisschen und gebe die Differenz in 
3 Formaten raus:
Stunden:Minuten,
Minuten,
Stunde dezimal
Wenn ich das Programm so laufen lasse kommen allerdings ganz komische 
Zahlen heraus und die Differenzen sind in jedem Format 0.
Stimmt jetzt das einlesen nicht? Die Übergabe an die Funktion mittels 
Pointer oder ist die Umrechnung in eine „richtige“ Zahl falsch?
Ich finde irgendwie den Fehler nicht.
Vielen Dank im Vor raus, hier noch mein C-Code:
1
#include "stdafx.h"
2
#include "stdio.h"
3
#include "stdlib.h"
4
#include "math.h"
5
6
void Funktion_Berechnung(char *startzeit, char *endzeit);
7
8
int main()
9
{
10
  char uhrzeit1[6], uhrzeit2[6];
11
  printf("Bitte geben Sie zwei Uhrzeiten ein (hh:mm)\n");
12
  printf("1. Uhrzeit:\n");
13
  scanf_s("%s", uhrzeit1, 5);
14
  fflush(stdin);
15
  printf("2. Uhrzeit:\n");
16
  scanf_s("%s", uhrzeit2, 5);
17
  Funktion_Berechnung(uhrzeit1, uhrzeit2);
18
}
19
void Funktion_Berechnung(char *startzeit, char *endzeit)
20
{
21
  int h1 = 0, m1 = 0, h2 = 0, m2 = 0, typ1, typ2, stunden, minuten, zeit;
22
  float minuten2;
23
24
  h1 = (((startzeit[0] - 48) * 10) + (startzeit[1] - 48));
25
  m1 = (((startzeit[3] - 48) * 10) + (startzeit[4] - 48));
26
27
  h2 = (((endzeit[0] - 48) * 10) + (endzeit[1] - 48));
28
  m2 = (((endzeit[3] - 48) * 10) + (endzeit[4] - 48));
29
30
  typ1 = h1 * 60 + m1;  // Umwandlung der ersten Uhrzeit in Minuten
31
  typ2 = h2 * 60 + m2;  // Umwandlung der zweiten Uhrzeit in Minuten
32
  zeit = typ2 - typ1;    // Differenz der zwei Uhrzeiten in Minuten
33
34
  stunden = zeit / 60;    // Umrechnung Differenz --> Stundenanteil
35
  minuten = zeit % 60;    // Umrechnung Differenz --> Minutenanteil
36
37
  minuten2 = (float)zeit / 60.0;  // Umrechnung in Gleitkommazahl --> Hier muss float verwendet werden
38
39
  printf("\nVon %d:%d bis %d:%d sind es %d:%d (Stunden/Minuten) \nbzw. %d Minuten \nbzw. %.2f Stunden\n\n", h1, m1, h2, m2, stunden, minuten, zeit, minuten2);
40
41
42
43
  system("pause");
44
}

von Klaus W. (mfgkw)


Lesenswert?

gute Gelegenheit, mal den Debugger zu probieren!
Damit kannst du dein Programm schrittweise abarbeiten lassen und alle 
berechneten Werte anschauen...

von npn (Gast)


Lesenswert?

Tobias Straub schrieb:
> Ich habe gerade ein Programm in C geschrieben

Hallo Tobias,

als erstes mal die Frage, willst du Berechnungen in C üben, oder soll 
das Programm einfach seinen Zweck erfüllen?
Wenn zweiteres der Fall ist, könntest du die zwei Zeiten mit den 
time-Funktionen, die in C enthalten sind, jeweils umrechnen in die 
Unix-Zeit (z.B. mktime). Dann die beiden subtrahieren und die Differenz 
einfach zurückwandeln z.B. in einen String (z.B. ctime oder asctime).

einzige Voraussetzung: #include <time.h>

von Tobias Straub (Gast)


Lesenswert?

npn schrieb:
> Tobias Straub schrieb:
>> Ich habe gerade ein Programm in C geschrieben
>
> Hallo Tobias,
>
> als erstes mal die Frage, willst du Berechnungen in C üben, oder soll
> das Programm einfach seinen Zweck erfüllen?
> Wenn zweiteres der Fall ist, könntest du die zwei Zeiten mit den
> time-Funktionen, die in C enthalten sind, jeweils umrechnen in die
> Unix-Zeit (z.B. mktime). Dann die beiden subtrahieren und die Differenz
> einfach zurückwandeln z.B. in einen String (z.B. ctime oder asctime).
>
> einzige Voraussetzung: #include <time.h>


Es ist eine Aufgabe von der Hochschule. Ich möchte das Programmieren 
üben. Vor allem auch die Übergabe von Funktionen. Anwendungen mit Arrays 
und und und. Also sollte es eher so gemacht werden wie ich es 
geschrieben habe. Allerdings finde ich hierbei keinen Fehler.


Das mit dem Debuggen ist nicht meine Stärke haha. Aber ich werde es mal 
versuchen. Habt ihr denn schon einen Fehler in meinem Programm gefunden?

von Klaus W. (mfgkw)


Lesenswert?

Tobias Straub schrieb:
> Habt ihr denn schon einen Fehler in meinem Programm gefunden?

Nein, habe ich nicht.
Ich habe es auch gar nicht genau angeschaut.

Grund: das ist ein typischer Fehler, den man mit einem Debugger leicht 
findet, und das ist eine Grundfertigkeit zum Programmieren.
Also darfst du dich da gerne selber reinfuchsen.

Ohne jede Gehässigkeit - wenn man sowas noch nicht gemacht hat, wird es 
Zeit.

von Tobias Straub (Gast)


Lesenswert?

Klaus Wachtler schrieb:
> Nein, habe ich nicht.
> Ich habe es auch gar nicht genau angeschaut.
>
> Grund: das ist ein typischer Fehler, den man mit einem Debugger leicht
> findet, und das ist eine Grundfertigkeit zum Programmieren.
> Also darfst du dich da gerne selber reinfuchsen.
>
> Ohne jede Gehässigkeit - wenn man sowas noch nicht gemacht hat, wird es
> Zeit.

Hey,
also habe gerade mal mit dem Debugger durchgeschaut. Hierbei habe ich 
erkannt das er in meinem String am Anfang die zahlen 51 und 52 jeweils 
drin stehen hat und beim beschreiben der Strings es nicht annimmt.
Was könnte der fehler an meinem scanf_s sein?

Das habe ich noch verändert:
1
char uhrzeit1[6] = { 0 }, uhrzeit2[6] = { 0 };

außerdem hier mein scanf_s:
1
  printf("1. Uhrzeit:\n");
2
  scanf_s("%s", uhrzeit1, 5);
3
  fflush(stdin);
4
  printf("2. Uhrzeit:\n");
5
  scanf_s("%s", uhrzeit2, 5);
6
  fflush(stdin);

von N. A. (hannilein)


Lesenswert?

Kleiner Tip: Nutze das Unix Time Format.

von npn (Gast)


Lesenswert?

N. A. schrieb:
> Kleiner Tip: Nutze das Unix Time Format.

Habe ich auch schon vorgeschlagen, geht aber nicht:

Tobias Straub schrieb:
> Es ist eine Aufgabe von der Hochschule. Ich möchte das Programmieren
> üben. Vor allem auch die Übergabe von Funktionen. Anwendungen mit Arrays
> und und und. Also sollte es eher so gemacht werden wie ich es
> geschrieben habe.

von Karl H. (kbuchegg)


Lesenswert?

Tobias Straub schrieb:

> Stimmt jetzt das einlesen nicht?


Wer oder was hindert dich daran, das Eingelesene gleich nach der Eingabe 
erst mal zur Sicherheit wieder auszugeben? Nur so, einfach nur um zu 
sehen, ob das auch alles geklappt hat.

Stimmt. Nichts hindert dich

> int main()
> {
>   char uhrzeit1[6], uhrzeit2[6];
>   printf("Bitte geben Sie zwei Uhrzeiten ein (hh:mm)\n");
>   printf("1. Uhrzeit:\n");
>   scanf_s("%s", uhrzeit1, 5);
>   fflush(stdin);
>   printf("2. Uhrzeit:\n");
>   scanf_s("%s", uhrzeit2, 5);
1
    printf( "Erste Eingabe: '%s'\n", uhrzeit1 );
2
    printf( "Zweite Eingabe: '%s'\n", uhrzeit2 );
>   Funktion_Berechnung(uhrzeit1, uhrzeit2);
> }

und schon brauchst du nicht mehr uns fragen, sondern dein Programm 
'erzählt' dir, was du wissen willst.

Merke: Es ist nicht verboten, sich während der Entwicklungsphase sein 
Programm mit printf zu spicken, so dass einem das Programm selbst 
erzählt, was es an welcher Stelle warum tut.

Die printf kommen dann wieder raus, wenn alles fertig ist und alles 
sieht so aus, als ob es immer und von Anfang an so gewesen wäre.


Das ist das Debugging des kleinen Mannes. Ein echter Debugger hat seine 
Vorteile, etwas flexibler reagieren zu können. Dafür hat die printf 
Methode den Vorteil, dass man erstens keine externen Werkzeuge benötigt 
und man zweitens die printf von einer Debug Sitzung zur nächsten 
'mitnehmen' kann. Ist eine Ausgabe erst mal im Programm, so erfolgt die 
Ausgabe bei jedem Testlauf und man kann untersuchen ob und was sich 
verändert hat. Speziell wenn die Datenstrukturen dann schon mal 
komplexer werden, können Debugger da selten mithalten.
Praktisch gesehen muss man mit beidem umgehen können.

von Klaus W. (mfgkw)


Lesenswert?

Noch was: wenn Funktionen einen Wert zurückliefern, macht es Sinn diesen 
Rückgabewert auch mal anzuschauen. Zusammen mit der Doku der Funktion 
hat man gelegentlich dann auch eine Idee, was schiefläuft.

von Karl H. (kbuchegg)


Lesenswert?

Und noch ein kleiner Tip.

Lies in deinen Unterlagen nach, was ein %s in der Format-Liste bei einem 
scanf ganz genau macht. Und dann stell das mal in Beziehung zu den 
Tasten, die du drückst. Und merke: Auch ein Return ist ein Tastendruck, 
der zu deinem Programm "durchgestellt" wird und der daher beim scanf 
ankommt.

von Tobias Straub (Gast)


Lesenswert?

Klaus Wachtler schrieb:
> Noch was: wenn Funktionen einen Wert zurückliefern, macht es Sinn diesen
> Rückgabewert auch mal anzuschauen. Zusammen mit der Doku der Funktion
> hat man gelegentlich dann auch eine Idee, was schiefläuft.

Meine Funktion liefert doch gar nichts zurück. Ich gebe nur die Arrays 
an die Funktion und in der Funktion mache ich dann auch die Ausgabe...
Das mit dem printf zur überprüfung hab ich gerade gemacht (mach ich 
öfters so). Das Problem ist jetzt das er mir für die erte zeit genau den 
string gibt den ich einlese, also bei mir 07:00 aber die zweite zeit 
zeigt er mir mittels der printf gar nicht an....
das ist voll komisch

von Klaus W. (mfgkw)


Lesenswert?

Tobias Straub schrieb:
> Meine Funktion liefert doch gar nichts zurück.

Deine nicht, aber das scanf.

von Tobias Straub (Gast)


Lesenswert?

Hab jetzt mit dem printf nochmal überprüft was mein scanf überhaupt 
einliest. Als ausgabe kommt bei beiden "(null)"
Das bedeutet doch das er meine zahlen überhaupt nicht speichert oder? 
Und null weil ich das array oben eben mit nullen fülle...
Aber ich hab nachgeschaut, ein string liest man so ein.
Kann mir bitte einer eine lösung geben?
Grüße

von Karl H. (kbuchegg)


Lesenswert?

Tobias Straub schrieb:
> Hab jetzt mit dem printf nochmal überprüft was mein scanf überhaupt
> einliest. Als ausgabe kommt bei beiden "(null)"
> Das bedeutet doch das er meine zahlen

Zahlen?
Wieso Zahlen?

Du hast keine Zahlen. Du hast erst mal nur Texte. An dieser Stelle ist 
es noch völlig unerheblich ob du "07:00" oder "Test" eingibst. Text ist 
Text und nur weil da einige Zeichen Ziffernzeichen sind, hast du noch 
lange keine Zahlen.

> überhaupt nicht speichert oder?
> Aber ich hab nachgeschaut, ein string liest man so ein.
> Kann mir bitte einer eine lösung geben?

Hast du direkt über deinem Posting von 18:21 mein Posting gesehen?
Das ist nämlich wichtig, dass du diesen Zusammenhang verstehst und was 
da abgeht.

: Bearbeitet durch User
von Tobias Straub (Gast)


Lesenswert?

Naja ich deklariere ein String mit 6 Zeichen, da ich 5 Zeichen eingebe 
(hh:mm) und das 6. Zeichen halte ich für das 0 Glied frei zum beenden 
des Strings. Und beim scanf_s also beim einlesen, lese ich dann aber nur 
5 Zeichen ein:

        scanf_s("%s", &uhrzeit1[5]);
  fflush(stdin);
  printf("2. Uhrzeit:\n");
  scanf_s("%s", &uhrzeit2[5]);
  fflush(stdin);

Und danach lösche ich noch den Tastaturpuffer um jeglichen Mist 
rauszuscheisen denn ich nicht will.

Mach ich denn dabei etwas falsch?

von Tobias Straub (Gast)


Lesenswert?

Habe gerade einfach mal in die zwei arrays schon eine feste uhrzeit 
eingeben. also

char uhrzeit1[6] = { 0,7,':',3,0 }, uhrzeit2[6] = { 0,8,':',3,0};

Dann rechnet er auch alles aus, egal was ich in mein bölödes scanfs 
einlese. Das heißt der scanf_s funktioniert eindeutig nicht. Aber ich 
finde einfach nicht den Fehler was ich ändern muss.

Please help :)

von hp-freund (Gast)


Lesenswert?

uhrzeit1[5] - wieviele Zeichen sind das?

von Karl H. (kbuchegg)


Lesenswert?

Tobias Straub schrieb:

>         scanf_s("%s", &uhrzeit1[5]);

&uhrzeit[5]  ?

von Karl H. (kbuchegg)


Lesenswert?

Tobias Straub schrieb:

> Und danach lösche ich noch den Tastaturpuffer um jeglichen Mist
> rauszuscheisen denn ich nicht will.

Tja
Nur. Genau genommen ist überhaupt nicht definiert, was ein
fflush(stdin)
überhaupt macht.

Es ist zwar eine weit verbreitete Annahme, das dieses alle noch 
wartenden Zeichen aus dem Eingabestrom rausschiesst. Aber wie das mit 
Annahmen eben so ist ....

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:
> Tobias Straub schrieb:
>
>>         scanf_s("%s", &uhrzeit1[5]);
>
> &uhrzeit[5]  ?

Du sagst deinem scanf damit:

Hier, das ist mein Array, in dem das Ergebnis landen soll
1
   +---+---+---+---+---+---+
2
   |   |   |   |   |   |   |
3
   +---+---+---+---+---+---+

und mittels &uhrzeit[5] sagst du dem scanf: Das eingelesene bitte ab 
hier
1
   +---+---+---+---+---+---+
2
   |   |   |   |   |   |   |
3
   +---+---+---+---+---+---+
4
                     ^
5
                     |
6
                   hier
ablegen.

Tja.
Ich würde ja mal sagen, der scanf sollte beim Einlesen vorne im Array 
anfangen und nicht mitten drinn.

von Klaus W. (mfgkw)


Lesenswert?

Aber im ursprünglichen Qelltext stand das noch anders...

von Tobias Straub (Gast)


Lesenswert?

Jo der array so ist falsch. Hier die richtige eingabe. Tut aber trotzdem 
nicht:
1
char uhrzeit1[6], uhrzeit2[6];
2
  printf("Bitte geben Sie zwei Uhrzeiten ein (hh:mm)\n");
3
  printf("1. Uhrzeit:\n");
4
  scanf_s("%s", &uhrzeit1,5);
5
  fflush(stdin);
6
  printf("2. Uhrzeit:\n");
7
  scanf_s("%s", &uhrzeit2,5);
8
  fflush(stdin);
9
  Funktion_Berechnung(uhrzeit1, uhrzeit2);


gruß

von Karl H. (kbuchegg)


Lesenswert?

Klaus Wachtler schrieb:
> Aber im ursprünglichen Qelltext stand das noch anders...

:-)
Wie meistens.
Planloses rumprobieren ohne zu wissen, was eigentlich das Problem ist.

von Karl H. (kbuchegg)


Lesenswert?

OK.
Machen wirs kurz

dein Problem ist
* das sich der scanf, so wie du den Format Specifier geschrieben hast, 
den Return NICHT aus dem Eingabestrom holt. Wodurch der 2.te scanf als 
erstes Zeichen den Return sieht und damit seinerseits die Eingabe 
bereits für beendet erklärt, noch ehe es zu den interessanten Zeichen 
kommt.
* das das Verhalten fflush(stdin) nicht definiert ist. Insbesonders ist 
es wohl auf deinem System so, dass dieses einfach nichts macht. 
Insbesondere nicht den Eingabebuffer ausleert.

Wenn du Strings einlesen willst, dann ist scanf keine so gute Wahl. Um 
Strings einzulesen nimmt man besser fgets, welches eine Menge Probleme 
löst. Insbesondere die, die dich jetzt plagen. Aber Achtung: fgets liest 
auch den \n vom Eingabestrom und speichert ihn im String ab! Du musst 
also Platz dafür vorsehen.

: Bearbeitet durch User
von Tobias Straub (Gast)


Lesenswert?

Problem GELÖST:

Beim scanf_s muss ich ihm ja sagen wie viel Zeichen er einlesen darf. 
Habe das ja auch gemacht mit ",5". ABER ich muss ja ",6" machen weil er 
ja das beenden zeichen auch nich braucht. So nen Sch*** haha
Sorry für das nerven aber auch vielen Dank für eure Hilfe. Ihr seit 
super!

Grüße

von Tobias Straub (Gast)


Lesenswert?

Karl Heinz schrieb:
> OK.
> Machen wirs kurz
>
> dein Problem ist
> * das sich der scanf, so wie du den Format Specifier geschrieben hast,
> den Return NICHT aus dem Eingabestrom holt. Wodurch der 2.te scanf als
> erstes Zeichen den Return sieht und damit seinerseits die Eingabe
> bereits für beendet erklärt, noch ehe es zu den interessanten Zeichen
> kommt.
> * das das Verhalten fflush(stdin) nicht definiert ist. Insbesonders ist
> es wohl auf deinem System so, dass dieses einfach nichts macht.
> Insbesondere nicht den Eingabebuffer ausleert.
>
> Wenn du Strings einlesen willst, dann ist scanf keine so gute Wahl. Um
> Strings einzulesen nimmt man besser fgets, welches eine Menge Probleme
> löst. Insbesondere die, die dich jetzt plagen. Aber Achtung: fgets liest
> auch den \n vom Eingabestrom und speichert ihn im String ab! Du musst
> also Platz dafür vorsehen.


Jap, genau das war das Problem. =)

von DirkB (Gast)


Lesenswert?

Du kannst auch einen Whitespace (z.B,. Leerzeichen) in den Formatsring 
vom scanf einbauen.
Das weist scanf an, Whitespaces zu überlesen (so sie denn vorhanden 
sind)


Karl Heinz schrieb:
> das das Verhalten fflush(stdin) nicht definiert ist. Insbesonders ist
> es wohl auf deinem System so, dass dieses einfach nichts macht.
> Insbesondere nicht den Eingabebuffer ausleert.

Das stdafx.h und auch das scanf_s deuten doch sehr stark auf Visual 
Studio/Windows hin.
Und von da kommt ja das unsägliche fflush(stdin)

von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

Ich habe jetzt nicht den gesamten Thread gelesen, aber ich würde 
folgende Strategie verwenden. Die ist für den User simpel, 
nachvollziehbar und man muss sich nicht mit selbstgestrickten 
Kalenderfunktionen herumärgern:

- Startzeit (Datum und Uhrzeit) in "total seconds" umrechnen
- Endzeit ebenso
- Startzeit von Endzeit abziehen
- Ergebnis von total seconds nach d:h:m:s formatieren ...

Als Basis für "total seconds" benutzen versch. Prog.-Sprachen versch. 
Bezugstermine, z.B. den 01.01.1900 00:00 oder andere, oft gibts diese 
Funktion auch "fertig" oder als Lib zum Hinzufügen.

Für die Eingabe würde ich irgend eine starre (!) Maske mit Auf- und 
Ab-Pfeil bzw. +- in einer Textumgebung machen. Das bewahrt vor mühsamem 
Parsing ... denn jeder Depp schreibt was Anderes, wenn er kann ... das 
entfällt dann enfach :-)

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.