Variable einer Schleife ersetzen

OP #1504005
Lesenswert?

Ich verwende folgende Schleife:
1
  while(1)
2
  {
3
    for (tpos=text1;pgm_read_byte(tpos)!='~';tpos++)
4
    {
5
        for (softx=0;softx<FONTWIDTH;softx++)
6
        {
7
        adcval = ReadChannel(6);
8
        ScrollLeft();
9
        PrintScrollColumn(pgm_read_byte(tpos),softx,0);
10
        Warte(adcval/1);
11
        }
12
    }
13
  }
14
  return 0;

Die Variable text1 ist eine Globale:
1
prog_uint8_t text1[] = "Das ist der erste Text ~";
2
prog_uint8_t text2[] = "Das ist der zweite Text ~";

Jetzt möchte ich gerne innerhalb der for-schleife eine Abfrage verwenden 
die mir tpos=text1 in tpos=text2 ändert. Sodas der 2te Text ausgegeben 
wird.

Also zb.:

if (ReadChannel(7) > 500) ...

Geht das? Wenn ja, wie?
Moderator (Firma: Titel) Persönliche Seite #1504130
Lesenswert?

> Jetzt möchte ich gerne innerhalb der for-schleife eine Abfrage verwenden
> die mir tpos=text1 in tpos=text2 ändert. Sodas der 2te Text ausgegeben
> wird.
Du willst mitten in der Ausgabe des ersten Strings direkt an die selbe 
Postition des 2. Strings? Oder soll einfach der 2. String von vorne 
ausgegeben werden?

> if (ReadChannel(7) > 500) ...
Wo hättest du die Umschaltung gern?

BTW:
Mit C-üblichen nullterminierten Strings kannst du auch so schreiben:
1
    for (tpos=text1;pgm_read_byte(tpos);tpos++) ...
#1504148
Lesenswert?

Ich kann die Fragestellung auch nicht interpretieren. Hauptsächlich 
allerdings deshalb, weil ich mir aus deinem geposteten Codeabschnitt 
überhaupt keinen Reim machen kann. Was soll das Ziel sein? Dass die 
Buchstaben von links nach rechts langsam ausgegeben werden? Eine Art 
Scheibenwischereffekt?

Aber ich denke, du solltest als erstes anfangen, dir ein paar 
Hilfsfunktionen zu machen. Einzelzeichen ausgeben. String ausgeben.
Gast #1504165
Lesenswert?

>Jetzt möchte ich gerne innerhalb der for-schleife eine Abfrage verwenden
>die mir tpos=text1 in tpos=text2 ändert. Sodas der 2te Text ausgegeben
>wird.


>for (tpos=text1;pgm_read_byte(tpos)!='~';tpos++)

Bastel dir einen Pointer, der statt fest auf "text1" zeigt, variabel 
ist.
Dann kannst du dir eine Abfrage bauen, in deren "then"-Zweig dieser 
Variablen die Adresse von text1 und in "else"-Zweig die Adresse von 
text2 zugewiesen wird.
Das kann man dann quasi unendlich erweitern...
Im Prinzip kannst du auch einfach tpos die jeweilige Adresse zuweisen.

Ich bin mir nicht sicher, aber vielleicht könnte es so gehen:

[c]
if (BedingungfuerText1)
   { tpos = text1;}
else
   { tpos = text2;}
for (;pgm_read_byte(tpos)!='~';tpos++)
.
.
.
}
OP #1504640
Lesenswert?

Zur Funktion:
Das ganze ist eine Scrollschriftanzeige die den Text auf einem 12x10 
LED-Board ausgibt.
Dabei wird Buchstabenweise aus der Variabel text1 / text2 ausgelesen und 
nach links verschoben.


Die Umschaltung müßte meiner Meinung nach direkt in der FOR-Schleife 
passieren, weil ich gerne auch wärend dem Scrollen auf den anderen Text 
umschalten möchte, der anschließen natürlich von vorne beginnen soll.
Also denke ich müßte man die Schleife auch mit einem break; abbrechen.

Mit nullterminierten meinst du wohl Leerzeichen, oder?
Das ist nicht so toll, da Leerzeichen sowohl auch am Schluss noch 
erwünscht sind um den Scroller Platz zu schaffen für eine Wiederholung.

Das beispiel oben könnte zwar funktionieren, erlaubt mir aber keine 
Änderung in der Schleife mehr.
Oder könnte ich die Abfrage direkt in die Schleife legen?
#1504649
Lesenswert?

Manfred W. schrieb:

> Mit nullterminierten meinst du wohl Leerzeichen, oder?

Nein.
Nullterminiert: eine binäre 0 am Ende.
So wie in C seit jeher Strings gebildet werden.
http://www.mikrocontroller.net/articles/FAQ#Wie_funktioniert_String-Verarbeitung_in_C.3F

Danke für die Funktionsbeschreibung. Jetzt ist klarer was das Ziel ist.

Du könntest es zb so machen
1
  useText = 1;
2

3
  while(1)
4
  {
5
    if( useText == 1 )   // was soll eigentlich angezeigt werden: Text1 oder Text2?
6
      tpos = text1;
7
    else
8
      tpos = text2;
9

10
    while( pgm_read_byte( tpos ) )
11
    {
12
      //
13
      // ein Zeichen komplett ausgeben
14
      //
15
      for (softx=0;softx<FONTWIDTH;softx++)
16
      {
17
        adcval = ReadChannel(6);
18
        ScrollLeft();
19
        PrintScrollColumn(pgm_read_byte(tpos),softx,0);
20
        Warte(adcval/1);
21
      }
22

23
      tpos++;
24

25
      //
26
      // Welcher Text sol überhaupt angezeigt werden
27
      //
28
      if( ReadChannel(7) > 500 )
29
        wantText = 2;
30
      else
31
        wantText = 1;
32

33
      // Hat sich das geändert gegenüber dem was zur Zeit angezeigt
34
      // wird
35
      if( wantText != useText )
36
      {
37
        // ja, dann schalte um und brich die momentante Ausgabeschleife ab
38
        // weiter gehts dann mit while(1) und dort wird dann der neue Text
39
        // eingestellt, indem tpos den neuen Textanfang kriegt
40
        useText = wantText;
41
        break;
42
      }
43
    }
44
  }
45
  return 0;

Ich habe das jetzt absichtlich etwas ausführlich und einfach 
geschrieben, damit du es verstehst. Man kann das auch alles etwas 
kompakter lösen. Aber so gehts auch.
Moderator (Firma: Titel) Persönliche Seite #1504688
Lesenswert?

> Mit nullterminierten meinst du wohl Leerzeichen, oder?
Ein Leerzeichen ist 0x20
Eine NULL ist 0x00

Dieser String:
>>> prog_uint8_t text1[] = "Das ist der erste Text ~";
sieht im Speicher so aus:
@text1 'D', 'a', 's', ' ', 'i', ... 'e', 'x', 't', ' ', '~', '/0'
@text1 0x44 0x61 0x73 0x20 0x69 ... 0x65 0x78 0x74 0x20 0x7E 0x00
Es ist im Speicher also 1 Byte mehr reserviert, als dein String 
tatsächlich lang ist. Und in diesem Zeichen steht die binäre Null als 
Ende-Kennung.
OP #1505331
Lesenswert?

Danke euch erstmal. Das ganze funtkioniert wunderbar anhand des 
Beispieles.
Ich habe den Code jetzt etwas abgespeckt und wollte das ganze mit 
CASE-Anweisungen verwenden, weil ich ja nicht nur 2 oder 3 verschiedene 
Texte einbauen möchte, sondern mehrere ca. 10

Nur scheint es in C keine vernünftige Anwendungsweise dafür zu geben.
CASE kann nur immer einen ganzen Wert haben, also nicht ">500" zb.?
1
  tpos = text1;
2

3
  while(1)                          // Endlosschleife
4
  {
5
    while(pgm_read_byte(tpos))                // Aktuelles Zeichen lesen
6
    {
7
      for(softx=0;softx<FONTWIDTH;softx++)        // Pixel des Zeichens abarbeiten
8
      {
9
         adcval = ReadChannel(6);
10
        ScrollLeft();                  // Platz schaffen und Zeilen nach links schieben
11
        PrintScrollColumn(pgm_read_byte(tpos),softx,0);  // Ganz rechts eine Spalte des Zeichens ausgeben
12
        Warte(adcval/1);                // Ein bischen warten damit es nicht zu schnell wird
13
      }
14
      tpos++;
15
      switch(ReadChannel(7))                  // was soll eigentlich angezeigt werden
16
      {
17
            case (>1000:)
18
          tpos = text1;
19
          break;
20
            case (>500)
21
          tpos = text2;
22
          break;
23
        case (>100)
24
          tpos = text3;
25
          break;
26
      }
27
    }
28
  return 0;
29
  }

Wie kann man sowas lösen?
Und was noch ein wenig unschön ist, das der Laufende Text verändert 
wird. Besser wäre, wenn die Anzeige komplett gelöscht wird und der 
Scroller mit dem neuen Text von vorne beginnt.
Moderator (Firma: Titel) Persönliche Seite #1505364
Lesenswert?

> Nur scheint es in C keine vernünftige Anwendungsweise dafür zu geben.
Mit einer If-Abfrage ginge das super...

BTW:
Deine forever loop hat ihren Namen nicht mehr verdient, weil sie durch 
ein return beendet wird   :-o
1
  while(1)                          // Endlosschleife
2
  {
3
    while(pgm_read_byte(tpos))                // Aktuelles Zeichen lesen
4
    {
5
      for(softx=0;softx<FONTWIDTH;softx++)        // Pixel des Zeichens 
6
      :
7
    }
8
    return 0;
9
  }
OP #1505534
Lesenswert?

ist kein LCD. Ist eine LED Platine mit 12x10 LEDs.

Noch eine andere Frage. Kann man bei einem else if kein or verwenden?

Also:
1
    if(useText==1) or (ReadChannel(7)>800)           // was soll eigentlich angezeigt werden: Text1 oder Text2?
2
      tpos=text1;
3
      else if(useText==2) or (ReadChannel(7)>400)
4
       tpos=text2;
5
    else
6
      tpos=text3;
Gast #1505554
Lesenswert?

ALTA!!!  Kannst du mir mal verraten, wie du etwas programmieren 
möchtest, ohne die einfachste C-Syntax zu kennen?

Nimm ein C-Buch, oder von mir aus ein Online Tutorial, da steht alles 
der Reihe nach und auf einander aufbauend drin.

Du versuchst doch auch nicht, zum Beispiel Französisch zu lernen, indem 
du als erstes versuchst, einen französischen Buch zu schreiben, oder?
Gast #1505556
Lesenswert?

... wie schon von Peter erwähnt:
Du brauchst ein C Buch!

...Natürlich kann man bei einem else if ein "OR" verwenden. Aber nicht 
so wie Du es gemacht hast.

Erst mal: guck mal auf Deine Klammersetzung. Was ist die else if 
Bedingung? Dein Compiler kann nicht hellsehen.

Zweitens: Wie wäre es mit:

else if ( ( Bedingung 1 ) || ( Bedingung 2 ) )



Werner
Moderator (Firma: Titel) Persönliche Seite #1505629
Lesenswert?

Der dezente Hinweis der Vorgängerposts geht in die Richtung:
1
    if( useText==1 || ReadChannel(7)>800 )           // was soll eigentlich angezeigt werden: Text1 oder Text2?
2
      tpos=text1;
3
    else if( useText==2 || (ReadChannel(7)>400 )
4
       tpos=text2;
5
    else
6
      tpos=text3;
Das Thema || sowie && wird in deinem neu zu kaufenden C-Buch unter dem 
Thema logische Operatoren abgehandelt. Binäre Verknüpfungen gehen mit | 
und &.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren