Kommando Interpreter C

SORRY!! Es ist C99, nicht C89..
Sieht das dein Compiler irgendwie anders?
WARNING CCN3076 ./com_b.c:165 Character constant 'cause I have no clue what they are for anyways.' has more than 4 characters. No more than rightmost 4 characters are used.
Das heisst eigentlich, dass der Compiler den "//"-Kommentar nicht akzeptiert (denn er liest das "'...'" einen int-Wert).

Also: Annahme: Dein Compiler ist auf C99 gestellt. Dann müsste das Programm jetzt eigentlich laufen. Wenn nicht: Fehlermeldungen/Warnungen?

Annahme: Compiler ist auf C89. Dann müsste er immer noch sehr viele Fehler und Warnungen ausspucken.

Was ist der Fall? ;)
Hast du den Compiler umgestellt? Denn wenn ja, solltest du nur stdbool.h inkludieren müssen und auch mein Code sollte gehen. Wenn nein, dann müsstest du noch die Kommentare wie schon angedeutet in /**/ umschreiben und alle Variablen an den Anfang ihres Scopes verschieben.

Gruss
cwriter
 
Sieht das dein Compiler irgendwie anders?

Das heisst eigentlich, dass der Compiler den "//"-Kommentar nicht akzeptiert (denn er liest das "'...'" einen int-Wert).

Also: Annahme: Dein Compiler ist auf C99 gestellt. Dann müsste das Programm jetzt eigentlich laufen. Wenn nicht: Fehlermeldungen/Warnungen?

Annahme: Compiler ist auf C89. Dann müsste er immer noch sehr viele Fehler und Warnungen ausspucken.

Was ist der Fall? ;)
Hast du den Compiler umgestellt? Denn wenn ja, solltest du nur stdbool.h inkludieren müssen und auch mein Code sollte gehen. Wenn nein, dann müsstest du noch die Kommentare wie schon angedeutet in /**/ umschreiben und alle Variablen an den Anfang ihres Scopes verschieben.

Gruss
cwriter
Das ist der aktuelle Code. Ich habe alle Kommentare entfernt und die Deklaration der Variablen aus den Loops vorgezogen.Ich habe kriege aber immernoch Fehler und weiss nicht woran das nun liegt.Könntest du bitte evtl. kurz schauen,was ich falsch mache? P.S: Es ist doch C89 und ich kann es leider nicht ändern.

C++:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef int (*cmd_func)(int argc, char* argv[]);

typedef struct {
        char* name;
        int parc;
        char** parv;
        int argc;
        char** argv;
        cmd_func func;

} cmd_desc;


bool exfree(void* p)
{
        if (p != NULL) {
                free(p);
                return true;
        }
        return false;
}


void clear_cmd_desc(cmd_desc* to_clear)
{
        int i;
        exfree(to_clear->name);
        for (i = 0; i < to_clear->parc; i++)
        {
                exfree(to_clear->parv[i]);
        }
        for (i = 0; i < to_clear->argc; i++)
        {
                exfree(to_clear->argv[i]);
        }
        memset(to_clear, 0, sizeof(cmd_desc));
}


cmd_desc* create_cmd_desc(const char* name, int parc, const char** parv, cmd_func func)
{
        cmd_desc* ptr = NULL;
        if (parc < 0)
        {
                return NULL;
        }
        ptr = (cmd_desc*)calloc(1, sizeof(cmd_desc));
        if (ptr == NULL)
        {
                return NULL;
        }
        ptr->name = (char*)malloc(strlen(name) + 1);
        strcpy(ptr->name, name);

        int i;
        if (parc > 0)
        {
                ptr->parc = parc;

                ptr->parv = (char**)malloc(sizeof(char*)*parc);
                for (i = 0; i < parc; i++)
                {
                        ptr->parv[i] = (char*)malloc(strlen(parv[i]) + 1);
                        strcpy(ptr->parv[i], parv[i]);
                }
        }
        ptr->func = func;

        return ptr;
}


bool push_input(cmd_desc* d, const char* input)
{
        char** tmp = NULL;
        tmp = (char**)realloc(d->argv, sizeof(char*) * (d->argc + 1));
        if (tmp == NULL)
        {
                return false;
        }
        else
        {
                d->argv = tmp;
        }
        d->argv[d->argc] = (char*)malloc(strlen(input) + 1);
        strcpy(d->argv[d->argc], input);
        d->argc++;
        return true;
}


void clear_input(cmd_desc* d)
{
        int i;
        for (i = 0; i < d->argc; i++)
        {
                exfree(d->argv[i]);
        }
        exfree(d->argv);
        d->argv = NULL;
        d->argc = 0;
}


bool add_cmd_desc(cmd_desc** arr, size_t* index, size_t* arrsize, cmd_desc* desc)
{
        cmd_desc* tmp = NULL;
        if (*index >= *arrsize)
        {
                tmp = (cmd_desc*)realloc(*arr, sizeof(cmd_desc) * *arrsize * 2);
                if (tmp == NULL)
                {
                        return false;
                }
                else
                {
                        *arrsize *= 2;
                        *arr = tmp;
                }
        }
        (*arr)[(*index)++] = *desc;

        free(desc);
        return true;
}


int adder(int argc, char* argv[])
{
        if (argc <= 0)
        {
                printf("Invalid parameters\n");
                return 0;
        }
        int sum = 0;
        int i;
        for (i = 0; i < argc; i++)
        {
                sum += atoi(argv[i]);
        }
        printf("Sum is %d, Average is %d and median is %d\n", sum, sum / argc, atoi(argv[argc / 2]));
        return sum;
}

int main(int argc, char* argv[])
{
        cmd_desc* cmd_desc_arr = NULL;
        size_t arr_ind = 0;
        size_t arr_size = 4;
        char* buf = NULL;
        char* bufbase = NULL;

        cmd_desc_arr = (cmd_desc*)calloc(arr_size, sizeof(cmd_desc));
        if (cmd_desc_arr == NULL)
        {
                return -1;
        }

        size_t bufstep = 256;
        size_t bufsize = 256;
        buf = (char*)calloc(bufsize, sizeof(char));
        bufbase = buf;

        if (buf == NULL)
        {
                free(cmd_desc_arr);
                return -1;
        }

        cmd_desc* d = create_cmd_desc("adder", 0, NULL, &adder);
        if (d == NULL)
        {
                printf("Something really bad happened. And the programmer was too lazy to clean up... Take cover.\n");
        }
        add_cmd_desc(&cmd_desc_arr, &arr_ind, &arr_size, d);

        printf("This is a little command line interface (cli) demo.\nEnter 'quit' to quit.\n");

        size_t i = 0;
        char* tmp = NULL;
        int diff;

        while (scanf("%255s", bufbase) > 0)
        {
                if (strcmp(bufbase, "quit") == 0)
                {
                        break;
                }
                for (; i < arr_ind; i++)
                {

                        cmd_desc* d = &cmd_desc_arr[i];

                        if (d->name == NULL)
                        {
                                continue;
                        }

                        if (strcmp(d->name, buf) == 0)
                        {
                                while (scanf("%255s", buf) > 0)
                                {
                                        if (buf[0] == '<') break;
                                        if (buf[bufstep-2] != 0)
                                        {
                                                buf += bufstep-1;
                                        }

                                        if (bufbase[bufsize - 2] != 0) {
                                                tmp = (char*)realloc(bufbase, bufsize * 2);
                                                if (tmp == NULL)
                                                {
                                                        printf("Failed to realloc.\n");
                                                        goto end;
                                                }
                                                diff = (buf - bufbase);
                                                bufbase = tmp;

                                                buf = buf + diff;

                                                bufsize *= 2;

                                                bufbase[bufsize - 2] = 0;
                                                bufbase[bufsize - 1] = 0;
                                        }

                                        push_input(d, bufbase);
                                }

                                d->func(d->argc, d->argv);

                                clear_input(d);

                                break;
                        }
                }

                printf("Ladies and gentlemen, next round, your input please...\n");
        }
end:
        free(bufbase);

        for (; i < arr_size; i++)
        {
                clear_cmd_desc(&cmd_desc_arr[i]);
        }
        exfree(cmd_desc_arr);

        getchar();
        return 0;
}

ERROR CCN3166 ./com_beta.c:18 Definition of function bool requires parentheses.
ERROR CCN3276 ./com_beta.c:18 Syntax error: possible missing '{'?
ERROR CCN3045 ./com_beta.c:20 Undeclared identifier p.
ERROR CCN3045 ./com_beta.c:22 Undeclared identifier true.
ERROR CCN3045 ./com_beta.c:24 Undeclared identifier false.
ERROR CCN3275 ./com_beta.c:59 Unexpected text 'int' encountered.
ERROR CCN3166 ./com_beta.c:77 Definition of function bool requires parentheses.
ERROR CCN3276 ./com_beta.c:77 Syntax error: possible missing '{'?
ERROR CCN3045 ./com_beta.c:80 Undeclared identifier d.
ERROR CCN3045 ./com_beta.c:83 Undeclared identifier false.
ERROR CCN3045 ./com_beta.c:89 Undeclared identifier input.
ERROR CCN3045 ./com_beta.c:92 Undeclared identifier true.
ERROR CCN3166 ./com_beta.c:109 Definition of function bool requires parentheses.
ERROR CCN3276 ./com_beta.c:109 Syntax error: possible missing '{'?
ERROR CCN3045 ./com_beta.c:112 Undeclared identifier index.
ERROR CCN3045 ./com_beta.c:112 Undeclared identifier arrsize.
ERROR CCN3045 ./com_beta.c:114 Undeclared identifier arr.
ERROR CCN3045 ./com_beta.c:117 Undeclared identifier false.
ERROR CCN3045 ./com_beta.c:125 Undeclared identifier desc.
ERROR CCN3045 ./com_beta.c:128 Undeclared identifier true.
ERROR CCN3275 ./com_beta.c:139 Unexpected text 'int' encountered.
ERROR CCN3275 ./com_beta.c:140 Unexpected text 'int' encountered.
ERROR CCN3046 ./com_beta.c:163 Syntax error.
ERROR CCN3046 ./com_beta.c:164 Syntax error.
ERROR CCN3046 ./com_beta.c:174 Syntax error.
ERROR CCN3046 ./com_beta.c:183 Syntax error.
ERROR CCN3275 ./com_beta.c:184 Unexpected text 'char' encountered.
ERROR CCN3275 ./com_beta.c:185 Unexpected text 'int' encountered.
 
Wenn dein Compiler stdbool.h hat (und erlaubt. Muss er aber nicht), dann inkludiere stdbool.h.
Ansonsten mach folgende defines hin:
C:
#define bool int
#define true 1
#define false 0

Das sollte die Anzahl Fehler stark reduzieren.
Welche bleiben bestehen?

Gruss
cwriter
 
Wenn dein Compiler stdbool.h hat (und erlaubt. Muss er aber nicht), dann inkludiere stdbool.h.
Ansonsten mach folgende defines hin:
C:
#define bool int
#define true 1
#define false 0

Das sollte die Anzahl Fehler stark reduzieren.
Welche bleiben bestehen?

Gruss
cwriter
Nur noch diese hier:

ERROR CCN3275 ./com_beta.c:63 Unexpected text 'int' encountered.
ERROR CCN3275 ./com_beta.c:143 Unexpected text 'int' encountered.
ERROR CCN3275 ./com_beta.c:144 Unexpected text 'int' encountered.
ERROR CCN3046 ./com_beta.c:167 Syntax error.
ERROR CCN3046 ./com_beta.c:168 Syntax error.
ERROR CCN3046 ./com_beta.c:178 Syntax error.
ERROR CCN3046 ./com_beta.c:187 Syntax error.
ERROR CCN3275 ./com_beta.c:188 Unexpected text 'char' encountered.
ERROR CCN3275 ./com_beta.c:189 Unexpected text 'int' encountered.
 
Zeile 63 hat kein int. Falls es oben 59 ist, Variablen dürfen in dem Fall nur am Anfang von Blöcken deklariert werden.


(Nicht hilfreiche Einmischung, aber:
Wozu verwendet man noch immer einen C89-Compiler? Alten Code kann ich verstehen, aber alte Tools (wenn neue das Geforderte auch noch können)?)
 
Wenn dein Compiler stdbool.h hat (und erlaubt. Muss er aber nicht), dann inkludiere stdbool.h.
Ansonsten mach folgende defines hin:
C:
#define bool int
#define true 1
#define false 0

Das sollte die Anzahl Fehler stark reduzieren.
Welche bleiben bestehen?

Gruss
cwriter
Ich habe die Fehler korrigiert. Es kompiliert nun fehlerfrei. Danke nochmals.
Ich habe nur noch 2 Fragen:
1) Inwiefern entspricht das der Aufgabenstellung?
2) Wie kann ich das am besten testen?Weil die Ausgabe wenn ich es ausführe ist

This is a little command line interface (cli) demo.
Enter 'quit' to quit.
 
2) Wie kann ich das am besten testen?Weil die Ausgabe wenn ich es ausführe ist

Probiere einfach mal den Input "adder 0 1 2 3 4 <" (das '<' beendet die Argumentkette) durch.

1) Inwiefern entspricht das der Aufgabenstellung?
Ach, brich mir nicht das Herz :oops:

Inwiefern entspricht es deiner Meinung nach nicht der Aufgabenstellung?
Kommando Interpreter mit einem Array von Kommandobeschreibungen;


eine Kommandobeschreibung enthält

- den Kommandonamen

- die Namen der Parameter

- den Pointer auf eine Funktion, die u.a. mit

- int argc /* Anzahl der Parameter in 'argv' */

- char * argv[] /* Parameter (als Strings) */

aufgerufen wird;
schau dir das struct cmd_desc an. Fehlt dir was?
(Ausser den Parameternamen ist auch alles definiert, aber mit jenen konnte ich nichts anfangen).

Gruss
cwriter
 
Ach, brich mir nicht das Herz :oops:

Inwiefern entspricht es deiner Meinung nach nicht der Aufgabenstellung?

schau dir das struct cmd_desc an. Fehlt dir was?
(Ausser den Parameternamen ist auch alles definiert, aber mit jenen konnte ich nichts anfangen).

Gruss
cwriter
Uups sorry. Ja du hast recht. Wenn ich dich mal seh geb ich einen aus :) Ok eine letzte Frage habe ich noch: Mit welchen Kommandos kann man das am "Ausgiebigsten" testen? Was sind die geläufigsten Tests bei solchen Kommando Interpretern?Und ich konnte kein "Memory Leak" finden,bin aber noch zu neu um mich auf mich zu verlassen.Siehst du irgendwo eine Stelle,bei dem Memory überschrieben wird,was nicht zusteht?
(adder 0 1 2 3 4 < habe ich getestet, funktioniert wunderbar).
 
Zuletzt bearbeitet:
Ok eine letzte Frage habe ich noch: Mit welchen Kommandos kann man das am "Ausgiebigsten" testen?
?
Ich habe keine komplette Bourne-Shell gebaut :D

Am besten testest du das so: Du guckst dir den Code an, schaust, wie du ein Kommando erstellst und hinzufügst, und wie ein Kommando intern funktioniert.
Dann schreibst du eines, fügst es hinzu und testest es damit.
C:
//Add our little example function. We shortcut the descriptions 'cause I have no clue what they are for anyways.
    cmd_desc* DEIN_CMD = create_cmd_desc("DEIN_CMD_NAME", 0/*would be param name count*/, NULL/*would be paramnames. Add if you fancy it*/, &DEIN_CMD_CALLBACK);
    if (DEIN_CMD == NULL) printf("Uh. Something really bad happened. And the programmer was too lazy to clean up... Take cover.\n");
    add_cmd_desc(&cmd_desc_arr, &arr_ind, &arr_size, DEIN_CMD);
Alles, was mit "DEIN_CMD" beginnt, solltest du entsprechend personalisieren. (Dieser Code sollte noch vor der ersten Eingabe stehen). Deine Funktion sollte so aussehen wie der adder:
C:
int adder(int argc, char* argv[])
{
   //Dein Code. Achtung: Nie weiter als argv[argc-1] lesen!
   //=======HIER KÖNNTE DEINE KREATIVITÄT STEHEN==============

   return 0;
}

Gruss
cwriter

Zum 2. Post:
Ja aber das ist auch nicht so wichtig hier,oder?Ich meine es funktioniert ja.
Eigentlich nicht - entspricht ja nicht der Spezifikation. Stell dir vor, du lässt jemanden ein komplettes Haus mit allem drum und dran bauen und dieser lässt die Wände ohne Farbe bzw. Tapete. Und wenn du ihn darauf ansprichst, sagt er: "Aber das ist ja nicht wichtig, oder? Das Haus steht ja. Das Geld für die Wände nehme ich aber trotzdem".
Ich glaube nicht, dass du sonderlich glücklich wärst. Aber ich habe es ja schön: Ich bin weder Subunternehmer noch reicht dein Arm weit genug, um mich zu hauen. Daher kann ich es mir leisten, mich nicht 100%ig an die Vorgaben zu halten :cool:
Aber wieder ein bisschen ernsthafter: Wenn das deine Aufgabe ist, solltest du die Aufgabe schon richtig erfüllen. Ich weiss nicht so recht, wofür die Paramternamen gut sein sollen, und ich sah nicht viel Zweck darin, nachzufragen. Das gilt für dich nicht. Also; wenn du den Code selbst schreibst: Frag deinen Prof/Chef/Hund/Was auch immer, was damit gemeint ist und implementiere es entsprechend.
 
Zuletzt bearbeitet:
Zurück