Hallo, ich würde gerne aus einer Textzeile argc (Argumenten Zähler) und **argv (Argumenten Vektor) ermitteln. Damit ich das ganze an eine andere Funktion übergeben kann. Das ganze soll darauf hinauslaufen das ich eine Textzeile (Kommandozeile) via UART rein bekomme und dann in ein Zweidimensionales Char Array (quasi ein String Array) wandle. Damit ich die Argumente wie vom PC gewöhnt in meiner Funktion verwenden kann. Ich habe das auch schon von Hand zu Fuß am laufen. Würde aber gerne mit strtok_r arbeiten und bekommen das nicht gebacken. Gruß vom Fönig
Der Fönig wrote: > Das ganze soll darauf hinauslaufen das ich eine Textzeile > (Kommandozeile) via UART rein bekomme und dann in ein Zweidimensionales > Char Array (quasi ein String Array) wandle. Achtung: Das original an main() übergebene argv ist kein 2D Array, sondern ein Array aus Pointern auf char-Arrays. > Ich habe das auch schon von Hand zu Fuß am laufen. > Würde aber gerne mit strtok_r arbeiten und bekommen das nicht gebacken. Zeig doch mal was du hast dann kann man auch mal analysieren wo denn die Probleme konkret liegen.
Karl heinz Buchegger wrote: > Zeig doch mal was du hast dann kann man auch mal analysieren > wo denn die Probleme konkret liegen. Schn der Ansatz gefällt mir aber nicht.
1 | enum { max_zeile=40, max_command=10, max_command_len=20 }; |
2 | |
3 | struct struct_command |
4 | {
|
5 | char command_cut[max_command_len]; |
6 | };
|
7 | |
8 | static unsigned char zeile[max_zeile+1]; |
9 | |
10 | struct struct_command command[max_command]; |
11 | unsigned char command_count; |
12 | unsigned char command_offset; |
13 | |
14 | unsigned char for_count; |
15 | |
16 | //------------------------------------------------------------------
|
17 | // Ausschnitt
|
18 | //------------------------------------------------------------------
|
19 | |
20 | for (for_count = 0;for_count < max_command ;for_count++) |
21 | {
|
22 | command[for_count].command_cut[0] = 0; |
23 | }
|
24 | command_count = 0; |
25 | command_offset = 0; |
26 | sprintf (zeile,"%s ", zeile); /* quick and dirty */ |
27 | /* TODO (#1#): Leerzeichen (Token) Handling verbessern:
|
28 | führende und doppelte leerzeichen ignorieren. */
|
29 | |
30 | for(for_count=0;(zeile[for_count] != 0);for_count++) |
31 | {
|
32 | if (command_count < max_command) |
33 | {
|
34 | if (zeile[for_count] != 32) |
35 | {
|
36 | command[command_count].command_cut[command_offset] = zeile[for_count]; |
37 | command_offset++; |
38 | } else { |
39 | command[command_count].command_cut[command_offset] = 0; |
40 | command_offset = 0; |
41 | command_count++; |
42 | }
|
43 | }
|
44 | }
|
Das ist ne ganz schöne Umkopiererer. Du sagtest, dass deine Routinen ein argc/argv Handling haben, woraufhin ich darauf hingewiesen habe, dass argv kein 2D Array sondern ein Array von Pointern darstellt. Der Unterschied ist: Deine Lösung sieht im Speicher so aus: command +---+---+---+---+---+---+---+ | | | | | | | | +---+---+---+---+---+---+---+ | | | | | | | | +---+---+---+---+---+---+---+ | | | | | | | | +---+---+---+---+---+---+---+ | | | | | | | | +---+---+---+---+---+---+---+ | | | | | | | | +---+---+---+---+---+---+---+ | | | | | | | | +---+---+---+---+---+---+---+ während die argv Lösung so aussieht: argv +-----+ +---+---+---+ | o--------->| | |\0 | +-----+ +---+---+---+ +---+---+---+---+ | o------------------------------->| | | |\0 | +-----+ +---+---+---+---+ +---+---+---+---+ | o--------->| | | |\0 | +-----+ +---+---+---+---+ +---+---+ | o------------------------------->| |\0 | +-----+ +---+---+---+ +---+---+ | o--------->| | |\0 | +-----+ +---+---+---+ +---+---+---+ | o------------------------------->| | |\0 | +-----+ +---+---+---+---+ +---+---+---+ | o--------->| | | |\0 | +-----+ +---+---+---+---+ |NULL | +-----+ Nun sagt aber niemand, dass die Arrayfetzelchen rechts alle unterschiedliche Arrays sein müssen. Die Pointer können durchaus alle in dasselbe Array zeigen (die aufgerufene Funktion, main(), hat sowieso kein Recht im argv irgendwelche Manipulationen durchzuführen): +---+---+---+---+---+---+---+---+---+---+---+---+ | | |\0 | |\0 | | | \0| | |\0 | | +---+---+---+---+---+---+---+---+---+---+---+---+ ^ ^ ^ ^ +-----+ | | | | | o--------+ | | | +-----+ | | | | o--------------------+ | | +-----+ | | | o----------------------------+ | +-----+ | | o----------------------------------------+ +-----+ |NULL | +-----+ Hintergrund der ganzen Storry: Dieses grosse Array hast du ja bereits. Es ist dein 'Zeile' Array. Alles was du noch tun musst um ein argv zu implementieren ist ein Array von Pointern aufzusetzen, welche in dieses Array hineinzeigen. Und natürlich müssen im 'Zeile' Array noch die \0 eingefügt werden um die jeweiligen String Enden zu markieren. Zum Aufsetzen des Arrays kommt jetzt strtok() ins Spiel. Es zeigt sich, dass strtok() eine dafür perfekt passende Aktion macht: * strtok() sucht nach dem ersten Zeichen, welches nicht als Trenn- zeichen angegeben wurde. Diese Position wird als Pointer retourniert und markiert den Beginn des Tokens * strtok() sucht nach dem Ende des Tokens, indem es solange den String weiterliest, bis eines der Trennzeichen auftaucht. Dieses Zeichen wird durch ein '\0' Zeichen ersetzt. * strtok() liefert NULL wenn es keinen Token mehr identifizieren konnte. (ungetesteter Code)
1 | const char* argv[max_command]; |
2 | int argc; |
3 | |
4 | ...
|
5 | |
6 | argc = 0; |
7 | char* Token = strtok( zeile, " \t" ); |
8 | |
9 | while( Token != NULL && argc < max_command - 1) { |
10 | argv[argc++] = Token; |
11 | Token = strtok( NULL, " \t" ); |
12 | }
|
13 | argv[argc] = NULL; |
14 | |
15 | ...
|
16 | //
|
17 | // und damit kann dann eine Funktion aufgerufen werden
|
18 | //
|
19 | foo( argc, argv ); |
Karl heinz Buchegger wrote: > Das ist ne ganz schöne Umkopiererer. > Du sagtest, dass deine Routinen ein argc/argv Handling > haben, woraufhin ich darauf hingewiesen habe, dass argv > kein 2D Array sondern ein Array von Pointern darstellt. Ich bin platt. Super Erklärung! Vielen viel Dank. Ich mach mich gleich dran das zu testen.
Hier ein mitlerweile getestetes Program
1 | #include "stdafx.h" |
2 | #include "string.h" |
3 | |
4 | #define max_command 40
|
5 | |
6 | const char* argv[max_command]; |
7 | int argc; |
8 | |
9 | void foo1( int argc, const char* argv[] ) |
10 | {
|
11 | while( *argv != NULL ) { |
12 | printf( "*%s*\n", *argv ); |
13 | argv++; |
14 | }
|
15 | printf( "\n" ); |
16 | }
|
17 | |
18 | void foo2( int argc, const char* argv[] ) |
19 | {
|
20 | for( int i = 0; i < argc; ++i ) |
21 | printf( "*%s*\n", argv[i] ); |
22 | printf( "\n" ); |
23 | }
|
24 | |
25 | int main() |
26 | {
|
27 | char zeile[] = "Dies ist ein Test"; |
28 | |
29 | argc = 0; |
30 | char* Token = strtok( zeile, " \t" ); |
31 | |
32 | while( Token != NULL && argc < max_command - 1) { |
33 | argv[argc++] = Token; |
34 | Token = strtok( NULL, " \t" ); |
35 | }
|
36 | argv[argc] = NULL; |
37 | |
38 | foo1( argc, argv ); |
39 | foo2( argc, argv ); |
40 | |
41 | return 0; |
42 | }
|
Es läuft und das genau so wie ich mir das Vorgestellt habe ;o) Nochmal vielen Dank nicht nur für die Lösung sondern auch für die Erklärungen dazu.
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.