Forum: Mikrocontroller und Digitale Elektronik scanf ("%s",.


von H.Joachim S. (crazyhorse)


Lesenswert?

Habs bisher noch nie für Zeichenketten verwendet und wollte das gestern 
benutzen...
Gibts ne Möglichkeit, dass Leerzeichen nicht als Ende-Zeichen erkannt 
werden?
Irgendwie blöd.
Konkret: Modem, Namen auslesen:
ATN?

Modemantwort:
ATN?

Test 45 84 89 00 00 00
Liefert 8 Ergebnisse statt wie erhofft 2 ("ATN?" und "Test 45 84 89 00 
00 00")

von Steel (Gast)


Lesenswert?

Setzt dich hin und formuliere die Frage nochmals so, dass sie auch 
jemand verstehen kann!

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Aus Deinem Kauderwelsch kann man zwar nicht so viel entnehmen, aber es 
ist wohl besser, wenn Du die Modemantwort zeilenweise mit fgets() 
einliest und dann Zeile für Zeile selbst analysierst, indem Du mit einem 
Pointer über den String "wanderst". scanf ist dafür absolut ungeeignet, 
denn es rastet nicht auf Zeilenenden ein.

EDIT: Die "Antwort"

      ATN?<CR><LF>

ist lediglich das (beim Modem) eingeschaltete Echo. Schalte es entweder 
aus (meist mit ATE0) oder sorge dafür, dass Du Echos wegfrisst, damit 
dann nur noch die Antwort selbst, also

      Test 45 84 89 00 00 00

übrigbleibt. Dann ist es ganz einfach.

: Bearbeitet durch Moderator
von Kaj (Gast)


Lesenswert?

Schau dir mal die Funktionen scanf, gets und fgets an, dann findest du 
auch die unterschiede.
Aber um es dir zu erleichtern:
NEIN, man scanf nicht beibringen white-spaces als ende zeichen zu 
ignorieren.
Deine lösungen heißen entweder selber schreiben oder fgets() benutzen.

Grüße

von H.Joachim S. (crazyhorse)


Lesenswert?

Ich fand die Frage eigentlich nicht so unverständlich :-)
Also scanf() kann es nicht und gets() funktioniert so wie gewünscht.

Das "ATN?" das Echo ist, ist mir klar und auch kein Problem. Es ging nur 
um evtl. Leerzeichen im Namen.

Vielen Dank, funktioniert.

von Karl H. (kbuchegg)


Lesenswert?

H.Joachim Seifert schrieb:
> Ich fand die Frage eigentlich nicht so unverständlich :-)
> Also scanf() kann es nicht und gets() funktioniert so wie gewünscht.

Nein!
Vergiss, dass es eine Funktion gets() gibt.
gets() ist pfui, bäh, schmutzig! Aus, legst du das zurück, das geht dich 
nix an!

fgets() ist die Funktion, die du willst.

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Karl Heinz Buchegger schrieb:
> Vergiss, dass es eine Funktion gets() gibt.

Genau, das Modem könnte Joachims PC per Buffer-Overflow hacken! :-)))

von H.Joachim S. (crazyhorse)


Lesenswert?

Ne, keine Sorge :-), hängt an nem Mega168.

von Karl H. (kbuchegg)


Lesenswert?

Frank M. schrieb:
> Karl Heinz Buchegger schrieb:
>> Vergiss, dass es eine Funktion gets() gibt.
>
> Genau, das Modem könnte Joachims PC per Buffer-Overflow hacken! :-)))

Solange immer alles gut geht, besteht die Gefahr nicht.
Spannend ist immer die Frage: was passiert im Fehlerfall?
Zb schadhaftes Kabel, zb Stecker abgefallen und wieder eingesteckt. Zb 
jemand spielt an den Baudratenschaltern vom Modem. etc., etc.

Da wirds dann interessant.
gets() kann dir in solchen Fällen nicht unter die Arme greifen und 
ballert den Speicher gnadenlos mit Bytes zu. fgets aber nicht :-)

: Bearbeitet durch User
von H.Joachim S. (crazyhorse)


Lesenswert?

Ich verstehe das Problem mit gets() nicht so ganz:

char *gets(char *str, unsigned char len)

inputs, using getchar, the character string str terminated by the new 
line character.
The new line character will be replaced with 0.
The maximum length of the string is len. If len characters were read 
without encountering the new line character, then the string is 
terminated with 0 and the function ends.
The function returns a pointer to str.


Ah, gerade nachgeschaut, die max. Länge ist wohl eine 
compilerspezifische Erweiterung, die es sonst nicht gibt?

von Karl H. (kbuchegg)


Lesenswert?

H.Joachim Seifert schrieb:
> Ich verstehe das Problem mit gets() nicht so ganz:
>
> char *gets(char *str, unsigned char len)

Dann hast du ein eigenes gets()

Die Definition von gets im C Standard sieht so aus
1
char * gets( char * str );

von Karl H. (kbuchegg)


Lesenswert?

Gerade gelernt
1
Entfernung aus dem Standard (C11)
2
3
In der Version C11 wurde gets() schließlich aufgrund der oben
4
genannten Probleme komplett aus C entfernt. Stattdessen wurde
5
eine sicherere Variante mit dem Namen gets_s() eingeführt, die
6
als zusätzlichen Parameter noch die maximale Anzahl an zu lesenden
7
Zeichen (inklusive '\0') übergeben bekommt:
8
9
char *gets_s( char *str, rsize_t n );
10
11
gets_s() entspricht somit der Anwendung von fgets() auf stdin:
12
fgets( str, n, stdin );

Na endlich!
Wer sagts denn? Das C-Komitee hatte nach 20 Jahren doch noch ein 
einsehen und dieses leidige Überbleibsel aus dem Ur-K&R C entfernt. Auf 
das Konto dieser Funktion gehen wahrscheinlich mehr Abstürze und 
Angriffe, als auf alle anderen schlechten Designs zusammen.

: Bearbeitet durch User
von H.Joachim S. (crazyhorse)


Lesenswert?

Ja, so ist es wohl.
Immer die Sachen, die man so selten braucht...
In der obigen Form mit max-Länge genehmigungsfähig? Ja, ich weiss, nicht 
portabel :-)

von H.Joachim S. (crazyhorse)


Lesenswert?

ups.
Na, dann werde den Herren Compilerbauern mal ne mail schicken, dass sie 
die Funktion umbenennen sollten.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Karl Heinz Buchegger schrieb:
> Solange immer alles gut geht, besteht die Gefahr nicht.
> Spannend ist immer die Frage: was passiert im Fehlerfall?

Jepp, ich weiß dass, schließlich bin ich auch schon seit knapp 30 Jahren 
C-Programmiererei dabei.

Karl Heinz Buchegger schrieb:
> Gerade gelernt
> Entfernung aus dem Standard (C11)
1
$ cat a.c
2
#include <stdio.h>
3
4
int
5
main ()
6
{
7
  char s[80];
8
9
  gets (s);
10
  return 0;
11
}
1
$ cc -Wall a.c
2
/tmp/cc9YmzN6.o: In function `main':
3
a.c:(.text+0x10): warning: the `gets' function is dangerous and should not be used.

Sagt doch alles, oder? ;-)

: Bearbeitet durch Moderator
von H.Joachim S. (crazyhorse)


Lesenswert?

Na, geht doch :-)

Thank you for your suggestion.
We will add a macro

#define get_s(str,len) get(str,len)

so that the name change will no create problems with old code

von DirkB (Gast)


Lesenswert?

Kaj schrieb:
> NEIN, man scanf nicht beibringen white-spaces als ende zeichen zu
> ignorieren.

Das ist falsch.
scanf kennt den %[ Specifier (auch schon seit C89).
1
scanf("%[^\n]", Arrayname);
 liest alle Zeichen bis auf das \n ein.

von Sven P. (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Na endlich!
> Wer sagts denn? Das C-Komitee hatte nach 20 Jahren doch noch ein
> einsehen und dieses leidige Überbleibsel aus dem Ur-K&R C entfernt.

Dafür schleppen sie nun den leidigen Unfug vom windows-CRT an. gets_s() 
ist heute doch mindestens genauso überflüssig wie getc() und strncopy_s.

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.