Folgenden Code vereinfachen

Gast #285222
Lesenswert?
• ▲
▼
Bin grad dabei einen Code zu schreiben.

Wie könnte man das vereinfachen...?

if (a==0) write_0();
  if (a==1) write_1();
  if (a==2) write_2();
  if (a==3) write_3();
  if (a==4) write_4();
  if (a==5) write_5();
  if (a==6) write_6();
  if (a==7) write_7();
  if (a==8) write_8();
  if (a==9) write_9();

danke für eure antworten
Gast #285227
Lesenswert?
• ▲
▼
mach ein array, das du schon zur design-zeit mit konstanten werten
füllst (für die jeweiligen ziffern der 7seg. anzeige)

dann musst du nurnoch die entsprechende zahl auswählen aus diesem
array

pseudocode ungefähr so:

array ziffern[11000, 00101, 10111]  (die versch. kodierungen der
ziffern)

darauf kannst du dann mit einem index zugreifen, z.b. willst du die
zahl "1" auf der 7seg. ausgeben, machst du:

port = ziffern[1]

ziffern[1] hätte in diesem beispiel den wert 00101, dies wär dann das
was auf dem port ausgegeben wird.

--> spart code, rechenzeit und nerven
Gast #285228
Lesenswert?
• ▲
▼
hab mal einen bekannten gefragt der hat gemeint das geht mit einer
sprungtabelle am besten geht wenn es durchgängige werte sind.

wie heißt das im c im fachjargon? -> zu sprungtabelle hab ich im google
fast nichts gefunden.

mfg
Gast #285229
Lesenswert?
• ▲
▼
Sprungtabellen sind arrays von Funktions-Pointern. Also z.B.

void(*)(void) sprungTabelle[10] = {
   write_1,
   write_2, ...
};

in main dann :

   sprungTabelle[a]();

Ist aber in deinem Fall ueberfluessig, Stefans Vorschlag erscheint mir
auch am sinnvollsten.
Gast #285230
Lesenswert?
• ▲
▼
Schreibe nur eine write-Funktion für alle Ziffern, z.B.:
1
#include<io.h>
2

3
typedef unsigned char  u8;
4
typedef   signed char  s8;
5
typedef unsigned short u16;
6
typedef   signed short s16;
7
typedef unsigned long  u32;
8
typedef   signed long  s32;
9

10

11
#define _A      0x02                            //segment order
12
#define _B      0x04
13
#define _C      0x40
14
#define _D      0x10
15
#define _E      0x08
16
#define _F      0x01
17
#define _G      0x20
18
#define _DP     0x80                            //decimal point
19

20
#define _0      (u8)~( _A+_B+_C+_D+_E+_F     )  //number pattern, low
21
active
22
#define _1      (u8)~(    _B+_C             )
23
#define _2      (u8)~( _A+_B+   _D+_E+   _G )
24
#define _3      (u8)~( _A+_B+_C+_D+      _G )
25
#define _4      (u8)~(    _B+_C+      _F+_G )
26
#define _5      (u8)~( _A+   _C+_D+   _F+_G )
27
#define _6      (u8)~( _A+   _C+_D+_E+_F+_G )
28
#define _7      (u8)~( _A+_B+_C             )
29
#define _8      (u8)~( _A+_B+_C+_D+_E+_F+_G )
30
#define _9      (u8)~( _A+_B+_C+_D   +_F+_G )
31

32
u8 numbers[] = { _0, _1, _2, _3, _4, _5, _6, _7, _8, _9 };
33

34

35

36
// und hier kommt die super Funktion !!!
37

38
void write_0_9( u8 val )
39
{
40
  PORTA = numbers[val];
41
}


Peter
Gast #285231
Lesenswert?
• ▲
▼
Einfachster Code ( wie in Teilen bereits oben vorgeschlagen):

uint8_t digits =
{
  0b0000000, // Eine 1 z.B. für das Segment, das leuchten soll
  0b0000011,
  ... // usw. jeweils die bitmuster die Du brauchst
}

void write( uint8_t i )
{
  PORT = digits[i]
}
#285233
Lesenswert?
• ▲
▼
Nicht ganz.
Ingo hat einen Fehler eingebaut :-)

uint8_t digits [] =

              ****

Und Peters Art die Konstanten zu bestimmen ist wesentlich
schöner und übersichtlicher als die Bitmuster selbst
zu bestimmen. Nach dem Motto: Lass den Compiler sich
um die Bitdetails kümmern, der Programmierer soll sich
nicht mit so einem Taschenrechnerkram rumärgern.
Gast #285234
Lesenswert?
• ▲
▼
Sprungtabelle:

Statt der Werte die Ausgegeben werden sollen stehen in der Tabelle die
Adressen der jeweiligen Ausgabefunktion => Unnötiger Overhead im
Quadrat

==>  Sprungtabelle == Mit Kanonen auf Spatzen schießen!
#285236
Lesenswert?
• ▲
▼
> ==>  Sprungtabelle == Mit Kanonen auf Spatzen schießen!

Im gegenstaendlichen Fall: Ja, klar. Voellig unnoetig.

Aber um mal das Prinzip zu demonstrieren:
Ich hab vor Jahren mal eine Z80 Simulation am PC gemacht
(in C++).

Die wesentliche Hauptschleife sah so aus:

void CPU::Run()
{
  BYTE OpCode;

  while( 1 ) {
    OpCode = m_Ram[m_PC++];
    (this->*m_Fnktions[OpCode])();
  }
}

Dazu gibts dann einen Haufen Funktionen, die die Funktionalitaet
einzelner OP-Codes implementieren: zb

void CPU::CALL ()
{
  WORD Address = FetchAddress();
  PushStack( m_PC );
  m_PC = Address;
}

void CPU::RET ()
{
  m_PC = PopStack();
}

...

Dazu gibt es dann ein Array von Funktionszeigern ....

class CPU
{
  ....

  void( CPU::* m_Fnktions[256] )();
}

... welches die Verknüpfung von Op_Codes zu den einzelnen
Funktionen herstellt:

CPU::CPU()
{
  ...
  m_Fnktions[0xC9] = RET;
  ...
  m_Fnktions[0xCD] = CALL;
  ...

In der Run-Schleife wird ueber den Program-Counter m_PC der
nechste OP-Code aus dem (simulierten) RAM geholt

    OpCode = m_Ram[m_PC++];

dieser OpCode als Index in die Funktionszeiger-Tabelle genommen

  m_Fnktions[OpCode]

und die entsprechende Funktion aufgerufen:

  (this->*m_Fnktions[OpCode])();

(stoert euch jetzt nicht an der Syntax. Die ist in C++ so
notwendig, wenn man Funktionszeiger auf Memberfunktionen machen
moechte).

War also der OpCode gleich 0xCD dann wird die Funktion CALL
dafuer aufgerufen.
Gast #285237
Lesenswert?
• ▲
▼
Sehr elegante Lösung!


Kannst Du mir bitte erklären warum man:

(this->*m_Fnktions[OpCode])();

schreiben muss und nicht

(this->m_Fnktions[OpCode])();

Im Array steht doch ein Zeiger auf eine Memberfunktion. Eigentlich ist
dann doch

(this->m_Fnktions[OpCode])

der Zeiger auf die Funktion, und

(this->m_Fnktions[OpCode])();

Dereferenzierung und Aufruf?

Fragt sich
Ingo
#285238
Lesenswert?
• ▲
▼
(this->m_Fnktions[OpCode])();

koenntest Du benutzen, wenn in m_Fnktions lauter
Pointer auf freistehende Funktionen stünden. Das ist
aber hier nicht der Fall. m_Fnktions enthaelt Pointer
auf Memberfunktionen einer Klasse.
Memberfunktionen muessen aber anders aufgerufen werden
(der this Pointer innerhalb der Funktion muss ja besetzt
werden). Daher ist eine neue Syntax notwendig:  ->*

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.