Forum: Compiler & IDEs Stringauswertung


von S. Q. (frido2001)


Lesenswert?

Hallo,

ich versuche einen String auszuwerten, welchen ich über den UART 
empfange.
Der String hat das Format x;xxxx
1
unsigned int c, c_temp, num_temp;
2
char *abschnitt;
3
char delimiter[]=";";
4
5
uart_gets(Line,sizeof Line);
6
abschnitt=strtok(Line,delimiter);
7
c_temp=abschnitt;
8
while (abschnitt!=NULL)
9
{
10
abschnitt=strtok(NULL,delimiter);
11
num_temp=abschnitt;
12
}
13
if ( c_temp & UART_NO_DATA )
14
{
15
  /* no data available from UART  */
16
}
17
else
18
{
19
c=c_temp;
20
}        
21
switch (c)
22
{
23
case 'a':
24
// mache etwas
25
break;
26
27
case 'b':          
28
  ...
29
}

Der String wird korrekt empfangen, der erste Teil vorm Trennzeichen auch 
korrekt in c_temp geschrieben.
Der zweite Teil des Strings landet schonmal nicht da wo er hin soll, 
d.h. num_temp ist leer.

Die switch-case Anweisung wird allerdings auch ignoriert, und es wird in 
den default-Zweig gesprungen (selbst wenn in c ein a steht).

Vielleicht sieht ja jemand gleich den Fehler.

von Rolf M. (rmagnus)


Lesenswert?

S. Q. schrieb:
> Die switch-case Anweisung wird allerdings auch ignoriert, und es wird in
> den default-Zweig gesprungen (selbst wenn in c ein a steht).

In c wird nie ein a stehen, da du die Adresse, die von strtok 
zurückgegeben wird, dort speicherst. Die Warnungen sollten dir auch 
mitgeteilt haben, daß du da Zeiger und nicht-Zeiger munter mischst.

von S. Q. (frido2001)


Lesenswert?

Ok, klingt einleuchtend. Wie behebe ich das Problem nun? Zeiger sind 
nicht so meine Welt, ich tippe mal auf dereferenzieren (wie?)?!

von Karl H. (kbuchegg)


Lesenswert?


von Udo S. (urschmitt)


Lesenswert?

S. Q. schrieb:
> Zeiger sind nicht so meine Welt,
Im Ernst, dann solltest du das zu allererst ändern oder auf Basic 
umschwenken. C ohne Zeiger ist wie Auto fahren nur im ersten Gang mit 
Standgas.

von Karl H. (kbuchegg)


Lesenswert?

> der erste Teil vorm Trennzeichen auch
> korrekt in c_temp geschrieben.

in c-temp wird überhaupt kein String geschrieben.
c_temp ist ein Zeiger auf den Anfang des ersten Teilstrings. Der String 
selbst existiert nach wie vor nur in 'Line' (welches du hoffentlich 
korrekt als Array definiert hast.

Du hast also von gets einen String gekriegt

   Line
   +---+---+---+---+---+---+---+---+---+---+
   | a | ; | x | y | z | \0|   |   |   |   |
   +---+---+---+---+---+---+---+---+---+---+


strtok liefert dir einen Pointer auf den Anfang des Teilstrings, der mit 
dem gesuchten Delimiter beendet ist.

   abschnitt=strtok(Line,delimiter);

   Line
   +---+---+---+---+---+---+---+---+---+---+
   | a | ; | x | y | z | \0|   |   |   |   |
   +---+---+---+---+---+---+---+---+---+---+
     ^
     |
     |
  +-----+
  |  o  |
  +-----+
  abschnitt

machst du jetzt einen

  c_temp=abschnitt;

dann kopierst du den Pointer in abschnitt. D.h. du erzeugst

   Line
   +---+---+---+---+---+---+---+---+---+---+
   | a | ; | x | y | z | \0|   |   |   |   |
   +---+---+---+---+---+---+---+---+---+---+
     ^^
     |+-------------+
     |              |
  +--|--+        +--|--+
  |  o  |        |  o  |
  +-----+        +-----+
  abschnitt       c_temp

(mal abgesehen davon, dass du mit c_temp den falschen Datentyp hast).
Aber kopiert wird der Wert vom Pointer und nicht das worauf er zeigt.


wenn du einen Pointer hast, zum Beispiel 'abschnitt' und du 
interessierst dich für den WErt an der Stelle an der der Pointer 
hinzeigt, dann musst du den Pointer dereferenzieren. In C macht man das, 
in dem man dem Pointer einen * voranstellt.

  c_temp = *abschnitt;


   Line
   +---+---+---+---+---+---+---+---+---+---+
   | a | ; | x | y | z | \0|   |   |   |   |
   +---+---+---+---+---+---+---+---+---+---+
     ^
     |
     |
  +-----+
  |  o  |
  +-----+
  abschnitt

     abschnitt           das ist der Pointer, such ihn in der Zeichnung
    *abschnitt           jetzt verfolgst du den Pfeil, wo der hinführt
                         und holst dir von dort den Wert. In diesem Fall
                         ist das das 'a', weil ja der Pfeil dort hin
                         führt.

 c_temp = *abschnitt;    und dieses 'a' kannst du jetzt in c_temp
                         speichern

   Line
   +---+---+---+---+---+---+---+---+---+---+
   | a | ; | x | y | z | \0|   |   |   |   |
   +---+---+---+---+---+---+---+---+---+---+
     ^
     |
     |
  +-----+     +---+
  |  o  |     | a |
  +-----+     +---+
  abschnitt   c_temp


Kleiner *, große Wirkung.

> Zeiger sind nicht so meine Welt

Dann besorg dir ein C-Buch, arbeite die Kapitel über Arrays und Pointer 
durch und mach die Übungen im Buch. Aber "Zeiger sind nicht so meine 
Welt" ist keine akzeptable Aussage. 60% der C-Programmierung dreht sich 
um Pointer und Arrays und wie das alles zusammenhängt. Und von den 
restlichen 40% sind 95% Strukturen, Files und dynamischen 
Datenstrukturen gewidment. Der noch fehlende Rest ist Pipifax. Und so 
wie es aussieht, ist gerade mal dieser Pipifax "deine Welt". Und das ist 
für einen C-Programmierer nicht akzeptabel.

von S. Q. (frido2001)


Lesenswert?

Das nenn ich mal eine Erklärung. Danke schön. Auch für die Ohrfeigen...
Da ich damit mein Geld nicht verdiene, kann ich mir das ganz gut 
verzeihen. Natürlich ist es nützlich es zu können, aber ich denke die 
wenigsten sind damit zur Welt gekommen.
Es heißt ja auch immer "Wer nicht fragt bleibt dumm."
Den Gedanken das C-Buch mal zu suchen werden ich mal genauer in Betracht 
ziehen und die Beispiele mal durch nehmen.
Danke nochmals.

von S. Q. (frido2001)


Lesenswert?

So weit, so schlecht. Ich habe jetzt die Variablendeklaration geändert. 
c_temp erhält jetzt den Inhalt von *abschnitt. Der zweite Aufruf von 
strtok schreibt mir allerdings nichts in num_temp.
Der zweite Aufruf müsste doch nun auf die Adresse des 'x' (lt. Bsp. 
K.-H. B.) zeigen und mir die Dereferenzierung den Inhalt in num_temp 
schreiben.

Mein eigentlicher Plan war es über uart_getc ein Zeichen zu Empfangen 
und damit in den jeweiligen Zweig der Switch-Case zu springen. Nun 
benötige ich aber nur zusätzlich einen Zahlenwert. Den wollte ich 
zugleich mit dem Zeichen senden --> String. Daher das Format c;01234
Wenn nun eine neue "Anweisung" empfangen wird sollte deer Zweig der 
Switch-Case geändert werden.
Bei mir funktioniert der Vergleich nun natürlich nicht mehr, da ich 
c_temp (char) mit UART_NO_DATA (int) vergleiche.
Mir fehlt die Idee das jetzt auszubügeln, oder sollte man das ganz 
anders angehen?
1
char c[0], c_temp[0], num_temp[3];
2
char *abschnitt;
3
char delimiter[]=";";
4
5
uart_gets(Line,sizeof Line);
6
abschnitt=strtok(Line,delimiter);
7
c_temp=*abschnitt;
8
while (abschnitt!=NULL)
9
{
10
abschnitt=strtok(NULL,delimiter);
11
num_temp=*abschnitt;
12
}
13
if ( c_temp & UART_NO_DATA )
14
{
15
  /* no data available from UART  */
16
}
17
else
18
{
19
c=c_temp;
20
}        
21
switch (c)
22
{
23
case 'a':
24
// mache etwas
25
//nutze num_temp
26
break;
27
28
case 'b':          
29
  ...
30
}

von Hmm (Gast)


Lesenswert?

>char c[0], c_temp[0], num_temp[3];

Du hast sicher nicht in 6 Stunden das C-Buch durchgelesen, die Beispiele 
durchgearbeitet und die Aufgaben gelöst.

In den nächsten vier Wochen wollen wir von Dir höchstens Fragen zu einer 
Aussage in einem C-Buch, vorzugsweise mit Referenz lesen.

von Hmm (Gast)


Lesenswert?

>Du hast sicher nicht in 6 Stunden das C-Buch durchgelesen, die Beispiele
>durchgearbeitet und die Aufgaben gelöst.

Falls doch, dann jedenfalls mit dem, angesichts der benötigten Zeit, zu 
erwartenden Nicht-Erfolg.

von S. Q. (frido2001)


Lesenswert?

Hmm schrieb:

> Du hast sicher nicht in 6 Stunden das C-Buch durchgelesen, die Beispiele
> durchgearbeitet und die Aufgaben gelöst.

Das ist wohl wahr.
Aber es steht auch nirgends, dass es verboten ist trotzdem Fragen zu 
stellen oder es einfach parallel zu probieren.

Wie gesagt, ich hatte es erst mit einem einzelnen Zeichen realisiert und 
es funktionierte, nun benötige ich zusätzlich noch den Zahlenwert als 
Parameter für eine weitere Funktion.

von Hmm (Gast)


Lesenswert?

>Aber es steht auch nirgends, dass es verboten ist trotzdem Fragen zu
>stellen oder es einfach parallel zu probieren.

Da muss ich wohl ein wenig deutlicher werden, da Du so hartleibig bist: 
Du wirst gut daran tun, Dir ein gewisses Wohlwollen der Leser hier zu 
erhalten. In dem Du aber darauf bestehst, mit einem gewissen Unterton 
von nicht abzuweisendem Anspruch, darauf bestehst, uns hier als Vorleser 
zu missbrauchen, wirst Du Dir Sympathien verscherzen.

Nun gut. Bei mir hast Du es geschafft. Willkommen in meinem css-File.

Dann noch ein schönes Leben.

von Karl H. (kbuchegg)


Lesenswert?

Lass mal ansehen, wie du Line definiert hast.

Spätestens nach sowas:
char c[0], c_temp[0], num_temp[3];


hab ich jegliches Vertrauen in irgendwelche Basisvertigkeiten komplett 
verloren. Da stimmt hinten und vorne nichts in deinem Code.

von Karl H. (kbuchegg)


Lesenswert?

> Da ich damit mein Geld nicht verdiene, kann ich mir das ganz gut
verzeihen.

Um das zurecht zu rücken.
Das hat nichts mehr mit 'Geld verdienen' zu tun. Das sind grundlegende 
Fertigkeiten, die auch ein Hobby-Programmierer im Schlaf beherrschen 
muss. Von einem Profi, der damit seine Brötchen verdient, bist du noch 
minestens 4 oder 5 JAHRE Lernzeit entfernt.
Und ich weiß wovon ich rede. Denn ich verdiene damit meine Brötchen.

Du kannst nicht eine Sonntag-Nachmittag Radtour machen, wenn es dich 
samt Stützrädern vom Fahrrad schmeißt. Da bist du von Tour de France 
noch weit entfernt.

von S. Q. (frido2001)


Lesenswert?

char c[0], c_temp[0], num_temp[3];


war in der Tat etwas vom Sinn befreit. Mittlerweile habe ich es aber zum 
Laufen bekommen, indem ich nur die erste Stelle des Strings in c_temp 
schreibe und ab der 3. Stelle die ASCII in Int wandle.

Um das mal zurecht zu rücken.
Ich habe nie behauptet damit mein Geld verdienen zu wollen, dass kann 
man auch anders ganz gut.
Es ist nur teilweise hier immer wieder das Gleiche, dass eine Frage 
gestellt wird und nachdem es nicht gleich nach dem nächsten Posting 
läuft sofort draufgehauen wird oder sich einfach mal im Ton vergriffen 
wird und man über das Ziel hinaus schießt.
Es hat hier niemand eine fertige Lösung erwartet, mir wurde geholfen, 
dafür habe ich mich bedankt, wenn man einmal mehr, mehr oder weniger 
sinnbehaftet, nachfragt hat dies nichts mit Undank zu tun. Einen 
Unterton hört zudem immer nur der, der ihn hören will, sollte sich aber 
auch nicht gleich auf den Schlips getreten fühlen, wenn er ihn selbst 
einsetzt.
Ab und an sollte man dochmal die Kirche im Dorf lassen.
Ich denke es hat sich hier niemand, auch ich nicht, im Forum das primäre 
Ziel gesetzt das Wohlwollen der Leser zu verscherzen, aber man sollte es 
wohl doch alles mit etwas mehr Abstand an der einen oder anderen Stelle 
betrachten.

von DirkB (Gast)


Lesenswert?

Auf einem PC hätte ich dafür sscanf genommen.

von Karl H. (kbuchegg)


Lesenswert?

S. Q. schrieb:


> Ab und an sollte man dochmal die Kirche im Dorf lassen.

Danke für die Kopfwäsche.

Ich hab daraufhin mal meine Position überdacht und bin zum Schluss 
gekommen, dass ich mich in Zukunft etwas mehr raushalten werde, wenn es 
um Themen geht von denen ich denke, dass die eigentlich jeder Amateur 
können sollte, weil sie in jedem noch so beschissenen C-Buch des langen 
und breiten erklärt werden.
Ich seh nämlich auch schon länger nicht mehr ein, warum ich hier als 
Erkläronkel fungieren soll, nur weil der Fragesteller wieder mal der 
irrigen Meinung ist, er könne C auch einfach so an 2 Nachmittagen lernen 
und alle die, die sich 1 Jahr lang durch die Literatur durchgearbeitet 
haben und die Dinge von der Pieke auf gelernt haben, wären alles 
Weicheier und er brauche das nicht, denn mit den 2 Stück 10-seitigen 
Tutorien, die er gelesen hat (wenn überhaupt), wäre alles geklärt.
Nur um mir dann wieder ein ums andere mal sagen lassen zu müssen: "Ich 
bin kein Profi, ich muss das nicht können." Nun gut, wenn man der 
Ansicht ist, diese Themen wären bereits etwas, was einen Profi von einem 
Amateuer unterscheidet, dann soll das so sein. Ich bin da zwar anderer 
Ansicht, aber ok. Ein Amateuer sollte meiner Meinung nach den Inhalt vom 
K&R beherrschen, zumindest beim Inhalt der ersten Hälfte muss er absolut 
sattelfest sein. Vorher ist das nämlich noch nicht mal Amateuer, sondern 
die Einstiegsstufe in die absolute Beginnerliga und mit diesem Wissen 
anzufangen reale Programme zu schreiben ist viel zu früh. Es ist wie 
einen 5-jährigen nach seinem ersten Judo-Trainingsabend auf ein Turnier 
zu schicken - absolut sinnlos und der Frust ist vorprogrammiert.
Bei dynamischen Datenstrukturen darf er anfangen zu schwächeln und wenn 
es dann um rekursive Algorithmen geht, kann ein Amateur komplett 
aussetzen (nicht jedoch ein Profi, für den dürfen Dinge wie Rekursion, 
Datenstrukturen, Bäume, Listen, viele Algorithmen, die Idee hinter 
Backtracking, eventbasiertes Arbeiten, etc.  keine Fremdwörter sein, 
genausowenig wie er keine Probleme im strukturellen Aufbau eines 
Programms haben darf. Wenn ein Amateuer ein 1000-Zeilen Programm nicht 
mehr überblicken kann, dann ist das ok. Für einen Profi liegt die Latte 
wesentlich höher - 1000 Zeilen sind da eher eine Fingerübung, die er 
problemlos in angemessener Zeit in den Griff kriegen können muss). Für 
einen Profi ist der Inhalt vom K&R bzw. die Beherrschung dieses 
kompletten(!) Stoffes gerade mal ca. 20% dessen, was er können muss um 
als Profi bestehen zu können.

Aber ist ok.

von S. Q. (frido2001)


Lesenswert?

> Danke für die Kopfwäsche.
Sollte keine sein, war auch nicht persönlich gemeint.
> Ich hab daraufhin mal meine Position überdacht und bin zum Schluss
> gekommen, dass ich mich in Zukunft etwas mehr raushalten werde, wenn es
> um Themen geht von denen ich denke, dass die eigentlich jeder Amateur
> können sollte, weil sie in jedem noch so beschissenen C-Buch des langen
> und breiten erklärt werden.
Ok.
> Ich seh nämlich auch schon länger nicht mehr ein, warum ich hier als
> Erkläronkel fungieren soll
Verlangt auch keiner. Aber es rechnet dir hier jeder hoch an, da du 
einer der wenigen bist, die es tun.

> Aber ist ok.
Ist es auch.
Es fühlt sich jeder immer gleich persönlich angegriffen, wenn man mal 
etwas zurück schreibt, selber soll man aber immer alles schön schlucken.

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.