Dynamischem Array Werte über Zwischenvariable zuweisen
-
Du musst für jeden messwert auch ein objekt besorgen.
Warum
strcat
(Zeile 40)? Was steht denn vorher da drin?Die Schleifenbedinging (feof(file)==0) ist falsch.
Zu dem Zeitpunkt kann die noch nicht funktionieren.
Nimm dasfscanf
in die Schleifenbedingung und vergleiche auf die Anzahl gelesener Werte.while (fscanf(file, "%d%c%[^,]%c%d%c%lf\n", &tempobjektnr, &c, &tempbezeichnung, &c, &tempmessnr, &c, &tempmesswert) == 7) {
tempbezeichnung ist ein Array, da komt kein & hin. Mit dem * Modifiere brauchst du das c auch nicht.
Mit ein paar Leerzeichen im Formatstring, werden auch Whitespaße überlesen.while (fscanf(file, "%d %*c %19[^,] %*c%d %*c%lf\n", &tempobjektnr, tempbezeichnung, &tempmessnr, &tempmesswert) == 4) {
Die free am Ende fehlen. Für jedes objekt und für dynfeld
Was soll das fseek(file, 50L, SEEK_SET); ?
Wenn du die erste Zeile überlesen willst, dann nimmfgets
oderfscanf(file, "%*[^\n]");
(das braucht keinen Speicher zum einlesen).
Oder schau da: http://www.c-plusplus.net/forum/p1146014#1146014Und das ^ (Zeile 48) macht nicht das mas du möchtest. Das ist der Exclusiv-Oder Operator.
Verdoppelung der Speicherbedarfs ist keine schlecht Idee.
Am Ende kannst du noch ein realloc mit der richtigen Größe machen.
-
Hmm.
Ich würde Dir vorschlagen, eine Funktion für das erstellen und zerstören von struct messwert einzuführen und auch das einlesen in eine Funktion auszulagern.
Das ist mein ernst.
Evtl. passieren dann auch nicht solche Knaller, dass Du ein ein Array von messwerten allozierst und nur für den ersten in der Reihe das Memberobjekt
zuweist.
(Du dereferenzierst den NULL pointer in Zeile 39, sobald0<zaehler
).Z.B. koennte das so aussehen:[code0"c"]// alloziert n messwerte
// gibt einen pointer auf das den ersten der Werte zurück
// NULL im Fehlerfall.
messwert* alloc_messwerte(size_t n);// gibt ein Array von Messwerten, das mit alloc_messwerte() alloziert wurde
// wieder frei
void free_messwerte(messwert* p);[/code]Versuch Dich mal dran.
-
DirkB schrieb:
Du musst für jeden messwert auch ein objekt besorgen.
Warum
strcat
(Zeile 40)? Was steht denn vorher da drin?Die Schleifenbedinging (feof(file)==0) ist falsch.
Zu dem Zeitpunkt kann die noch nicht funktionieren.
Nimm dasfscanf
in die Schleifenbedingung und vergleiche auf die Anzahl gelesener Werte.while (fscanf(file, "%d%c%[^,]%c%d%c%lf\n", &tempobjektnr, &c, &tempbezeichnung, &c, &tempmessnr, &c, &tempmesswert) == 7) {
tempbezeichnung ist ein Array, da komt kein & hin. Mit dem * Modifiere brauchst du das c auch nicht.
Mit ein paar Leerzeichen im Formatstring, werden auch Whitespaße überlesen.while (fscanf(file, "%d %*c %19[^,] %*c%d %*c%lf\n", &tempobjektnr, tempbezeichnung, &tempmessnr, &tempmesswert) == 4) {
In
strcat
steht vorher nichts drinn. Da soll ja tempbezeichnung drinn gespeichert werden.Aber mir deiner Schleifenbedingung überprüfe ich doch nur, ob auch alle Werte eingelesen und in "temp..." gespeichert werden. Hört diese denn auch am Ende der Datei auf?
Und wofür steht die 19 bei
while (fscanf(file, "%d %*c %19[^,] %*c%d %*c%lf\n", &tempobjektnr, tempbezeichnung, &tempmessnr, &tempmesswert) == 4) {
Und wieso soll
while (feof(file)==0) {
nicht funktionieren? Wenn ich die Werte aus der Datei in den Zwischenvariablen speicher und ausgeben bekomme ich alle bis zum Ende. Ich denke mal danach springt er dann aus der Schleife raus
-
mezzix schrieb:
In
strcat
steht vorher nichts drinn. Da soll ja tempbezeichnung drinn gespeichert werden.Wie kommst du darauf?
Abgesehen davon, das z.Zt. dieser Speicher noch nicht einmal für dich reserviert ist, kannst du nicht davon ausgehen, das da nichts drin steht. (nur globale und static Variablen werden automatisch initialisiert)
Sonst steht das drin, was vorher mal an der Stelle gespeichert wurde.mezzix schrieb:
Aber mir deiner Schleifenbedingung überprüfe ich doch nur, ob auch alle Werte eingelesen und in "temp..." gespeichert werden.
Genau. Wenn du nicht alle Werte lesen konntest, hast du ein Problem und solltest abbrechen.
mezzix schrieb:
Hört diese denn auch am Ende der Datei auf?
Was soll sie denn sonst machen?
mezzix schrieb:
Und wofür steht die 19 bei
while (fscanf(file, "%d %*c %19[^,] %*c%d %*c%lf\n", &tempobjektnr, tempbezeichnung, &tempmessnr, &tempmesswert) == 4) {
Woher weißt du denn, was %[ oder %d machen? -> http://www.cplusplus.com/reference/cstdio/fscanf/
Das gibt die maximal Anzahl der einzulesenden Zeichen an.mezzix schrieb:
Und wieso soll
while (feof(file)==0) {
nicht funktionieren? Wenn ich die Werte aus der Datei in den Zwischenvariablen speicher und ausgeben bekomme ich alle bis zum Ende. Ich denke mal danach springt er dann aus der Schleife raus
Wenn dein Code mit der letzten Zeile fertig ist, dann steht da zumindest noch das '\n' im Eingabestrom. Also gibt feof() 0 zurück und deine Schleife läuft weiter.
Dasfscanf
will dann lesen und findet keine Daten mehr, und schreibt auch keine neuen Daten in die Variablen.
Also wird die letzte Zeile zweimal in deiner Struktur abgelegt.
-
DirkB schrieb:
mezzix schrieb:
Und wieso soll
while (feof(file)==0) {
nicht funktionieren? Wenn ich die Werte aus der Datei in den Zwischenvariablen speicher und ausgeben bekomme ich alle bis zum Ende. Ich denke mal danach springt er dann aus der Schleife raus
Wenn dein Code mit der letzten Zeile fertig ist, dann steht da zumindest noch das '\n' im Eingabestrom. Also gibt feof() 0 zurück und deine Schleife läuft weiter.
Dasfscanf
will dann lesen und findet keine Daten mehr, und schreibt auch keine neuen Daten in die Variablen.
Also wird die letzte Zeile zweimal in deiner Struktur abgelegt.Dann müsste mir doch auch in der Konsole aber auch zwei mal die letzte Zeile ausgegeben werden. Und das passiert nicht.
Wenn ich jedochwhile (fscanf(file, "%*d %*c %19[^,] %*c%d %*c%lf\n", &tempobjektnr, &c, tempbezeichnung, &c, &tempmessnr, &c, &tempmesswert )== 4) {
benutze werden nicht alle Werte eingelesen.
-
mezzix schrieb:
Wenn ich jedoch
while (fscanf(file, "%*d %*c %19[^,] %*c%d %*c%lf\n", &tempobjektnr, &c, tempbezeichnung, &c, &tempmessnr, &c, &tempmesswert )== 4) {
benutze werden nicht alle Werte eingelesen.
Dann schau doch mal genau hin, wieviel &c ich in der Zeile mit dem == 4 habe.
-
Hat die letzte Zeile in der Datendatei auch ein '\n' am Ende?
-
mezzix schrieb:
ich habe momentan das Problem, dass ich einem dynamischem Array Werte über Zwischenvariablen zuweisen möchte. Diese Zwischenvariablen enthalten Daten aus einer .txt. Leider stürzt das Programm beim ausführen immer ab.
Das weist auf undefinierten Speicherzugriff hin.
Wenn du unsicher bei malloc & Co. bist, dann nimm erstmal ein statisches Array,
dynamisieren kannst du später immer noch.
Wenn das Zeilenformat nicht einheitlich für jede Zeile ist, ist fscanf unbrauchbar.
Hier bietet sich fgets/sscanf an, fgets liest erstmal jede Zeile ein, mit sscanf entscheidest du dann, welche Zeile gültig ist:typedef struct { int objektnr; char bezeichnung [20]; } messobjekt; typedef struct { messobjekt objekt; int messnr; double messwert; } messwert; int main () { /* struct-Array mit fester Größe; spart malloc/realloc */ messwert m[1000]; char zeile[1000]; int zaehler = 0; FILE * file; file = fopen("messungen.txt", "r"); if(!file) perror("messungen.txt"),exit(1); while(fgets(zeile,1000,file)) if( 4==sscanf(zeile,"%d,%19[^,],%d,%lf",&m[zaehler].objekt.objektnr, m[zaehler].objekt.bezeichnung, &m[zaehler].messnr, &m[zaehler].messwert)) ++zaehler; fclose(file); printf("\n%d Daten eingelesen\n",zaehler); while(zaehler--) printf("\n%d,%s,%d,%f",m[zaehler].objekt.objektnr, m[zaehler].objekt.bezeichnung, m[zaehler].messnr, m[zaehler].messwert); return 0; }
-
Oke, zur Übersichtlichkeit hier nochmal der aktuelle Code:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> typedef struct { int objektnr; char bezeichnung [20]; } messobjekt; typedef struct { messobjekt *objekt; int messnr; double messwert; } messwert; int main () { int size = 3; messwert *dynfeld; dynfeld = (messwert*)calloc(size, sizeof(messwert)); dynfeld->objekt = (messobjekt*)calloc(size, sizeof(messobjekt)); FILE * file; file = fopen("messungen.txt", "r"); int tempmessnr; double tempmesswert; int tempobjektnr; char tempbezeichnung [20]; int zaehler = 0; int wieoftdurchlaufen = 0; //fseek(file, 50L, SEEK_SET); fscanf(file, "%*[^\n]"); while (feof(file)==0) { //while (fscanf(file, "%d %*c %19[^,] %*c%d %*c%lf\n", &tempobjektnr, tempbezeichnung, &tempmessnr, &tempmesswert ) == 4) { fscanf(file, "%d %*c %19[^,] %*c%d %*c%lf\n", &tempobjektnr, tempbezeichnung, &tempmessnr, &tempmesswert); //fscanf(file, "%d %c %19[^,] %c%d %c%lf\n", &tempobjektnr, &c, tempbezeichnung, &c, &tempmessnr, &c, &tempmesswert); //fscanf(file, "%d%c%[^,]%c%d%c%lf\n", &tempobjektnr, &c, tempbezeichnung, &c, &tempmessnr, &c, &tempmesswert); //fscanf(file, "%d%c%[^,]%c%d%c%lf\n", &dynfeld[zaehler].objekt->objektnr, &c, &dynfeld[zaehler].objekt->bezeichnung, &c, &(dynfeld[zaehler].messnr), &c, &(dynfeld[zaehler].messwert)); printf("\nWerte: %d,%s,%d,%lf", tempobjektnr, tempbezeichnung, tempmessnr, tempmesswert); //*(dynfeld+zaehler)->objekt->objektnr = tempobjektnr; // dynfeld[zaehler].objekt->objektnr = tempobjektnr; // strcat(dynfeld[zaehler].objekt->bezeichnung, tempbezeichnung); // dynfeld[zaehler].messnr = tempmessnr; // dynfeld[zaehler].messwert = tempmesswert; //printf("\nWerte: %d,%s,%d,%lf", dynfeld[zaehler].objekt->objektnr, dynfeld[zaehler].objekt->bezeichnung, dynfeld[zaehler].messnr, dynfeld[zaehler].messwert); zaehler++; //Rechnung noch nicht richtig? evtl wieoftdurchlaufne-1 if (zaehler == 3*pow(2, wieoftdurchlaufen)) { //if (zaehler == 3*(2^(wieoftdurchlaufen)) ) { dynfeld = (messwert*)realloc(dynfeld, 2*zaehler*sizeof(messwert)); if (dynfeld == NULL) { printf("Speicher reservieren fehlgeschlagen!"); return 1; } wieoftdurchlaufen = 0; printf("\nSpeicher erfolgreich verdoppelt!"); wieoftdurchlaufen++; } //zaehler++; } // int zaehler2 = 0; // int feldLaenge = sizeof(dynfeld)/sizeof(messwert); // for (; zaehler2 < feldLaenge; zaehler++) { // printf("\n%d,%s,%d,%f", dynfeld[zaehler].objekt->objektnr, dynfeld[zaehler].objekt->bezeichnung, dynfeld[zaehler].messnr, dynfeld[zaehler].messwert); // } return 0; }
Wenn ich
while (fscanf(file, "%d %*c %19[^,] %*c%d %*c%lf\n", &tempobjektnr, tempbezeichnung, &tempmessnr, &tempmesswert ) == 4) {
benutze werden wirklich nicht alle Werte eingelesen, mit
while (feof(file)==0) {
allerdings schon und das auch ohne einen Wert doppelt zu haben. Habs ja ausprobiert indem ich mir in die Zwischenvariablen in der Schleife ausgeben lasse.
Das weist auf undefinierten Speicherzugriff hin.
Wenn du unsicher bei malloc & Co. bist, dann nimm erstmal ein statisches ArrayIch muss nur ein dynamisches Array benutzen.
-
Welche werte werden denn nicht eingelesen?
-
DirkB schrieb:
Welche werte werden denn nicht eingelesen?
Eingelesen werden:
1,tower,2,17.410 1,tower,4,18.342 1,tower,6,17.523 1,tower,7,17.683 3,building,1,101.334 3,building,2,107.128 3,building,3,99.987 3,building,3,105.821 2,bridge,3,247.521 2,bridge,4,248.731 2,bridge,5,249.008
Insgesamt gibt es:
objektnummer,objektbezeichnung,messnummer,messwert 1,tower,1,17.334 1,tower,2,17.410 1,tower,3,16.986 1,tower,4,18.342 1,tower,5,15.999 1,tower,6,17.523 2,bridge,1,249.121 1,tower,7,17.683 1,tower,8,18.001 3,building,1,101.334 1,tower,9,17.332 3,building,2,107.128 1,tower,10,18.019 3,building,3,99.987 3,building,3,110.320 3,building,3,105.821 2,bridge,2,251.988 2,bridge,3,247.521 1,tower,11,16.891 2,bridge,4,248.731 2,bridge,5,249.008
Also wird jeder zweite und der letzte Wert gespeichert.
-
Wenn du Zeile 35 aktivierst, musst du auch Zeile 36 auskommentieren.
Sonst liest du zwei Zeilen ein.
-
Oke das stimmt natürlich.
Nur hat jemand noch einen Tipp, wie ich die Werte in das Array speichere?
-
Fang erstmal einfach an.
typedef struct { int objektnr; char bezeichnung [20]; } messobjekt; typedef struct { messobjekt objekt; // mach hier das Objekt rein. Keinen Zeiger. int messnr; double messwert; } messwert;
Das mit dem Speicher verdoppeln solltest du dir nochmal überlegen.
Warum das 3*pow ?In size steht die Größe des Speichers.
In zaehler der aktuelle Bedarf.
Wann musst du den Speicher vergrößern?
Welchen Wert bekommt size danach?
-
In dem Struct soll aber ein Zeiger sein. Ich kann ja nicht einfach die Aufgabe ändern
Ebenso wie den Speicher verdoppeln.
Die if-Bedingung hab ich jetzt allerdings verändert.if (zaehler == size) { //if (zaehler == 3*pow(2, wieoftdurchlaufen)) { dynfeld = (messwert*)realloc(dynfeld, 2*zaehler*sizeof(messwert)); if (dynfeld == NULL) { printf("Speicher reservieren fehlgeschlagen!"); return 1; } size = 2*size; printf("\nSpeicher erfolgreich verdoppelt!"); }
War wohl vorher ein bisschen zu kompliziert gedachte. Danke schon mal
-
mezzix schrieb:
In dem Struct soll aber ein Zeiger sein. Ich kann ja nicht einfach die Aufgabe ändern
Dann musst du vor jedem Zugriff auf objekt auch dafür Speicher mit
malloc
besorgen.
-
DirkB schrieb:
mezzix schrieb:
In dem Struct soll aber ein Zeiger sein. Ich kann ja nicht einfach die Aufgabe ändern
Dann musst du vor jedem Zugriff auf objekt auch dafür Speicher mit
malloc
besorgen.Vielen Dank! Da lag der Fehler
-
Sorry, dass das nicht verständlicher war.
Aber das meinte ich am 13:34:46 15.04.2014 mit "Du musst für jeden messwert auch ein objekt besorgen. "