Forum: Mikrocontroller und Digitale Elektronik Verständnisproblem bei C-Programmierung


von Christian (Gast)


Lesenswert?

Hallo,

habe einen Auf- und Abwartszähler für ein LC-Display in C mit ATMega16 
programmiert. Der Code funktionierte, war aber noch etwas lang. Habe ihn 
also etwas gekürzt. Darauf hin funktionierte nur noch das 
Aufwärtszählen. Ich kann mir nicht erklären warum nur noch das 
Aufwärtszählen funktioniert und das Abwärtszählen nicht. Kann mir das 
jemand erklären? Oder habe ich einen Fehler gemacht, den ich nicht 
entdeckt habe?

Hier die Programmausschnitte.

Funktionierende Abwärtszählung
1
if ((*z_i <= 48 ) & (*e_i <= 48))
2
   {
3
       *h_i = *h_i - 1;
4
  
5
        *z_i = 57;
6
        *e_i = 57;
7
   }
8
9
   else
10
   {
11
        if (*e_i <=48)
12
        {
13
          *z_i = *z_i - 1;
14
          *e_i = 57;
15
        }
16
            
17
        else
18
        {
19
          *e_i = *e_i - 1;
20
        }
21
   }

Funktionierende Aufwärtszählung gekürzt
1
if ((*z_u & *e_u) >= 57)
2
{
3
        *h_u = *h_u + 1;
4
5
        *z_u = 48;
6
        *e_u = 48;
7
}
8
9
else
10
{
11
        if (*e_u >=57)
12
        {
13
           *z_u = *z_u + 1;
14
           *e_u = 48;
15
        }    
16
17
        else
18
        {
19
            *e_u = *e_u + 1;
20
        }
21
}

Nichtfunktionierende Abwärtszählung gekürzt
1
if ((*z_u & *e_u) <= 48)
2
{
3
        *h_u = *h_u - 1;
4
5
        *z_u = 57;
6
        *e_u = 57;
7
}
8
9
else
10
{
11
        if (*e_u <= 48)
12
        {
13
          *z_u = *z_u - 1;
14
          *e_u = 57;
15
        }    
16
17
        else
18
        {
19
          *e_u = *e_u - 1;
20
        }
21
}

von us73 (Gast)


Lesenswert?

Du kennst den Unterschied zwischen "bitwise AND" und "logical AND" ??

Ich bin mir nahezu sicher, dass Du statt "&" hier besser "&&" verwenden 
solltest..., weil ich kann mir nicht vorstellen, dass Du die 
Dereferenzierungen von z_u und e_u bitwise UND verknüpfen willst.

von us73 (Gast)


Lesenswert?

Zudem sind das zwei Bedingungen, die Du prüfen willst. Also prüfe sie 
auch getrennt.

if ((*z_u <= 48) &&  (*e_u <= 48))

Da gibt es nichts zu verkürzen.

von Karl H. (kbuchegg)


Lesenswert?

Deine magischen Konstanten kommen mir aber sehr bekannt vor.

Wenn du den Code so schreiben würdest
1
    if ((*z_i <= '0' ) && (*e_i <= '0' ))
2
   {
3
       *h_i = *h_i - 1;
4
  
5
        *z_i = '9';
6
        *e_i = '9';
7
   }
8
9
   else
10
   {
11
        if (*e_i <= '0')
12
        {
13
          *z_i = *z_i - 1;
14
          *e_i = '9';
15
        }
16
            
17
        else
18
        {
19
          *e_i = *e_i - 1;
20
        }
21
   }

dann wäre wenigstens ansatzweise klar, dass dein Zähler im Grunde im 
ASCII Code zählt.

Noch einfacher wäre es allerdings, wenn du das Ganze so machst, wie man 
das auch mit Papier und Bleistift machen würde. Man fängt bei den Einern 
an und subtrahiert 1. Bei einem Unterlauf (borgen von der nächsten 
Stelle) arbeitet man sich dann immer weiter 'nach links' vor.
1
     *e_i = *e_i - 1;          // Einerstelle 1 abziehen
2
3
     if( *e_i < '0' )          // Unterlauf?
4
     { 
5
       *z_i = *z_i - 1;        //    von den Zehnern eines runter
6
       *e_i = '9';
7
8
       if( *z_i < '0' )        //    Zehner Unterlauf?
9
       {
10
         *h_i = *h_i - 1;      //        von den Hundertern eines runter
11
         *z_i = '9';           
12
       }
13
     }

In vielen Fällen ist es klug, einfach zu beobachten wie man selbst ein 
Problem mit Papier und Bleistift löst, und diese Lösungsstrategie dann 
in Code umsetzt.

von Christian (Gast)


Lesenswert?

Vielen Dank für die Hilfe. Habe den vereinfachten Code benutzt. Jetzt 
klappt es einwandfrei. Auch das mit dem ASCII war sehr nützlich, war mir 
gar nicht klar, dass ich das in dieser Form so machen kann.

Was ich jetzt noch gerne zum Verständnis und für das nächste mal genauer 
wissen würde ist:
Warum hat das hier geklappt mit dem Verknüpfen:
1
if ((*z_u & *e_u) >= 57)

und hier nicht?
1
if ((*z_u & *e_u) <= 48)

Mal davon abgesehen das es hier besser wäre logisch statt bitweise zu 
verknpüfen, weil das erste hat ja trotzdem funktioniert.

von Karl H. (kbuchegg)


Lesenswert?

Christian schrieb:

> Warum hat das hier geklappt mit dem Verknüpfen:
>
1
if ((*z_u & *e_u) >= 57)
>
> und hier nicht?
>
1
if ((*z_u & *e_u) <= 48)

Weil das ganz was anderes macht.

Hier wird *z_u  mit *e_u UND verknüpft und das Ergebnis der Verknüfung 
befragt, ob es kleiner als 48 ist.

von us73 (Gast)


Lesenswert?

Christian schrieb:
> Warum hat das hier geklappt mit dem Verknüpfen:if ((*z_u & *e_u) >= 57)
> und hier nicht?if ((*z_u & *e_u) <= 48)

Weil eben das Ergebnis der Operation >= 57 war.
Ich würde es als zufällig richtiges Verhalten bezeichnen - und nicht als 
gewünscht.
Es hätte ebenso auch andersrum sein können - oder auch gar nicht.
Rein zufällig, und auch abhängig von den Daten, die Du bereitstellst. 
Aber nicht so, wie Du das haben wolltest...

Christian schrieb:
> Mal davon abgesehen das es hier besser wäre logisch statt bitweise zu
> verknpüfen, weil das erste hat ja trotzdem funktioniert.

Es wäre nicht besser. Es wäre richtig.

Logisch und Bitweise sind wie Apfel und Birne, das hat miteinander 
nichts zu tun, zwei komplett unterschiedliche Operationen.

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.