# Kommando Interpreter C



## Joe1903 (12. Dezember 2016)

Hallo zusammen,

ich muss bei einer Programmieraufgabe einen Kommando-Interpreter in C schreiben,welches folgendes machen soll:


_*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;*_

Wie kann ich das angehen?Kann mir jemand eine Hilfestellung geben,wie ich diese Aufgabe angehen kann,ob es evtl. bereits "Rahmenprogramme" gibt,bei denen man nur Anpassungen vornehmen muss etc.

Vielen Dank im Voraus.


----------



## cwriter (12. Dezember 2016)

Kommt dir int argc, char* argv[] bekannt vor?
In diesem Format ist auch die int main().

Es funktioniert also so:
Ein erstes scanf("%s") liest den Kommandonamen. Dann weisst du schon, ob das Kommando existiert. Wenn nicht: Abbruch, Leeren des input buffers (gets()) und beginne von vorne.
Ansonsten: Scanf, bis alle Parameter gelesen sind. Diese Parameter sollten in einem char* arr[] gespeichert werden, die Anzahl in einem uint. Dann einfach die verlinkte Funktion mit den Parametern aufrufen -> fertig.

Gruss
cwriter


----------



## Joe1903 (12. Dezember 2016)

cwriter hat gesagt.:


> Kommt dir int argc, char* argv[] bekannt vor?
> In diesem Format ist auch die int main().
> 
> Es funktioniert also so:
> ...



Glaubst du,du könntest mir auch hier den Rohbau aufzeigen?Also später.


----------



## cwriter (12. Dezember 2016)

Joe1903 hat gesagt.:


> Glaubst du,du könntest mir auch hier den Rohbau aufzeigen?Also später.


Ich glaube nicht, ich weiss es.
Was ich nicht weiss, ist, ob der Code korrekt ist. Er scheint zumindest halbwegs zu funktionieren.
Probiere einfach mal den Input "adder 0 1 2 3 4 <" (das '<' beendet die Argumentkette) durch.
Ich habe etwas viel mit realloc herumgespielt, um dir die Mechaniken ein bisschen zu zeigen - aber es ist gut möglich, dass ich da selbst auf die Schnauze gefallen bin...

Und da VS prinzipiell ungeprüfte Funktionen nicht so mag, sind manche Funktionen im Code non-Standard. Ich habe ein paar defines hingeklatscht, die helfen sollten.

Das ist alles so in einer knappen Stunde entstanden, also kein (grosser) Gewähr 


```
//VS-Specific, ignore
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//Function signature definition
typedef int (*cmd_func)(int argc, char* argv[]);

//Some hacky defines
#define strcpy_s(dest, s, src) strcpy(dest, src);
#define memcpy_s(dest, destsize, source, sourcesize) memcpy(dest, source, sourcesize);


typedef struct {
    char* name;            //Command name; will be checked against
    int parc;            //param count: How many strings there are in parv
    char** parv;        //Names of the parameters (for whatever reason we have them here...)
    int argc;            //argument count: Value to be passed to func
    char** argv;        //argument vector: Value to be passed to func
    cmd_func func;        //Actual command function

} cmd_desc;

///<summary>
///Extended free: Frees only if p != NULL
///</summary>
///<returns>true if p was freed, false otherwise</returns>
bool exfree(void* p)
{
    if (p != NULL) {
        free(p);
        return true;
    }
    return false;
}

///<summary>
///Clears a cmd_desc struct instance by setting all bytes to 0
///</summary>
///<param name="to_clear">pointer to allocated structure that shall be cleared</param>
void clear_cmd_desc(cmd_desc* to_clear)
{
    exfree(to_clear->name);
    for (int i = 0; i < to_clear->parc; i++) exfree(to_clear->parv[i]);    //Free parameter names
    for (int i = 0; i < to_clear->argc; i++) exfree(to_clear->argv[i]);    //Free arguments
    memset(to_clear, 0, sizeof(cmd_desc));
}

///<summary>
///Creates a valid cmd_desc structure with the values provided as parameters.
///</summary>
///<returns>A calloc-created pointer to a valid struct, or NULL if no valid struct could be generated</returns>
cmd_desc* create_cmd_desc(const char* name, int parc, const char** parv, cmd_func func)
{
    if (parc < 0) return NULL;
    cmd_desc* ptr = (cmd_desc*)calloc(1, sizeof(cmd_desc));    //calloc is very nice here: it automatically sets the memory to 0
    if (ptr == NULL) return NULL;
    ptr->name = (char*)malloc(strlen(name) + 1);
    strcpy_s(ptr->name, strlen(name) + 1, name);        //This is non-standard. If errors occur: Remove the 2nd param and change to strcpy().

    //Some (illegal) shortcut.
    if (parc > 0)
    {
        ptr->parc = parc;

        ptr->parv = (char**)malloc(sizeof(char*)*parc);
        //Loop over all arguments to copy, then allocate, then copy
        for (int i = 0; i < parc; i++) {
            ptr->parv[i] = (char*)malloc(strlen(parv[i]) + 1);
            strcpy_s(ptr->parv[i], strlen(parv[i]) + 1, parv[i]);    //Non-standard again
        }
    }
    ptr->func = func;

    return ptr;


}

///<summary>
///Pushes an input at the end of a cmd_desc structure
///</summary>
bool push_input(cmd_desc* d, const char* input)
{
    char** tmp = (char**)realloc(d->argv, sizeof(char*) * (d->argc + 1));    //WARNING: This is really bad. If you fancy, try making this more efficient.
    //One way of making the line above more efficient: Double the current size each time we would exceed the current memory limit. This would logarithmically decrease the need of new allocations.
    if (tmp == NULL) return false;
    else d->argv = tmp;
    d->argv[d->argc] = (char*)malloc(strlen(input) + 1);
    strcpy_s(d->argv[d->argc], strlen(input) + 1, input);
    d->argc++;
    return true;
}

///<summary>
///Clears all input from cmd_desc* d.
///</summary>
void clear_input(cmd_desc* d)
{
    for (int i = 0; i < d->argc; i++) exfree(d->argv[i]);
    exfree(d->argv);
    d->argv = NULL;
    d->argc = 0;
}

///<summary>
///Adds a cmd_desc to the global array
///</summary>
bool add_cmd_desc(cmd_desc** arr, size_t* index, size_t* arrsize, cmd_desc* desc)
{
    //Logarithmic reallocation procedure
    if (*index >= *arrsize)
    {
        cmd_desc* tmp = (cmd_desc*)realloc(*arr, sizeof(cmd_desc) * *arrsize * 2);
        if (tmp == NULL) return false;
        else {
            *arrsize *= 2;
            *arr = tmp;
        }
    }
    //Set copy the contents of desc (*desc) to its location in the array
    (*arr)[(*index)++] = *desc;

    //Free desc as we have copied it already
    free(desc);
    return true;
}

///<summary>
///Converts all strings in argv to integers and adds them, returning the sum. It prints sum, average and median to stdout.
///</summary>
///<returns>Integer sum of all valid values in argv</returns>
int adder(int argc, char* argv[])
{
    if (argc <= 0)
    {
        printf("Invalid parameters\n");
        return 0;
    }
    int sum = 0;
    for (int 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;

    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;
    char* buf = (char*)calloc(bufsize, sizeof(char));    //Input buffer
    char* bufbase = buf;

    if (buf == NULL)
    {
        free(cmd_desc_arr);    //Free some sad things
        return -1;
    }

    //Add our little example function. We shortcut the descriptions 'cause I have no clue what they are for anyways.
    cmd_desc* d = create_cmd_desc("adder", 0, NULL, &adder);
    if (d == 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, d);

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



    while (scanf("%255s", bufbase) > 0) //Scanf string, 255 characters at max.
    {
        if (strcmp(bufbase, "quit") == 0) break;
        for (size_t i = 0; i < arr_ind; i++)
        {
          
            cmd_desc* d = &cmd_desc_arr[i];
          
            if (d->name == NULL) continue;

            if (strcmp(d->name, buf) == 0)
            {
                //Function found, now we can read data in
                while (scanf("%255s", buf) > 0) //This format string could be created with ssprintf, but I'm too lazy now
                {
                    if (buf[0] == '<') break;
                    //If not full yet / Broken mid-word, so we need to fix it...
                    if (buf[bufstep-2] != 0)
                    {
                        buf += bufstep-1;
                    }

                    if (bufbase[bufsize - 2] != 0) {
                        //No more space here, so we have to increase the size
                        char* tmp = (char*)realloc(bufbase, bufsize * 2);
                        if (tmp == NULL) {
                            printf("Failed to realloc.\n");
                            goto end;
                        }
                        int diff = (buf - bufbase);
                        bufbase = tmp;
                        //Some magic here: Reset the buf to keep its relative offset to bufbase
                        buf = buf + diff;

                        bufsize *= 2;

                        //Some safety measures
                        bufbase[bufsize - 2] = 0;
                        bufbase[bufsize - 1] = 0;
                    }
                    //Else we are done here and we can add the argument

                    push_input(d, bufbase);
                }

                //Call the functions
                d->func(d->argc, d->argv);

                //Clean up
                clear_input(d);

                //We could cleanup, i.e. reduce the size of the input buffer here. I won't.
                break;    //Break as there should only be one function per name
            }
        }

      

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

    free(bufbase);

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

    getchar();
    return 0;
}
```

Ich habe dir auch die .cpp angehängt, falls du nicht gerne aus dem Forum kopierst.

Gruss
cwriter

/EDIT: Der Median in der Beispielfunktion ist natürlich nur der Median, falls die Zahlenfolge sortiert ist... Sonst ist es einfach die mittlere Zahl der Zahlenfolge.
Mea Culpa.


----------



## Joe1903 (13. Dezember 2016)

cwriter hat gesagt.:


> Ich glaube nicht, ich weiss es.
> Was ich nicht weiss, ist, ob der Code korrekt ist. Er scheint zumindest halbwegs zu funktionieren.
> Probiere einfach mal den Input "adder 0 1 2 3 4 <" (das '<' beendet die Argumentkette) durch.
> Ich habe etwas viel mit realloc herumgespielt, um dir die Mechaniken ein bisschen zu zeigen - aber es ist gut möglich, dass ich da selbst auf die Schnauze gefallen bin...
> ...


Vielen vielen Dank für deine Mühe.Ich habs getestet,konnte es aber nicht zum Laufen bringen.
Könntest du es überfliegen,ob dir ein Fehler ins Auge fällt?Nochmals vielen Dank.


----------



## cwriter (13. Dezember 2016)

Joe1903 hat gesagt.:


> Vielen vielen Dank für deine Mühe.Ich habs getestet,konnte es aber nicht zum Laufen bringen.
> Könntest du es überfliegen,ob dir ein Fehler ins Auge fällt?Nochmals vielen Dank.


Und woran lag das? Ich kann keinen Bug reproduzieren, du müsstest schon ein bisschen mithelfen und deine Eingabe oder ggf. Compilerwarnungen und -fehler aufzählen.
Ich bin nicht so der Überflieger (pun intended) und kann daher nicht einfach den Fehler auf 200 Zeilen Code finden.

Gruss
cwriter


----------



## Joe1903 (13. Dezember 2016)

cwriter hat gesagt.:


> Und woran lag das? Ich kann keinen Bug reproduzieren, du müsstest schon ein bisschen mithelfen und deine Eingabe oder ggf. Compilerwarnungen und -fehler aufzählen.
> Ich bin nicht so der Überflieger (pun intended) und kann daher nicht einfach den Fehler auf 200 Zeilen Code finden.
> 
> Gruss
> cwriter


Ok ich schick morgen die Compilermeldungen.Habe grad kein Zugriff auf den Rechner und weiss die nicht mehr auswendig.


----------



## Joe1903 (14. Dezember 2016)

cwriter hat gesagt.:


> Und woran lag das? Ich kann keinen Bug reproduzieren, du müsstest schon ein bisschen mithelfen und deine Eingabe oder ggf. Compilerwarnungen und -fehler aufzählen.
> Ich bin nicht so der Überflieger (pun intended) und kann daher nicht einfach den Fehler auf 200 Zeilen Code finden.
> 
> Gruss
> cwriter


Hallo.Das sind die Fehler die ich beim Kompilieren bekommen habe:

*ERROR CCN3206 ./com.c:58    Suffix of integer constant 2nd is not valid.
ERROR CCN3010 ./com.c:58    Macro strcpy invoked with a null argument for parameter x.
ERROR CCN3041 ./com.c:58    The invocation of macro strcpy contains fewer arguments than are required by the macro definition.
ERROR CCN3209 ./com.c:168   Character constants must end before the end of a line.
WARNING CCN3076 ./com.c:168   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.
ERROR CCN3209 ./com.c:190   Character constants must end before the end of a line.
WARNING CCN3076 ./com.c:190   Character constant 'm too lazy now' has more than 4 characters. No more than rightmost 4 characters are used.
ERROR CCN3209 ./com.c:228   Character constants must end before the end of a line.
INFORMATIONAL CCN4118 ./com.c:228   Character constant 't.' has more than 1 character.*


----------



## vfl_freak (14. Dezember 2016)

Moin,

fein fein - und welche Zeilen sind das jeweils ???

Gruß Klaus


----------



## Joe1903 (14. Dezember 2016)

vfl_freak hat gesagt.:


> Moin,
> 
> fein fein - und welche Zeilen sind das jeweils ???
> 
> Gruß Klaus


Das ist der obige Code von cwriter (ohne 1-3).


----------



## vfl_freak (14. Dezember 2016)

Moin,


Joe1903 hat gesagt.:


> Das ist der obige Code von cwriter (ohne 1-3).


Das Du Dich auf deinen Code beziehst, ist ja klar, nur :
welches die in den Fehlermeldungen genannten Zeilen ????? 
Zählen wird hier keiner  :-]

Gruß Klaus


----------



## cwriter (14. Dezember 2016)

IBM-Compiler sind nicht standardkonform? Kann ich mir nicht vorstellen. Hast du den Code wirklich 1 zu 1 kopiert? (Nimm am besten die angehängte Datei).

Es scheint aber meine Makros nicht zu mögen. Naja. Ersetze alle strcpy_s(a, b, c) durch strcpy(a, c) und alle memcpy_s(a, b, c, d) durch memcpy(a, c, d).
(wobei a, b, c, d jeweils nur repräsentativ für das steht, was an der jeweiligen Stelle stand).
Dann löschst du die beiden defines für memcpy_s und strcpy_s.

Gruss
cwriter


----------



## Joe1903 (14. Dezember 2016)

cwriter hat gesagt.:


> IBM-Compiler sind nicht standardkonform? Kann ich mir nicht vorstellen. Hast du den Code wirklich 1 zu 1 kopiert? (Nimm am besten die angehängte Datei).
> 
> Es scheint aber meine Makros nicht zu mögen. Naja. Ersetze alle strcpy_s(a, b, c) durch strcpy(a, c) und alle memcpy_s(a, b, c, d) durch memcpy(a, c, d).
> (wobei a, b, c, d jeweils nur repräsentativ für das steht, was an der jeweiligen Stelle stand).
> ...


Wie gesagt ich habe die angeängte Datei verwendet und lediglich Zeilen 1-3 gelöscht bzw auskommentiert.
Ich nehme jetzt die Anpassungen vor und melde mich dann.


----------



## Joe1903 (14. Dezember 2016)

vfl_freak hat gesagt.:


> Moin,
> 
> Das Du Dich auf deinen Code beziehst, ist ja klar, nur :
> welches die in den Fehlermeldungen genannten Zeilen ?????
> ...


Man sieht doch auf der Seite die Zeilen oder?


----------



## Joe1903 (14. Dezember 2016)

cwriter hat gesagt.:


> IBM-Compiler sind nicht standardkonform? Kann ich mir nicht vorstellen. Hast du den Code wirklich 1 zu 1 kopiert? (Nimm am besten die angehängte Datei).
> 
> Es scheint aber meine Makros nicht zu mögen. Naja. Ersetze alle strcpy_s(a, b, c) durch strcpy(a, c) und alle memcpy_s(a, b, c, d) durch memcpy(a, c, d).
> (wobei a, b, c, d jeweils nur repräsentativ für das steht, was an der jeweiligen Stelle stand).
> ...


Also ich habe nun folgenden Code versucht zu kompilieren (Anpassungen von strcpy und memcpy gemacht):

```
#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)
{
 exfree(to_clear->name);
 for (int i = 0; i < to_clear->parc; i++) exfree(to_clear->parv[i]);
 for (int 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)
{
 if (parc < 0) return NULL;
 cmd_desc* ptr = (cmd_desc*)calloc(1, sizeof(cmd_desc)); /
 if (ptr == NULL) return NULL;
 ptr->name = (char*)malloc(strlen(name) + 1);
 strcpy(ptr->name, strlen(name) + 1);

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

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

 return ptr;


}


bool push_input(cmd_desc* d, const char* input)
{
 char** 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], strlen(input) + 1);
 d->argc++;
 return true;
}


void clear_input(cmd_desc* d)
{
 for (int 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)
{
 
 if (*index >= *arrsize)
 {
  cmd_desc* 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;
 for (int 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;

 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;
 char* buf = (char*)calloc(bufsize, sizeof(char));
 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("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, d);

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

 while (scanf("%255s", bufbase) > 0)
 {
  if (strcmp(bufbase, "quit") == 0) break;
  for (size_t i = 0; 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) {
      char* tmp = (char*)realloc(bufbase, bufsize * 2);
      if (tmp == NULL) {
       printf("Failed to realloc.\n");
       goto end;
      }
      int 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 (size_t i = 0; i < arr_size; i++)
 {
  clear_cmd_desc(&cmd_desc_arr[i]);
 }
 exfree(cmd_desc_arr);

 getchar();
 return 0;
}
```

Folgende Fehler bekam ich raus (die Zeilennummer kann man glaub im Code oben an der Seite sehen oder?):

*ERROR CCN3166 ./com.c:18    Definition of function bool requires parentheses.
ERROR CCN3276 ./com.c:18    Syntax error: possible missing '{'?
ERROR CCN3045 ./com.c:20    Undeclared identifier p.
ERROR CCN3045 ./com.c:22    Undeclared identifier true.
ERROR CCN3045 ./com.c:24    Undeclared identifier false.
ERROR CCN3993 ./com.c:31    The declaration part of a "for" statement is not allowed.
ERROR CCN3275 ./com.c:31    Unexpected text 'int' encountered.
ERROR CCN3993 ./com.c:32    The declaration part of a "for" statement is not allowed.
ERROR CCN3334 ./com.c:32    Identifier i has already been defined on line 31 of "./com.c".
ERROR CCN3275 ./com.c:32    Unexpected text 'int' encountered.
ERROR CCN3046 ./com.c:40    Syntax error.
ERROR CCN3275 ./com.c:40    Unexpected text '/' encountered.
ERROR CCN3280 ./com.c:43    Function argument assignment between types "const char*" and "unsigned int" is not allowed.
ERROR CCN3993 ./com.c:51    The declaration part of a "for" statement is not allowed.
ERROR CCN3275 ./com.c:51    Unexpected text 'int' encountered.
ERROR CCN3280 ./com.c:54    Function argument assignment between types "const char*" and "unsigned int" is not allowed.
ERROR CCN3166 ./com.c:65    Definition of function bool requires parentheses.
ERROR CCN3276 ./com.c:65    Syntax error: possible missing '{'?
ERROR CCN3045 ./com.c:67    Undeclared identifier d.
ERROR CCN3045 ./com.c:68    Undeclared identifier false.
ERROR CCN3045 ./com.c:70    Undeclared identifier input.
ERROR CCN3280 ./com.c:71    Function argument assignment between types "const char*" and "unsigned int" is not allowed.
ERROR CCN3045 ./com.c:73    Undeclared identifier true.
ERROR CCN3993 ./com.c:79    The declaration part of a "for" statement is not allowed.
ERROR CCN3275 ./com.c:79    Unexpected text 'int' encountered.
ERROR CCN3166 ./com.c:86    Definition of function bool requires parentheses.
ERROR CCN3276 ./com.c:86    Syntax error: possible missing '{'?
ERROR CCN3045 ./com.c:89    Undeclared identifier index.
ERROR CCN3045 ./com.c:89    Undeclared identifier arrsize.
ERROR CCN3045 ./com.c:91    Undeclared identifier arr.
ERROR CCN3045 ./com.c:92    Undeclared identifier false.
ERROR CCN3045 ./com.c:99    Undeclared identifier desc.
ERROR CCN3045 ./com.c:103   Undeclared identifier true.
ERROR CCN3275 ./com.c:114   Unexpected text 'int' encountered.
ERROR CCN3993 ./com.c:115   The declaration part of a "for" statement is not allowed.
ERROR CCN3275 ./com.c:115   Unexpected text 'int' encountered.
ERROR CCN3046 ./com.c:132   Syntax error.
ERROR CCN3046 ./com.c:133   Syntax error.
ERROR CCN3275 ./com.c:134   Unexpected text 'char' encountered.
ERROR CCN3275 ./com.c:135   Unexpected text 'char' encountered.
ERROR CCN3046 ./com.c:144   Syntax error.
ERROR CCN3993 ./com.c:153   The declaration part of a "for" statement is not allowed.
ERROR CCN3275 ./com.c:153   Unexpected text 'size_t' encountered.
ERROR CCN3275 ./com.c:177   Unexpected text 'int' encountered.
ERROR CCN3993 ./com.c:204   The declaration part of a "for" statement is not allowed.
ERROR CCN3275 ./com.c:204   Unexpected text 'size_t' encountered.*


----------



## vfl_freak (14. Dezember 2016)

Moin,

irgendwie fehlt das was , oder?
Soll das eine eigene Klasse sein??
Falls ja, warum geht es nach den includes direkt mit TypDefs los??

Hast Du mal die fehlernummern gegooglet? Es gibt beim IBM doch jede Menge Erklärungen ....

Gruß Klaus


----------



## cwriter (14. Dezember 2016)

Oha. Mea Culpa.
Dir fehlt das include
#include <stdbool.h>
.
(Nur bei moderenen C-Versionen...)
Sag mal, nutzt dein Compiler irgendeinen prähistorischen Standard, aka c89 oder so? Kannst du das auf eine zeitgemässe Alternative (c99 oder c11) umstellen? Ansonsten wird das eine Menge Arbeit (und es gibt eigentlich keinen Grund mehr, heutzutage mit so alten Standards zu arbeiten...).
Warte mal... realloc und c89? Geht das überhaupt ohne void*?

Ansonsten müsstest du _alle_ Variablen an den Anfang ihres Scopes setzen, bei allen for-Loops die Startkondition (int i = 0) aus dem Loop rausnehmen (also z.B. int i; for(i = 0; i < bla; i++)) und dann aufräumen, also Doppeldefinitionen eliminieren.



vfl_freak hat gesagt.:


> irgendwie fehlt das was , oder?


Was denn? 



vfl_freak hat gesagt.:


> Soll das eine eigene Klasse sein??


In C? Unwahrscheinlich...



vfl_freak hat gesagt.:


> Falls ja, warum geht es nach den includes direkt mit TypDefs los??


Wo sollten die denn sonst hin?

size_t sollte aber eigentlich in stdio.h definiert sein.

Gruss
cwriter

OT: Oh Gott oh gott...
Lese gerade die Schauergeschichten von https://de.wikipedia.org/wiki/Varianten_der_Programmiersprache_C...
*Schauder*

Back to Topic: Nein, ernsthaft, tue dir C89 nicht an. Das ist völlig praxisfern. Wenn dein Prof das von dir verlangt, dann heuere einen Profikiller an hast du mein ernsthaftes Beileid.


----------



## Joe1903 (14. Dezember 2016)

cwriter hat gesagt.:


> Oha. Mea Culpa.
> Dir fehlt das include
> #include <stdbool.h>
> .
> ...



Also ich hab stdbool.h eingebaut, nun wurden die Fehler wieder weniger:

*ERROR CCN3206 ./com_b.c:55    Suffix of integer constant 2nd is not valid.
ERROR CCN3010 ./com_b.c:55    Macro strcpy invoked with a null argument for parameter x.
ERROR CCN3041 ./com_b.c:55    The invocation of macro strcpy contains fewer arguments than are required by the macro definition.
ERROR CCN3209 ./com_b.c:165   Character constants must end before the end of a line.
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.
ERROR CCN3209 ./com_b.c:187   Character constants must end before the end of a line.
WARNING CCN3076 ./com_b.c:187   Character constant 'm too lazy now' has more than 4 characters. No more than rightmost 4 characters are used.
ERROR CCN3209 ./com_b.c:225   Character constants must end before the end of a line.
INFORMATIONAL CCN4118 ./com_b.c:225   Character constant 't.' has more than 1 character.*

Der Compiler benutzt c89,aber umstellen kann ich es nicht,da es bei der Arbeit benutzt wird...Leider...
Und strcpy habe ich auch geändert.Was sind die übrigen Fehler nun genau?Kannst du damit was anfangen?


----------



## cwriter (14. Dezember 2016)

Joe1903 hat gesagt.:


> Der Compiler benutzt c89,aber umstellen kann ich es nicht,da es bei der Arbeit benutzt wird...Leider...


Kleines OT:
Wir haben 2016, bald 2017. Es gibt seit 6 Jahren C11 bzw. C+11, seit ~3 Jahren ist es benutzbar.
Es gibt seit fast 18 Jahren C99. C89 ist schwieriger zu optimieren (register loops), schlechter zu lesen (Variablen vor Kilometern an Quellcode definiert, wirre Casts) und hat keinen einzigen Vorteil gegenüber C99 (ausser für Masochisten). Ganz ehrlich: Hätte ich die Wahl zwischen C89 und Assembly, würde ich Assembly nehmen...
</rant>

*Seufz*
Hilft ja alles nichts.
Also: Alle Kommentare (//...) solltest du durch Zeilenkommentare (/*...*/) ersetzen.

Zum Makro strcpy: Ich habe keinen Schimmer, wie IBM das implementiert. (strcpy ist eigentlich eine Funktion, kein Makro). Was sagt denn deine IDE, was die Definition des Makros ist?
Ausser, dein System ist nicht POSIX-Compliant, aber dann haben wir eh ein ganz anderes Problem...
Du hast aber scheinbar schon die Loops umstrukturiert. Allerdings stimmen jetzt die Zeilennummern auch nicht mehr...

Wie sieht denn den Code momentan aus?
(Sorry, dass sich das so hinzieht  )

Gruss
cwriter

/EDIT: Beschwert sich der Compiler nicht bei meinen Funktionen? Eigentlich müssten die nach C89 so aufgebaut sein (Das wäre der älteste Standard. Ganz so schlimm ist es dann doch nicht  ):
char * strcpy (String1, String2) char *String1; const char *String2;

-> Entweder ist das nicht C89 oder IBM hält nicht allzuviel vom Standard.
Oder hast du das schon korrigiert?
-> Es ist C89 

/EDIT2: Bei strcpy scheinst du strcpy_s(a, b, c) zu strcpy(a, b) statt strcpy(a, c) geändert zu haben. Das ist ein Grund für ein paar Fehler im Code.


----------



## Joe1903 (14. Dezember 2016)

cwriter hat gesagt.:


> Kleines OT:
> Wir haben 2016, bald 2017. Es gibt seit 6 Jahren C11 bzw. C+11, seit ~3 Jahren ist es benutzbar.
> Es gibt seit fast 18 Jahren C99. C89 ist schwieriger zu optimieren (register loops), schlechter zu lesen (Variablen vor Kilometern an Quellcode definiert, wirre Casts) und hat keinen einzigen Vorteil gegenüber C99 (ausser für Masochisten). Ganz ehrlich: Hätte ich die Wahl zwischen C89 und Assembly, würde ich Assembly nehmen...
> </rant>
> ...


SORRY!! Es ist C99, nicht C89..

Der Code sieht aktuell so aus:


```
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

//Function signature definition
typedef int (*cmd_func)(int argc, char* argv[]);


typedef struct {
        char* name;                     //Command name; will be checked against
        int parc;                       //param count: How many strings there are in parv
        char** parv;            //Names of the parameters (for whatever reason we have them here...)
        int argc;                       //argument count: Value to be passed to func
        char** argv;            //argument vector: Value to be passed to func
        cmd_func func;          //Actual command function

} cmd_desc;

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

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

cmd_desc* create_cmd_desc(const char* name, int parc, const char** parv, cmd_func func)
{
        if (parc < 0) return NULL;
        cmd_desc* ptr = (cmd_desc*)calloc(1, sizeof(cmd_desc)); //calloc is very nice here: it automatically sets the memory to 0
        if (ptr == NULL) return NULL;
        ptr->name = (char*)malloc(strlen(name) + 1);
        strcpy(ptr->name, name);                //This is non-standard. If errors occur: Remove the 2nd param and change to strcpy().

        //Some (illegal) shortcut.
        if (parc > 0)
        {
                ptr->parc = parc;

                ptr->parv = (char**)malloc(sizeof(char*)*parc);
                //Loop over all arguments to copy, then allocate, then copy
                for (int i = 0; i < parc; i++) {
                        ptr->parv[i] = (char*)malloc(strlen(parv[i]) + 1);
                        strcpy(ptr->parv[i], parv[i]);  //Non-standard again
                }
        }
        ptr->func = func;

        return ptr;


}

bool push_input(cmd_desc* d, const char* input)
{
        char** tmp = (char**)realloc(d->argv, sizeof(char*) * (d->argc + 1));   //WARNING: This is really bad. If you fancy, try making this more efficient.
        //One way of making the line above more efficient: Double the current size each time we would exceed the current memory limit. This would logarithmically decrease the need of new allocations.
        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)
{
        for (int 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)
{
        //Logarithmic reallocation procedure
        if (*index >= *arrsize)
        {
                cmd_desc* tmp = (cmd_desc*)realloc(*arr, sizeof(cmd_desc) * *arrsize * 2);
                if (tmp == NULL) return false;
                else {
                        *arrsize *= 2;
                        *arr = tmp;
                }
        }
        //Set copy the contents of desc (*desc) to its location in the array
        (*arr)[(*index)++] = *desc;

        //Free desc as we have copied it already
        free(desc);
        return true;
}

int adder(int argc, char* argv[])
{
        if (argc <= 0)
        {
                printf("Invalid parameters\n");
                return 0;
        }
        int sum = 0;
        for (int 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;

        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;
        char* buf = (char*)calloc(bufsize, sizeof(char));       //Input buffer
        char* bufbase = buf;

        if (buf == NULL)
        {
                free(cmd_desc_arr);     //Free some sad things
                return -1;
        }

        //Add our little example function. We shortcut the descriptions 'cause I have no clue what they are for anyways.
        cmd_desc* d = create_cmd_desc("adder", 0, NULL, &adder);
        if (d == 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, d);

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



        while (scanf("%255s", bufbase) > 0) //Scanf string, 255 characters at max.
        {
                if (strcmp(bufbase, "quit") == 0) break;
                for (size_t i = 0; i < arr_ind; i++)
                {

                        cmd_desc* d = &cmd_desc_arr[i];

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

                        if (strcmp(d->name, buf) == 0)
                        {
                                //Function found, now we can read data in
                                while (scanf("%255s", buf) > 0) //This format string could be created with ssprintf, but I'm too lazy now
                                {
                                        if (buf[0] == '<') break;
                                        //If not full yet / Broken mid-word, so we need to fix it...
                                        if (buf[bufstep-2] != 0)
                                        {
                                                buf += bufstep-1;
                                        }

                                        if (bufbase[bufsize - 2] != 0) {
                                                //No more space here, so we have to increase the size
                                                char* tmp = (char*)realloc(bufbase, bufsize * 2);
                                                if (tmp == NULL) {
                                                        printf("Failed to realloc.\n");
                                                        goto end;
                                                }
                                                int diff = (buf - bufbase);
                                                bufbase = tmp;
                                                //Some magic here: Reset the buf to keep its relative offset to bufbase
                                                buf = buf + diff;

                                                bufsize *= 2;

                                                //Some safety measures
                                                bufbase[bufsize - 2] = 0;
                                                bufbase[bufsize - 1] = 0;
                                        }
                                        //Else we are done here and we can add the argument

                                        push_input(d, bufbase);
                                }

                                //Call the functions
                                d->func(d->argc, d->argv);

                                //Clean up
                                clear_input(d);

                                //We could cleanup, i.e. reduce the size of the input buffer here. I won't.
                                break;  //Break as there should only be one function per name
                        }
                }



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

        free(bufbase);

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

        getchar();
        return 0;
}
```


----------



## cwriter (14. Dezember 2016)

Joe1903 hat gesagt.:


> SORRY!! Es ist C99, nicht C89..


Sieht das dein Compiler irgendwie anders?


Joe1903 hat gesagt.:


> 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


----------



## Joe1903 (14. Dezember 2016)

cwriter hat gesagt.:


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


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.


```
#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.*


----------



## cwriter (14. Dezember 2016)

Wenn dein Compiler stdbool.h hat (und erlaubt. Muss er aber nicht), dann inkludiere stdbool.h.
Ansonsten mach folgende defines hin:

```
#define bool int
#define true 1
#define false 0
```

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

Gruss
cwriter


----------



## Joe1903 (14. Dezember 2016)

cwriter hat gesagt.:


> Wenn dein Compiler stdbool.h hat (und erlaubt. Muss er aber nicht), dann inkludiere stdbool.h.
> Ansonsten mach folgende defines hin:
> 
> ```
> ...


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.*


----------



## sheel (14. Dezember 2016)

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)?)


----------



## Joe1903 (14. Dezember 2016)

cwriter hat gesagt.:


> Wenn dein Compiler stdbool.h hat (und erlaubt. Muss er aber nicht), dann inkludiere stdbool.h.
> Ansonsten mach folgende defines hin:
> 
> ```
> ...


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.*


----------



## cwriter (14. Dezember 2016)

Joe1903 hat gesagt.:


> 2) Wie kann ich das am besten testen?Weil die Ausgabe wenn ich es ausführe ist





cwriter hat gesagt.:


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





Joe1903 hat gesagt.:


> 1) Inwiefern entspricht das der Aufgabenstellung?


Ach, brich mir nicht das Herz 

Inwiefern entspricht es deiner Meinung nach nicht der Aufgabenstellung?


Joe1903 hat gesagt.:


> _*Kommando Interpreter mit einem Array von Kommandobeschreibungen;*
> 
> *
> eine Kommandobeschreibung enthält
> ...


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


----------



## Joe1903 (14. Dezember 2016)

cwriter hat gesagt.:


> Ach, brich mir nicht das Herz
> 
> Inwiefern entspricht es deiner Meinung nach nicht der Aufgabenstellung?
> 
> ...


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).


----------



## Joe1903 (14. Dezember 2016)

cwriter hat gesagt.:


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


Ja aber das ist auch nicht so wichtig hier,oder?Ich meine es funktioniert ja.


----------



## cwriter (14. Dezember 2016)

Joe1903 hat gesagt.:


> Ok eine letzte Frage habe ich noch: Mit welchen Kommandos kann man das am "Ausgiebigsten" testen?


?
Ich habe keine komplette Bourne-Shell gebaut 

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.

```
//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:

```
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 
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.


----------



## Joe1903 (29. Dezember 2016)

cwriter hat gesagt.:


> ?
> Ich habe keine komplette Bourne-Shell gebaut
> 
> 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.
> ...


Hey cwriter.
Dürfte ich dich um ein kleines Gefallen bitten.Und zwar wenn ich beim Testen irgendwas schreibe (z.B. awa awa awa beeee) dann kommt 4-mal Next Input please.Aber sollte ja abbrechen eigentlich.Kannst du bitte mal schauen,woran das liegt??Es ist ja dein Code,du siehst schneller als ich.Wäre echt dankbar.


----------



## cwriter (29. Dezember 2016)

Joe1903 hat gesagt.:


> Dürfte ich dich um ein kleines Gefallen bitten.Und zwar wenn ich beim Testen irgendwas schreibe (z.B. awa awa awa beeee) dann kommt 4-mal Next Input please.


Naja, ist halt eine scanf-Sache.


Joe1903 hat gesagt.:


> Aber sollte ja abbrechen eigentlich.


War das eine Spezifikation? Wenn nein, dann ist es schlicht ein Ausnutzen des Undefined Behaviour.



Joe1903 hat gesagt.:


> Kannst du bitte mal schauen,woran das liegt??


Weiss ich auch so: Scanf. Ist nun mal so, dass scanf bei Whitespaces (auch ' ') abbricht.
Eine Lösung: Nach dem printf("Next input please"); ein

```
scanf("%*[^\n]");
```
einfügen. Das liest einfach alles bis zum '\n' ein und ignoriert es direkt ('*').



Joe1903 hat gesagt.:


> Es ist ja dein Code,du siehst schneller als ich.


Vorsicht. Du bist im Moment entweder auf dem Pfad des Copy-Paste oder auf dem des zeilenweisen Abschreibens. So nicht - du lernst so ja nichts. Ja, es sind 260 Zeilen, und ja, die Thematik ist durch die Edgecases nicht ganz so einfach, aber dann nimm dir halt mal einen Nachmittag Zeit, um den Code zu lesen und zu verstehen. 
Im Moment scheint es so, als würdest du Code haben, den du nicht verstehst, und wolltest dann einfach ein paar Änderungen daran vornehmen, weisst aber nicht, wie.
Es ist ok, Fragen zu stellen. Aber ein bisschen ein eigener Aufwand, herauszufinden, wo das Problem liegt, müsste schon drinliegen. Dann wäre deine Frage zu einem "Wie kann ich den Eingabebuffer bis zum nächsten "\n" leeren?", daraus wäre wiederum eine englische Version der Frage geworden, die Google verdaut und dir dann etwa so einen Link ausspuckt:
http://stackoverflow.com/questions/8097620/how-to-read-from-input-until-newline-is-found-using-scanf
Dann noch ohne Buffer (denn das würde ja Speicher brauchen):
http://stackoverflow.com/questions/7607550/scanf-skip-variable

Und schwupps hast du deine Lösung.
Im Übrigen finde ich meinen Code jetzt nicht wirklich schwer verständlich. Er ist ja sogar mit Kommentaren versehen.



Joe1903 hat gesagt.:


> Wäre echt dankbar.


Und ich wäre echt dankbar, würdest du mal an den Riemen reissen und ein bisschen Eigeninitiative zeigen.

Ist auch nicht böse gemeint, aber: "Gib jemandem einen Fisch, und er ernährt sich einen Tag lang. Lehre ihn zu fischen, und er ernährt sich ein Leben lang."

Gruss
cwriter


----------



## Joe1903 (30. Dezember 2016)

cwriter hat gesagt.:


> Naja, ist halt eine scanf-Sache.
> 
> War das eine Spezifikation? Wenn nein, dann ist es schlicht ein Ausnutzen des Undefined Behaviour.
> 
> ...


Danke für deine Hilfestellung.Ich bin gerade am zeilenweise durchgehen,aber ich werde es nicht abgeben.Ich schiesse mir ja nicht ins eigene Bein wenn ich etwas abgebe was ich zumindest nicht verstehe-aber eine Frage habe ich noch.
Ich habe das scanf eingebaut. Nun funktionier "adder 0 1 2 3 4 <" aber sobald ich "awa awa awea" eingebe,gibt es "Next input please" aus (erwartungsgemäss) jedoch wenn ich danach wieder "adder 10 22 30 40 <" eingebe, gibt es wieder "Next input please". Ich denke, dass es den Speicher nicht (richtig) leert.Bin ich auf dem richtigen Weg?Weisst du,warum es so sporadisch funktioniert?


----------



## cwriter (30. Dezember 2016)

```
This is a little command line interface (cli) demo.
Enter 'quit' to quit.
adder 0 <
Sum is 0, Average is 0 and median is 0
Ladies and gentlemen, next round, your input please...
aw aw
Ladies and gentlemen, next round, your input please...
adder 0 <
Sum is 0, Average is 0 and median is 0
Ladies and gentlemen, next round, your input please...
```
Gibt es bei dir auch so einen Output?



Joe1903 hat gesagt.:


> Ich denke, dass es den Speicher nicht (richtig) leert.Bin ich auf dem richtigen Weg?


Wie kommst du darauf? Es kann Speicher weder richtig noch unrichtig leeren, denn scanf() ist POSIX-standardisiert. Würde bei dir etwas anderes rauskommen, hätten wir ein Problem, denn dann wäre die POSIX-Compliance meines Systems von der des deinigen unterschiedlich und es würde ziemlich mühsam werden.
Die Codezeile des Scanf ist so definiert, dass es alle Zeichen bis zum '\n' als dem Eingabestrom löscht. Fertig. D.h. wenn das für dich "richtig" ist, dann ist dieser Teil des Programms semantisch korrekt.
Ich denke eher, dass du das "Next input please" als Fehlermeldung verstehst, was es nicht ist. Es zeigt nicht an, ob ein Fehler passiert war, sondern wird unkonditional ausgeführt. Das sähe man aber auch im Code.

Gruss
cwriter


----------



## Joe1903 (30. Dezember 2016)

cwriter hat gesagt.:


> ```
> This is a little command line interface (cli) demo.
> Enter 'quit' to quit.
> adder 0 <
> ...


Leider nicht..

Der Code momentan bei mir ist wie folgt:


```
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define bool int
#define true 1
#define false 0

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

typedef struct cmd_desc
{
        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)
{
        int i;
        cmd_desc* ptr = NULL;

        if (parc < 0)
        {
                exit(1);
        }

        ptr = (cmd_desc*)calloc(1, sizeof(cmd_desc));

        if (ptr == NULL)
        {
                printf("Allocation failed.\n");
                exit(1);
        }
        ptr->name = (char*)malloc(strlen(name) + 1);
        strcpy(ptr->name, name);

        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)
        {
                printf("Reallocation failed.\n");
                exit(1);
        }
        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)
                {
                        printf("Reallocation failed.\n");
                        exit(1);
                }
                else
                {
                        *arrsize *= 2;
                        *arr = tmp;
                }
        }
        (*arr)[(*index)++] = *desc;
        free(desc);
        return (true);
}


int adder(
        int argc,
        char* argv[])
{
        int i;
        int sum = 0;

        if (argc <= 0)
        {
                printf("Invalid parameters.\n");
                exit(1);
        }

        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;
        cmd_desc* d = NULL;
        size_t arr_ind = 0;
        size_t arr_size = 4;
        size_t i = 0;
        size_t bufstep = 256;
        size_t bufsize = 256;
        char* buf = NULL;
        char* bufbase = NULL;
        char* tmp = NULL;
        int diff;

        cmd_desc_arr = (cmd_desc*)calloc(arr_size, sizeof(cmd_desc));

        if (cmd_desc_arr == NULL)
        {
                printf("Allocation failed.\n");
                exit(1);
        }

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

        if (buf == NULL)
        {
                printf("Allocation failed.\n");
                free(cmd_desc_arr);
                exit(1);
        }

        d = create_cmd_desc("adder", 0, NULL, &adder);

        if (d == NULL)
        {
                printf("Error occured.\n");
                exit(1);
        }

        add_cmd_desc(&cmd_desc_arr, &arr_ind, &arr_size, d);

        printf("Command line interface.\nEnter 'quit' to quit.\n");

        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("Next input please..\n");
                scanf("%*[^\n]");
        }
end:
        free(bufbase);

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

        getchar();
        return (0);
}
```

Ausgabe ist so:

```
T540972@TD01:/home/t540972/test ==> c2_beta
Command line interface.
Enter 'quit' to quit.
adder 2 3 <
Sum is 5, Average is 2 and median is 3
Next input please..
awa awa
Next input please..
adder 3 4 <
Next input please..
adder 3 <
Next input please..
aqaw
Next input please..
adder 3 4 5 <
Next input please..
```


----------



## cwriter (30. Dezember 2016)

Geht es, wenn du nach dem "Next input please" ein

```
buf = bufbase;
```
hinmachst?

cwriter


----------



## Joe1903 (30. Dezember 2016)

cwriter hat gesagt.:


> Geht es, wenn du nach dem "Next input please" ein
> 
> ```
> buf = bufbase;
> ...


Nein leider nicht.Ausgabe ist gleich wie oben..


----------



## Joe1903 (30. Dezember 2016)

cwriter hat gesagt.:


> Geht es, wenn du nach dem "Next input please" ein
> 
> ```
> buf = bufbase;
> ...


Leider nicht..Ausgabe ist gleich wie oben.. Warum funktioniert es bei dir und nicht bei mir??


----------



## cwriter (30. Dezember 2016)

Joe1903 hat gesagt.:


> Leider nicht..Ausgabe ist gleich wie oben.. Warum funktioniert es bei dir und nicht bei mir??


Ich habe mal deinen Code in meine IDE eingefügt und ausgeführt. Innert 3 Minuten kann man herausfinden, dass du im Loop

```
for (; i < arr_ind; i++)
```
Den Zähler nicht auf 0 setzt.
Case closed.

cwriter


----------



## Joe1903 (30. Dezember 2016)

cwriter hat gesagt.:


> Ich habe mal deinen Code in meine IDE eingefügt und ausgeführt. Innert 3 Minuten kann man herausfinden, dass du im Loop
> 
> ```
> for (; i < arr_ind; i++)
> ...


CWriter danke für die Antwort.Ich arbeite ohne IDE,weil es so gefordert ist.
Dürfte ich dich etwas letztes fragen?
Du hast in deinem Code "Invalid parameters" falls argc <= 0 ist,also es keine Argumente gibt.Wie erreiche ich aber dies?Wenn ich nichts eingebe,kommt diese Meldung auch nicht.


----------



## cwriter (30. Dezember 2016)

Joe1903 hat gesagt.:


> Ich arbeite ohne IDE,weil es so gefordert ist.


Ah ja. Du warst ja der mit dem C89-Standard-IBM-Compiler. Auftragsmörder schon engagiert?
Debugger auch nicht erlaubt? Da ist ja komisch, dass du einen Texteditor verwenden darfst. Ein Hexeditor tut es doch auch.
</s>


Joe1903 hat gesagt.:


> Du hast in deinem Code "Invalid parameters" falls argc <= 0 ist,also es keine Argumente gibt.Wie erreiche ich aber dies?Wenn ich nichts eingebe,kommt diese Meldung auch nicht.





Joe1903 hat gesagt.:


> Du hast in deinem Code "Invalid parameters" falls argc <= 0 ist,also es keine Argumente gibt.


Ja, denn dann würde bspw. der "Median" (der keiner ist) nicht funktionieren.


Joe1903 hat gesagt.:


> Wie erreiche ich aber dies?Wenn ich nichts eingebe,kommt diese Meldung auch nicht.


Was heisst "nichts"?

```
adder <
```
sorgt für den error,

```
adder
```
lässt nachfolgende Eingaben zu.

Gruss
cwriter


----------



## Joe1903 (2. Januar 2017)

cwriter hat gesagt.:


> Ah ja. Du warst ja der mit dem C89-Standard-IBM-Compiler. Auftragsmörder schon engagiert?
> Debugger auch nicht erlaubt? Da ist ja komisch, dass du einen Texteditor verwenden darfst. Ein Hexeditor tut es doch auch.
> </s>
> 
> ...


Dank cwriter.Und gutes neues Jahr!

Wie kann man bei


```
ptr->parv = (char**)malloc(sizeof(char*)*parc);
...
ptr->parv[i] = (char**)malloc(sizeof(char*)*parv[i]+1);
```

testen,ob malloc geklappt hat?

Wie hier?:


```
ptr = (cmd_desc*)calloc(1, sizeof(cmd_desc));
       if (ptr == NULL)
       {
               printf("Allocation failed.\n");
               exit(1);
       }
```


----------



## sheel (2. Januar 2017)

Hi

genau, die Variable auf Gleichheit mit NULL prüfen.


----------



## Joe1903 (2. Januar 2017)

sheel hat gesagt.:


> Hi
> 
> genau, die Variable auf Gleichheit mit NULL prüfen.


ptr->parv == NULL bzw. ptr->parv_ == NULL 
Oder
ptr == NULL?
Das hab ich hier nicht ganz verstanden._


----------



## sheel (2. Januar 2017)

Bei der ersten Zeile ptr->parv, bei der zweiten ptr->parv[i]. Immer der Teil vorm =


----------



## Joe1903 (2. Januar 2017)

sheel hat gesagt.:


> Bei der ersten Zeile ptr->parv, bei der zweiten ptr->parv[i]. Immer der Teil vorm =


Super vielen Dank.
P.S. Könntest du bitte einen kurzen Blick auf meine letzten beiden Fragen im Thema "Dynamisches fgets in C" werfen?


----------



## Joe1903 (2. Januar 2017)

cwriter hat gesagt.:


> Ah ja. Du warst ja der mit dem C89-Standard-IBM-Compiler. Auftragsmörder schon engagiert?
> Debugger auch nicht erlaubt? Da ist ja komisch, dass du einen Texteditor verwenden darfst. Ein Hexeditor tut es doch auch.
> </s>
> 
> ...


Kurze Frage.Muss man bei deinem Code im Main dies machen:


```
if (d == NULL)
{
   printf("Error occurred.\n");
   free(cmd_desc_arr);
   free(buf);
   free(bufbase);
   exit(1);
}
```

Und ganz am Ende bei "end:" free(buf); hinzufügen?


----------



## cwriter (2. Januar 2017)

Joe1903 hat gesagt.:


> Kurze Frage.Muss man bei deinem Code im Main dies machen:


Mhm. Zumindest, wenn du noch nichts im cmd_desc_arr hast.
Allerdings ist buf==bufbase, also nur eines der beiden freigeben.


Joe1903 hat gesagt.:


> Und ganz am Ende bei "end:" free(buf); hinzufügen?


Hm. Sag du es mir. Zeig mal deine Gedankengänge.

Gruss
cwriter


----------



## Joe1903 (2. Januar 2017)

cwriter hat gesagt.:


> Mhm. Zumindest, wenn du noch nichts im cmd_desc_arr hast.
> Allerdings ist buf==bufbase, also nur eines der beiden freigeben.
> 
> Hm. Sag du es mir. Zeig mal deine Gedankengänge.
> ...





cwriter hat gesagt.:


> Mhm. Zumindest, wenn du noch nichts im cmd_desc_arr hast.
> Allerdings ist buf==bufbase, also nur eines der beiden freigeben.
> 
> Hm. Sag du es mir. Zeig mal deine Gedankengänge.
> ...


Ok am Ende brauch ich es nicht,da bereits free(bufbase); dort steht.

Jedoch beim obigen bin ich unsicher.Aber ich würde sagen auch hier würde free(bufbase); und free(cmd_desc_arr); reichen,oder?


----------



## cwriter (2. Januar 2017)

Joe1903 hat gesagt.:


> Ok am Ende brauch ich es nicht,da bereits free(bufbase); dort steht.


Nicht nur. free(buf) könnte schlicht falsch sein (Warum?)


Joe1903 hat gesagt.:


> Aber ich würde sagen auch hier würde free(bufbase); und free(cmd_desc_arr); reichen,oder?


Sofern nichts im cmd_desc_arr ist, ja.
(Ein netter Kerl hat mal eine Funktion geschrieben, die das Aufräumen übernehmen sollte:

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

Gruss
cwriter


----------

