PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Pointer als Parameter und Rückgabewert



Bumbum
28.11.2012, 09:54
Hallo,

ich möchte eine kleine Funktion schreiben die mir in einem Char-Array ein Zeichen sucht. Die Funktion soll mit einem Pointer auf das erste Zeichen, bei dem die Suche begonnen werden soll aufgerufen werden. Dieser Pointer als Parameter soll auch als Rückgabewert dienen. Hierbei happert es noch ein bisschen. Hier mal meine Funktion:



bool MoveBuffer2Char (volatile char **Buffer, char Char, U8 MaxChars)
{
volatile char *CheckBuffer = *Buffer;

while ((*CheckBuffer++ != Char) & (--MaxChars > 0));

if (MaxChars > 0)
{
Buffer = &CheckBuffer;
return (TRUE);
}
else
return (FALSE);
}


Mein Aufruf sieht so aus:



volatile char RS232Buffer[0x50];
volatile char *Buffer = &RS232Buffer[0];

// ...

if (MoveBuffer2Char (&Buffer, ',', 6))
{
// ...
}


Leider steht die Variable Buffer nach dem Aufruf der Funktion wieder auf dem Startwert. Was mache ich falsch, bzw. wie mache ich es richtig?

Viele Grüße
Andreas

DanielSan
28.11.2012, 10:19
Bin mir nicht ganz sicher aber ich glaub wenn du sie als "static" machst müsste sich das erledigt haben.

Bumbum
28.11.2012, 10:25
Nein, ich habe es mittlerweile durch rumprobieren herausgefunden. So funktioniert es:



if (MaxChars > 0)
{
*Buffer = CheckBuffer;
return (TRUE);


Viele Grüße
Andreas

Wsk8
28.11.2012, 10:30
Wieso so kompliziert?
Geht doch auch etwas einfacher:


char *func(char *buffer, char ch, size_t size) {
int i = 0;
for(i = 0; i < size; i++) {
if(*buffer == ch) {
return buffer;
break;
}
buffer++;
}


return NULL;
}



char buf[] = "Hallo";
char *c = 0;


c = func(buf, 'a', sizeof(buf));


if(c == 0) printf("Fehler");
else printf("%c", *c);

mfg

Bumbum
28.11.2012, 16:20
Stimmt, so gehts auch (nicht getestet, aber es fehlt zumindest ein & im Funktionsaufruf). Bei dieser Lösung ist die Fuktion zwar kürzer, aber dafür die Auswertung um eine Zeile länger. Quasi Geschmackssache.
Ich habe die Funktion so implementiert, damit die Auswertung übersichtlicher ist und bleibe somit bei meiner Lösung.

Viele Grüße
Andreas

Klebwax
28.11.2012, 18:44
Stimmt, so gehts auch (nicht getestet, aber es fehlt zumindest ein & im Funktionsaufruf).

Nein, das & fehlt nicht, das gehört da nicht hin.

Es geht aber noch einfacher:



#include <string.h>
char buf[] = "Hallo";
char *c = 0;

c = strchr(buf, 'a');

if(!c)
printf("Fehler");
else
printf("%c", *c);


Diese Version hat den Vorteil, daß sie nicht durch "rumprobieren" entstanden ist, sondern der Programmierer wußte, was er tat. Zusätzlich ist sie millionenfach getestet worden und hat eine sehr schöne Doku, die man leicht in einem C-Buch oder im Internet nachlesen kann. Und wenn man schon etwas eigenes schreibt, daß eine Funktion der libc nachbildet, sollte man Übergabeparameter und Returnwerte wie die Libraryfunktion verwenden. Das macht anderen und einem selbst nach einigen Monaten das Leben und das Verstehen leichter.

MfG Klebwax

Bumbum
29.11.2012, 17:18
Hallo Klebwax,

ich habe mir die Beschreibung der Funktion nicht genau angesehen, aber mein String ist nicht Null-Terminiert und kann es aus technischen Gründen ohne vorher umkopiert zu werden auch nicht werden. Deshalb bin ich überhaupt auf die Idee gekommen eine eigene Funktion dafür zu schreiben, und deshalb auch der Parameter MaxChars.

Viele Grüße
Andreas

Klebwax
29.11.2012, 19:03
... aber mein String ist nicht Null-Terminiert ...

Das ist natürlich unschön. Dann kann man die Stringfunktionen der libc garnicht verwenden.

MfG Klebwax

Wsk8
29.11.2012, 19:16
Hallo Klebwax,
aber mein String ist nicht Null-Terminiert
Das ist aber ganz schlechter Programmierstil!!! Den Fehler wissen ihn aber dann nicht ausbessern geht ja mal gar nicht. Wenn dein String zu kurz ist, musste ihn halt ein Zeichen länger machen oder wenn er lang genug ist, setzt du halt bei maxchar+1 einfach direkt ein '\0'.

mfg

Bumbum
29.11.2012, 19:53
Hallo Wsk8,

es ist immer leicht zu schimpfen, wenn man nicht alle Umstände kennt. ;-) Zu meiner Verteidigung: Der String "wächst" während er ausgewertet ist. Es handelt sich hierbei um einen RS232-Ring-Buffer, der ständig via IRQ mit Daten gefüllt wird. Ich muss also während des Empfangs auswerten. Eine bessere, performantere und ressourcenschonendere Lösung ist mir nicht eingefallen.

Viele Grüße
Bumbum

ahabakukuk
01.12.2012, 20:34
Hallo Bumbum

Zum Thema Ring- Buffer:

Ist das Ziel eines Ring- Buffers nicht, das man die Daten in einem Rutsch einlesen , danach auswerten und wieder löschen kann und so dem Ring- Buffer auch eine fixe Grösse zuweisen kann?

Ich sehe das jedenfalls so und mache es auch so.

Gruss

Bumbum
02.12.2012, 14:11
Hallo ahabakukuk,

ich glaube genau das ist nicht der Sinn eines Ringbuffers. Wenn du eh weißt wieviele Daten kommen kannst du dann, wie von dir schon herausgefunden, einen Buffer fester Größe definieren, alles einlesen und dann auswerten. Beim nächsten Datensatz fängst du einfach wieder vorne am Buffer an.

Einen Ringbuffer nimmt ma bei anderen Gegenheiten wie z.B. bei meinem Fall. Da kommen ca. 64kB (64000 Bytes) Daten oder mehr in ein paar Sekunden über die RS232. Von dieser "Datenflut" brauche ich dann ein paar Bytes zwischendrin. Die Daten werden per Interrupt in den Ringbuffer geschrieben und zwar ringförmig. Wenn ich das letzte Byte in den Buffer geschrieben habe kommt das nächste automatisch wieder an den Anfang des Buffers.
Ich muss nur schneller auswerten, wie Daten gesendet sind. In meinem Fall komme ich z.B. mit ca. 50 Bytes an Ringbuffer zurecht und kann die Kilobytes an Daten mit einem ATMega162 mit gerade mal 1kB RAM problemlos auswerten.

Viele Grüße
Andreas