Forum: Mikrocontroller und Digitale Elektronik sscanf und Leerzeichen AVR Atmega


von Anton G. (antong)


Lesenswert?

Hallo,
zuerst einmal, ich habe das Internet und auch dieses Forum schon mehrere 
Tage nach sscanf und dem Leerzeichenproblem durchsucht. Entweder bin ich 
zu schusselig oder ich kann die Lösungen (meistens mit scanf und fgets) 
für mein Problem irgendwie nicht anwenden.

Hintergrund: Ich habe eine Textzeile in der Zahlen und Text steht. Ich 
möchte diese Zahlen und den Text mittles sscanf in Variablen ablegen .
So lange ich in dem Text kein Leerzeichen habe funktioniert alles (siehe 
"Vierter Versuch mit Unterstrich statt Leerzeichen" in meinem Code).
Das Leerzeichenproblem ist ja "normal", da sscanf dort abbricht.

Nun habe ich mehrere Varianten ausprobiert (siehe Code). Ich schaffe das 
auch, dass sscanf nicht mehr bei dem Leerzeichen abbricht. Dann aber ist 
meine Variable "ZweiteZahl",die nach dem Text kommt, leer.

Geht das wirklich nicht, oder fehlt mir da noch der letzte feinschliff?
1
#include <avr/io.h>
2
#include <string.h>
3
#include <stdio.h>
4
#include "uart1.h"
5
6
7
int main(void)
8
{
9
  char Ursprung[26];  //Ursprungsstring
10
  char Gesamtausgabe[200];  //Für alle Ausgaben über UART 
11
  unsigned int ErsteZahl;  //für die 120
12
  unsigned int ZweiteZahl;  //für die 121
13
  char MittlererText[18]; //Ein Byte mehr Platz als der Text wegen \0 "Dies ist ein Text"=17 Zeichen
14
  
15
  USART1_initialisieren(MYUBRR);
16
  
17
  strcpy(Ursprung,"120  Dies ist ein Text  121"); //Die Zahlen und der Text sind jeweils durch Tabulator getrennt
18
  
19
  USART1_String_senden("--------------------------Normaler Versuch-----------------------------------------------\n\r");  
20
  sprintf(Gesamtausgabe,"Gesamter Text:%s\n\r",Ursprung);
21
  USART1_String_senden(Gesamtausgabe);
22
  sscanf(Ursprung,"%u\t%s\t%u",&ErsteZahl,MittlererText,&ZweiteZahl);
23
  sprintf(Gesamtausgabe,"Erste Zahl:%u\n\r",ErsteZahl);
24
  USART1_String_senden(Gesamtausgabe);  
25
  sprintf(Gesamtausgabe,"Mittlerer Text:%s\n\r",MittlererText);
26
  USART1_String_senden(Gesamtausgabe);  
27
  sprintf(Gesamtausgabe,"Zweite Zahl:%u\n\r",ZweiteZahl);
28
  USART1_String_senden(Gesamtausgabe);    
29
  
30
  
31
  
32
  USART1_String_senden("--------------------------Erster Versuch-----------------------------------------------\n\r");  
33
  sprintf(Gesamtausgabe,"Gesamter Text:%s\n\r",Ursprung);
34
  USART1_String_senden(Gesamtausgabe);
35
  sscanf(Ursprung,"%u\t%[^\n]s\t%u",&ErsteZahl,MittlererText,&ZweiteZahl);
36
  sprintf(Gesamtausgabe,"Erste Zahl:%u\n\r",ErsteZahl);
37
  USART1_String_senden(Gesamtausgabe);  
38
  sprintf(Gesamtausgabe,"Mittlerer Text:%s\n\r",MittlererText);
39
  USART1_String_senden(Gesamtausgabe);  
40
  sprintf(Gesamtausgabe,"Zweite Zahl:%u\n\r",ZweiteZahl);
41
  USART1_String_senden(Gesamtausgabe);  
42
  
43
  USART1_String_senden("--------------------------Zweiter Versuch-----------------------------------------------\n\r");  
44
  sscanf(Ursprung,"%u\t%[ a-zA-Z0-9]s\t%u",&ErsteZahl,MittlererText,&ZweiteZahl);
45
  sprintf(Gesamtausgabe,"Erste Zahl:%u\n\r",ErsteZahl);
46
  USART1_String_senden(Gesamtausgabe);  
47
  sprintf(Gesamtausgabe,"Mittlerer Text:%s\n\r",MittlererText);
48
  USART1_String_senden(Gesamtausgabe);  
49
  sprintf(Gesamtausgabe,"Zweite Zahl:%u\n\r",ZweiteZahl);
50
  USART1_String_senden(Gesamtausgabe);
51
  
52
  USART1_String_senden("--------------------------Dritter Versuch-----------------------------------------------\n\r");  
53
  sscanf(Ursprung,"%u\t%[^\t]s\t%u",&ErsteZahl,MittlererText,&ZweiteZahl);
54
  sprintf(Gesamtausgabe,"Erste Zahl:%u\n\r",ErsteZahl);
55
  USART1_String_senden(Gesamtausgabe);  
56
  sprintf(Gesamtausgabe,"Mittlerer Text:%s\n\r",MittlererText);
57
  USART1_String_senden(Gesamtausgabe);  
58
  sprintf(Gesamtausgabe,"Zweite Zahl:%u\n\r",ZweiteZahl);
59
  USART1_String_senden(Gesamtausgabe);
60
  
61
  USART1_String_senden("--------------------------Vierter Versuch mit Unterstrich statt Leerzeichen------------\n\r");  
62
  strcpy(Ursprung,"120  Dies_ist_ein_Text  121"); //Die Zahlen und der Text sind jeweils durch Tabulator getrennt
63
  sscanf(Ursprung,"%u\t%s\t%u",&ErsteZahl,MittlererText,&ZweiteZahl);
64
  sprintf(Gesamtausgabe,"Erste Zahl:%u\n\r",ErsteZahl);
65
  USART1_String_senden(Gesamtausgabe);  
66
  sprintf(Gesamtausgabe,"Mittlerer Text:%s\n\r",MittlererText);
67
  USART1_String_senden(Gesamtausgabe);  
68
  sprintf(Gesamtausgabe,"Zweite Zahl:%u\n\r",ZweiteZahl);
69
  USART1_String_senden(Gesamtausgabe);
70
  while(1)
71
    {    
72
        //TODO:: Please write your application code 
73
    }
74
}
Folgende Ausgaben über UART hat das zur Folge:
1
--------------------------Normaler Versuch-----------------------------------------------
2
Gesamter Text:120       Dies ist ein Text       121
3
Erste Zahl:120
4
Mittlerer Text:Dies
5
Zweite Zahl:0
6
--------------------------Erster Versuch-----------------------------------------------
7
Gesamter Text:120       Dies ist ein Text       121
8
Erste Zahl:120
9
Mittlerer Text:Dies ist ein Text        121
10
Zweite Zahl:0
11
--------------------------Zweiter Versuch-----------------------------------------------
12
Erste Zahl:120
13
Mittlerer Text:Dies ist ein Text
14
Zweite Zahl:0
15
--------------------------Dritter Versuch-----------------------------------------------
16
Erste Zahl:120
17
Mittlerer Text:Dies ist ein Text
18
Zweite Zahl:0
19
--------------------------Vierter Versuch mit Unterstrich statt Leerzeichen------------
20
Erste Zahl:120
21
Mittlerer Text:Dies_ist_ein_Text
22
Zweite Zahl:121
Wäre schön, wenn ihr mir da helfen könntet.

PS.: Sorry für den vielen geposteten Code, aber ich wollte die Varianten 
die ich schon versucht habe, auch alle posten.
Gruß Antong

von Peter II (Gast)


Lesenswert?

für soetwas ist sscanf sehr ungeeignet.

gehen doch einfach den String zeichenweise durch.

solange wie ziffer kommen, bist du noch in der 1.Zahl
solange wie keine ziffer kommt, ist Text
solange wie eine ziffer kommt, ist die 2.Zahl

von Timmo H. (masterfx)


Lesenswert?

Bist du sicher, dass du so viele Strings im popeligen RAM des ATmegas 
ablegen willst? Dazu dann noch so eine "große" lib wie scanf, printf 
etc?
Ich glaube dass dein RAM schon recht voll sein dürfte.
Schau dir mal PGMSPACE an 
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Programmspeicher_.28Flash.29

Zu deinem Problem, evtl liegt es daran, das "\t" ein Tab erwartet und 
kein Leerzeichen. Ich würde aber eher jede Zahl einzeln abfragen, das 
ist sicherer, auch gegen Eingabefehler.

von Anton G. (antong)


Lesenswert?

@Peter II
Danke.Zeichenweise habe ich mir auch schon überlegt. Ich wollte den Code 
aber eigentlich "einfach" halten und sscanf nutzen.

@Timmo H.
Ja, mir ist bewusst, dass diese beiden Funktionen sscanf und printf sehr 
speicherhungrig sind. Ich habe ein ATmega2561, da habe ich noch 
reichlich Platz. Auch der String ist nur kurz im RAM. Mein Code ist ja 
auch nur ein Beispiel. Trotzdem Danke für den Hinweis.

Aber irgendwie muß das doch mit sscanf funktionieren, oder?

Gruß Antong

von Peter II (Gast)


Lesenswert?

Anton G. schrieb:
> Aber irgendwie muß das doch mit sscanf funktionieren, oder?

ich denke nicht, sscanf ist viel zu unflexiebel.

von ./. (Gast)


Lesenswert?

Der korrekte Formatstring lautet
1
%u%[ a-zA-Z]%u

von Anton G. (antong)


Lesenswert?

./. schrieb:
> Der korrekte Formatstring lautet
1
%u%[ a-zA-Z]%u

Ja super. Das funktioniert.

Da lag ich mit meiner zweiten Variante ja gar nicht so ganz verkehrt.
1
sscanf(Ursprung,"%u\t%[ a-zA-Z0-9]s\t%u",&ErsteZahl,MittlererText,&ZweiteZahl);
Ich hatte lediglich das "s" noch hinter der Klammer. Da wäre ich nicht 
drauf gekommen. Vielen Dank, der Sonntag ist gerettet.
Schönen Sonntag euch allen.
Gruß Antong

von Georg G. (df2au)


Lesenswert?

Falls deutscher Text mit Umlauten möglich ist:

%u%[ a-zA-ZäöüßÄÖÜ]%u

von Georg G. (df2au)


Lesenswert?

Nachtrag: die "\t" sind unnötig und können zu Problemen führen. Jeder 
Whitespace (egal ob TAB oder SPACE) wird automatisch als Trennzeichen 
genommen.

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.