Wenn die einfachste Lösung für Ihren Fall zu aufwändig ist, könnten Sie in Betracht ziehen, eine selbst zu programmieren.
Dann können Sie:
- den String scannen und zählen, wie viele Argumente es gibt (und Sie erhalten Ihr argc)
- ein Array von char * (für Ihr argv) zuweisen
- den String erneut durchsuchen, die Zeiger im zugewiesenen Array zuweisen und Leerzeichen durch '\0' ersetzen (wenn Sie den String, der die Argumente enthält, nicht ändern können, sollten Sie ihn duplizieren).
- vergessen Sie nicht, das Allokierte freizugeben!
Das folgende Diagramm sollte es hoffentlich verdeutlichen:
aa bbb ccc "dd d" ee <- Original-String
aa0bbb0ccc00dd d00ee0 <- transformierter String
| | | | |
argv[0] __/ / / / /
argv[1] ____/ / / /
argv[2] _______/ / /
argv[3] ___________/ /
argv[4] ________________/
Ein möglicher API könnte sein:
char **parseargs(char *arguments, int *argc);
void freeparsedargs(char **argv);
Sie benötigen zusätzliche Überlegungen, um freeparsedargs() sicher zu implementieren.
Wenn Ihr String sehr lang ist und Sie nicht zweimal scannen möchten, könnten Sie Alternativen in Betracht ziehen, wie z. B. das Allozieren von mehr Elementen für die argv-Arrays (und bei Bedarf eine Neuallokation).
EDIT: Vorgeschlagene Lösung (behandelt kein argument in Anführungszeichen).
#include
static int setargs(char *args, char **argv)
{
int count = 0;
while (isspace(*args)) ++args;
while (*args) {
if (argv) argv[count] = args;
while (*args && !isspace(*args)) ++args;
if (argv && *args) *args++ = '\0';
while (isspace(*args)) ++args;
count++;
}
return count;
}
char **parsedargs(char *args, int *argc)
{
char **argv = NULL;
int argn = 0;
if (args && *args
&& (args = strdup(args))
&& (argn = setargs(args,NULL))
&& (argv = malloc((argn+1) * sizeof(char *)))) {
*argv++ = args;
argn = setargs(args,argv);
}
if (args && !argv) free(args);
*argc = argn;
return argv;
}
void freeparsedargs(char **argv)
{
if (argv) {
free(argv[-1]);
free(argv-1);
}
}
int main(int argc, char *argv[])
{
int i;
char **av;
int ac;
char *as = NULL;
if (argc > 1) as = argv[1];
av = parsedargs(as,&ac);
printf("== %d\n",ac);
for (i = 0; i < ac; i++)
printf("[%s]\n",av[i]);
freeparsedargs(av);
exit(0);
}
0 Stimmen
Für welche Plattform? Wie Befehlszeilen in argc/argv umgewandelt werden, unterscheidet sich erheblich zwischen Windows und UNIX-basierten Systemen, zum Beispiel. Auf UNIX transformiert die Shell in der Regel die Befehlszeile erheblich, einschließlich des Durchlaufens (Dateimustererweiterung) und der Variablensubstitution. Auf Windows wird die Dateimustererweiterung nicht von der Shell durchgeführt (es sei denn, Sie verwenden etwas wie Cygwin oder das MKS Toolkit).
0 Stimmen
Wenn Sie nicht einmal mit zitierten Argumenten umgehen müssen, würde ich wirklich vorschlagen, Ihre eigene Funktion zu codieren, anstatt eine Bibliothek von Drittanbietern nur für diese Aufgabe einzuführen.
2 Stimmen
Hast du getopt() ausprobiert? (man 3 getopt). Du kannst die Quellen für die meisten Standard-UNIX/Linux-Tools für Beispiele einsehen, eine RIESIGE Anzahl davon. Selbst die Man-Page (zumindest die Linux-Version) enthält ein ordentliches Beispiel. Es gibt auch eine Reihe von Wrapper-Funktionen (du siehst hier Empfehlungen), aber getopt() scheint die einzige verfügbare für JEDE UNIX-Plattform zu sein (tatsächlich scheint sie Teil des POSIX-Standards zu sein).
0 Stimmen
Wenn Sie immer noch interessiert sind und industrielle Stärke von Grund auf wollen, in einem kleinen Codepaket. Suchen Sie auf dieser Seite nach
nargv
Mit Abstand die beste Lösung, die ich hier aus reinem c-Code gesehen habe. Bitte stimmen Sie für diese Antwort! Damit andere sie finden können.0 Stimmen
@user735796 Ich habe nach
nargv
gesucht und dein Kommentar ist der einzige Treffer. Also habe ich gegoogelt: github.com/hypersoft/nargv ... Ein paar Anmerkungen jedoch. Dies verwendet C99, daher wird es nicht mit dem Microsoft C-Compiler funktionieren. Auch eine Idee ist es, Unit-Tests mit einer Vielzahl von Testfällen zu haben, die jeden Typ von Szenario für den Parser überprüfen, um sicherzustellen, dass es wie erwartet funktioniert.0 Stimmen
Für Unix-Entwickler, die eine sehr einfache, aber leistungsstarke Implementierung wünschen, die das Bash-Style Escaping und Quoting behandelt: github.com/pasztorpisti/cmd2argv
0 Stimmen
Du möchtest wahrscheinlich auch das Globbing aktivieren, also siehe glob(7) und folge den dortigen Verweisen.
0 Stimmen
Nicht sicher, warum getopt hier Upvotes bekommt --- es löst ein anderes Problem (Analyse des Inhalts eines argv-Arrays, anstatt tatsächlich ein argv-Array aus einem String zu erstellen, wonach der OP gefragt hat).
0 Stimmen
Schau dir das an: stackoverflow.com/a/54617539/236062