Forum: Mikrocontroller und Digitale Elektronik Fehler mit if Anweisung


von Tom (Gast)


Angehängte Dateien:

Lesenswert?

Hallo ZUsammen,

ich hätte mal eine Frage,
Auf wieviele Anweisungen innerhalb einer () ist man gegrenzt oder gibt
es keine Begrenzung.
Ich beschäftige mich noch nicht sehr lange mit dem Thema C
programmieren.
Ich versuche das DCF Signal auszulesen,ich werde bereits die
Paritätsits aus und wollte nun noch die die Werte für Uhrzeit,Datum auf
Ihre Richtigkeit hin überprüfen.
Doch leider gibt die if Anweisung immer den Wert als OK aus selbst wenn
ich einen Wert Eingebe der bei der Prüfung eigentlich schlecht sein
müssste.

Danke für Eure Antworten.

Tom

von crazy horse (Gast)


Lesenswert?

was ist das denn für ein Monstrum?
Ob es Beschränkungen gibt, weiss ich nicht, wenn ja, dann nicht von C
allgemein her, sondern vom Compiler her. Schon aus Gründen der
Übersichtlichkeit solltest du das etwas vereinfachen und sinnlose
Ausdrücke ersatzlos streichen :-)
Ich habe nicht versucht zu verstehen, was du meinst.

(STD_ZEHN<=2)&&(STD_ZEHN>=2) //STD_Zehn==2?
(STD_EIN<=3)&&(STD_EIN>=0)   //STD_EIN<=3?
(MIN_ZEHN<=5)&&(MIN_ZEHN>=0) //STD_EIN<=5?
(MIN_EIN<=9)&&(MIN_EIN>=0)   //dto
(TAG_ZEHN<=3)&&(TAG_ZEHN>=0) //usw
(TAG_EIN<=9)&&(TAG_EIN<=1)   //usf

von Tom (Gast)


Lesenswert?

jaja ist schon etwas grösser als sonst.
1.(STD_ZEHN<=2)&&(STD_ZEHN>=2) //STD_Zehn==2?
2.(STD_EIN<=3)&&(STD_EIN>=0)   //STD_EIN<=3?
3.(MIN_ZEHN<=5)&&(MIN_ZEHN>=0) //STD_EIN<=5?
4.(MIN_EIN<=9)&&(MIN_EIN>=0)   //dto
5.(TAG_ZEHN<=3)&&(TAG_ZEHN>=0) //usw
6.(TAG_EIN<=9)&&(TAG_EIN<=1)   //usf

zu 1. ich habe nur <=2 eingegeben damit das Ergebnis falsch sein sollte
normalerweise <=0.
zu 2-6. ich werte die werte in einer und zehner aus, also z.B. STD_EIN
=5 und STD_Zehn =1 daraus ergibt sich 15.
Nun wollte ich alle Werte prüfen hier die Erkärung für Stunden.
Stunden Einer (STD_EIN) muss zwischen 0 und 9 liegen und (STD_ZEHN)
zwischen 0 und 2 und das eben mit allen Werten damit ich sicher bin
dass nichts wie 34 Stunden herauskommt.

Gruss

TOM

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Du verknüpfst viele einzelne Bedingungen mit logischem Oder - damit
genügt es, wenn eine einzige der Bedingungen zutrifft, damit der
gesamte Ausdruck zutrifft.

Du solltest Deine Bedingungen anders formulieren ...

if ((STD_ZEHN < 0) || (STD_ZEHN > 2) || (STD_EIN < 0) || (STD_EIN > 9)
.. etc

um Fehler zu lokalisieren.

Wobei das nicht wirklich genügt; so würde beispielsweise 27 als
Stundenwert akzeptiert.

Sinnvoller ist ein Umrechnen in ganze Zahlen und nachfolgender Test der
Ergebnisse:

   int stunden = STD_ZEHN * 10 + STD_EIN;

   if ((stunden < 0) || (stunden > 23))
    ... fehler

etc.

von Tom (Gast)


Lesenswert?

@Rufus,

ich habe nur bedenken wenn z.B. in den STD_ZEHN 1 steht und in den
STD_EIN eine 12 (-->fehlerhafte Daten) und ich addiere diese dann kommt
22 heraus.
Und der Wert würde auch akzeptiert. Ich denke ich muss beides abfragen
sowohl die einzelnen werte als auch die Summe.
Ist auf alle Fälle ein guter Tipp gewesen habe nicht an eine solche
Möglichkeit gedacht.
Bis ich die Zeit mit der nachsten Schaltsekunde setzten muss habe ich
ja genügend Zeit ~1.8 Sekunden da kann der MC schon was tun bevor er
sich langweilt:-).

Gruß und DANKE !!!!!!!!!!!!!1

Tom

von Peter D. (peda)


Lesenswert?

In C kann man beliebig unübersichtlich schreiben, da gibt es keine
Begrenzung.

Wenn man viele komplexe Bedingungen zu testen hat, schreibt man sie
besser untereinander mit goto oder in einer Schleife mit break.
1
for(;;){
2
  if( blabla1 ) // Fehlerbedingung 1
3
    break;
4
  if( blabla2 ) // Fehlerbedingung 2
5
    break;
6
  if( blabla3 ) // Fehlerbedingung 3
7
    break;
8
  ...
9
  // hier ist kein Fehler
10
  return;
11
}
12
// hier ist ein Fehler aufgetreten
13
return;


Peter

von Unbekannter (Gast)


Lesenswert?

Also Rufus und Peter haben ja schon Möglichkeiten angedeutet.

Du kannst Die Überprüfung auch Schrittweise machen. Speziell für Dein
Stundenproblem ist das ja sehr einfach.

Zwei Zahlen sind gegeben. Die erste Zahl soll die Zehner-Ziffer sein,
die zweite Zahl die Einer-Ziffer.

Also weißt Du schon mal:

  a.) Gültigkeitsbereich erste Zahl (Zehner): 0 bis 2  (inkl.)

  b.) Gültigkeitsbereich zweite Zahl (Einer): 0 bis 9  (inkl.)

Nun sollen diese beiden Zahlen zu einer Stundenangabe zusammengerechnet
werden.

  Stunde = Zehner * 10 + Einer

Und das Ergebnis darf nicht größer als 23 werden (Stunde 24 gibt es
nicht...):

  c.) Gültigkeitsbereich Stunde: 0 bis 23  (inkl).


Das Prinzip ist immer gleich: Teile und hersche.

Das Problem immer in kleine Teilprobleme zerlegen und die kleinen
Teilprobleme nacheinander lösen. Das ist immer leichter als alles auf
einmal machen zu wollen.

Und wenn Du es dann noch ganz schön machen willst, gibts Du jeder
Bedingungen einen eigenen Namen, machst also aus jeder Bedingung eine
kleine Mini-Funktion. Zusätzlich fasst Du verschiede Sachen zusammen.
Dann wird Dein Code wunderbar einfach zu lesen und zu verstehen. Also
in etwa so:


  bool ist_ziffer_gueltig(int ziffer)
  {
    return ( ziffer >= 0 )  &&  ( ziffer <= 9 );
  }

  bool ist_stunde_gueltig(int stunde)
  {
    return ( stunde => 0 )  &&  ( stunde <= 23 );
  }

  bool ist_minute_gueltig(int minute)
  {
    return ( minute => 0 )  &&  ( minute <= 59 );
  }

  int kombiniere_ziffern(int zehner_ziffer, int einer_ziffer)
  {
    return zehner_ziffer * 10  +  einer_ziffer;
  }


Mit diesem Rüstzeug kannst Du nun das Problem erschlagen:

  int stunde_zehner = ...
  int stunde_einer = ...
  int minute_zehner = ...
  int minute_einer = ...

  bool alle_ziffern_gueltig =
     ist_ziffer_gueltig(stunde_zehner)
  && ist_ziffer_gueltig(stunde_einer)
  && ist_ziffer_gueltig(minute_zehner)
  && ist_ziffer_gueltig(minute_einer);

  int stunde = kombiniere_ziffern(stunde_zehner, stunde_einer);
  int minute = kombiniere_ziffern(minute_zehner, minute_einer);

  bool uhrzeit_gueltig =
     alle_ziffern_gueltig
  && ist_stunde_gueltig(stunde)
  && ist_minute_gueltig(minute);

  if (!( uhrzeit_gueltig ))
  {
    // Fehlerbehandlung
    // Entweder ganz einfach, oder je nachdem wo der Fehler
    // genau lag.
  }


Keine Angst vor den vielen Zeilen. Dieser C-Code ist garantiert absolut
verständlich, auch wenn Du nach 10 Jahren wieder daran etwas ändern
musst. Vor allem brauchst Du keinerlei Hilfkonstrukte wie for(;;) und
break usw.

Und das allerschönste daran: Du brauchst Keine Kommentare zu schreiben.
Der C-Code ist so ausführlich und einfach dass jeder Kommentar
überflüssig ist. Was der C-Code macht, wird sofort ersichtlich.

von The Daz (Gast)


Lesenswert?

@Unbekannter

Beim Thema divide-et-impera hast du voellig Recht. Was ich nicht
verstehe ist, warum loops fuer dich Hilfskonstrukte sind. Eigentlich
sind das ganz zentrale Konstrukte um den Code nicht unnoetig
aufzublaehen. Habe ich dich falsch verstanden ?

   Daz

von Unbekannter (Gast)


Lesenswert?

Ach, das

    if (!( uhrzeit_gueltig ))

schreibt man besser als

    if ( uhrzeit_gueltig == false )

Dann ist der Sinn besser verständlich.


Manche Schreiben auch:

    if ( false == uhrzeit_gueltig )

Das gefällt mir aber nicht so toll. Die Idee dahinter ist, dass bei der
zweiten Form garantiert jeder Compiler einen Fehler meldet, wenn man
anstatt "==" nur ein "=" schreibt.

Vernüftige und moderne Compiler bringen dafür aber auch in der ersten
Form eine Warnmeldung. Von daher schaue ich lieber auf die
Warnmeldungen anstatt den Sinn des Codes zu verdrehen.

von Unbekannter (Gast)


Lesenswert?

@The Daz:

Ich bezug mich auf peter danneggers Vorschlag:


  for(;;){
    if( blabla1 ) // Fehlerbedingung 1
      break;
    if( blabla2 ) // Fehlerbedingung 2
      break;
    if( blabla3 ) // Fehlerbedingung 3
      break;
    ...
    // hier ist kein Fehler
    return;
  }
  // hier ist ein Fehler aufgetreten


Ein for(;;) um die Fehlerbehandlung zu strukturieren finde ich nicht so
der Hit.

von Peter D. (peda)


Lesenswert?

@Unbekannter

"Ein for(;;) um die Fehlerbehandlung zu strukturieren finde ich nicht
so der Hit."


Ich habe auch nicht vor, Hits zu schreiben, sondern gut lesbare und
verstehbare Programme und das ist es doch oder ?

Ich nehme mit Absicht kein do{}while(0), weil dieses for(;;){} sehr
charakeristisch darauf hinweist, daß hier anders abgebrochen wird.

Man kann natürlich auch Ketten von ORs untereinander schreiben.
Aber wenn die Ausdrücke komplexer werden, verliert man schnell den
Überblick in dem Klammern-Wust.

Auch hat die Schleifenmethode den Vorteil, zwischen den Tests weitere
Berechnungen einfügen zu könnnen.
Es macht ja keinen Sinn alle Berechnungen zu Anfang zu machen um dann
nach dem ersten Test festzustellen, daß die meisten unnötig waren.


Peter

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.