Forum: PC-Programmierung Probleme mit Aufgabe für Bitoperationen


von Schnubbi (Gast)


Lesenswert?

Hallo zusammen,

Wir sitzen hier mit vier Mann zusammen und versuchen ein Programm zu 
erstellen, da wir C erlernen wollen. Leider fehlt uns im Moment der 
Ansatz. Könntet ihr uns helfen, wie man die folgende Aufgabe lösen kann?

Schreiben Sie ein Programm, das acht einzelne Lampen an- und ausschalten 
kann und das den Status aller Lampen in einem einzigen Byte (8 Bit, 
C-Typ char) hält. Dabei steht jedes der acht Bit für den Status der 
jeweiligen Lampe, d.h. 0 steht für „Lampe an“, 1 steht für „Lampe aus“. 
Der Benutzer muss über Eingaben die einzelnen Lampen an- und ausschalten 
können. Die Benutzereingabe 7X muss Lampe 7 anschalten, die Eingabe 4- 
muss die Lampe 4 ausschalten.
Hinweis: Die Bitoperationen & und | sind hier hilfreich.
Der Benutzerdialog muss wie folgt aussehen:
1
| L1 | L2 | L3 | L4 | L5 | L6 | L7 | L8 |
2
| -  | -  | -  | -  | -  | -  | -  | -  |
3
> 4X
4
| L1 | L2 | L3 | L4 | L5 | L6 | L7 | L8 |
5
| -  | -  | -  | X  | -  | -  | -  | -  |
Man könnte doch zunächst mit

unsigned char status=8 beginnen. So hat man zumindest schon mal ein 
char, das genau ein Bit groß ist. aber wie gehe ich dann dann weiter 
vor?
Wir arbeiten mit Eclipse auf einem Windos 7 OS und GCC compiler.

: Bearbeitet durch User
von Yalu X. (yalu) (Moderator)


Lesenswert?

Googeln nach

  c bits setzen löschen

sollte weiterhelfen.

von Karl H. (kbuchegg)


Lesenswert?

Schnubbi schrieb:

> kann und das den Status aller Lampen in einem einzigen Byte (8 Bit,
> C-Typ char) hält.

unsigned char.

Wenn von Bytes die Rede ist, dann ist unsigned char der Datentyp der 
Wahl. Gewöhn dir an, den Datentyp char ausschliesslich für 
Textverarbeitung zu benutzen.


> unsigned char status=8 beginnen. So hat man zumindest schon mal ein
> char, das genau ein Bit groß ist.

Nö.
Ein unsigned char ist sowieso 1 Byte groß. (ok, ist nicht garantiert, 
aber ich wills jetzt nicht noch zusätzlich verkomplizieren). Und 1 Byte 
hat definitionsgemäß 8 Bit. Ob du da jetzt einen Wert vorgibst, der in 
'Status' gespeichert wird oder nicht.

> aber wie gehe ich dann dann weiter
> vor?

Indem du dir klar machst, wie man in einem Byte (einem unsigned char) 
gezielt
* 1 Bit setzt
* 1 Bit löscht
* abfragt, ob 1 Bit auf 1 ist oder nicht
Und zwar unter Vorgabe der gewünschten Bitnummer.

Eure Gedanken kreisen momentan um das falsche Thema. Mit
1
int main()
2
{
3
  unsigned char Status = 0;
4
...

hast du bereits die Speicherfläche für 8 Bit. Die Zuweisung von 0 sorgt 
einfach nur dafür, dass an dieser Stelle alle 8 Bits gezielt auf 0 sind.
Du musst sie nur noch gezielt einzelne Bits auf 1 bzw. auf 0 setzen, 
bzw. entsprechend abfragen.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

> Hinweis: Die Bitoperationen & und | sind hier hilfreich.

Nimm noch den ~ mit dazu, je nachdem den <<, und du hast alle Zutaten, 
die du brauchst.

von Karl H. (kbuchegg)


Lesenswert?

> aber wie gehe ich dann dann weiter vor?

Es hat sich gezeigt, dass es sinnvoll ist, zunächst mal mit der Ausgabe 
zu beginnen.

In eurem Fall also mit einer Funktion, die das hier
1
| L1 | L2 | L3 | L4 | L5 | L6 | L7 | L8 |
2
| -  | -  | -  | -  | -  | -  | -  | -  |
hinmalt, wenn 'Status' den Wert 0 hat, die das hier
1
| L1 | L2 | L3 | L4 | L5 | L6 | L7 | L8 |
2
| X  | -  | -  | -  | -  | -  | -  | -  |
hinmalt, wenn Status den Wert 1 hat (denn 1 ist binär ja 00000001, und 
da ist dieses eine Bit auf 1), bzw. die zb das hier hinmalt
1
| L1 | L2 | L3 | L4 | L5 | L6 | L7 | L8 |
2
| X  | -  | X  | -  | -  | -  | -  | -  |
wenn Status den Wert 5 hat (denn 5 ist binär ja 00000101)

Dazu braucht ihr noch keine Eingabe und auch keine Bit setzen oder 
löschen. Sondern einfach nur
1
...
2
int main()
3
{
4
  Status = 5;
5
6
  .... euer Code hier
7
}
und dann muss das Programm diese Ausgabe
1
| L1 | L2 | L3 | L4 | L5 | L6 | L7 | L8 |
2
| X  | -  | X  | -  | -  | -  | -  | -  |
produzieren.

Durch Verändern von Status direkt im Code und neucompilieren, könnt ihr 
erst mal testen, ob dieser Ausgabecode korrekt ist.


Damit würde ich anfangen, wenn ich ihr wäre.
Das grundlegende Prinzip lautet: Teile und herrsche.
Teile die Aufgabe in Teilbereiche auf und barbeite diese Teilbereiche in 
einer Reihenfolge, so dass du sie testen kannst und spätere 
implementierte Teilbereiche auf der vorhergehenden Arbeit aufbauen.
Man kann natürlich mit der Eingabe und dem Setzen von Bits anfangen. 
Kann man. Aber wie testest du das? Um zu testen ob das alles korrekt 
ist, braucht es eine Möglichkeit für die Ausgabe. Eine funktionierende 
Ausgabe ist daher so etwas eine Voraussetzung, um die Bereiche Bits 
setzen bzw. löschen auch verifizieren zu können. Also fängt man erst mal 
damit an. Es zeigt sich im allgemeinen, dass diese Strategie, erst mal 
die Ausgabe zu machen, in vielen Fällen eine gute Wahl ist. Dann kann 
man für andere Dinge einfach mal etwas annehmen (wie zb hier den Wert 
und damit die Bitbelegung in Status) und so die Ausgabefunktionalität 
durchtesten. Eine funktionierende und gesichert korrekte Ausgabe ist 
dann in weiterer Folge viel wert, weil die Unsicherheit, wo jetzt der 
Fehler im Progamm sitzt, in der Verarbeitung oder in der Ausgabe, schon 
mal wegfällt. Ist die Ausgabe ausreichend getestet, dann sitzt ein 
auftauchender Fehler meist in der Verarbeitung bzw. Eingabe.

: Bearbeitet durch User
von Schnubbi (Gast)


Lesenswert?

Erstmal danke für die Antworten. Hat uns schonmal um einiges 
weitergeholfen. Eine Frage habe ich aber noch:

Wenn wir zunächst den Char "Lampen" mit
1
unsigned char lampen=255;

angeben, sollte es sich doch um Byte handeln und nur die Stellen der 
einzelnen Bits. Sprich die 255 ergeben sich aus 128,64,32,16,8,4,2,1 der 
einzelnen Bits die addiert werden oder?

Danke schonmal.

von Karl H. (kbuchegg)


Lesenswert?

Schnubbi schrieb:

> angeben, sollte es sich doch um Byte handeln und nur die Stellen der
> einzelnen Bits. Sprich die 255 ergeben sich aus 128,64,32,16,8,4,2,1 der
> einzelnen Bits die addiert werden oder?

Ja.
es ist ein Stellenwert System, so wie du es auch in den dir vertrauten 
Dezimalzahlen kennst.
1
Bitposition   7   6   5   4   3   2   1   0
2
            +---+---+---+---+---+---+---+---+
3
            |   |   |   |   |   |   |   |   |
4
            +---+---+---+---+---+---+---+---+
5
              ^   ^   ^   ^   ^   ^   ^   ^
6
              |   |   |   |   |   |   |   |
7
              |   |   |   |   |   |   |   +- Wertigkeit   1, oder  2 hoch 0
8
              |   |   |   |   |   |   +----- Wertigkeit   2, oder  2 hoch 1
9
              |   |   |   |   |   +--------- Wertigkeit   4, oder  2 hoch 2
10
              |   |   |   |   +------------- Wertigkeit   8, oder  2 hoch 3
11
              |   |   |   +----------------- Wertigkeit  16, oder  2 hoch 4
12
              |   |   +--------------------- Wertigkeit  32, oder  2 hoch 5
13
              |   +------------------------- Wertigkeit  64, oder  2 hoch 6
14
              +----------------------------- Wertigkeit 128, oder  2 hoch 7

Das ist alles wie in den Dezimalzahlen, wie du die kennst. Nur dass wir 
10 unterschiedliche Ziffern haben und nicht nur 2, und dass die 
Wertigkeit einer Stelle '10 hoch x' ist und nicht '2 hoch x'.

Die Dezimalzahl 5289 setzt sich zusammen aus

1
    5289
2
       +---   9 * 10 hoch 0   =      9
3
      +----   8 * 10 hoch 1   =     80
4
     +-----   2 * 10 hoch 2   =    200
5
    +------   5 * 10 hoch 3   =   5000
6
                                 -----
7
                                  5289

nichts anders ist es bei Binärzahlen

die Binärzahl  01101100 setzt sich zusammen aus
1
   01100100
2
          +--   0 *  2 hoch 0   =     0
3
         +---   0 *  2 hoch 1   =     0
4
        +----   1 *  2 hoch 2   =     4
5
       +-----   1 *  2 hoch 3   =     8
6
      +------   0 *  2 hoch 4   =     0
7
     +-------   1 *  2 hoch 5   =    32
8
    +--------   1 *  2 hoch 6   =    64
9
   +---------   0 *  2 hoch 7   =     0
10
                                   -----
11
                                    108

die Binärzahl 01101100 entspricht also der Dezimalzahl 108

: Bearbeitet durch User
von Random .. (thorstendb) Benutzerseite


Lesenswert?

Auf die Schnelle mal runtergetippert:
1
unsigned char led = 0;
2
3
void SetLED (int num) {
4
  led |= (1 << num);
5
}
6
7
int GetLED (int num) {
8
  return((led >> num) & 1);
9
}
10
11
void ClrLED (int num) {
12
  led &= ~(1 << num);
13
}

Das mal ausprobieren und dabei mit dem Debugger vertraut machen!

> Wir arbeiten mit Eclipse auf einem Windos 7 OS und GCC compiler.
Schnappt euch die Express Version vom MS Visual Studio (ist frei), es 
gibt keinen besseren Debugger unter Windows :-)

: Bearbeitet durch User
von Kaj (Gast)


Lesenswert?

Random ... schrieb:
> es
> gibt keinen besseren Debugger unter Windows :-)

Da muss ich zustimmen. Das habe ich auch schon oft von Kollegen gehört, 
die sonst eher der Linux-Fraktion angehören. Wer unter Windows arbeitet, 
fährt mit Visual Studio (2010 oder 2012) am besten.

von Random .. (thorstendb) Benutzerseite


Lesenswert?

VS2010 und MDK-ARM sind mein täglich Werkzeug :-)

---
Und, Aufgabe gelöst, Bitschubserei verstanden?

von Struddel (Gast)


Lesenswert?

Auch wenn der Beitrag etwas älter ist, hat jemand die Lösung dazu? 
Möchte gerne die C-Sprache lernen und wollte diese Aufgabe mal testen. 
Habe nur keine Ahnung wie... :( Bzw. wie man anfangen soll, da mein 
Problem gerade die logische Umsetzung ist.

lg Struddel

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Die logische Umsetzung hat Karl Heinz in epischer Breite erklärt. Wie 
wäre es, wenn Du einfach nochmal den Thread genau und gründlich 
durchlesen würdest?

Die Aufgabe ist so einfach, daß das ein Programmieranfänger ohne weitere 
fremde Hilfe lösen können muss, erst recht mit dem, was Karl Heinz 
geschrieben hat, im Gepäck.

Lesen! Verstehen!

(Und dann, aber wirklich erst dann, Fragen stellen. Konkrete Fragen. 
Fragen, die erkennen lassen, daß Du auch wirklich was gelesen hast)

von Quatschkopp (Gast)


Lesenswert?

Äh? Wie war das im Mittelteil?

(Otto (Kevin Kline) in: "Ein Fisch namens Wanda")


P.S.
Kann gelöscht werden. Ist mir nur durch den Kopf geschossen.

P.P.S

Ach Karl-Heinz. Waren das noch Zeiten!

von Struddel (Gast)


Lesenswert?

Ich habe es so weit geschafft:

#include <stdio.h>
#include <stdlib.h>
#define Max 255
int Lampe[2][8] = {1,2,3,4,5,6,7,8};

int main()
{
  int i, j;
  //Schleife fuer Zeilen, Y-Achse
  for (i=0; i<2; i++)
  {
    //Schleife fuer Spalten, X-Achse
    for (j=0; j<8; j++)
    {
      printf("|%d", Lampe[i][j]);
    }
    printf("|\n");
  }
}

nur leider spuckt er mir das aus:
|1|2|3|4|5|6|7|8|
|0|0|0|0|0|0|0|0|

und hier, trotz mehrfachem Lesen, komme ich nicht weiter. Wenn man es 
kann, dann kommt einem immer alles leicht vor. Nur leider habe ich 
gerade einen Denkfehler, den ich nicht rausbekomme.

von Volker S. (vloki)


Lesenswert?

Struddel schrieb:
> int Lampe[2][8] = {1,2,3,4,5,6,7,8};

Was soll deiner Meinung nach in der zweiten Zeile stehen?

Was hat das mit "Bitoperationen" zu tun?
(Ersetze doch mal das 2dimensionale Feld durch eine einfache 8 Bit 
Variable)

: Bearbeitet durch User
von Struddel (Gast)


Lesenswert?

Habe das von Random mal verwendet und bin jetzt so weit:
1
#include <stdio.h>
2
#include <stdlib.h>
3
#define Max 255
4
5
unsigned char status = 0;
6
7
void SetLED (int num) {
8
  status |= (1 << num);
9
}
10
11
int GetLED (int num) {
12
  return((status >> num) & 1);
13
}
14
15
void ClrLED (int num) {
16
  status &= ~(1 << num);
17
}
18
19
int Lampe[8] = {1,2,3,4,5,6,7,8};
20
21
int main()
22
{
23
  int i, j;
24
25
  //Schleife fuer Zeilen, Y-Achse
26
  for (i=1; i<8; i++)
27
  {
28
    printf("| L%d ", i);
29
  }
30
  printf("|\n");
31
32
    //Schleife fuer Spalten, X-Achse
33
    for (j=0; j<8; j++)
34
    {
35
      if(status == 0)
36
      {
37
        printf("| - ", Lampe[j]);
38
      }
39
      else
40
      {
41
        printf("| x ");
42
      }
43
      printf("|\n");
44
45
      SetLED(4);
46
      GetLED(4);
47
      return 0;
48
  }
49
}

Herausgeben tut mir die Konsole das:
| L1 | L2 | L3 | L4 | L5 | L6 | L7 |
| - |

Oh je... bin hoffnungslos...

--

C-Quelltext bitte in [ c ] [ /c ] - Tags einschließen.
-rufus

: Bearbeitet durch User
von Volker S. (vloki)


Lesenswert?

Das Array komplett löschen. Wozu brauchst du das?
if(status == 0) -> if(GetLED(j)) ?

von Struddel (Gast)


Lesenswert?

1
#include <stdio.h>
2
#include <stdlib.h>
3
#define Max 255
4
5
unsigned char status = 0;
6
7
void SetLED (int num) {
8
  status |= (1 << num);
9
}
10
11
int GetLED (int num) {
12
  return((status >> num) & 1);
13
}
14
15
void ClrLED (int num) {
16
  status &= ~(1 << num);
17
}
18
19
int main()
20
{
21
  int i, j;
22
23
  //Schleife fuer Zeilen, Y-Achse
24
  for (i=1; i<8; i++)
25
  {
26
    printf("| L%d ", i);
27
  }
28
  printf("|\n");
29
30
    //Schleife fuer Spalten, X-Achse
31
    for (j=0; j<8; j++)
32
    {
33
      if(GetLED(j))
34
      {
35
        printf("| - ");
36
      }
37
      else
38
      {
39
        printf("| x ");
40
      }
41
      printf("|\n");
42
43
      SetLED(0);
44
      GetLED(1);
45
      return 0;
46
  }
47
}

Trotzdem:
| L1 | L2 | L3 | L4 | L5 | L6 | L7 |
| x |

Ich finde den Fehler nicht

--
s.o.

-rufus

: Bearbeitet durch User
von Volker S. (vloki)


Lesenswert?

Das Hauptproblem wird wohl die falsch platzierte schließende Klammer der 
zweiten for-Schleife sein. Die anderen "Feinheiten" musst du dann selber 
rausfinden können!
(setz aber mal status am Anfang auf 170, (0xAA, 0b1010101010) damit man 
gleich was sieht)

von Rolf M. (rmagnus)


Lesenswert?

Erstmal vernünftig einrücken. Dann schau dir mal an, was du so in deiner 
Schleife tust. Geh den Inhalt der Schleife mal Schritt für Schritt 
durch. Was passiert alles vor der schließenden Klammer der Schleife?

von uwe (Gast)


Lesenswert?

int main()
{
  int i, j;

  //Schleife fuer Zeilen, Y-Achse
  for (i=0; i<8; i++)
  {
    printf("| L%d ", i);
  }
  printf("|\n");

    //Schleife fuer Spalten, X-Achse
    for (j=0; j<8; j++)
    {
      if(GetLED(j))
      {
        printf("| - ");
      }
      else
      {
        printf("| x ");
      }
      printf("|\n");

      SetLED(0);
      GetLED(1);
      return 0;
  }
}

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.