Forum: PC-Programmierung Fehlerspeicher speichern in einer txt.Datei


von Jamie (Gast)


Angehängte Dateien:

Lesenswert?

Hallo an alle,

ich brauche eure Hilfe. Und zwar ich möchte einen Fehlerspeicher aus 
einem Steuergerät in einer txt.Datei
abspeichern. Die Infos werden aus einer vorhandenen csv.datei gelesen 
und in einem Sequenzer aufgelistet. Bisher habe ich es geschaft die 
Fehlernummer und den Fehlerstatus abzuspeichern. Den struct Errorcode 
und den Errortext kriege ich komischerweise nicht hin.

Die Ausgabe txt.Datei sieht bis jetzt noch so aus:

Nr | Fehlercode | FST | FNR | Text
   |            |     |     |
 0 |            |   9 |  75 |
 1 |            |   9 |   8 |
 2 | 01.01.01   |   0 |   0 | Kommunikationsfehler
 3 | 01.01.01   |   0 |   0 | Kommunikationsfehler
 4 | 01.01.01   |   0 |   0 | Kommunikationsfehler
 5 | 01.01.01   |   0 |   0 | Kommunikationsfehler
 6 | 01.01.01   |   0 |   0 | Kommunikationsfehler
 7 | 01.01.01   |   0 |   0 | Kommunikationsfehler

Das merkwürdige ist, dass ab Nr 2 die erste Zeile aus der csv.datei 
gespeichert wird obwohl ich in der Schleife hochzähle. In Nr 0 und 1 
passiert nichts. Das verstehe ich nicht.

Den folgende Code habe ich dem Anhang hinzugefügt. Zur besseren 
Verständnis beginnt die Funktion Btn_Read_ErrorCode.

Für jeden Tipp wäre ich sehr Dankbar!

von Jamie (Gast)


Lesenswert?

struct strErrorCode
{
    char *sCode;
    char *sIndexHex;
    char *sIndexDec;
    char *sText;
} ErrorCode[1024];

von Wegstaben V. (wegstabenverbuchsler)


Lesenswert?

die schlechte Nachricht:
du hast einen Tippfehler in deiner Fehlertext-Meldung:
"Unbekannter Fehler beim einlesen der Fehelrtext-Datei!"

die gute Nachricht:
Das ist nicht die Ursache, daß dein Programm micht so läuft wie 
gewünscht

von Karl H. (kbuchegg)


Lesenswert?

>                     ErrorCode[i].sCode = strtok(sLine[i], ";");

Du kannst das nicht so machen.
strtok liefert dir einen Pointer in den bestehenden String. Als einen 
Pointer, der in einen Teil von sLine[i] zeigt.
sLine wiederrum ist aber eine lokale Variable. Wird die Funktion 
verlassen, ist das Array wieder weg.


Alles in allem.
Anstelle der bescheuerten

   if( NULL == .... )

Schreibweise, wäre es vernünftig, erst mal die Grundlagen von
* C-Strings
* Filebehandlung
zu lernen (denn die 256-er for Schleife da am Anfang ist doch auch 
bescheuert)

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz Buchegger schrieb:
>>                     ErrorCode[i].sCode = strtok(sLine[i], ";");
>
> Du kannst das nicht so machen.
> strtok liefert dir einen Pointer in den bestehenden String. Als einen
> Pointer, der in einen Teil von sLine[i] zeigt.


Autsch.
Du hast das quer durch die Bank gemacht.
Und dann auch noch in der Abfragefunktion (der unteren) ungeprüft in das 
ErrorCode Array zugegriffen.

Ts, ts, ts.

von Karl H. (kbuchegg)


Lesenswert?

Jamie schrieb:
> struct strErrorCode
> {
>     char *sCode;
>     char *sIndexHex;
>     char *sIndexDec;
>     char *sText;
> } ErrorCode[1024];


Was ist hier eigentlich der Sinn der Sache, wenn du sowieso immer fix 
dimensionierte Arrays an die Pointer hängst?

            ErrorCode[i].sCode = (char*)malloc(20 * sizeof(char));
            ErrorCode[i].sIndexHex = (char*)malloc(5 * sizeof(char));
            ErrorCode[i].sIndexDec = (char*)malloc(5 * sizeof(char));
            ErrorCode[i].sText = (char*)malloc(256 * sizeof(char));


Warum nicht gleich in die Strukturdefinition entsprechend dimensionierte 
Arrays einbauen? Zu einfach?


Und PS:
Du sollst den Returnwert von malloc nicht casten.
Wenn du es tun musst, dann benutzt du keinen C Compiler sondern einen 
C++ Compiler. Und in dem Falle wäre dann sowieso die Benutzung der 
std::string Klasse angebracht.

von Jamie (Gast)


Lesenswert?

Hallo Karl Heinz Buchegger,

vielen Dank für deine Antworten. Kurz zur Info. Ich bin leider kein 
Profiprogrammierer sondern nur ein Elektrotechniker und ich will noch 
sehr viel dazulernen.

1. Zu der 256-er for Schleife: Natürlich hast du Recht. Das ist 
schwachsinn. Der Grund dafür ist ein copy-paste Fehler.

2. Zur if( NULL == .... ) Abfrage: Ich habs nun so gelernt. Was spricht 
dagegen?

3. Mit Speicher alloc... usw. habe ich wenig gearbeitet. Da brauche ich 
noch etwas Übung. Was bedeutet bei euch Programmierern genau casten?
Ich soll den Returnwert von malloc nicht casten?  Also doch lieber so?

ErrorCode[i].sCode = malloc(20 * sizeof(int));

D.h. in C ist es unnötig. Also void und keinen Zeiger  char *..... 
stimmts?

4. Autor: Karl Heinz Buchegger
   > Du kannst das nicht so machen.
   > strtok liefert dir einen Pointer in den bestehenden String. Als 
einen
   > Pointer, der in einen Teil von sLine[i] zeigt.

Verstehe ich nicht ganz!? Bei mir funktioniert diese Variante.


Autor: Karl Heinz Buchegger
Autsch.
Du hast das quer durch die Bank gemacht.
Und dann auch noch in der Abfragefunktion (der unteren) ungeprüft in das
ErrorCode Array zugegriffen.

Also meinst du in dieser Abfragefunktion?

if (0xFF != ucReceiveBuffer[1] && 0xFF != ucReceiveBuffer[3])
{
   iFNR[i] = ucReceiveBuffer[1];
   iFST[i] = ucReceiveBuffer[3];
   SetTableCellVal(herrorcode_panel_gl, ERROR_CODE_Tab_ErrorCode,
MakePoint(1,i+1), ErrorCode[ucReceiveBuffer[1]].sCode);
   SetTableCellVal(herrorcode_panel_gl, ERROR_CODE_Tab_ErrorCode, 
MakePoint(2,i+1), sFNR);
   SetTableCellVal(herrorcode_panel_gl, ERROR_CODE_Tab_ErrorCode, 
MakePoint(3,i+1), sFST);
   SetTableCellVal(herrorcode_panel_gl, ERROR_CODE_Tab_ErrorCode, 
MakePoint(4,i+1), ErrorCode[ucReceiveBuffer[1]].sText);
                    iNumberOfErrors = i;
                }



5. > struct strErrorCode
   > {
   >     char *sCode;
   >     char *sIndexHex;
   >     char *sIndexDec;
   >     char *sText;
   > } ErrorCode[1024];

Autor: Karl Heinz Buchegger
Was ist hier eigentlich der Sinn der Sache, wenn du sowieso immer fix
dimensionierte Arrays an die Pointer hängst?

So habe ich das gelernt und konnte gut damit leben aber wenn du mir 
einen Hinweis geben könntest wie ich es einfacher machen soll, wäre ich 
dir dankbar. Kurzes Beispiel würde mir weiter helfen. Wie gesagt der 
Speicher macht mir viele Sorgen.



Gruß Jamie

von Karl H. (kbuchegg)


Lesenswert?

Jamie schrieb:
> Hallo Karl Heinz Buchegger,
>
> vielen Dank für deine Antworten. Kurz zur Info. Ich bin leider kein
> Profiprogrammierer sondern nur ein Elektrotechniker und ich will noch
> sehr viel dazulernen.

Tu dir einen Gefallen und besorg dir ein C-Buch.
Stringverarbeitung in C ist die erste Hürde für Neulinge. Und dann 
warten noch 100-erte weitere auf dich.

> 2. Zur if( NULL == .... ) Abfrage: Ich habs nun so gelernt. Was spricht
> dagegen?

Das du nicht so denkst.
Du sagst nicht:
wenn es wahr ist, dass Null gleich dem Ergebnis des Funktionsaufrufs 
ist.
Du sagst kurz und prägnat: Wenn das Ergebnis NULL ist.

   if( Ergebnis == NULL )

Ja, ich kenne die Argumente für deine SChreibweise. Und ich halte sie 
für nicht stichhaltig. Ich halte allerdings die Argumentation für 
stichhaltig, dass man durch die Schreibweise die 'Begreifbarkeit' eines 
Code steigern kann.
Der Fehler, gegen den deine Schreibweise schützen soll

   if( i = 5 )

macht jeder mal, das ist nicht das Thema. Aber diesen Fehler machst du 
am Anfang vielleich 3 oder 5 mal, wenns hoch kommt soll es meinetwegen 
10 mal sein. Aber danach machst du ihn nie wieder.

> 3. Mit Speicher alloc... usw. habe ich wenig gearbeitet.

Warum tust du es dann, zumal es in deinem Fall sowieso nichts bringt?

> Da brauche ich
> noch etwas Übung. Was bedeutet bei euch Programmierern genau casten?
> Ich soll den Returnwert von malloc nicht casten?  Also doch lieber so?
>
> ErrorCode[i].sCode = malloc(20 * sizeof(int));
>
> D.h. in C ist es unnötig. Also void und keinen Zeiger  char *.....
> stimmts?
>
> 4. Autor: Karl Heinz Buchegger
>    > Du kannst das nicht so machen.
>    > strtok liefert dir einen Pointer in den bestehenden String. Als
> einen
>    > Pointer, der in einen Teil von sLine[i] zeigt.
>
> Verstehe ich nicht ganz!? Bei mir funktioniert diese Variante.

Das sieht nur so aus.
In Wirklichkeit funktioniert sie eben nicht.
Auch wenn man manchmal in bereits freigegebenem Speicher noch eine 
zeitlang die Daten wiederfindet, irgendwann sind sie weg bzw. durch 
andere Daten überschrieben.


> MakePoint(1,i+1), ErrorCode[ucReceiveBuffer[1]].sCode);


Wer sagt dir, dass ucReceiveBuffer[1] einen gültigen Wert hat. Was ist 
wenn das File nicht gefunden werden konnte und es überhaupt keine 
ErrorCodes gibt?

> So habe ich das gelernt und konnte gut damit leben

Tu dir einen Gefallen und kauf dir ein C-Buch!
Ernsthaft.
Ganz ganz ehrlich.

Das hat doch keinen Sinn, wenn du nur 5% deiner Programmiersprache 
beherrscht.

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz Buchegger schrieb:

> Tu dir einen Gefallen und kauf dir ein C-Buch!

vergessen:
.... und arbeite es durch!

Das ist wichtig. In einem guten C-Buch sind neben Beispielen immer auch 
Übungen drinn!

von Karl H. (kbuchegg)


Lesenswert?

Auf einem PC hast du den Speicher, da brauchst du nicht sparen.
1
struct strErrorCode
2
{
3
    char  sCode[20];
4
    char  sIndexHex[5];
5
    char  sIndexDec[5];
6
    char  sText[256];
7
} ErrorCode[1024];
8
int nrErrorCodes = 0;
9
10
#define ERROR_FILE "ErrorCode.csv"
11
12
int ReadErrorFile( void )
13
{
14
  FILE* file;
15
  char  sLine[512];
16
  char* pPart;
17
18
  nrErrorCodes = 0;
19
  file = fopen(ERROR_FILE , "r");
20
            
21
  if (file == NULL) {
22
    MessagePopup("Error", "Konnte Datei \"" ERROR_FILE "\" nicht öffnen!");
23
    return 0;
24
  }
25
            
26
  while( fgets(sLine, sizeof(sLine), file) )
27
  {
28
    ErrorCodes[nrErrorCodes].sCode[0]     = '\0';
29
    ErrorCodes[nrErrorCodes].sIndexHex[0] = '\0';
30
    ErrorCodes[nrErrorCodes].sIndexDec[0] = '\0';
31
    ErrorCodes[nrErrorCodes].sText[0]     = '\0';
32
33
    if( (pPart = strtok( sLine, ";" )) )
34
      strcpy( ErrorCodes[nrErrorCodes].sCode, pPart );
35
36
    if( (pPart = strtok( NULL, ";" )) )
37
      strcpy( ErrorCodes[nrErrorCodes].sIndexHex, pPart );
38
39
    if( (pPart = strtok( NULL, ";" )) )
40
      strcpy( ErrorCodes[nrErrorCodes].sIndexDec, pPart );
41
42
    if( (pPart = strtok( NULL, ";" )) )
43
      strcpy( ErrorCodes[nrErrorCodes].sText, pPart );
44
45
    if( nrErrorCodes < sizeof(ErrorCode)/sizeof(*ErrorCode) - 2 )
46
      nrErrorCodes++;
47
  }
48
49
  if( !feof( file ) )
50
    MessagePopup("Error", "Fehler beim Lesen der Datei \"" ERROR_FILE "\"!");
51
52
  fclose(file);
53
54
  return 1;
55
}

Die Funktion ReadErrorFile rufst du beim Programmstart EINMAL auf. Es 
gibt keinen Grund, die Fehlermeldungen wieder und immer wieder 
einzulesen. Einmal reicht völlig aus.
1
int CVICALLBACK Btn_Read_ErrorCode  (int panel, int control, int event,
2
void *callbackData, int eventData1, int eventData2)
3
{
4
  int   i;
5
  int             iResult                 = 0;
6
  int             iSTADR                  = 0x400;
7
  char            sFNR[32];
8
  char            sFST[32];
9
  unsigned char   sTransmit[512]          = {""};
10
  unsigned char   ucReceiveBuffer[8]      = {0};                                                       
11
 
12
  switch (event)
13
  {
14
    case EVENT_COMMIT:
15
16
      iNumberOfErrors  = 0;
17
    
18
      for (i = 0; (i < 25) && (ucReceiveBuffer[1] != 0xFF); i++)
19
      {
20
        sprintf(sTransmit, "D9 03 %02X %02X 00 00 00 00", (iSTADR>>8) & 0xFF, iSTADR & 0xFF);
21
            
22
        //Befehl senden und Antwort empfangen:
23
        iResult = CANReqRespBuff(sTransmit, ucReceiveBuffer);
24
        if ( iResult != 1 )
25
          return 0;
26
                
27
        sprintf(sFNR, "%3d [0x%02X]", ucReceiveBuffer[1], ucReceiveBuffer[1]);
28
29
        sprintf(sFST, "%3d [0x%02X]", ucReceiveBuffer[3], ucReceiveBuffer[3]);
30
                    
31
        if (0xFF != ucReceiveBuffer[1] && 0xFF != ucReceiveBuffer[3])
32
        {
33
          iFNR[i] = ucReceiveBuffer[1];       
34
          iFST[i] = ucReceiveBuffer[3];
35
  
36
          if( ucReceiveBuffer[1] < nrErrorCodes )
37
            SetTableCellVal(herrorcode_panel_gl, ERROR_CODE_Tab_ErrorCode, MakePoint(1,i+1), ErrorCode[ucReceiveBuffer[1]].sCode);
38
          else
39
            SetTableCellVal(herrorcode_panel_gl, ERROR_CODE_Tab_ErrorCode, MakePoint(1,i+1), "unkown");
40
41
          SetTableCellVal(herrorcode_panel_gl, ERROR_CODE_Tab_ErrorCode, MakePoint(2,i+1), sFNR);
42
43
          SetTableCellVal(herrorcode_panel_gl, ERROR_CODE_Tab_ErrorCode, MakePoint(3,i+1), sFST);
44
45
          if( ucReceiveBuffer[1] < nrErrorCodes )
46
            SetTableCellVal(herrorcode_panel_gl, ERROR_CODE_Tab_ErrorCode, MakePoint(4,i+1), ErrorCode[ucReceiveBuffer[1]].sText);
47
          else
48
            SetTableCellVal(herrorcode_panel_gl, ERROR_CODE_Tab_ErrorCode, MakePoint(4,i+1), "unknown Error Code");
49
50
51
          iNumberOfErrors = i;
52
        }
53
                
54
        
55
        iSTADR += 0x10;
56
      }
57
            
58
      break;                                                  
59
    }
60
61
    return 0;
62
}
63
64
65
int CVICALLBACK Btn_Save_ErrorCode (int panel, int control, int event,                                       
66
        void *callbackData, int eventData1, int eventData2)
67
{
68
  FILE* file;
69
  int   i = 0;
70
     
71
  switch (event)
72
  {
73
    case EVENT_COMMIT:
74
            
75
      if (FileSelectPopup ("C:\\", "Fehlerspeicher.txt", "*.txt", "Save file as...", VAL_SAVE_BUTTON, 0, 1, 1, 1, sFileName) < 0)
76
        break;
77
78
      if ((file = fopen(sFileName, "w")) == NULL)
79
      {
80
        MessagePopup( "Fehler", "Fehler: konnte die Datei nicht öffnen" );
81
        return 0;
82
      }
83
84
            
85
      fprintf(file,"Nr | Fehlercode | FST | FNR | Text\n");
86
      fprintf(file,"   |            |     |     |\n");
87
      
88
      for (i = 0; i < iNumberOfErrors; i++)
89
      {
90
        if( iFNR[i] < nrErrorCodes )
91
          fprintf(file,"%2d | %10s | %3d | %3d | %s\n", 
92
                        i,
93
                        ErrorCode[iFNR[i]].sCode,
94
                        iFST[i],
95
                        iFNR[i],
96
                        ErrorCode[iFNR[i]].sText);
97
        else
98
          fprintf(file,"%2d | %10s | %3d | %3d | %s\n", 
99
                        i,
100
                        "##########",
101
                        iFST[i],
102
                        iFNR[i],
103
                        "unknown Error Code");
104
      }
105
106
      fclose(file);
107
      break;   
108
    }      
109
110
    return 0;        
111
}

von Karl H. (kbuchegg)


Lesenswert?

Und bevor du dann weitermachst, setzt du dir erst mal einen Breakpoint 
in die Funktion ReadErrorFile und siehst dir an, ob die Fehlercodes 
einwandfrei gelesen werden.

von Jamie (Gast)


Lesenswert?

Funktioniert prima. Allerdings kann ich es leider nicht ganz testen weil 
mein Steuergerät nicht richtig funktioniert. Etwas stimmt mit dem 
Fehlerspeicher nicht.

Die Fehlercodes werden einwandfrei gelesen. So wie ich es wollte danke.

Eine Frage noch. Diese Zeile ist doch sinnlos oder?

if( nrErrorCodes < sizeof(ErrorCode)/sizeof(*ErrorCode) - 2 )


Und warum benutzt du strcpy bei diesen Zeilen? Mann kann könnte das doch 
kürzer machen oder was ist der Zweck? Lesbarkeit, sicherere Ausführung?

   if( (pPart = strtok( sLine, ";" )) )
      strcpy( ErrorCodes[nrErrorCodes].sCode, pPart );

    if( (pPart = strtok( NULL, ";" )) )
      strcpy( ErrorCodes[nrErrorCodes].sIndexHex, pPart );

    if( (pPart = strtok( NULL, ";" )) )
      strcpy( ErrorCodes[nrErrorCodes].sIndexDec, pPart );

    if( (pPart = strtok( NULL, ";" )) )
      strcpy( ErrorCodes[nrErrorCodes].sText, pPart );

    if( nrErrorCodes < sizeof(ErrorCode)/sizeof(*ErrorCode) - 2 )
      nrErrorCodes++;

von Karl H. (kbuchegg)


Lesenswert?

Jamie schrieb:

> Eine Frage noch. Diese Zeile ist doch sinnlos oder?
>
> if( nrErrorCodes < sizeof(ErrorCode)/sizeof(*ErrorCode) - 2 )

Was ist an einem Fehlerabfangen sinnlos?

> Und warum benutzt du strcpy bei diesen Zeilen? Mann kann könnte das doch
> kürzer machen oder was ist der Zweck?

Ehrlich.
Kauf dir ein C-Buch

von Jamie (Gast)


Lesenswert?

Wenn das ein Fehlerabfang ist, wo ist denn da die Abbruchbedingung?

if.... und dan wird  nrErrorCodes inkrementiert.

Das sind vielleicht blöde Fragen für dich aber diese Frage hat sich auch 
mein Betreuer gestellt, der gut programmieren kann.

Ich brauche keine Bücher. Google und learning bei doing reicht.

von Jamie (Gast)


Lesenswert?

by doing

von Jamie (Gast)


Lesenswert?

mit

if( (ErrorCodes[nrErrorCodes].sCode = strtok( sLine, ";" )) )

habe ich den gleichen Effekt und paar Zeilen gespart.

von heinz (Gast)


Lesenswert?

Jamie schrieb:
> Wenn das ein Fehlerabfang ist, wo ist denn da die Abbruchbedingung?
>
> if.... und dan wird  nrErrorCodes inkrementiert.

Ja genau, und damit das beschreiben des Arrays über seine Grenzen hinaus 
abgefange...


> Das sind vielleicht blöde Fragen für dich aber diese Frage hat sich auch
> mein Betreuer gestellt, der gut programmieren kann.
>
> Ich brauche keine Bücher.

Doch ich denke schon. Und dein Betreuer wohl auch...

von heinz (Gast)


Lesenswert?

Jamie schrieb:
> if( (ErrorCodes[nrErrorCodes].sCode = strtok( sLine, ";" )) )
>
> habe ich den gleichen Effekt und paar Zeilen gespart.

Nein, hast du nicht:

char *strtok( char *string1, const char *string2 );

strtok zerlegt einen String in Token.
string1 ist der zu zerlegende String, string2 enthält die Trennzeichen, 
anhand derer der String zerlegt wird.

strtok betrachtet den durch string1 angegebenen String als Folge von 
Token, die durch ein oder mehrere in string2 definierte Zeichen 
voneinander getrennt sind.

Der erste Aufruf von strtok überspringt führende Trennzeichen, liefert 
einen Zeiger auf den Anfang des ersten gefundenen Token in string1 
zurück und setzt ein NULL-Zeichen unmittelbar hinter das Token-Ende. 
Folgende Aufrufe von strtok mit dem Wert NULL anstelle des Arguments 
string1 liefern Zeiger auf weitere Token. Wenn kein weiteres Token 
gefunden wird, liefert strtok den Wert NULL. Der String wurde dann 
vollständig analysiert.

string1 wird während der Analyse durch das Einfügen von NULL-Zeichen 
verändert.
string2 kann bei jedem Aufruf von strtok gewechselt werden.

Rückgabewert:
Die Funktion liefert bei ihrem ersten Aufruf einen Zeiger auf das erste 
Token in string1.
Enthält der String keines der gesuchten Trennzeichen, bleibt er 
unverändert.

von Jamie (Gast)


Lesenswert?

Ganz ehrlich, ich kann doch nicht so dumm sein.

    if( nrErrorCodes < sizeof(ErrorCode)/sizeof(*ErrorCode) - 2 )
      nrErrorCodes++;

Wenn ich if auskommentiere

   // if( nrErrorCodes < sizeof(ErrorCode)/sizeof(*ErrorCode) - 2 )
      nrErrorCodes++;

was ist dann anders?

D.h doch: wenn 292864 kleiner (1024 geteilt durch 286) - 2

oder heißt das

          wenn 292864 kleiner 1024 dann teile durch 286 - 2?

kann doch nicht wahr sein

von Karl H. (kbuchegg)


Lesenswert?

Jamie schrieb:
> Ganz ehrlich, ich kann doch nicht so dumm sein.
>
>     if( nrErrorCodes < sizeof(ErrorCode)/sizeof(*ErrorCode) - 2 )
>       nrErrorCodes++;
>
> Wenn ich if auskommentiere
>
>    // if( nrErrorCodes < sizeof(ErrorCode)/sizeof(*ErrorCode) - 2 )
>       nrErrorCodes++;
>
> was ist dann anders?

Wenn mehr Zeilen im File sind, als dein Array groß dimensioniert wurde, 
dann passiert
A) in meinem Code nichts
b) in deinem Code: du bügelst dir Speicher der dir nicht gehört über
   den Haufen. WEnn du Glück hast, dann stürzt dein Programm einfach ab.
   Wenn du Pech hast, dann stösst du auf und beschreibst dabei
   unabsichtlich irgendwelche Portregister, welche die Herz-Lungen
   Maschine des Patienten in Zimmer 405 abstellen.


Und PS: Es soll schon vorgekommen sein, dass man mal unabsichtlich einem 
Programm das falsche File vorgeworfen hat.

von heinz (Gast)


Lesenswert?

Jamie schrieb:
> if( nrErrorCodes < sizeof(ErrorCode)/sizeof(*ErrorCode) - 2 )

Nochmal LANGSAM:

sizeof(ErrorCode) liefert die Größe des gesammten Arrays.
sizeof(*ErrorCode) liefert die Größte des des ersten Array-Elements.

also steht da 29284/286 = 1024.

Das ist die Größe des Array (ErrorCode[1024]).
Da du bei einem Array aber mit ErrorCode[0] anfängst und nicht über
das letzte Element herausgeschrieben willst, ziehst du noch zwei ab.

alles klar?

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Jamie schrieb:
> if( (ErrorCodes[nrErrorCodes].sCode = strtok( sLine, ";" )) )
>
> habe ich den gleichen Effekt und paar Zeilen gespart.

Nicht in C.
Kauf' Dir ein Lehrbuch und arbeite es durch.

Ich hatte bis vor kurzem auch einen Mitarbeiter, der entsprechend 
uneinsichtig war, indem er meinte, mangelndes Verständnis durch 
Copy&Paste ausgleichen zu können. Das hat ihn leider seinen Job 
gekostet...

von Karl H. (kbuchegg)


Lesenswert?

Jamie schrieb:
> Wenn das ein Fehlerabfang ist, wo ist denn da die Abbruchbedingung?
>
> if.... und dan wird  nrErrorCodes inkrementiert.
>
> Das sind vielleicht blöde Fragen für dich aber diese Frage hat sich auch
> mein Betreuer gestellt, der gut programmieren kann.

Ich denke eigentlich, dass das sogar nicht mal besonders schwer zu 
durchschauen ist, weil es in der generellen Philosophie des
"wenn du ein Array der Größe n dimensionierst, dann stelle sicher, dass 
du nie mit n bzw. etwas größerem als n in das Array indizierst"
verläuft.
Eigentlich eine Standardaktion für jeden, der sich seine ersten Sporen 
in der Array Programmierung in C verdient hat: Stell sicher, dass du 
nicht ausserhalb des definierten Arrays zugreifst.

Vielleicht sollte dein Betreuer sich selbst erst mal einen Betreuer 
suchen? Sonderlich gut scheint es nicht um seine Kentnisse bestellt zu 
sein, wenn er in 10 Minuten nicht rausfindet, was es damit auf sich hat.
Klingt jetzt vielleicht etwas hart, aber die Wahrheit ist oft hart.


Und ja. Man könnte das auch anders machen. Ich hab mich halt dafür 
entschieden, den Index nicht mehr zu erhöhen, wenn das Array bereits 
angefüllt ist. Ist sicherlich nicht die eleganteste Lösung aber sie 
erfüllt zumindest erst mal ihren Zweck. Denn nrErrorCodes benötige ich, 
um in den Abfragefunktionen feststellen zu können, ob es für den 
angegebenen Index auch eine entsprechende Fehlermeldung gibt.
Aber: es ist dein Programm. Wenn du diesen Fehlerfall anders abfangen 
willt und zb eine entsprechende Fehlermeldung ausgeben willst, steht es 
dir natürlich frei das zu tun. Es ist dein Projekt - du bist der 
Programmierer und nicht ich.

von Jamie (Gast)


Lesenswert?

A) Also vergessen wir meinen komischen Quellcode. Meine letzten 
Kommentare  waren auf deinen Quellcode bezogen.

B) Vor lauter Verwirrung wünsche ich mir im Zimmer 405 zu liegen.


Ich denke meine ganze Abteilung muß neu programmieren lernen. Von denen 
habe ich das mit NULL== ... usw. z.b.

Sorry aber mein Compiler sagt mir 1024/286. Das mit der - 2 ist schon 
klar. usw. alles wunderbar nur ich sehe da nicht viel Sinn.

von Jamie (Gast)


Lesenswert?

Ok das wollte ich hören. War etwas verwirrt sorry

von Jean Player (Gast)


Lesenswert?

Hi,
ich würde noch das ergänzen.
1
if( (pPart = strtok( sLine, ";" )) )
2
{
3
   if(strlen(pPart) < (sizeof(ErrorCodes[nrErrorCodes].sCode) /sizeof(ErrorCodes[nrErrorCodes].sCode[0]))
4
   {
5
      strcpy( ErrorCodes[nrErrorCodes].sCode, pPart );
6
   }
7
}

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Jamie schrieb:
> Ich denke meine ganze Abteilung muß neu programmieren lernen. Von denen
> habe ich das mit NULL== ... usw. z.b.

Typischer Fall von "Das haben wir schon immer so gemacht":
http://www.kadett-forum.de/archive/51922/thread.html
letzlich ist das aber nur eine konvention, das mit dem "programmieren 
lernen" bezog sich wohl eher darauf, dass dein Betreuer offensichtlich 
nicht in der Lage ist einfachste Standard C Konstrukte zu verstehen 
"obwohl er gut programmieren kann".

Jamie schrieb:
> habe ich den gleichen Effekt und paar Zeilen gespart

Für gesparte Zeilen gibt es kein Geld zurück, gerade am Anfang sollte 
man sich tunlichst zurückhalten möglichst viel "in eine Zeile" zu 
bringen, lieber Kleinschrittig und dann verstehen! Und daran hapert es 
bei dir, wenn du bei so einer Zeile

> if( nrErrorCodes < sizeof(ErrorCode)/sizeof(*ErrorCode) - 2 )
dir unsicher bist
a) was da passiert
b) in welcher Reihenfolge die Operatoren ausgewertet werden

von Karl H. (kbuchegg)


Lesenswert?

Jean Player schrieb:
> Hi,
> ich würde noch das ergänzen.
>
>
1
> if( (pPart = strtok( sLine, ";" )) )
2
> {
3
>    if(strlen(pPart) < (sizeof(ErrorCodes[nrErrorCodes].sCode)
4
> /sizeof(ErrorCodes[nrErrorCodes].sCode[0]))
5
>    {
6
>       strcpy( ErrorCodes[nrErrorCodes].sCode, pPart );
7
>    }
8
> }
9
>

Ist eine Möglichkeit, ja
Man könnte es auch so machen
1
  if( (pPart = strtok( sLine, ";" )) )
2
  {
3
    strncpy( ErrorCodes[nrErrorCodes].sCode, pPart, sizeof(ErrorCodes[0].sCode) );
4
    ErrorCodes[nrErrorCodes].sCode[ sizeof(ErrorCodes[0].sCode)-1 ] = '\0';
5
  }

viele Wege führen nach Rom.
Es gäbe auch Lösungen, die komplett ohne strcpy auskommen. Nur darf es 
dann da keinerlei Unsicherheiten bezüglich Strings/Arrays/Pointer geben. 
Etwas was ich beim TO noch nicht sehe.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.