Forum: PC-Programmierung [C++] Array verliert Werte


von Maxim (maxim) Benutzerseite


Lesenswert?

Ich habe ein Array von void-Zeigern, genannt quantities. Ein Zeiger aus 
diesem Array zeigt auf ein int-Array. Dieses wird in der Methode void 
readConfigFile(string configFile) möchte ich mit der Mehtode int 
get(quantity::ofTypeInt q, size_t index); die Werte aus diesem int-Array 
auslesen.

Wenn ich das erste Element im int-Array mit
1
((int*)quantities[L])[0] = 7;
belege und es gleich in der nächsten Zeile auslese, funktioniert es ohne 
Probleme. Greife ich aber auf diesen Zeiger später außerhalb der Methode 
void readConfigFile(string configFile) zu (z.B. per get(L, 0)), bekomme 
ich keine 7 sondern irgend einen Müll. Woran kann das liegen?


inout.h
1
#ifndef INOUT_H
2
#define INOUT_H
3
#include "common.h"
4
#include <iterator>
5
6
using std::cout;
7
using std::cin;
8
using std::endl;
9
using std::flush;
10
using std::string;
11
using std::ifstream;
12
using std::ofstream;
13
using std::istringstream;
14
using std::istream_iterator;
15
16
namespace quantity {
17
  enum ofTypeInt {
18
    L,
19
    T,
20
    NLSteps,
21
    NTSteps,
22
    deltaStep,
23
    ofTypeIntCount = 5
24
  };
25
  
26
  enum ofTypeFp {
27
    dt,
28
    tEql,
29
    tAvg,
30
    ofTypeFpCount = 3
31
  };
32
  
33
  enum common {
34
    length = -1
35
  };
36
}
37
38
class InputOutput {
39
public:
40
  InputOutput();
41
  ~InputOutput();
42
43
  int get(quantity::ofTypeInt q);
44
  int get(quantity::ofTypeInt q, size_t index);
45
  fp_type get(quantity::ofTypeFp q);
46
  fp_type get(quantity::ofTypeFp q, size_t index);
47
  
48
   void readConfigFile(string configFile);
49
  
50
private:
51
  void *quantities[quantity::ofTypeIntCount + quantity::ofTypeFpCount];
52
};
53
54
#endif // INOUT_H


inout.cpp
1
#include "inout.h"
2
#include <boost/lexical_cast.hpp>
3
4
using std::vector;
5
using std::back_inserter;
6
7
using namespace quantity;
8
9
InputOutput::InputOutput() {
10
}
11
12
InputOutput::~InputOutput() {
13
14
}
15
16
void InputOutput::readConfigFile(string configFile) {
17
  string tmpStr;
18
  ifstream inputStream;
19
  
20
  if(configFile != "") {
21
    cout << "Loading configuration file " << configFile << endl;
22
    inputStream.open(configFile.c_str());
23
    do {
24
      getline(inputStream, tmpStr);
25
      cout << "line: " << tmpStr << endl;
26
      istringstream inputStringStream(tmpStr);
27
      vector<string> tokens;
28
      copy(istream_iterator<string>(inputStringStream), istream_iterator<string>(), back_inserter<vector<string>>(tokens));
29
      if(tokens.size() > 0) {
30
        if(tokens.at(0) == "L:") {
31
          quantities[NLSteps] = new int;
32
          *(int*)quantities[NLSteps] = tokens.size() - 1;
33
          
34
          quantities[L] = new int[*(int*)quantities[NLSteps]];
35
          
36
          ((int*)quantities[L])[0] = 7;
37
          cout << "test " <<  ((int*)quantities[L])[0] << endl;
38
      }
39
    } while(tmpStr != "");
40
    inputStream.close();
41
  }
42
  
43
}
44
45
46
47
int InputOutput::get(quantity::ofTypeInt q, size_t index) {
48
  switch(q) {
49
    case L: return ((int*)quantities[L])[index]; break;
50
    default: return 0;
51
  }
52
}

von Udo S. (urschmitt)


Lesenswert?

Maxim S. schrieb:
> Greife ich aber auf diesen Zeiger später außerhalb der Methode
> void readConfigFile(string configFile) zu (z.B. per get(L, 0)), bekomme
> ich keine 7 sondern irgend einen Müll. Woran kann das liegen?

Sind denn die Variablen auf die die Zeiger zeigen ausserhalb der Methode 
überhaupt noch gültig? Oder waren das in der Methode lokal angelegte 
Variablen?

>Array verliert Werte
Köstlicher Titel :-) Dann musst du es abdichten.

von nicht "Gast" (Gast)


Lesenswert?

Hallo,

zur Lösung kann ich nur ein beitragen.

Schmeiß dein void array weg. Das ist C und du willst so was nicht in C++ 
machen. (Da es unhöflich ist zu schreien, stell dir einfach alles in 
Großbuchstaben vor :)

Mit Void Zeigern arbeitet man in C++ nicht. in C++ will und kann man 
streng typisiert arbeiten. Das versuchst du zu umgehen.

Wenn du noch nicht weißt, was du in deinem Array speichern willst, 
benutz Templates oder in deinem Fall gleich einen std::vector

Grüße,

von Maxim (maxim) Benutzerseite


Lesenswert?

Udo Schmitt schrieb:
> Sind denn die Variablen auf die die Zeiger zeigen ausserhalb der Methode
> überhaupt noch gültig? Oder waren das in der Methode lokal angelegte
> Variablen?

void *quantities[N] ist im Header deklariert. Das int-Array wird in 
readConfigFile() mit new definiert, muss also nach meinem Wissen auch 
außerhalb der Methode verfügbar sein.

von Karl H. (kbuchegg)


Lesenswert?

nicht "Gast" schrieb:

> Wenn du noch nicht weißt, was du in deinem Array speichern willst,
> benutz Templates oder in deinem Fall gleich einen std::vector

Zumal in diesem Beispiel wirklich nicht ersichtlich ist, wozu dieses 
void* Array tatsächlich gut sein soll, ausser das man sich durch 
ständige Casts selber ins Knie schiesst.

von Karl H. (kbuchegg)


Lesenswert?

Maxim S. schrieb:
> Udo Schmitt schrieb:
>> Sind denn die Variablen auf die die Zeiger zeigen ausserhalb der Methode
>> überhaupt noch gültig? Oder waren das in der Methode lokal angelegte
>> Variablen?
>
> void *quantities[N] ist im Header deklariert. Das int-Array wird in
> readConfigFile() mit new definiert, muss also nach meinem Wissen auch
> außerhalb der Methode verfügbar sein.

Im Prinzip ja.
Solange du nur ein einziges derartiges InputOutput  Objekt hast.

Wir sind wieder dort, wo wir schon so oft waren: Mit den gegegenen 
INformationen kann man nicht entscheiden wo das konkret vorleigende 
Problem tatsächlich liegt. Man kann allerdings, abseits vom konkreten 
Problem schon sagen, dass der ganze Aufbau der Klasse zumindest 
zwielichtig ist. Das löst zwar das Problem nicht und eröffnet eine 
weitere Baustelle. Allerdings eine, die man auch fixen sollte - selbst 
wenn sie mit dem momentanen Problem erst mal wahrscheinlich nichts zu 
tun hat.

: Bearbeitet durch User
von Maxim (maxim) Benutzerseite


Lesenswert?

Ok, das war Quatsch. Ich bin auf Templates umgestiegen. Trotzdem würde 
mich die Fehlerquelle interessieren, da der Code so schon funktionieren 
sollte ...

von Karl H. (kbuchegg)


Lesenswert?

Maxim S. schrieb:
> Ok, das war Quatsch. Ich bin auf Templates umgestiegen. Trotzdem würde
> mich die Fehlerquelle interessieren

bau Testcode ein.

Ausgaben in:
* Konstruktor
* Destruktor

In der Abfrage-Funktion testen auf 0-Pointer

Copy Constructor und Assignment Operator durch setzen in die 
private-Sektion der Klasse und nicht implementieren unbrauchbar machen. 
Das sollte man generell immer machen, wenn man sich selber an 
dynamischer Resource-Verwaltung versucht und noch nicht weiß wie man die 
beiden implementieren soll bzw. die nicht implementieren will. Ein 
Referenz-& in einer Funktions-Argument Liste ist schnell vergessen und 
dann wird eine Kopie der Pointer mit katastophalen Konsequenzen gemacht.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Ich seh nicht, inwiefern da jetzt Templates einen Vorteil gegenüber
einem simplen
1
...
2
3
  private:
4
    std::vector<int> L_Steps;
5
    std::vector<int> N_Steps;
6
    int              Delta_Step;
7
8
    double dt;
9
    double tEql;
10
    double tAvg;
11
};
bringt.

von Josef (Gast)


Lesenswert?

Hier

          quantities[NLSteps] = new int;
          *(int*)quantities[NLSteps] = tokens.size() - 1;

          quantities[L] = new int[*(int*)quantities[NLSteps]];

wird doch ein Element zu wenig angelegt, oder?
(Also bei tokens.size()==1 gibt das new int[0]).

Der Code ist schrecklich. Ich wuerde auch empfehlen in umzuschreiben,
oder eine Menge Kommentare dazu zu machen.

Gruss

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.