mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik UART, String, Array, einzelne Zeichen extrahieren


Autor: Björn Niethammer (bniethammer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo liebes Forum!

Ich hab ein kleines Problem beim Zerstückeln eines Strings den ich über 
die UART empfangen hab. Der String steht in dem Array buf drinn. An ganz 
bestimmten Stellen dieses Arrays stehen Informationen die ich brauche. 
Die stehen auch immer genau da, weil es so vom Protokoll vorgegeben ist. 
Zum Beispiel will ich die beiden Zeichen buf[10] und buf[11] 
hintereinander in einen String Pointer schreiben. Den Pointer brauche 
ich damit ich damit dann eine Suchanfrage in einer SQL Datenbank starten 
kann.

Kleiner Codeauszug:

char buf[255];
char *status;
char temp[10];

/* lese aus UART in buf ein, mache malloc für status */

temp[0] = buf[10];
temp[1] = buf[11];
temp[2] = '\0';
status = (char *)temp;

An dieser Stelle bricht das Programm dann mit einem segmentation fault 
ab.

Hat einer eine Idee was ich falsch mache oder wie es eleganter 
funktioniert?

Hab selbst schon mit sprintf() und mit strncat() es versucht. Aber bei 
beidem ein seg. fault.

Gruß Björn Niethammer

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sicher das der "segmentation fault" bei diesem Code Schnipsel auftritt, 
denn so verkehrt sieht das ganze nicht aus. Es sind alles einfache 
Zuweisungen da kann so etwas nicht passieren.

Was soll der Kommentar sagen "mache malloc für status " ich sehe im dem 
Code kein malloc.


Eventuell mal etwas mehr Code schicken.

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also hab das mal kompiliert (und probiert)... geht ohne Probleme(seg 
fault..)
int main() {
  char buf[255];
  char *status;
  char temp[10];
  buf[10] = 'c';
  buf[11]= 'd';

  temp[0] = buf[10];
  temp[1] = buf[11];
  temp[2] = '\0';
  status = (char *)temp;
  return 0;
}

Autor: Björn Niethammer (bniethammer)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter!

Danke für deine Antwort. Ich fand meine Code eigentlich auch nicht so 
schlecht. Aber anscheind ist da ja doch noch ein gravierender Fehler 
drinn. Bin mir eigentlich super sicher das bei den Codezeilen der Fehler 
auftaucht. Denn wenn ich es weglasse funktioniert mein Programm.

Hab mal einen etwas ausführlicheren Code angehängt. Mit UART 
Initialisierung und einlesen und allem drum und dran. Die Sachen für den 
Datenbank Zugriff hab ich gelöscht denn das funktioniert auch soweit 
alles.

Zum Verständnis: Es wird etwas über UART empfangen und dann anhand des 
Zeichen an der Stelle 9 im Buffer ausgewählt was zu tun ist. Nachdem das 
vollzogen ist und der Fall das dort das Zeichen '6' drinn steht soll 
weiter geschaut werden was für Zeichen an den anderen Positionen stehen. 
Damit muss dann später eine SQL Anweisung zusammengebastelt werden a la: 
"UPDATE TABLE WHERE STATUS_ID = <Wert von status>;" Deswegen der ganze 
Aufwand.

Gruß Björn

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe jetzt nicht alles angeschaut, aber der Fehler liegt wol hier:

temp[0] = (char)buf[10];
temp[1] = (char)buf[11];
temp[2] = '\0';
status = temp;

temp[0] = (char)buf[16];
temp[1] = (char)buf[17],
temp[2] = '\0';
zentr_nr = temp;

temp[0] = (char)buf[20];
temp[1] = (char)buf[21];
temp[2] = (char)buf[22];
temp[3] = (char)buf[23];
temp[4] = '\0';
linien_nr = temp;

temp[0] = (char)buf[24];
temp[1] = (char)buf[25];
temp[2] = '\0';
melder_nr = temp;


die Variablen status, zentr_nr, linien_nr, melder_nr sind alles Zeiger 
und habe selber keinen Inhalt - sie Zeigen nur auf das Array temp. Damit 
Zeigen alle auf die selben daten.
Der SegmentFault wird wohl kommen weil die Variablen nicht den Inhalt 
haben den du willst.

Autor: peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
habe jetzt nur flüchtig hingeschaut und weiss auch nicht um welchen 
Compiler es geht, aber meiner Meinung nach fehlt bei den 
Zeigerzuweisungen der Adressoperator.

Bsp.
status = &temp[0];

Autor: Björn Niethammer (bniethammer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke Peter. Ich hatte dann auch gedacht dass es mit einem 
Adressoperator geht. Aber dann bleibt es trotzdem der gleiche Inhalt auf 
den die Zeiger zeigen. Hab mich deswegen von den Zeigern getrennt und 
dafür auch Arrays deklariert und nun funktioniert es.

Als Compiler wird übrigens ein GCC Derivat der als ARM Cross Compiler 
installiert ist genutzt.

Vielen Dank für deine Mühe.

Gruß Björn

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du hast stehen:
status = (char *)temp;

Das müsste aus dem Wert in Temp (ich weiß nicht genau, als was er das 
interpretiert, als u8 oder u16) eine Adresse machen.
Also steht vorher der u16-Wert zB 40000 drin, steht nachher im Pointer 
status auch der Wert 40000.
Das ist als Adresse natürlich unsinn.

Es sollte wohl so:
status = &temp;

Oder vielleicht so sein:
status = (uint8_t*)  (uint16_t)buf[10]   |  ( (uint16_t)buf[11] << 8);

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Peter:
@ Matthias Lipinsky:

temp ist ein char-Array, damit ist
temp
(char*)temp
&temp
&temp[0]
hier alles äquivalent.

> Oder vielleicht so sein:
>
> status = (uint8_t*)  (uint16_t)buf[10]   |  ( (uint16_t)buf[11] << 8);
> 

Und das ist doch gänzlich unsinnig. Nicht nur, dass da eine Klammerung 
fehlt, du glaubst doch nicht wirklich, dass beim OP ein Pointer per UART 
übertragen wird, der dann beim Empfänger irgendwo in den Speicher zeigt, 
oder?

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>dass beim OP ein Pointer per UART
>übertragen wird, der dann beim Empfänger irgendwo in den Speicher zeigt,
>oder?

Nein. Stimmt. Wenn dann wird ein Arrayindex übertragen.
Ich ziehe den Post zurück

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.