Forum: Compiler & IDEs Einfach Frage zu einer Funktion!


von Stefan (Gast)


Lesenswert?

Hallo !

Ich bin mir nicht 100% sicher, wie ich eine Rückgabe meiner Funktion 
richtig programmiere. Deswegen brauch ich mal schnell und kurz eure 
Hilfe.

// Lesen eines Filediskriptors

int auslesen( char ARRAY[256], int len )
{
 read(fd,ARRAY,256);     // Abfrage Serielle Schnittstelle
 len = strlen(ARRAY);    // Abfrage Länge des ARRAY
}


// Im Hauptprogramm möchte ich gerne BUFFER bzw. den Inhalt und den len 
weiter nutzen.

int main()
{
...
auslesen(BUFFER);
...
}


Wie muss "int auslesen" richtig programmieren, sodaß ich den Inhalt 
verwerten kann ??
Oder ist das so richtig ??

Vielen Dank !!

von kosmonaut pirx (Gast)


Lesenswert?

hallo,

annahme: du hast den fildescriptor fd global definiert (und geholt)

dann sollte read so funktionieren, obwohl ich das mit pointer ja lieber 
mag .. aber das thema gabs ja neulich schon.

und du solltest das "len" zurückliefern: return len;
dein compiler hat sich sicherlich schon über den fehlenden return-wert 
beschwert.

bye kosmo

von Stefan (Gast)


Lesenswert?

Wie keine Pointer oder Adresszeiger ?
Einfach das return noch mit einfügen und dann ist gut ?

int auslesen( char ARRAY[256], int len )
{
 read(fd,ARRAY,256);     // Abfrage Serielle Schnittstelle
 len = strlen(ARRAY);    // Abfrage Länge des ARRAY
 return len;
}

von kosmonaut pirx (Gast)


Lesenswert?

literatur ist sicher eine gute idee, aber wenn's mal wieder eilig ist, 
braucht auch niemand den oberlehrer auspacken. scnr.

und dies noch zum feierabend:
im beispielcode bleibt noch ungeklärt, wie der filedescriptor in der 
main deklariert, aber in der anderen routine benutzt werden soll.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Außerdem hat Angela Merkel nicht verstanden, dass man natürlich einen
Array-Parameter deklarieren kann, wenngleich die Angabe der Array-
Größe dort witzlos ist.  Weiterhin hat sie zwar die sinnlose Deklaration
von len als Funktionsparameter eliminiert (wird dann sowieso nur als
lokale Variable missbraucht, da kann man auch gleich eine lokale
Variable definieren), aber dafür gleich gar keine Definition von len
mehr in auslesen() übrig gelassen.  So richtig hat sie sich die Bücher
wohl auch nicht angeguckt...

An den OP: bist du dir sicher, dass strlen() das richtige ist, d.h.
dass du nach dem Versuch, 256 Bytes zu lesen, einen String bekommst,
der am Ende mit Nullbytes gefüllt wird?  Oder willst du vielmehr
wissen, wie viele Bytes von read() überhaupt gelesen werden konnten?
Dafür braucht's kein strlen(), sondern diese Anzahl gibt read() selbst
zurück.

Um aber richtig helfen zu können, musst du mehr über deine Umgebung
(ist das ein Unix-Umfeld?) sowie über deine Daten (Texte, Binärdaten)
sowie Datenquelle (Terminal, Datei) schreiben.

von Rolf Magnus (Gast)


Lesenswert?

> Dafür braucht's kein strlen()

Genauer gesagt: Da funktioniert strlen() gar nicht. Selbst wenn die 
gelesenen Daten mit einem \0-Zeichen terminiert wären, sollte man sich 
nicht darauf verlassen. Bei einem Übertragungsfehler wird das vielleicht 
mal verschluckt, und schon schmiert einem gleich der µC ab.

von Klaus F. (kfalser)


Lesenswert?

Das ist aber nicht die liebevolle Art, für die sich Angela Merkel sonst 
rühmt.

Jörg und Rolf haben schon recht, die read() Funktion schließt das Feld 
niemals mit '\0' ab, wenn man die Daten mit den Stringfunktionen 
weiterverarbeiten will dann sollte man ganz explizit ans Ende einen 
Null-Character schreiben.

len = read(fd, array, LEN-1);
array[len] = '\0';

Klaus

von Klaus F. (kfalser)


Lesenswert?

> Wo habt ihr nur alle eure Glaskugeln her?

Ollivanders Zauberladen, Winkelgasse, natürlich !

von pumpkin (Gast)


Lesenswert?

Ich spüre negative Schwingungen.

von Rolf Magnus (Gast)


Lesenswert?

> Wenn Stefan die Länge des Arrays mittels strlen bestimmen will, muss er
> die eingelesenen Daten so angelegt haben, dass das letzte eingelesene
> Zeichen '\0' ist. Dann braucht man nix Nullen anhängen.

Dafür muß man vor jedem Aufruf der Funktion das komlette Array 
ausnullen, und das nur, damit strlen nochmal unnötig durchiterieren 
kann. Das wäre zumindest nicht besonders zweckmäßig. Außerdem gehen 
Daten verloren, wenn in den empfangenen Bytes ein Nullbyte ist.

von Stefan (Gast)


Lesenswert?

Hallo erstmal und Danke für Eure Beiträge, besonders die mit der 
Glaskugel ;-)

Nun, aber mal wieder zurük zur meiner Frage.

Im wesentlichen wollte ich einen Funktionsaufruf haben, der mir den 
Inhalt meines ARRAY und die Lange des ARRAY wieder gibt.

auslesen(BUFFER,len);  oder
len = auslesen(BUFFER); habe ich in meinem Programm übernommen.

Ein weiteres ist, da ich einen Ringpuffer auslesen muss, die Funktion an 
mehren Stellen in meinem Hauptprogramm aufzurufen.

Nun,angenommen der Ringpuffer beinhaltet 100Bytes an Daten. Jetzt möchte 
ich diese Daten auswerten. Wie würdet Ihr dies anstellen. Die Nutzdaten 
sind unterschiedliche Länge und wie filter ich die Nutzdaten heraus?

Soll man den ganz Puffer auslesen, und mit einen strcmp() vergleichen?

Aber selbst dann stehen die Nutzdaten, quasi hintereinander
LAMPEPUMPETESTSTOPSTART so stehen die Nutzdaten im Ringpuffer, wie soll 
man damit klar kommen ??? Oder soll explizit beim schreiben eine 
Terminierung stattfinden LAMPE0PUMPE0TEST0STOP0.... etc...

MFG Stefan

von kosmonaut pirx (Gast)


Lesenswert?

hallo,
nun, um eine terminierung kommst du nicht so einfach herum.

>Nun,angenommen der Ringpuffer beinhaltet 100Bytes an Daten. Jetzt möchte
>ich diese Daten auswerten. Wie würdet Ihr dies anstellen. Die Nutzdaten
>sind unterschiedliche Länge und wie filter ich die Nutzdaten heraus?

also, ringbuffer: du weißt sicher, das ist im prinzip eine 
warteschlange/queue, die nicht "begrenzt" ist. in dieser queue gibt es 
einträge. zugriffe auf die queue gibt es nur mit push (anstellen) und 
pop (abarbeiten).
für einen kompletten verlgeich aller einträge ist eine queue nicht so 
recht passend. dazu musst du alle einträge holen, vergleichen und ggf. 
wieder rauf packen.
du möchtest die daten auswerten, schreibst du. dazu machst du immer 
einen "pop" auf die queue. ist diese noch nciht leer, kriegst du den 
nächsten eintrag und kannst ihn auswerten. jeder eintrag wird 
von-wem-auch-immer einfach in die queue ge-pushed, und fertig ist. dabei 
kann auch die terminierung erfolgen.

soweit halbwegens verstanden? :)

bye kosmo

von Stefan (Gast)


Lesenswert?

Hallo !

Was ist denn wenn ich anstatt einer Terminierung, den String durchsuche?

char puffer[8] = { "EISBAER" };
char suche[8]  = { "BAER" };

char *ptr;

ptr = strstr(puffer,suche);


Was ist mit so einer Lösung?

Ist so eine Art der Programmierung zum auswerten eines Ringpuffers 
empfehlenswert?

von Karl H. (kbuchegg)


Lesenswert?

Stefan wrote:

> Was ist mit so einer Lösung?
>
> Ist so eine Art der Programmierung zum auswerten eines Ringpuffers
> empfehlenswert?

Nein.

Der Grundsatz jeder Basisdatenstruktur sollte sein:
So wie ich die Daten an die Struktur übergebe, so will
ich sie aus der Datenstruktur wiederhaben.

Alles andere: Ask for troubles

Was hast du für ein Problem damit einen String den
du byteweise in den Ringbuffer schreibst mit einem
'\0' Zeichen abzuschliessen? So wie das in C für
Strings üblich ist und seit 40 Jahren praktiziert wird.

von Stefan (Gast)


Lesenswert?

Nein, ich habe da kein Problem mit !
Ich muss es halt nur extra hinzufügen!


Wie ist das denn generell noch mal für mein Verständnis!

Ich habe eine  ARRAY6] = "SONNE";

Jetzt schreibe ich das ARRAY in meinen Ringpuffer. Dazu muss ich doch 
jetzt noch explizit das /0 hinzufügen! Korrekt ?

Das ARRAY hat ja bereits nen Abschluss mit ner /0, die wird aber nicht 
mit in den Ringpuffer übernommen, somit müßte ich eigentlich schreiben:


ARRAY[8] = "SONNE/0";

Habe ich das richtig auf dem Schirm ?

von Karl H. (kbuchegg)


Lesenswert?

Stefan wrote:

> Wie ist das denn generell noch mal für mein Verständnis!
>
> Ich habe eine  ARRAY6] = "SONNE";
>
> Jetzt schreibe ich das ARRAY in meinen Ringpuffer. Dazu muss ich doch
> jetzt noch explizit das /0 hinzufügen! Korrekt ?
>
> Das ARRAY hat ja bereits nen Abschluss mit ner /0

Korrekt.

> die wird aber nicht
> mit in den Ringpuffer übernommen, somit müßte ich eigentlich schreiben:

Das kommt drauf an, wie du die Einstellfunktion in den Ringbuffer
schreibst.

Ich geh mal davon aus, dass du eine Funktion hast, die 1 Byte
in den Ringbuffer stellt. Ich nenn die mal Enqueue. Dann ist
es trivial darauf aufbauend eine Funktion zu schreiben, die
einen kompletten String, inklusive Terminierung, einstellt
1
void Enqueue( uint8_t Byte )
2
{
3
  ....
4
}
5
6
void EnqueueString( const char* String )
7
{
8
  while( *String != '\0' )
9
    Enqueue( *String++ );
10
  Enqueue( '\0' );
11
}
12
13
int main()
14
{
15
  char Test[] = "Juhu";
16
17
  EnqueueString( Test );
18
  EnqueueString( "Noch ein Test" );
19
}

Und genauso simpel ist es die gegenteilige Funktion zu schreiben,
die, aufbauend auf einer Funktion die ein Byte aus dem Ringbuffer
holt, dies mit einem String tut: Sie holt solange Bytes aus
dem Ringbuffer bis das '\0' Zeichen erreicht wird und speichert
die Bytes in der bereitgestellten Speicherfläche (normalerweise
wahrscheinlich ein Array) ab. Inklusive '\0' natürlich.

PS: Die traditionellen Namen für diese Funktionen sind Enqueue
und Dequeue, da es sich hier um eine Warteschlange handelt, ein
FIFO
Push und Pop werden normalerweise für Stacks benutzt, also einen LIFO

von Stefan (Gast)


Lesenswert?

Hallo kbuchegg!

Danke für das Programmbeispiel...
Das Auswerten der einzelnen Strings würdest Du über strcmp() machen?

Was ist, wenn ich 30 Wörter in meinem Ringpuffer habe? Ist das n. etwas 
umständlich, anderes rum gibt es überhaupt ne andere Möglichkeit außer 
dies mit strcmp zu machen? Eine Statemaschine die die einzelnen String 
überprüft, wäre wohl das sinnvollste, oder ? Was ist Deine Meinung ?

Mfg Stefan

von Karl H. (kbuchegg)


Lesenswert?

Stefan wrote:

> Was ist Deine Meinung ?

Meine Meinung:

Zuallerst sorge dafür, dass dein Programm korrekt funktioniert.
Wenn es dann läuft, sieh dir an ob es schnell genug läuft.
Tut es das: Super. Fertig.
Tut es das nicht: Finde raus, wo die meiste Zeit verbraucht wird
(zb. mit einem Profiler) und fang dort zu optimieren an.

Das heist nicht, dass es ok ist, wenn man im Vorfeld schludert
und der Maschine unnötige Lasten aufbürdet. Es heist aber:
Nimm einen normalen Programmierstil her und erst wenn der
nachweislich nicht mehr reicht, erst dann fange zu tricksen an.


> Das Auswerten der einzelnen Strings würdest Du über strcmp()
> machen?

Sicher. Warum nicht?

> Was ist, wenn ich 30 Wörter in meinem Ringpuffer habe?

Dann warten eben 30 Wörter im Ringbuffer, dass sie abgeholt
werden und mit ihnen etwas gemacht wird. Solange der Ring-
buffer nicht übergeht ist das ja kein Problem.

> Ist das n. etwas umständlich,

Das weis ich nicht, weil ich nicht weis was du machen willst.

> anderes rum gibt es überhaupt ne andere Möglichkeit außer
> dies mit strcmp zu machen?

Das hat aber erst mal nichts mit dem Ringbuffer zu tun.
Gewöhn dir an die Dinge funktional zu trennen. Der Ringbuffer
hat eine einzige Aufgabe: Daten zwischenzuspeichern. Es ist
nicht Aufgabe des Ringbuffers sich darum zu kümmern woher
die Daten kommen bzw. was mit ihnen weiter passiert. Im
Ringbuffer werden die Daten (in deinem Fall wohl Strings)
zwischengeparkt. Wenn deine Ringbufferfunktionen das fehlerfrei
können, dann erfüllen sie ihre Aufgabe zu 100%

> Eine Statemaschine die die einzelnen String
> überprüft, wäre wohl das sinnvollste,

Kann sein, kann aber auch nicht sein.
Wieviele verschiedene Wörter hast du denn?
Auf die Auswertung eines Wortes folgt ja eine Aktion: Wie
ist das geschätzte Verhältnis von Auswertung/Aktion
Wo kommt die Eingabe überhaupt her?

Möglichkeiten:
  * plain vanilla linear in einer Tabelle suchen
  * ebenfalls die Schlüsselwörter in eine Tabelle aber
    diesmal sortiert. -> Binär suchen
  * Hashtable
  * Statemachine. Wobei das das unflexibelste ist, wenn sich
    die Liste der Schlüsselwörter mal ändert. Auf der anderen
    Seite könnte man sich ein Programm schreiben, welches die
    Statemaschine aus der Liste der Schlüsselwörter generiert.

Da ich aber notorisch faul bin, würde ich als allererstes mal
Option 1 (plain vanilla Tabelle mit linearem Suchen) nahmen,
es sein denn die Liste der Schlüsselwörter ist relativ gross
oder es stellt sich im Vorfeld heraus, dass das zu langsam wird.
Dann würde ich auf eine sortierte Liste mit binärer Suche ausweichen.

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.