Forum: Compiler & IDEs Folgenden Code vereinfachen


von Christian (Gast)


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

von Björn Z. (whocares)


Lesenswert?

switch ?!? Nur so n vorschlag

von Chris (Gast)


Lesenswert?

Hallo Christian!

Was macht denn jeweils write_n();?

Grüße

Chris

von Christian (Gast)


Lesenswert?

write_n

n die zahl die am 7 seg ausgegeben wird
also irgendwelche werte auf einem port.

mfg

von Chris (Gast)


Lesenswert?

Hallo Christian!

Häng doch mal den Quelltext (bzw. einen Ausschnitt) davon an.
Sagt mehr als ewiges herumgestocher in der Luft ;)

Grüße

Chris

von Stefan M. (Gast)


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

von Christian (Gast)


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

von The Daz (Gast)


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.

von peter dannegger (Gast)


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

von Ingo (Gast)


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]
}

von peter dannegger (Gast)


Lesenswert?

@Ingo,

nicht in Teilen, sondern ganz genau so.


Peter

von Karl H. (kbuchegg)


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.

von Werner B. (Gast)


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!

von Ingo (Gast)


Lesenswert?

@Peter & Karl-Heinz:

Ihr habt ja recht. Pfui über mich!

Dann aber vielleicht noch:
#define _A      (1<<PIN1)

statt magic number?

von Karl H. (kbuchegg)


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.

von Ingo (Gast)


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

von Karl H. (kbuchegg)


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:  ->*

von Ingo (Gast)


Lesenswert?

Super, danke.

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.