strstr() & strncpy()

#3013056
Lesenswert?

Ich raffs nicht ...

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

1
ptr=strstr(buffer, "1-0:21.7.0*255");
2
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

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

Und egal was ich mache -> Segmentation fault.

:-/
#3013084
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?
#3013105
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 ...

1
        while (1) {
2

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

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

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

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

13
                }
14
        }
#3013186
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.
#3013197
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:

1
double w = atof(value);

ranhängen ?!
#3013423
Lesenswert?

Henrik Wellschmidt schrieb:


> Fehlt also hier                            ^
>
> |0|0|0|2|3|
>
> Ich wollte aber danach eigentlich gleich:
>
>
>
1
> double w = atof(value);
2
>
>
> 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?
#3014607
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 :(


1
        while (1) {
2

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

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

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

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

14

15
                }
16
        }

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.
#3014863
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)'

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

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

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

1
/HAG5eHZ010C_EHZ1WA02
2

3
1-0:0.0.0*255(1095110000152759)
4
1-0:1.8.0*255(000005.2786)
5
1-0:96.5.5*255(82)
6
0-0:96.1.255*255(0000152759)
7
1-0:32.7.0*255(232.15*V)
8
1-0:52.7.0*255(232.16*V)
9
1-0:72.7.0*255(000.00*V)
10
1-0:31.7.0*255(000.10*A)
11
1-0:51.7.0*255(000.21*A)
12
1-0:71.7.0*255(000.00*A)
13
1-0:21.7.0*255(+00023*W)
14
1-0:41.7.0*255(+00042*W)
15
1-0:61.7.0*255(+00000*W)
16
1-0:96.50.0*0(67)
17
1-0:96.50.0*1(07CF)
18
1-0:96.50.0*2(19)
19
1-0:96.50.0*3(09)
20
1-0:96.50.0*4(25)
21
1-0:96.50.0*5(1A)
22
1-0:96.50.0*6(003D381B300AF9003D00490200009F80)
23
1-0:96.50.0*7(00)
24
!

Und

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

sucht mir schoen das was ich brauche ...
1
1-0:21.7.0*255(+00023*W)
2
1-0:21.7.0*255(+00023*W)
3
1-0:21.7.0*255(+00023*W)
4
1-0:21.7.0*255(+00023*W)
5
1-0:21.7.0*255(+00023*W)
6
1-0:21.7.0*255(+00023*W)
7
1-0:21.7.0*255(+00023*W)
8
1-0:21.7.0*255(+00023*W)
9
1-0:21.7.0*255(+00023*W)
10
1-0:21.7.0*255(+00023*W)
11
1-0:21.7.0*255(+00023*W)
12
1-0:21.7.0*255(+00023*W)

Und dann verlässt es mich ...
#3014965
Lesenswert?

Hallo,

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

versuche mal das hier, achte auf das '&' bei value.
1
                 char value[10];
2
                 strncpy(&value, ptr+14,5);
3
                 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
#3014984
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?)

1
   char buffer[100];
2

3
...
4

5
   while (1) {
6

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

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

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

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

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


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.
#3014985
Lesenswert?

Volkmar Dierkes schrieb:
> Hallo,
>
> Henrik Wellschmidt schrieb:
>
1
>                 char value[10];
2
>>                 strncpy(value, ptr+14,5);
3
>>                 value[5] = '\0';
4
>
>
> 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.
#3014994
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.
#3015003
Lesenswert?

Karl Heinz Buchegger schrieb:
>
>
1
> 
2
> ...
3
> 
4
>    while (1) {
5
> 
6
>      res = read(fd, buffer, sizeof(buffer) -1);
7
> 
8
>      if (res > 0) {
9
>        buffer[res] = '\0';
10
> 
11
>        printf( "received >%s<\n", buffer );
12
> 
13
>        ptr = strstr( buffer, "1-0:21.7.0*255" );
14
>        if( ptr != NULL ) {
15
>          char value[6];
16
>          strncpy( value, ptr + 16, 5 );
17
>          value[5] = '\0';
18
> 
19
>          printf( "'%s' -> '%s'\n", buffer, value );
20
>        }
21
>      }
22
>    }
23
>

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

1
00023
2
00023
3
00023
4
00023
5
00023
6
00023
7
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)
#3015009
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.
#3015193
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.
#3015338
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

...
#3015483
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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren