Forum: Compiler & IDEs "while" Bedingung hält nicht was es verspricht


von Attila (Gast)


Lesenswert?

Hallo!

Dieses "Konstrukt":
1
void uartstr (char* buffer)
2
{  
3
  int i;
4
  while(i!=',')
5
  {
6
    i=receive();
7
    *buffer++=i;
8
  }
9
  *buffer='\0';
10
}

Gibt als letztes Zeichen ein Komma aus und ich verstehe nicht

1) Warum das passiert? Und:
2) Wie ich das ändern kann?

Vielen Dank!

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Also wenn es an sowas hapert, hilft es häufig obskure "Konstrukte" 
aufzulösen...
Erstmal wir i nicht initialisiert, als nächstes wird Buffer etwas 
zugewiesen bevor die Schleife verlassen wird, und als nächstes wird 
falls kein Komma kommt (warum auch immer) fröhlich der Speicher 
vollgeschrieben in alle möglichen anderen Datenstrukturen hin nein...

1
void uartstr (char* buffer, int len)
2
{  
3
  int i = 0;
4
  for(; i < len; i++) {
5
    char c = receive();
6
    if (c == ',') {
7
     break;
8
    }
9
    buffer[i] = c;
10
  }
11
  buffer[i] = '\0';
12
}

von Fixer (Gast)


Lesenswert?

weil deine Prüfung mit dem vorletzten Zeichen erfolgt respektive du nach 
der Prüfung ein neues Zeichen einliesst und das entsprechend 
abspeicherst.
1
void uartstr (char* buffer)
2
{  
3
  int i;
4
  i=receive();
5
  while(i!=',')
6
  {
7
    *buffer++=i;
8
    i=receive();
9
  }
10
  *buffer='\0';
11
}

sollte klappen.

Cheers

von Attila (Gast)


Lesenswert?

Dieses "Konstrukt" ist das Ergebniss eines "Einlaufs" den ich hier im 
Forum bekommen habe weil ich es gewagt habe das Komma NICHT zur 
auswertung heranzuziehen. ;-) ;-) ;-)

Ich lese damit ein NMEA Protokol ein. Beispiel:

$GPRMC,083559.00,A,4717.11437,N,00833.91522,E,0.004,77.52,091202,,,A*57

Das Konstrukt liest das auch wunderschön ein. Auch der Vergleich des 
Strings "GPRMC," mit dem eingelesenen String funktioniert. Ich würde nur 
gerne "GPRMC" und nicht "GPRMC," vergleichen.

von Attila (Gast)


Lesenswert?

@Fixer: Aaaaaaaaaahhhhh!!! Danke vielmals! :-)

von Fixer (Gast)


Lesenswert?

Gern geschehen. Aber die Tips von Läubi solltest du auch noch beachten.
Ansonsten handelst du dir früher oder später eine Buffer-Overflow ein.

von Attila (Gast)


Lesenswert?

Ich möchte es gerne verstehen:

1) Warum muss ich i initialisieren? Ich schreibe doch unmittelbar mit 
recieve() was rein!
2) Warum sollte denn das NMEA Protokol kein Komma ausspucken? Oder 
andersrum: Sollte es kein Komma mehr ausspucken ist dann nicht sowieso 
alles schon zu spät und der Buffer dann auch egal?

von Attila (Gast)


Lesenswert?

Ich meine es wirklich im Sinne von verstehen wollen:

Mein C Buch sagt dass in einer nicht initialsierten variablen eben 
irgendein Wert drin steht. Aber das ist doch nicht schlimm wenn man 
unmittelbar was hineinschreibt?

Wenn das Komma zu unsicher ist ( habe ich das richtig verstanden?) um 
eine Schleife zu beenden, was wäre dann der bessere Weg?

von geist (Gast)


Lesenswert?

Und was ist wenn in i dann zufällig ein "," drin steht?

von Attila (Gast)


Lesenswert?

@geist: Wow! Da wäre ich nie drauf gekommen! Aber natürlich: Das wäre 
natürlich eine böse Falle!

von Stefan E. (sternst)


Lesenswert?

Attila schrieb:
> Mein C Buch sagt dass in einer nicht initialsierten variablen eben
> irgendein Wert drin steht. Aber das ist doch nicht schlimm wenn man
> unmittelbar was hineinschreibt?

Ja, aber in deiner ersten Version wird nicht unmittelbar was 
hineingeschrieben. Vorher findet schon der erste "i!=','"-Test statt.

> Wenn das Komma zu unsicher ist ( habe ich das richtig verstanden?) um
> eine Schleife zu beenden, was wäre dann der bessere Weg?

Besser wäre es zusätzlich eine Längenbegrenzung mit in die Schleife 
aufzunehmen.

von Peter (Gast)


Lesenswert?

Du hängst jedes Zeichen nach receive() an den buffer an.

hier ist es natürlich einfach

void uartstr (char* buffer)
{
  int i;
  while((i=receive())!=',')
  {
    *buffer++=i;
  }
  *buffer='\0';
}


Oft hilft auch der ,-Operator im while um einen zweiten identischen 
Funktionsaufruf zu umgehen, sieht dann so aus:

while(scanf("%d",&i), i!=0)
{
 ...
}

Peter

von Attila (Gast)


Lesenswert?

@Peter: Ganz ehrlich: Ich habe auch nach mehrmaligem lesen nicht 
verstanden was Du sagst.

Der ,- operator? Was ist das?

zweiter identischer Funktionsaufruf?Wie jetzt?

Das "Konstrukt":

while(scanf("%d",&i), i!=0)
{
 ...
}

bedeutet dass solange niemand eine "0" eingibt die while Schleife nicht 
verlassen wird, richtig?

von Peter (Gast)


Lesenswert?

Mit dem ,-Operator kannst du mehrere Anweisungen nacheinander ausführen,
fast wie das ;. In while() darf z.B. kein Semikolon stehen, hier
und in for() ist der ,-operator manchmal ganz praktisch

Prinzipiell wird erst der Ausdruck links vom , bestimmt, das Ergebnis
wird dann weggeworfen, dann wird der Wert rechts vom ,  bestimmt
und das ist dann das Ergebnis.

In der oben angegebenen whileschleife bestimmt also das i!=0 ob
die Schleife ausgeführt wird. Das Ergebnis des Scanf ist hierfür
völlig irrelevant (außer das als Nebeneffekt natürlich i einen
neuen Wert bekommt)

http://en.wikipedia.org/wiki/Comma_operator

Peter

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Attila schrieb:
> Wenn das Komma zu unsicher ist ( habe ich das richtig verstanden?) um
> eine Schleife zu beenden, was wäre dann der bessere Weg?
Nein das Komma an sich ist nicht unsicher!

Unsicher ist es einen Pointer gnadenlos ohne wissen der Länge des 
reservierten Speichers vollzuschreiben.

Attila schrieb:
> Warum sollte denn das NMEA Protokol kein Komma ausspucken?
Wer garantiert dir das du einen gültigen NEMA String empfängst? Zumal 
dieser nicht mit einem Komma Endet! (Ein Zeilenumbruch sollte also am 
besten auch noch die Schleife abbrechen..., und das anfängliche $ könnte 
man auch noch unterdrücken...)
Und spätestens hier kommt man an einen Punkt, wo alles in eine While 
Bedingung zu packen die Sache nicht übersichtlicher macht.

Und das ist am Anfang das aller wichtigste!

Und was machst du wenn der Aufrufer (sei es auch Speichernot sei es aus 
Unachtsamkeit) nur einen Buffer der Länge 3 angelegt hat... deshalb 
sollte man immer die Länge des buffers zusätzlich übergeben und auch 
prüfen!

von Karl H. (kbuchegg)


Lesenswert?

Peter schrieb:
> Mit dem ,-Operator kannst du mehrere Anweisungen nacheinander ausführen,

Bitte!
Theatere den Fragesteller nicht in den Komma-Operator hinein, zumal er 
an dieser Stelle unnötig ist, weil ein && hier ganeusogut das gewünschte 
erledigt. Ganz im Gegenteil, wenn der scanf schief geht, kannst du dir 
mit dem Komma Operator hier ganz schönen Ärger einhandeln, weil kein 
Mensch dir garantiert, dass i dann 0 wird.

Der Komma-Operator ist ein konstanter Quell des Ärgernisses, 
insbesondere für Neulinge.

von Karl H. (kbuchegg)


Lesenswert?

Läubi .. schrieb:

>> Warum sollte denn das NMEA Protokol kein Komma ausspucken?
> Wer garantiert dir das du einen gültigen NEMA String empfängst?

@Attila
Das ist überhaupt ein wichtiger Punkt bei (fast) jeglicher 
Eingabeverarbeitung.
Nachdem du deine Eingabebehandlung fertig hast, setz dich hin und 
überleg dir, was alles noch passieren kann. Dazu stellst du dir einfach 
vor, deine Engabe kommt nicht einfach voin irgendwo her, sondern von 
einer Tastatur und auf diese legst du einen Stein drauf. Übersteht das 
deine Eingaberoutine?
Oder noch schlimmer, du fährst mit der Hand ein paar mal wahllos von 
links nach rechts und wieder zurück über die Tastatur (Gewiefte setzen 
ein Kleinkind an die Tastatur und lassen es einfach drauflosklimpern). 
Eine gute Eingaberoutine übersteht so etwas, ohne das etwas Schlimmes 
passiert. Klar das Programm wird (und soll) einen Fehler registrieren 
und vielleicht sogar auch melden, aber es wird unter keinen Umständen 
etwas Schlimmes passieren, wie zb Speicher niederbügeln, der gar nicht 
mehr zum Eingabearray gehört oder Auswertungen mit falschen Daten 
machen.

Das Interessante daran. Es ist gar nicht mal so schwer eine Eingabe 
gegen derartige Dinge abzusichern und oft sind die Modifikationen gar 
nicht schwer und gar nicht mal so groß. Mit ein paar kleinen 
Umstellungen und Abfragen ist das alles erledigt und berücksichtigt.

von Attila (Gast)


Lesenswert?

@Läubi und @Karl Heinz:

Vielen vielen Dank für den Input und ich werde ihn versuchen Schritt für 
Schritt umzusetzen!
Wenn ich sehe was ich mir hier zusammenstricke und mit euren Kommentaren 
verquicke......stelle ich fest: Ich habe noch einen sehr weiten Weg zu 
gehen!

Wenn es recht ist werde ich das "Konstrukt" nochmal überarbeiten und 
hier wieder einstellen.

Danke euch Jungs, andere müssen für sowas zahlen!

von Attila (Gast)


Lesenswert?

So richtig?

void uartstr (char* buffer)
{
  int i=0,check=0;

  i=receive();
  while(i!=','&&check<=10)
  {
    check++;
    *buffer++=i;
    i=receive();
  }
  *buffer='\0';
}

von Karl H. (kbuchegg)


Lesenswert?

Attila schrieb:
> So richtig?
>
> void uartstr (char* buffer)

nein.
Wenn du eine Funktion schreibst, die in einem Array etwas ablegen soll, 
dann ist es PFLICHT, dass der Aufrufer die Größe des Arrays mitgeben 
muss.

Alles andere ist 'Ask for trouble'

> {
>   int i=0,check=0;
>
>   i=receive();
>   while(i!=','&&check<=10)

:-)
Woher weißt du die 10?
Genau davon hat der erste Absatz gehandelt. Diese 10 muss der Aufrufer 
der Funktion der Funktion mitgeben. Denn nur er kann das wissen.
1
void uartstr (char* buffer)
2
{
3
  int i=0,check=0;
4
5
  i=receive();

int i? Wieso int? Hier ist von Zeichen aus der UART die Rede. Konkret 
ASCII Zeichen. Also char

von Attila (Gast)


Lesenswert?

@Karl Heinz:

Genau: Wieso eigentlich int? Ärgerlicher Fehler!

Zu der 10: Ich lese ja ein NMEA Protokol aus. Zumindest in dem Protokol 
(RMC) was ich auslese ist das länsgte string 10 Zeichen lang. Nämlich 
der Längengrad. Ist aber falsch gedacht wie ich jetzt begriffen habe. 
Allerdings wirft das eine neue Frage auf:

Wie mache ich das denn bei einem String bei dem das Protokol selber 
entscheided wieviele zeichen es hat?

Beispiel: Geschwindigkeit über Grund kann vom Format her "0" bis "0.000" 
Knoten sein.

von Karl H. (kbuchegg)


Lesenswert?

Attila schrieb:
> @Karl Heinz:
>
> Genau: Wieso eigentlich int? Ärgerlicher Fehler!
>
> Zu der 10: Ich lese ja ein NMEA Protokol aus. Zumindest in dem Protokol
> (RMC) was ich auslese ist das länsgte string 10 Zeichen lang. Nämlich
> der Längengrad. Ist aber falsch gedacht wie ich jetzt begriffen habe.

Yep.
Frag dich einfach:

Ist diese Funktion in irgendeiner Art und Weise NMEA spezifisch?
Eigentlich doch nicht. Denn diese Funktion soll einen String empfangen. 
Ob den ein Benutzer eingibt, oder ob der von einer Fräsmaschine kommt 
oder eben wie bei dir von einem GPS Empfänger ist doch erst mal für die 
Funktion selber uninteressant.

Und da du nicht bei jedem Projekt das Rad immer wieder neu erfinden 
willst, schreibst du dir am liebsten immer Funktionen, die eben dieses 
Wissen nicht in ihrem Code enthalten haben, sondern allgemein verwendbar 
sind.

In deinem Code gibt es keinerlei Sicherung gegen diesen Fall

  char buffer[4];
  uartstr (buffer);

Ooops. Das Feld hier ist nur 4 Zeichen lang. Trotzdem behandelt es deine 
Funktion als ob es 10 Zeichen lang wäre. Komplette Rechenzentren wurden 
wegen solcher blödsinniger Annahmen in Funktionen schon lahmgelegt.

Hier, beim Aufruf weiß ich, wei lang mein Array ist, in welches ich den 
String reinhaben möchte. Also

  char buffer[4];
  uartstr( buffer, sizeof(buffer) );

uartstr muss jetzt nur noch mit dieser Zahl arbeiten. Das kostet uartstr 
nichts und das kostet mir hier beim Aufruf nichts. Nur hab ich plötzlich 
eine Funktion, die ich allgemeiner benutzen kann.

Welche Annahmen hast du in uartstr noch getroffen?
Du hast noch die Annahme getroffen, dass der String mit einem ',' 
aufhört. Muss das so sein? (Denk jetzt an den allgemeinen Fall). Könnte 
man diese Annahme in der Funktion leicht loswerden?

Ja, könnte man
Dann sieht halt der Aufruf so aus

  char buffer[4];
  uartstr( buffer, sizeof(buffer), ',' );

und die Funktion bekommt das Ende Zeichen mit.

> Allerdings wirft das eine neue Frage auf:
>
> Wie mache ich das denn bei einem String bei dem das Protokol selber
> entscheided wieviele zeichen es hat?

Das geht in C auf deinem µC nicht vernünftig. Dazu müsste man dynamisch 
Speicher allokieren und das möchte man auf so einem kleinen µC 
eigentlich nicht tun. Leb damit, dass du den Buffer beim Aufrufer 
großzügig genug dimensionierst, so dass alles reinpasst.

http://www.mikrocontroller.net/articles/FAQ#wie_schreibt_man_eine_Funktion.2C_die_einen_String_liefert.3F

von Attila (Gast)


Lesenswert?

Karl Heinz!

Ok ich habe verstanden dass es nicht sonderlich "schön" ist was ich mir 
da zusammengebastelt habe und ich werde alles was Du oben anmerkst auch 
umsetzen. Nur: Ist denn das was ich jetzt habe falsch im Sinne von 
"abstürzenden Rechenzentren"?

void uartstr (char* buffer,int laenge)
{
  char i=0;
  int zaehler=0;

  i=receive();
  while(i!=','&&zaehler<=laenge)
  {
    zaehler++;
    *buffer++=i;
    i=receive();
  }
  *buffer='\0';
}

Wobei im main dies steht:

char rein[11]

Und als Aufruf dies z.b.:

uartstr(rein,1);  //Wenn es um das Zeichen "N" oder "S" oder ähnliches 
geht

Oder z.B.:

uartstr(rein,10) //Wenn es um den Längengrad geht

von Karl H. (kbuchegg)


Lesenswert?

Attila schrieb:

> Wobei im main dies steht:
>
> char rein[11]
>
> Und als Aufruf dies z.b.:
>
> uartstr(rein,1);  //Wenn es um das Zeichen "N" oder "S" oder ähnliches
> geht

Nein, das machst du so nicht.
Du hast das ',' von der Eingabe, welches den String beendet.

Hier geht es nicht darum, wie lang der String ist, den du erwartest, 
sondern darum wie groß der Buffer ist, den du uartstr zur Vefügung 
stellst um dort den String abzulegen.


Denn ob von der SChnittstelle tatsächlich der String kommt, den du 
erwartest, kannst du sowieso nicht sicher stellen.

> uartstr(rein,10) //Wenn es um den Längengrad geht

  char rein[11]
  uartstr(rein,11);

weil rein 11 char groß ist.
Oder eben

  char rein[11]
  uartstr( rein, sizeof(rein) );

dann brauchst du das nicht selber abzählen sondern der Compiler macht 
das für dich.

von Attila (Gast)


Lesenswert?

Ich glaube so soll es sein:

void uartstr (char* buffer,int size,char zeichen)
{
  char i=0;
  int zaehler=0;

  i=receive();
  while(i!=zeichen&&zaehler<=size)
  {
    zaehler++;
    *buffer++=i;
    i=receive();
  }
  *buffer='\0';
}

Aufruf geht so:

uartstr(rein,sizeof(rein),',');

Funktioniert, sieht besser aus, löst aber mein Problem nicht: Ich 
versuche es mal zu beschreiben:

Ich habe ein Programm geschrieben welches den Kurs von einer Koordinate 
zu einer anderen Koordinate berechnet.
Diese funktionert auch auf Visual Express korrekt.
Ich habe das ganze dann auf einen Atmega8 übertragen inclusive der UART 
Funktion und der Displaysteuerung.
Wenn ich eine Zielkoordinate Eingebe die etwas weiter weg von meiner 
aktuellen Position ist arbeitet es halbwegs in etwa 98% der Zeit 
richtig.

Wenn ich meine aktuelle Poition als Ziel eingebe dann "eiert" der Kurs 
genau genommen ja um mich herum. Schön und faszinierend anzusehen und 
auch richtig wenn nicht nach kürzester Zeit dinge wie "836" auf meinem 
Display stehen würde. Das kann garnicht sein weil ein Arkustangens 
nunmal nur etwas zwischen -180 und +180 generieren kann. Irgenwann 
bleibt die Anzeige bei -180 eingefroren stehen.

2 Fragen nun:

Kann es sein das der Atmega 8 schlichtweg überfordert ist? Ist ja ne 
Menge Holz (wie ich als Anfänger finde)

Soll ich diesbezüglich einen neuen Thread aufmachen?

von Karl H. (kbuchegg)


Lesenswert?

Attila schrieb:
> Ich glaube so soll es sein:
>
> void uartstr (char* buffer,int size,char zeichen)
> {
>   char i=0;
>   int zaehler=0;
>
>   i=receive();
>   while(i!=zeichen&&zaehler<=size)
>   {
>     zaehler++;
>     *buffer++=i;
>     i=receive();
>   }
>   *buffer='\0';
> }
>
> Aufruf geht so:
>
> uartstr(rein,sizeof(rein),',');
>
> Funktioniert, sieht besser aus,

Ist so schon eine gute Lösung.

> löst aber mein Problem nicht:

Das ist jetzt aber auch eine komplett andere Baustelle

> Kann es sein das der Atmega 8 schlichtweg überfordert ist?

Überfordert wäre er jetzt höchstens, wenn er mit der Rechenzeit nicht 
mehr mitkommt. Aber davon war ja jetzt erst mal noch überhaupt nicht die 
Rede

Zum anderen musst du bedenken, dass dein Mega mit wesentlich weniger 
Kommastellen arbeitet als dein PC. Rechenungenauigkeiten werden so im 
Lauf der Zeit immer größer, wenn man es ungeschickt anfängt.

Deine Beschreibung klingt aber eher nach einem Programmfehler.

Ohne Programm kann man da aber wenig dazu sagen.
Was mich stutzig macht ist, das du anscheinend beim UART Empfang schon 
weißt, was du empfangen wirst. Das kann gut gehen, muss es aber nicht, 
je nachdem wie es programmiert ist. Daher würde ich NMEA auch niemals so 
empfangen, dass ich der Empfangsroutine sage: lies mal alles bis zum 
','. Sondern immer so, dass ich erst mal eine komplette NMEA Zeile 
empfange. Und nur dann, wenn ich die komplett habe, fange ich an sie zu 
zerlegen und weiterzuverarbeiten. Denn eines ist auch klar. Während der 
Mega am Rechnen ist, beginnt das GPS schon die nächste Übertragung. Das 
wartet nicht auf dich.

Aber wie gesagt: Ohne Programm kann man da überhaupt nichts sagen.

von Stefan E. (sternst)


Lesenswert?

Karl heinz Buchegger schrieb:
> Ist so schon eine gute Lösung.

Na, na, na, Karl Heinz, also ich sehe da einen Out-Of-Bound-Zugriff. ;-)

von Attila (Gast)


Lesenswert?

Jaja lieber Karl Heinz: Komplett andere Baustelle weil die Baustelle die 
ich vermutete nicht die Richtige war.

Ich arbeite , so glaube ich, mit, für einen Atmega, ziemlich grossen 
Zahlen beispiel: 81356.8

Dennoch:

track=360+atan2(-distl,distb)*180/3.141592;


Selbst wenn distl und distb falsch sind ist es doch so dass egal welche 
zahlen man da reinschreibt das Ergebniss nie , im schlimmsten Falle, 
grösser als 540 ist.

Bedeutet doch: Der Fehler liegt hinter dieser Zeile und nicht davor, 
richtig?

Und dahinter passiert nur ein itoa und die Ausgabe.

von Attila (Gast)


Lesenswert?

@Stefan: Ein "Raus aus Schranke" Zugriff? ;-) Und was ist das? Warum 
haben C Bücher eigentlich kein Stichwortverzeichniss? Gnrlgnn ;-) Da 
könnte ich dann nachschlagen und versuchen das Problem selber zu lösen!

von Attila (Gast)


Lesenswert?

@Karl Heinz:

Diese Bemerkung von Dir ist "Stöffchen" für , locker, die nächsten 2 
Tage:

Denn eines ist auch klar. Während der
Mega am Rechnen ist, beginnt das GPS schon die nächste Übertragung. Das
wartet nicht auf dich.

Vielen Dank dafür! Ich melde wenn ich die Konsequenzen deiner Anmerkung 
abgearbeitet habe!

von Attila (Gast)


Lesenswert?

@Karl Heinz:

Doch nicht 2 Tage das Programm umstricken. Es fragt nämlich nicht das 
UART ab bevor es zu ende gerechnet hat.

Ich habe, glaube und hoffe ich, das Problem an dieser Stelle 
eingegerenzt:

float track (float distb,float distl)
{
  float track;

  if(distl<=0)
  {
  track=atan2(-distl,distb)*180/3.141592;
  }
  if(distl>0)
  {
  track=360+atan2(-distl,distb)*180/3.141592;
  }
  return track;
}

 Im Moment spielen sich distl und distb bei +- 1.00 ab. Kann es sein das 
man die funktion atan2 nicht mit floats füttern darf?

von Spess53 (Gast)


Lesenswert?

Hi

>Während der Mega am Rechnen ist, beginnt das GPS schon die nächste
>Übertragung. Das wartet nicht auf dich.

Normalerweise kommen die NMEA-Strings etwa in Sekundentakt. Da kann der 
Controller noch nebenbei Kuchen backen.

MfG Spess

von Attila (Gast)


Lesenswert?

Hallo Spess!
Sie kommen 4 mal pro Sekunde, aber das macht den Kohl wohl auch nicht 
fett.

von Attila (Gast)


Lesenswert?

Ich hab da was gefunden, das könnte das Problem sein:

If both arguments passed are zero, a domain error occurs, which sets the 
global variable ERRNO to the EDOM value.

von Karl H. (kbuchegg)


Lesenswert?

Stefan Ernst schrieb:
> Karl heinz Buchegger schrieb:
>> Ist so schon eine gute Lösung.
>
> Na, na, na, Karl Heinz, also ich sehe da einen Out-Of-Bound-Zugriff. ;-)

Hast recht.
Zwischendurch hab ich ihn mal gesehen, aber dann wieder verschwizt.

von Karl H. (kbuchegg)


Lesenswert?

Attila schrieb:
> @Stefan: Ein "Raus aus Schranke" Zugriff? ;-) Und was ist das?

Wenn du 6 Zeichen in ein Array der Länge 5 quetschen willst


  while(i!=zeichen&&zaehler<=size)

Hier: das <= fängt diesen potentiellen Fehler nicht ab.

von Attila (Gast)


Lesenswert?

@Karl Heinz

Muss es < heissen damit noch Platz für das "/0" ist?

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Attila schrieb:
> Muss es < heissen damit noch Platz für das "/0" ist?
nein, weil die Zählung bei 0 beginnt...
Warum beist du dich eigentlich mit aller Kraft an deiner while Schleife 
fest? Ich hatte oben doch shcon ein Beispiel gepostet was dieses 
"Problem" umgeht, und welches die "normale" Notation für Array zugriffe 
nutzt...
Ebenso das problem mit int/char war dort auch schon gelöst man darf auch 
gerne sich Beispiele mal angucken, es besteht keine Pflicht zu 
iterative-trial-and-error-programming...

von Attila (Gast)


Lesenswert?

Hallo Läubi!

Es muss size-1 heissen!

Ich hatte das so verstanden dass meine Schleife jetzt in Sinne aller 
Profis korrekt ist:

Hier nochmal die fertige Lösung:

void uartstr (char* buffer,int size,char zeichen)
{
  char i=0;
  int zaehler=0;

  i=receive();
  while(i!=zeichen&&zaehler<size-1)
  {
    zaehler++;
    *buffer++=i;
    i=receive();
  }
  *buffer='\0';
}

Und hier der Aufruf:

uartstr(rein,sizeof(rein),',');

Den Fehler im Programm ( welches jetzt einwdfrei läuft) habe ich auch 
gefunden und obwohl es mir sehr peinlich ist, vielleicht hilft es 
anderen:

Meine LCD Routine machte nur Cursor return und NICHT clear display. Wenn 
dann der Kurs z:b 347 war stand da:

"347"

Und wenn Kurs sich dann nach 8 Grad änderte stand da:

"857"

Ich weiss es tut weh. ;-)

von Attila (Gast)


Lesenswert?

Sorry vertippt:

Nach

"347"

kommt

"847"

von Karl H. (kbuchegg)


Lesenswert?

Attila schrieb:

> Meine LCD Routine machte nur Cursor return und NICHT clear display.

Sie soll auch nicht 'Clear Display' machen.

Das führt zu Flackern auf dem LCD.

Ist doch nicht so schwer. Wenn du die Zeichen dahinter weghaben willst, 
dann schreib halt einfach Leerzeichen drüber.
Oder formatiere die Zahl immer so, dass sie immer in einem String mit 3 
Zeichen rechtsbündig dargestellt wird. Aussuchen kannst du dir ob du 
führende 0-en haben willst oder ob führende 0-en durch Leerzeichen 
ersetzt werden sollen.

Clear Display willst du sparsam einsetzen, aber auf keinen Fall um dein 
Display in Ordnung zu halten, wenn sich Werte ändern.

von Attila C. (attila)


Lesenswert?

@Karl Heinz:

Ich finde das nicht einfach.Echt nicht.
Ich finde deinen Hinweis aber sehr nützlich und werde versuchen ihn 
umzusetzen.

Gibt es Beispiele zu , am liebsten, beide Versionen?

von Attila C. (attila)


Lesenswert?

Ach so: Wieso will man clear display nicht einsetzen um das Display in 
Ordnung zu halten. Nur wegen des Flackerns oder gibt es noch andere 
Gründe?

von Karl H. (kbuchegg)


Lesenswert?

Attila Ciftci schrieb:
> Ach so: Wieso will man clear display nicht einsetzen um das Display in
> Ordnung zu halten. Nur wegen des Flackerns

Genau.
Ausserdem musst du dann andere Dinge auf dem LCD wieder neu schreiben. 
Ist ja alles ebenfalls weg.

Nach Möglichkeit willst du am LCD immer nur die Dinge verändern, die 
auch verändert werden müssen. Und das so, dass du nichts anderes dabei 
beschädigst.  Clear ist so ziemlich die schlimmste Form von 
'Beschädigung', die du deiner Anzeige antun kannst.


Wie gesagt, die Technik dazu ist nicht weiter schwierig (*). Du musst 
nur darauf achten, dass auch immer alles alte überschrieben wird. Am 
einfachsten geht das, wenn man für jede Ausgabe auf dem LCD ein 'Feld' 
mit einer bestimmten Stellenanzahl vorsieht und dort Zahlen 
reinschreibt. Wenn alle Stricke reissen, kann man vorher immer noch 
genau dieses Feld vorher mit einer entsprechenden Anzahl Leerzeichen 
'löschen' und dann die neue Zahl dort hinschreiben. Macht man diesen 
Update nur dann, wenn er auch tatsächlich notwendig ist (nur dann wenn 
sich die Zahl auch geändert hat), dann merkt das noch nicht einmal wer. 
Aber es ist auch nicht weiter schwer, die Zahlen so zu formatieren, dass 
sie immer alles überschreiben.

Zahlen auch am besten rechtsbündig ausgeben. Nichts ist so lästig, wie 
eine Zahl zu beobachten, die am Display ständig hin und her springt. Die 
Einerstelle der Zahl sollte immer an der gleichen Position am LCD sein.

(*) Entweder schreibt man sich selber was, oder aber wenn man es sich 
leisten kann benutzt man einfach sprintf. Das hat ein paar nette 
Formatieroptionen mit, die man hier sinnvoll einsetzen kann.

von Attila C. (attila)


Lesenswert?

@Karl Heinz:

Diese Tipps sind natürlich GOLD!  Klasse! Vielen Dank!

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.