Hallo C-Freunde und Forumsmitglieder, ich möchte eigentlich nur einen String der 40 Integerwerte beeinhaltet, die jeweils mit ";" abgetrennt sind aufteilen in 40 einzelne Integerwerte. Also "A[LEERZEICHEN]wert1;wert2;....;....;" Beispiel: string = "A 1000;2000;3000;4000;5000;6000;7000;8000;5100;5200;5300;5400;5500;5600;57 00;5800;10000;11000;12000;13000;14000;15000;16000;17000;18000;1;2;1;2;1; 2;1;2;" mein code ist bis jetzt soweit, dass er per uart-interrupt alle zeichen in einen string "string" hineinschreibt und erst bei "RETURN" springt er in die Funktion "remote()" zum auswerten. [c] void remote( void ) //RS-232 { // Ein Return ist eingetroffen. Damit ist der String vollständig string[f] = '\0'; // erst mal einen sauberen C-String daraus machen befehl = strtok(string, trennzeichen); // dann zerteilen wert[1] = strtok(NULL, trennzeichen); k=2; for(t=0;t<40;t++) { wert[k] = strtok(NULL, strichpunkt); empfang[k] = atoi(wert[k]); k++; } if (strcmp(befehl, "A") == 0) //Befehl 3 { messbereich[1] = empfang[1]; messbereich[2] = empfang[2]; messbereich[3] = empfang[3]; messbereich[4] = empfang[4]; messbereich[5] = empfang[5]; messbereich[6] = empfang[6]; messbereich[7] = empfang[7]; messbereich[8] = empfang[8]; abgleichwert[1] = empfang[9]; abgleichwert[2] = empfang[10]; abgleichwert[3] = empfang[11]; abgleichwert[4] = empfang[12]; abgleichwert[5] = empfang[13]; abgleichwert[6] = empfang[14]; abgleichwert[7] = empfang[15]; abgleichwert[8] = empfang[16]; test = messbereich[1]; testa = messbereich[2]; testb = messbereich[3]; } } [c/] nun sollte doch zumindest in dem Arrays "messbereich" und "abgleichwert" etwas drinstehen. die variable ändert sich aber nicht. noch ne frage geht es, dass ich einen String-Array mache (siehe wert[..]) danke für eure hilfe!!!!1 martin
>alle zeichen in einen string "string" hineinschreibt
Und warum nicht gleich in die int-Array?
Etwa so:
1 | volatile int16_t values[..]; |
2 | |
3 | ISR (Uart-Empfang) |
4 | {
|
5 | static uint8_t idx = 0; |
6 | uint8_t x = udr; |
7 | |
8 | if ( x >= 16#30 ) || ( x<= 16#30 ) |
9 | {
|
10 | values[idx]:= ( ( 10 * values[idx] ) + ( x - 16#30 ) ); |
11 | }
|
12 | else if ( x == ';' ) |
13 | {
|
14 | idx++; |
15 | }
|
Hi wie sieht denn die initialisierung der Felder/Arrays aus die du verwendest? Zum Thema String-Array: In C gibt es keine richtigen Strings. Ein "String" ist nichts anderes als ein Vektor aus char. Du kannst ein "String-Array" im Prinzip erstellen, indem du ein Array aus Zeigern auf die Strings machst. Über die Zeiger kommst du dann wieder zum String. Thomas
Martin 567 schrieb: > befehl = strtok(string, trennzeichen); // dann zerteilen > wert[1] = strtok(NULL, trennzeichen); ... > wert[k] = strtok(NULL, strichpunkt); Du verwendest den Delimiter nicht konsistent und vertraust blind auf die Rückgabewerte von strtok(). Beides würde ich als erstes mal bereinigen. Weiter würd' ich zeitig nach int konvertieren, die ganze Sache in nen hübschen loop packen und nicht mit defines geizen, statt mehrererere Arrays zu führen. Wieviel RAM haste eigentlich auf deinem MC? > noch ne frage geht es, dass ich einen String-Array mache (siehe > wert[..]) Wiewas?
hallo zusammen Prozessor: at90can128 10Mhz der string wird ja auch noch für andere funktionen benutzt beispielsweise um kurze befehle wie "U IST" oder "I SOLL" einzulesen. würde zwar dann anderst auch gehen aber jetzt hab ichs schon so weit hingebracht, da muss doch dann der rest auch gehn. hier sämtliche variablen: [c] float Strom; int ADCWert; int empfang[50],abgleichwert[9], adckorrektur[9], messbereich[9], eemessbereich[9], eeabgleichwert[9], eeadckorrektur[9], eefaktor[9]; unsigned char f, i, g, t, k, zeichen, merker=1, durchzahler=1, puffer, buffer, einstellen=0, abgleichmerker=0; char kal=0, schutz=0, acdc=0, abgl=0, scan=0, adck=0, zugang=0; int Messwert[9], faktor[9], test, testa, testb; int z,y,x,v,q,r,p,w; //für RS-232 Übertragung---------- unsigned char size; char counter = 1; char zahler = 1; unsigned char indeks = 1; char next[10]; char sendestring[100]; char string[20]; char *wert[40], *befehl; const char strichpunkt[] = ";"; const char trennzeichen[] = " "; //-------------------------------- [c/]
Martin 567 schrieb: > char *wert[40]; [...] > k=2; > for(t=0;t<40;t++) > { > wert[k] = strtok(NULL, strichpunkt); > empfang[k] = atoi(wert[k]); > k++; > } Hier läuft der Index von wert (k) bis 42. Maximal zulässiger Index ist aber 39. Du schreibst also wild in den Speicher. Woanders: > messbereich[1] = empfang[1]; empfang wird erst ab Index 2 beschrieben, in empfang[1] steht also zuverlässig undefiniertes Zeugs. Es fällt auch auf, dass Du Indices immer ab 1 laufen lässt. Ob das System hat, weil Dir nicht klar ist, dass der kleinste Index in C 0 heißt und nicht 1, kann ich nicht beurteilen. Bezüglich mangelnder Fehlererkennung, z.B. bei strtok, wurde schon das Nötige gesagt. Du riskierst, wild in Adresse 0 herumzufuhrwerken, spätestens bei Übertragungsstörungen.
Hast du schon mal gedebugged? Evtl wird nie die IF-Bedingung erfüllt. Bitte versuche den Code hier entsprechend zu formatieren ;) Thomas
>Hast du schon mal gedebugged?
Was ist das denn? Zeitliche Vorsteinzeit?
also ich kann schon debuggen er geht in die if bedingung rein die 3 "test"-variablen bleiben jedoch unverändert egal was ich schicke also ich habe schon ein programm, dass den string per Com schickt, das funktioniert auf jeden fall, weil ich es mit einem nullmodem-kabel einmal im Kreis geschickt hab sieht im Hyperterminal folgendermaßen aus: A 10;100;1000;1;20;200;2000;2;30;300;3000;1;40;400;4000;2;50;500;5000;1;60 ;600;6 000;2;70;700;7000;1;80;800;8000;2; Verteilung des strings im code folgendermaßen: START A [LEERZEICHEN] messbereich[1] abgleichwert[1] adckorrektur[1] faktor[1] messbereich[2] abgleichwert[2] ... .... ..... faktor[8] ENDE
Hallo ich habe den Code mal ausprobiert und bin auf folgendes gekommen: 1. Die Definition der Variable string[20] ist mit einer Länge von 20 um einiges zu kurz. Du solltest dir über die maximale Länge Gedanken machen und diese hier einsetzten. (Ich hab hier mal 255 verwendet, aber ich weiß ja nicht was du alles reinschreiben willst ;)) 2. Ich habe einen Teil deines Codes (insbesondere den Teil mit der for-Schleife) mal durch folgendes ersetzt:
1 | befehl = strtok(string, trennzeichen); // dann zerteilen |
2 | do
|
3 | {
|
4 | wert[t] = strtok(NULL, strichpunkt); |
5 | empfang[t] = atoi(wert[t]); |
6 | t++; |
7 | }while(empfang[t-1] != NULL); |
8 | |
9 | if (strcmp(befehl, "A") == 0) //Befehl 3 |
10 | {
|
11 | // hier kommt der Rest ....
|
12 | }
|
Bei mir funktioniert es so ;) Gruß Thomas
Hallo Thomas habe deinen code eingefügt bekomme aber ein warning bei folgender zeile: while(empfang[t-1] != NULL); ..:250: warning: comparison between pointer and integer geht das trotzdem??
Mh seltsam, diese Warning schmiss er bei mir nicht, obwohl der Compiler natürlich Recht hat. Müsste
1 | }while(wert[t-1] != NULL); |
heißen. Thomas
Hallo Thomas, habs nun ausprobiert, war ja klar dass wert hingehört, bin schon selber so doof, dass ich nix mehr eigenständig weiß!! sorry hier ist nun mal die ganze "remote" funktion, die bei einem "RETURN" aufgerufen wird. der Debugger springt auch die "A" Bedingung an. aber die 4 "test" Variablen bleiben leer.
1 | void remote( void ) //Fernsteuerung über RS-232 |
2 | {
|
3 | |
4 | // Ein Return ist eingetroffen. Damit ist der String vollständig
|
5 | string[f] = '\0'; // erst mal einen sauberen C-String daraus machen |
6 | |
7 | |
8 | |
9 | //---------------------------------------------------------------
|
10 | befehl = strtok(string, trennzeichen); // dann zerteilen |
11 | do
|
12 | {
|
13 | wert[t] = strtok(NULL, strichpunkt); |
14 | empfang[t] = atoi(wert[t]); |
15 | t++; |
16 | }while(wert[t-1] != NULL); |
17 | |
18 | |
19 | |
20 | if (strcmp(befehl, "S") == 0) //Befehl 1 |
21 | {
|
22 | if (strcmp(wert[1], "IST") == 0) |
23 | {send_serial();} |
24 | }
|
25 | |
26 | |
27 | else if (strcmp(befehl, "W") == 0) //Befehl 2 |
28 | {
|
29 | if (strcmp(wert[1], "IST") == 0) |
30 | {
|
31 | |
32 | indeks = 1; |
33 | sendestring[0] = 'W'; |
34 | |
35 | for (i=0;i<8;i++) |
36 | {
|
37 | zahler = 1; |
38 | |
39 | for (t=0;t<4;t++) |
40 | {
|
41 | switch (zahler) |
42 | {
|
43 | case 1: itoa(messbereich[indeks],next,10); |
44 | break; |
45 | |
46 | case 2: itoa(abgleichwert[indeks],next,10); |
47 | break; |
48 | |
49 | case 3: itoa(adckorrektur[indeks],next,10); |
50 | break; |
51 | |
52 | case 4: itoa(faktor[indeks],next,10); |
53 | break; |
54 | }
|
55 | |
56 | zahler = zahler + 1; |
57 | strcat(sendestring, next); |
58 | strcat(sendestring, strichpunkt); |
59 | }
|
60 | |
61 | indeks = indeks +1; |
62 | }
|
63 | |
64 | itoa(Messwert[8],next,10); //letzten Wert hinten (ohne ";") anfügen |
65 | strcat(sendestring, next); |
66 | |
67 | size = strlen(sendestring); |
68 | sendestring[size] = '\0'; |
69 | |
70 | rprintfStr(sendestring); |
71 | rprintfCRLF(); |
72 | |
73 | |
74 | |
75 | |
76 | for(t=0;t<40;t++) //RS232-String wird gelöscht |
77 | sendestring[t] = 0; |
78 | |
79 | |
80 | }
|
81 | }
|
82 | |
83 | |
84 | else if (strcmp(befehl, "A") == 0) //Befehl 3 |
85 | {
|
86 | |
87 | |
88 | messbereich[1] = empfang[1]; |
89 | abgleichwert[1] = empfang[2]; |
90 | adckorrektur[1] = empfang[3]; |
91 | faktor[1] = empfang[4]; |
92 | |
93 | messbereich[2] = empfang[5]; |
94 | abgleichwert[2] = empfang[6]; |
95 | adckorrektur[2] = empfang[7]; |
96 | faktor[2] = empfang[8]; |
97 | |
98 | messbereich[3] = empfang[9]; |
99 | abgleichwert[3] = empfang[10]; |
100 | adckorrektur[3] = empfang[11]; |
101 | faktor[3] = empfang[12]; |
102 | |
103 | messbereich[4] = empfang[13]; |
104 | abgleichwert[4] = empfang[14]; |
105 | adckorrektur[4] = empfang[15]; |
106 | faktor[4] = empfang[16]; |
107 | |
108 | messbereich[5] = empfang[17]; |
109 | abgleichwert[5] = empfang[18]; |
110 | adckorrektur[5] = empfang[19]; |
111 | faktor[5] = empfang[20]; |
112 | |
113 | messbereich[6] = empfang[21]; |
114 | abgleichwert[6] = empfang[22]; |
115 | adckorrektur[6] = empfang[23]; |
116 | faktor[6] = empfang[24]; |
117 | |
118 | messbereich[7] = empfang[25]; |
119 | abgleichwert[7] = empfang[26]; |
120 | adckorrektur[7] = empfang[27]; |
121 | faktor[7] = empfang[28]; |
122 | |
123 | messbereich[8] = empfang[29]; |
124 | abgleichwert[8] = empfang[30]; |
125 | adckorrektur[8] = empfang[31]; |
126 | faktor[8] = empfang[32]; |
127 | |
128 | test = empfang[1]; |
129 | testa = empfang[2]; |
130 | testb = empfang[3]; |
131 | testc = empfang[4]; |
132 | |
133 | |
134 | }
|
135 | |
136 | |
137 | |
138 | |
139 | f=0; |
140 | for(g=0;g<20;g++) //string wird gelöscht |
141 | string[g] = 0; |
142 | }
|
vielleicht kannst du was erkennen übrigens danke für all deine bemühungen und das ausprobieren bist ne ganz große hilfe für mich martin!!!!!
hallo tom kommando zurück es geht doch eine kleine zeile hat noch gefehlt "t=1;" vor deine do-while-schleife danke, danke mit diesen string-operationen hatte ich schon mehrfach probleme aber langsam bekomme ich es in den griff danke nochmal du warst die größte hilfe seit langer zeit in diesem forum martin!!!!
Hallo mein Problem ist zwar schon gelöst, aber ich hab trotzdem mal eine allgemeine Frage. was bedeutet eigentlich das NULL in der Zeile: wert[t] = strtok(NULL, strichpunkt); Und wieso macht der prozessor dann mit dem richtigen String weiter? Er weiß ja gar nicht welchen String er "token" soll oder? nur mal so ne vertständnissfrage (klar gehts, aber ich würde es gern wissen) da ich mich selber eigentllich noch zu den Anfängern zähle, würde mich das schon mal interessieren wieso man da NULL schreiben muss?? danke martin!!!
Hallo Martin laut http://www.cplusplus.com/reference/clibrary/cstring/strtok/ <-- übrigens eine sehr hilfreiche Seite wenns um solche Sachen geht, musst du nur beim ersten mal den String-Pointer angeben. Wenn du dann den Befehl noch öfter benutzt, dann brauchst du ihn nicht mehr anzugeben, dann reicht ein einfaches NULL. Sollte sich der String allerdings zwischenzeitlich ändern, bin ich mir nicht ganz sicher was passiert. Vermutlich "speichert" die funktion einfach einen Zeiger auf den String, dann müssten die Änderungen mit einwirken. Gruß Thomas
Beim ersten Aufruf übergibt man keine NULL, sondern den tatsächlichen String. strtok merkt sich von Aufruf zu Aufruf in einer internen Variable, wie weit es bisher kam, und wenn man es mit NULL aufruft, wird dieser letzte Wert wiederverwendet. Genau das ist der Grund, warum strtok nicht reentrant ist: Wenn mehrere Threads gleichzeitig strtok verwenden, geht es schief. Oder wenn man in einem Interrupt und außerhalb strtok benutzt.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.