Folgenden Code vereinfachen

Gast #285222
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
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
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
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
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
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]
}
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
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!
> ==>  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
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
(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

Eine eigene Frage? Dieser Thread ist über 20 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

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.