www.mikrocontroller.net

Forum: PC-Programmierung strstr() & strncpy()


Important announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Henrik Wellschmidt (w3llschmidt)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Ich raffs nicht ...

ich erstell mir einen Zeiger aus einem FD auf ein String,

ptr=strstr(buffer, "1-0:21.7.0*255");
printf(ptr);

1-0:21.7.0*255(+00023*W)
1-0:21.7.0*255(+00023*W)
1-0:21.7.0*255(+00023*W)

Super! Aber nun will ich die Zahl in den Klammern extrahieren mit

char value[6];         
strncpy(value, ptr+16, 5);

Und egal was ich mache -> Segmentation fault.

:-/

Autor: Rolf Magnus (rmagnus)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Henrik Wellschmidt schrieb:
> Ich raffs nicht ...
>
> ich erstell mir einen Zeiger aus einem FD auf ein String,

Was ist denn ein "Zeiger aus einem FD"?

> ptr=strstr(buffer, "1-0:21.7.0*255");
> printf(ptr);
>
> 1-0:21.7.0*255(+00023*W)
> 1-0:21.7.0*255(+00023*W)
> 1-0:21.7.0*255(+00023*W)
>
> Super! Aber nun will ich die Zahl in den Klammern extrahieren mit
>
> char value[6];
> strncpy(value, ptr+16, 5);
>
> Und egal was ich mache -> Segmentation fault.

Hast du auch daran gedacht, das '\0' anzuhängen?

Autor: Peter II (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
welchen datentype hat ptr?

Autor: Henrik Wellschmidt (w3llschmidt)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Rolf Magnus schrieb:
> Was ist denn ein "Zeiger aus einem FD"?

Hallo Rolf,

also ich lese mit read() aus einem 'File Fescriptor' in ein
char array (buffer) ...

strstr() liefert dann einen Zeiger auf die Fundstelle
im char array (buffer).

Das wollte ich damit sagen ;-)

Autor: Henrik Wellschmidt (w3llschmidt)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Peter II schrieb:
> welchen datentype hat ptr?

char *ptr;

Autor: Volkmar Dierkes (volkmar)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Hast Du Rolfs Frage gesehen?

Rolf Magnus schrieb:
>> Und egal was ich mache -> Segmentation fault.
>
> Hast du auch daran gedacht, das '\0' anzuhängen?

Was kommt noch nach der strncpy-Anweisung, eine Ausgabe mit printf?

Volkmar

Autor: Henrik Wellschmidt (w3llschmidt)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Volkmar Dierkes schrieb:
> Hast Du Rolfs Frage gesehen?

Ja, kann ich aber noch nicht zuordnen ...

> Was kommt noch nach der strncpy-Anweisung, eine Ausgabe mit printf?

Erstmal noch nischt ... ich wollte dann mit atof[] in ein Float wandeln
und dann ein eine andere Funktion schicken ...

        while (1) {

                res = read(fd, buffer, sizeof(buffer) -1);

                if (res >=0) {
                buffer[res]=0;

                ptr=strstr(buffer, "1-0:21.7.0*255");

                char value[6]; 
                strncpy(value, ptr+16, 5);

                }
        }

Autor: Rolf Magnus (rmagnus)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Henrik Wellschmidt schrieb:
> Volkmar Dierkes schrieb:
>> Hast Du Rolfs Frage gesehen?
>
> Ja, kann ich aber noch nicht zuordnen ...

Strings müssen nullterminiert sein. Ein strncpy kopiert zwar ein \0 des 
Originalstrings mit, wenn es einen kompletten String kopiert, aber wenn 
der Quellstring länger ist als die angegebene Maximallänge, dann hängt 
es keins an.

>> Was kommt noch nach der strncpy-Anweisung, eine Ausgabe mit printf?
>
> Erstmal noch nischt ...

Dann dürfte aber auch kein Segfault passieren. Der kommt erst, wenn du 
mangels String-Ende-Zeichen über das Ende hinaus liest.

Autor: Henrik Wellschmidt (w3llschmidt)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Rolf Magnus schrieb:
> Strings müssen nullterminiert sein. Ein strncpy kopiert zwar ein \0 des
> Originalstrings mit, wenn es einen kompletten String kopiert, aber wenn
> der Quellstring länger ist als die angegebene Maximallänge, dann hängt
> es keins an.

Ahh!

1-0:21.7.0*255(+00023*W)

|1|-|0|:|2|1|.|7|.|0|*|2|5|5|(|+|0|0|0|2|3|*|W|)|\0

strncpy(value, ptr+16, 5);

| | | | | | | | | | | | | | | | |0|0|0|2|3| | | |\0

Fehlt also hier                            ^

|0|0|0|2|3|

Ich wollte aber danach eigentlich gleich:

double w = atof(value);

ranhängen ?!

Autor: Karl Heinz Buchegger (kbuchegg) (Moderator)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Henrik Wellschmidt schrieb:


> Fehlt also hier                            ^
>
> |0|0|0|2|3|
>
> Ich wollte aber danach eigentlich gleich:
>
>
>
> double w = atof(value);
> 
>
> ranhängen ?!

Na dann setz halt hinten in value ein 0 Byte ein

    strncpy(value, ptr+16, 5);
    value[5] = '\0';


Egal was strncpy gemacht hat, jetzt ist das Zeug im Array value ganz 
sicher ein String, weil sichergestellt ist, dass da auf jeden Fall eine 
0-Terminierung existiert.

Und du solltest den Pointer, den dir strstr gegeben hat, 
sicherheitshalber auch gegen NULL prüfen :-)

PS: Wärs nicht besser und auch einfacher, nach der öffnenden Klammer '(' 
suchen zu lassen?

Autor: Henrik Wellschmidt (w3llschmidt)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Karl Heinz Buchegger schrieb:
>
>     strncpy(value, ptr+16, 5);
>     value[5] = '\0';
>
>
> Egal was strncpy gemacht hat, jetzt ist das Zeug im Array value ganz
> sicher ein String, weil sichergestellt ist, dass da auf jeden Fall eine
> 0-Terminierung existiert.
>
> Und du solltest den Pointer, den dir strstr gegeben hat,
> sicherheitshalber auch gegen NULL prüfen :-)
>
> PS: Wärs nicht besser und auch einfacher, nach der öffnenden Klammer '('
> suchen zu lassen?

Hallo  Karl Heinz ...

Segmentation fault :(



        while (1) {

                res = read(fd, buffer, sizeof(buffer) -1);

                if (res >=0) {
                buffer[res]=0;

                ptr = strstr(buffer, "1-0:21.7.0*255");

                char value[10];
                strncpy(value, ptr+14,5);
                value[5] = '\0';


                }
        }

Ich denke das liegt an dem zeiger ptr 'strncpy(value, ptr+14,5);'

In den beispielen verwenden die immer 'char arrays' keine pointer
auf ein 'char arry' ...

Mist.

Autor: Thomas Miletich (thomil)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
In deinem letzten Code:

Liest read() genug Zeichen ein? Wenn read() einen Fehler zurückliefert, 
dann wird 'buffer' nie 0-Terminiert und du liest u.U. über das buffer 
ende.

Findet strstr() auch wirklich den gesuchten string? Ansonsten ist ptr 
ein NULL pointer der beim Zugriff zu einem segfault führt.

Autor: W.S. (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Henrik Wellschmidt schrieb:
> Ich raffs nicht ...

Tja, Stringverarbeitung war schon immer eine der besonderen Stärken von 
C.

W.S.
(dem heut abend beim Tempranillo nach Stänkern zumute ist)

Apropos char* Pointer: versuche es doch mal mit

strncpy(value, &buffer[16], 5);

vielleicht verschafft dir das ne Erkenntnis.

Autor: Henrik Wellschmidt (w3llschmidt)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Thomas Miletich schrieb:
> In deinem letzten Code:
>
> Liest read() genug Zeichen ein? Wenn read() einen Fehler zurückliefert,
> dann wird 'buffer' nie 0-Terminiert und du liest u.U. über das buffer
> ende.
>
> Findet strstr() auch wirklich den gesuchten string? Ansonsten ist ptr
> ein NULL pointer der beim Zugriff zu einem segfault führt.

Ja, das passt alles ... ich greif ja nur auf buffer zu
wenn 'if (res >=0)'

res = read(fd, buffer, sizeof(buffer) -1);

if (res >=0) {
buffer[res]=0;

Das kommt 5sekündlich über die Schnittstelle rein ->

/HAG5eHZ010C_EHZ1WA02

1-0:0.0.0*255(1095110000152759)
1-0:1.8.0*255(000005.2786)
1-0:96.5.5*255(82)
0-0:96.1.255*255(0000152759)
1-0:32.7.0*255(232.15*V)
1-0:52.7.0*255(232.16*V)
1-0:72.7.0*255(000.00*V)
1-0:31.7.0*255(000.10*A)
1-0:51.7.0*255(000.21*A)
1-0:71.7.0*255(000.00*A)
1-0:21.7.0*255(+00023*W)
1-0:41.7.0*255(+00042*W)
1-0:61.7.0*255(+00000*W)
1-0:96.50.0*0(67)
1-0:96.50.0*1(07CF)
1-0:96.50.0*2(19)
1-0:96.50.0*3(09)
1-0:96.50.0*4(25)
1-0:96.50.0*5(1A)
1-0:96.50.0*6(003D381B300AF9003D00490200009F80)
1-0:96.50.0*7(00)
!

Und

ptr = strstr(buffer, "1-0:21.7.0*255");
printf(ptr);

sucht mir schoen das was ich brauche ...
1-0:21.7.0*255(+00023*W)
1-0:21.7.0*255(+00023*W)
1-0:21.7.0*255(+00023*W)
1-0:21.7.0*255(+00023*W)
1-0:21.7.0*255(+00023*W)
1-0:21.7.0*255(+00023*W)
1-0:21.7.0*255(+00023*W)
1-0:21.7.0*255(+00023*W)
1-0:21.7.0*255(+00023*W)
1-0:21.7.0*255(+00023*W)
1-0:21.7.0*255(+00023*W)
1-0:21.7.0*255(+00023*W)

Und dann verlässt es mich ...

Autor: Volkmar Dierkes (volkmar)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Hallo,

Henrik Wellschmidt schrieb:
>                 char value[10];
>                 strncpy(value, ptr+14,5);
>                 value[5] = '\0';

versuche mal das hier, achte auf das '&' bei value.
                 char value[10];
                 strncpy(&value, ptr+14,5);
                 value[5] = '\0';

Wenn ich mich nicht irre, mußt Du der strncpy-Funktion ja eine Adresse 
übergeben, wo der String hingeschrieben werden soll. Aber da value kein 
Pointer ist, sondern eine Array of char, brauchst Du die Adresse davon.

Volkmar

Autor: Karl Heinz Buchegger (kbuchegg) (Moderator)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Henrik Wellschmidt schrieb:

> Und dann verlässt es mich ...

Das einzige was dich verlässt ist, dass dein printf offenbar eine 
Sicherung gegen NULL-Pointer hat ....
  UND DEIN CODE NICHT !

Frag jetzt endlich mal den Pointer ab, den du von strstr kriegst. Denn 
das kann ich aus 300km Entfernung sehen, dass in der Hälfte deiner Daten 
der Suchstring gar nicht vorkommt. Und in dem Fall liefert dir strstr 
einen NULL-Pointer! Und mit einem NULL Pointer kannst du nicht weiter 
arbeiten!

Bei ausnahmslos jeder Suche muss man immer damit rechnen, dass der 
gesuchte Wert nicht vorhanden ist! Auch du musst damit rechnen! So wie 
alle anderen auch!

Und buffer ist hoffentlich ein char Array!
(Immer diese HickHack Technik nur Ausschnitte aus einem Programm zu 
zeigen. Was ist da so toll drann? Ist das wirklich cool, wenn wir auf 
der anderen Seite des Monitors Rätselspielchen spielen müssen?)


   char buffer[100];

...

   while (1) {

     res = read(fd, buffer, sizeof(buffer) -1);

     if (res > 0) {
       buffer[res] = '\0';

       printf( "received >%s<\n", buffer );

       ptr = strstr( buffer, "1-0:21.7.0*255" );
       if( ptr != NULL ) {
         char value[6]; 
         strncpy( value, ptr + 16, 5 );
         value[5] = '\0';

         printf( "'%s' -> '%s'\n", buffer, value );
       }
     }
   }


Und ich schätze mal, das alles funktioniert überhaupt nicht, weil gar 
nicht garantiert ist, dass read immer eine komplette Zeile liefert. 
read() interessieren deine Zeilen nämlich nicht, der liefert was da ist, 
bzw. füllt dir den Buffer randvoll an. Verwende fgets. Dann bist du 
zumindest dieses Problem los. fgets teilt die eingehenden Daten schön in 
Zeilen auf und liefert dir immer eine komplette Zeile.

Wenn du fgets nimmst, musst du deinen open durch einen fopen austauschen 
und den close gegen einen fclose.

Autor: Karl Heinz Buchegger (kbuchegg) (Moderator)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Volkmar Dierkes schrieb:
> Hallo,
>
> Henrik Wellschmidt schrieb:
>
>                 char value[10];
>>                 strncpy(value, ptr+14,5);
>>                 value[5] = '\0';
> 
>
> versuche mal das hier, achte auf das '&' bei value.

Quatsch


> übergeben, wo der String hingeschrieben werden soll. Aber da value kein
> Pointer ist, sondern eine Array of char, brauchst Du die Adresse davon.

Kauf dir ein C-Buch und lies mal nach wie Arrays übergeben werden.

Autor: Thomas Miletich (thomil)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Henrik Wellschmidt schrieb:
> Thomas Miletich schrieb:
>> In deinem letzten Code:
>>
>> Liest read() genug Zeichen ein? Wenn read() einen Fehler zurückliefert,
>> dann wird 'buffer' nie 0-Terminiert und du liest u.U. über das buffer
>> ende.
>>
>> Findet strstr() auch wirklich den gesuchten string? Ansonsten ist ptr
>> ein NULL pointer der beim Zugriff zu einem segfault führt.
>
> Ja, das passt alles ... ich greif ja nur auf buffer zu
> wenn 'if (res >=0)'

Stimmt. Hab ich aufgrund der fehlerhaften Formatierung falsch gelesen.

Autor: Henrik Wellschmidt (w3llschmidt)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Karl Heinz Buchegger schrieb:
>
>
> 
> ...
> 
>    while (1) {
> 
>      res = read(fd, buffer, sizeof(buffer) -1);
> 
>      if (res > 0) {
>        buffer[res] = '\0';
> 
>        printf( "received >%s<\n", buffer );
> 
>        ptr = strstr( buffer, "1-0:21.7.0*255" );
>        if( ptr != NULL ) {
>          char value[6];
>          strncpy( value, ptr + 16, 5 );
>          value[5] = '\0';
> 
>          printf( "'%s' -> '%s'\n", buffer, value );
>        }
>      }
>    }
> 

Danke Karl Heinz!!!! Das rockt!!!

00023
00023
00023
00023
00023
00023
00023

Karl Heinz Buchegger schrieb:
>Und mit einem NULL Pointer kannst du nicht weiter arbeiten!

Jetzt verstehe ich ....

(null)(null)(null)(null)(null)(null)(null)(null)(null)(null)(null)(null) 
(null)(null)(null)(null)(null)(null)(null)(null)(null)(null)(null)1-0:21 
.7.0*255(+00000*W)

Autor: Henrik Wellschmidt (w3llschmidt)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Thomas Miletich schrieb:
> Stimmt. Hab ich aufgrund der fehlerhaften Formatierung falsch gelesen.

Ich weiss, ich habe da grosse Differenzen zum Standard ;-)

Autor: Karl Heinz Buchegger (kbuchegg) (Moderator)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Es hilft alles nichts. Du brauchst ein C-Buch und musst es 
durcharbeiten. Diese Try&Error Programmierung, das Zusammenkopieren von 
Code, das funktioniert vielleicht bei kleinen Programmen (und auch da 
nicht besonders gut), aber irgendwann ist ein Punkt erreicht, an dem man 
ohne solide gelernte Grundlagen nicht weiter kommt.


> Ich weiss, ich habe da grosse Differenzen zum Standard ;-)
Und warum tust du dann nichts dagegen?
Wenigstens Einrückungen richtig zu stellen, kostet dir nichts. Die sind 
aber ein solides und erprobtes Mittel um { } Fehler zu sehen und zu 
finden. Erfordert Dispziplin, schon klar. Aber im Vergleich zu dem, was 
dir die restliche Programmierung an Disziplin abverlangt, ist das 
Pipifax.

Autor: Henrik Wellschmidt (w3llschmidt)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Karl Heinz Buchegger schrieb:
> Es hilft alles nichts. Du brauchst ein C-Buch und musst es
> durcharbeiten. Diese Try&Error Programmierung, das Zusammenkopieren von
> Code, das funktioniert vielleicht bei kleinen Programmen (und auch da
> nicht besonders gut), aber irgendwann ist ein Punkt erreicht, an dem man
> ohne solide gelernte Grundlagen nicht weiter kommt.

Ich habe 4 C-Bücher :-)

Aber es ist halt zu verlockend sich vor den Rechner zu setzen.

Ich verstehe ja ganz gut was hier geschrieben wird und lerne dabei.

Klar, blind Code kopieren wäre wirlich blöde.

Beitrag #3015196 wurde vom Autor gelöscht.
Autor: Henrik Wellschmidt (w3llschmidt)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Karl Heinz Buchegger schrieb:
> bzw. füllt dir den Buffer randvoll an. Verwende fgets. Dann bist du
> zumindest dieses Problem los. fgets teilt die eingehenden Daten schön in
> Zeilen auf und liefert dir immer eine komplette Zeile.

Hallo Karl Heinz,

Ich habe noch nirgens gesehen, wie man fopen() und tcsetattr() zusammen
bekommt ...

http://en.wikibooks.org/wiki/Serial_Programming/termios

...

Autor: DirkB (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Henrik Wellschmidt schrieb:
> Ich habe noch nirgens gesehen, wie man fopen() und tcsetattr() zusammen
> bekommt ...

Das sollte über die Funktion fileno() gehen.

Autor: Karl Heinz Buchegger (kbuchegg) (Moderator)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Henrik Wellschmidt schrieb:

> Ich habe 4 C-Bücher :-)
>
> Aber es ist halt zu verlockend sich vor den Rechner zu setzen.

Ich kann das ja verstehen.
Aber es bringt nichts. Dafür, dass du 4 Bücher hast, schwächelst du 
extrem. Um es mal freundlich auszudrücken.

Du musst die Dinger auch durcharbeiten! In einem guten Buch sind am Ende 
eines jeden Kapitels Übungen drinnen mit denen man kontrollieren kann, 
ob man alles verstanden hat.

> Ich verstehe ja ganz gut was hier geschrieben wird und lerne dabei.

Das was hier geschrieben wird, ist noch nicht mal ein matter Abklatsch 
dessen, was es zu den Themenkreisen Files, Strings, deren Zusammenspiel, 
Textparsing, Konvertierungen, Pointer, Arrays und der Zusammenhang 
Pointer zu Arrays, ... zu sagen gibt. Und das sind in deinem Code gerade 
mal 8 Zeilen, die in den Büchern aber 3 bis 5 komplette Kapitel 
(teilweise auch kapitelübergreifend) in Anspruch nehmen, mit allem drum 
und drann. In Programmiersprachen ist es oft so, dass die Dinge 
zusammenhängen, wie Zahnräder in einem Getriebe. Man kann ein Getriebe 
nicht dadurch verstehen, indem man sich jedes Zahnrad einzeln ansieht. 
Es ist die Gesamtheit aller Räder, die ein Getriebe ausmachen.

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




Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder GIF-Format hochladen.
Siehe Bildformate

Mit dem Abschicken erkennst du die Nutzungsbedingungen an.

webmaster@mikrocontroller.netImpressumNutzungsbedingungenWerbung auf Mikrocontroller.net