Aus Datei daten in Struktur einlesen
-
RajHid schrieb:
Achtung nicht verwirren lassen da kommt ein fenster bei dem man seine Handy nummer angeben soll --> wegklicken
dann muss man ca. ne Minute warten und ein Capcha lösenDanke für die Warnung.
Wenn dein Problem in den 40 Zeilen ist dann kannst du es auch zusammenkürzen.
http://www.c-plusplus.net/forum/136013
-
Hier mal ein Beispiel, wie du dein Problem auf das wesentliche zusammen stauchen kannst:
#include <stdio.h> #include <conio.h> struct Artikel { int dumpint; int nr; char bezeichnung[20]; char name[20]; double preis; } art; FILE *datei ; int lesen() { char header[80]; int satz; datei=fopen("katalog.data","r+"); printf("===================================================\n\n"); for( int i = 0; i < 5; i++) fscanf(datei,"%s ", header); while(!feof(datei)) { satz = fscanf(datei," %i %i %s %s %lf", &art.dumpint, &art.nr, art.bezeichnung, art.name, &art.preis); printf("%i %s %s %.2f\n", art.nr, art.bezeichnung, art.name, art.preis); printf("%d\n", satz); // zur Kontrolle für fscanf } fclose(datei); printf("Weiter mit beliebiger Taste..."); getch(); return 0; } int main() { lesen(); }
Das entspricht aber nicht der von dir geforderten Lösung!
Und dieses Beispiel könnte man noch kürzer fassen.
Mit den Änderungen für deinen speziellen Fall sollte das etwa die gleiche Zeilenzahl werden.
Irgend welche Hoster wo Handynummern oder sonstiges gefordert wird werden hier nur die wenigsten öffnen. Und Zeit in der Warteschleife fördert die Lesebereitschaft auch nicht gerade.
Wenn dein Quelltext halbwegs übersichtlich geschrieben sein sollte, sollten die maximal 50 Zeilen und dein Problem komplett hier zu zeigen, kein Problem sein.
-
Da ist viel laienhafter Kram bei:
- globale Variablen
- unnötiges C99
- redundante Leerzeichen in Formatstrings
- kein Fehlerbehandlung für Dateilesefehler
- keine Stringüberlaufprüfung
- fehlerhaft für Stringwerte mit Whitespaces
- unportabel wegen conio.h
- kein Speichern in Array#define MAXDS 20 int main() { struct Artikel { int dumpint; int nr; char bezeichnung[100]; char name[100]; double preis; } art[MAXDS]; int i=0; char zeile[100]; FILE *f = fopen("daten.txt","r"); while( i<MAXDS && fgets(zeile,100,f) ) if( 5==sscanf(zeile,"%d%d%99s%99[^+-0-9]%lf",&art[i].dumpint,&art[i].nr,art[i].bezeichnung,art[i].name,&art[i].preis) ) ++i; fclose(f); while( i-- ) printf("%3d%3d%20s%30s%f\n",art[i].dumpint,art[i].nr,art[i].bezeichnung,art[i].name,art[i].preis); return 0; }
Das Problem sind die offensichtlich möglichen Stringwerte mit Leerzeichen "Willory and Borch" für Hersteller, sollen die auch für Artikelname möglich sein, hast du ein größeres Problem bei der Zuordnung, da du keine Feldtrennzeichen verwendest.
-
Wutz schrieb:
Das Problem sind die offensichtlich möglichen Sttringwerte mit Leerzeichen "Willory and Borch" für Hersteller, sollen die auch für Artikelname möglich sein, hast du ein größeres Problem bei der Zuordnung, da du keine Feldtrennzeichen verwendest.
Na hoffentlich hat er das jetzt verstanden.
-
Danke für eure Hilfe bei mir funktioniert das Einlesen jetz,
@ Wutzkannst du die Zeile
if( 5==sscanf(zeile,"%d%d%99s%99[^+-0-9]%lf",&art[i].dumpint,&art[i].nr,art[i].bezeichnung,art[i].name,&art[i].preis) )
mal bitte erklären? vor allem die Platzhalter interessieren mich (%d%d%99s%99[^+-0-9]%lf), da scheint man ja eine menge mit anstellen zu können kann man das irgendwo nachlesen, nach was muss ich dafür suchen?.
Was ich noch erwähnen sollte ich benutze Linux als basissystem
ZUdem hatte ich noch etliche feheler in meinem Programm.
Erstmal hab ich versucht mit einem Falschen Dateinamen die Datei mit den Daten zu öffnen.
zweitens scheint die fscanf Funktion so zu funktionieren dass diese keine Daten in die Strucktur schreibt wenn die Platzhalter nicht stimmen.
-
if( 5==sscanf(zeile,"%d%d%99s%99[^+-0-9]%lf",&art[i].dumpint,&art[i].nr,art[i].bezeichnung,art[i].name,&art[i].preis) )
OK, ich versuche es mal, ist aber sehr viel Tipparbeit, ich hoffe es ohne Fingerkrampf hinzubekommen
- %d Integerliteral wird versucht zu lesen, führende Whitespaces werden übergangen, Verarbeitung stoppt am ersten nicht zum Integerliteral passendem Zeichen
- %d Integerliteral wird versucht zu lesen, führende Whitespaces werden übergangen, Verarbeitung stoppt am ersten nicht zum Integerliteral passendem Zeichen
- %99s eine Zeichenfolge wird versucht zu lesen bis ein Whitespace vorkommt oder 99 Zeichen erreicht wurden, führende Whitespaces werden übergangen
- %99[^+-0-9] eine Zeichenfolge wird versucht zu lesen bis '+','-' oder '0'..'9' vorkommt oder 99 Zeichen erreicht wurden
- %lf ein Fließkommaliteral wird versucht zu lesen, führende Whitespaces werden übergangenRückgabewert von sscanf wie auch von fscanf ist die Anzahl der erfolgreich abgearbeiteten Formatspezifizierer. Wurde ein Format nicht richtig erkannt, wird die gesamte Verarbeitung beendet.
Was ich noch erwähnen sollte ich benutze Linux als basissystem
fgets+sscanf+fscanf+... ist C89, also portabel, d.h. OS-unabhängig (das ist ja gerade ein wesentlicher Vorteil von Standard C)
ZUdem hatte ich noch etliche feheler in meinem Programm.
soll vorkommen, u.a. auch bei Anfängern
Erstmal hab ich versucht mit einem Falschen Dateinamen die Datei mit den Daten zu öffnen.
Dazu musst du den Rückgabewert von fopen auswerten, das habe ich jetzt nicht mit aufgeschrieben, irgendwas sollst du ja auch noch selbst machen.
zweitens scheint die fscanf Funktion so zu funktionieren dass diese keine Daten in die Strucktur schreibt wenn die Platzhalter nicht stimmen.
Meine Rede. fscanf ist für Anfänger zu kompliziert. Gehe davon aus, dass fscanf fehlerfrei funktioniert und du diese Funktion nur falsch anwendest. Außerdem war mein Vorschlag fgets+sscanf und nicht fscanf, du solltest dich für eine Variante entscheiden und dann jeweils in jedem Fall die Rückgabewerte auswerten!
-
so mein Kram funktioniert jetzt
ist sicher noch verbesserungsfähig
Hier mal die gesammte funktionint AusDateiLesen(struct Wahren* Artikel, int *anz){ int i=0,dumpint=0; FILE *datei; char dumpchar[100]; char zeile[100]; strcpy(zeile,"5"); datei = fopen ("Datendatei.txt", "r"); if (datei == NULL){ printf("Fehler beim oeffnen der Datei."); return 1; } if (datei != NULL) { fscanf(datei,"%99s%s%99s%99s%99s",dumpchar,dumpchar,dumpchar,dumpchar,dumpchar); //strcpy(dumpchar,"TEST"); /* Schleife lauft so lange wie Zeilen aus Datei Ausgelesen werden*/ while (fgets(zeile,100,datei)){ /*fscanf liefert die anzahl der Richtig gelesenen Formatspezifizierer an *zeile */ *zeile==fscanf(datei,"%d %d %99s %99s %lf",&dumpint,&Artikel[i].nr,Artikel[i].bezeichnung,Artikel[i].name,&Artikel[i].preis); i++; } fclose (datei); } i--;// minus 1 wegen Richtiger Anzahl *anz=i;// Zuweisung der Anzahl ausgelesener zeilen in die wichtige Zaelvariable anz, return 0; }
-
So werden die Werte aber nur aus jeder zweiten Zeile genommen.
Lies es die nochmal genau durch:Wutz schrieb:
Außerdem war mein Vorschlag fgets+sscanf und nicht fscanf,
-
Warum in Zeile 11 kein else?
Zeile 19 verstehe ich nicht?Nur für die Optik - Waren oder Wahren?
-
DirkB schrieb:
So werden die Werte aber nur aus jeder zweiten Zeile genommen.
Ich nehme das mit der zweiten Zeile zurück.
Mit dem fgets liest du nur noch den Rest der Zeile ein, den fscanf übrig gelassen hat. Und wenn es nur das '\n' ist.
Trotzdem war es so nicht gemeint.
-
Was war so nicht gemeint? das verwirrt mich etwas
ich bin jedenfalls erst mal zufrieden mit meinem Code, er liefert das was ich haben möchte.
Obwohl ich selber zugeben muss das mir nicht alles hundert prozentig klar ist was mein Code genau macht.Ich versuche das mal zu beschreiben.
hier lese ich die Zeile mit den Tabellenköpfen ein, diese Zeile wird verworfen.
Position in der Datei ist jetzt noch Zeile1.fscanf(datei,"%99s%s%99s%99s%99s",dumpchar,dumpchar,dumpchar,dumpchar,dumpchar);
while (fgets(zeile,100,datei)){ /*fscanf liefert die anzahl der Richtig gelesenen Formatspezifizierer an *zeile */ *zeile==fscanf(datei,"%d %d %99s %99s %lf",&dumpint,&Artikel[i].nr,Artikel[i].bezeichnung,Artikel[i].name,&Artikel[i].preis); i++; }
Die Schleife läuft solange wie fgets(zeile,100,datei)einen Wahren wert leifert.
Wert von zeile ist 5,
Durch fgets wird nun das Return am Ende von Zeile1 in zeile gespeichert. Position in der Datei ist jetzt Anfang Zeile2
danach wird fscanf ausgeführt, diese liest mit hilfe der Formatspezifizierer die Zeile aus und weist die gefundenen Zeichenketten dem Strukturarray zu.
Der Rückgabewert von fscanf sind die Anzahl der richtig ausgelesenen Formatspezifizierer. das sind hier 5.
i wird erhöt um 1 und wir landen wider bei der Prüfung der Wihle bedingung.
damit sind wir wieder an der Stelle wo in Zeile2 das Return am Ende Steht.Wenn jetzt die letzte Zeile eingelesen wurde liefert fscanf eine 0 an zeile und die Prüfung der while Bedingung ergibt einen Fehler, weil da kein Zeichen mehr kommt. damit wird die Bedingung falsch und die while Schleife wird verlassen.
Was meint ihr? ist das halbwegs richtig
-
Okay in Zeile 6 kopierst du "5" in zeile.
In Zeile 17 wird der Inhalt von zeile geändert, oder nicht
Welche Auswirkung oder Zweck soll der Vergleichsoperator == in Zeile 19 haben?
Sehe da kein if, while oder ähnliches?
-
RajHid schrieb:
Was war so nicht gemeint? das verwirrt mich etwas
Du liest mit Zeile 14 (
fscanf(datei,"%99s%s%99s%99s%99s",dumpchar,dumpchar,dumpchar,dumpchar,dumpchar);
) die Überschriften ein.
Das '\n' aus der Zeile bleibt aber noch im Eingabepuffer.Das wird dann in Zeile 17 (
while (fgets(zeile,100,datei))
) ausgelesen.
In Zeile 19 liest du dann die Werte aus der nächsten Zeile (bis auf das '\n').
Das wird dann in Zeile 17 ...
Geh mal mit dem Debugger schrittweise durch.Gemeint war, die komplette Zeilen mit fgets auslesen und mit sscanf auswerten:
fgets(zeile,100,datei) // Überschrift lesen Reichen 100 ZEichen aus? /* Schleife lauft so lange wie Zeilen aus Datei Ausgelesen werden*/ while (fgets(zeile,100,datei)){ /*sscanf liefert die Anzahl der richtig gelesenen Formatspezifizierer zurück */ if (5!=sscanf(zeile,"%d %d %99s %99s %lf",&dumpint,&Artikel[i].nr,Artikel[i].bezeichnung,Artikel[i].name,&Artikel[i].preis)) { Fehler, Was jetzt? }; i++; }
-
Nen Debugger benutze ich nicht ich mach das nur mit Konsole und vim
Ist halt manchmal etwas schwieriger.Über die Funktion muss ich aber noch mal drüber schauen da sind noch Ungereimtheiten drin.
-
RajHid schrieb:
Nen Debugger benutze ich nicht ich mach das nur mit Konsole und vim
Ist halt manchmal etwas schwieriger.Fuer den Debugger brauchst du auch nur die Konsole.
Und der ist auch schon dabei.gdb
-
Hab mir mal gdb angeschaut, hätte ich schon eher verwenden sollen hätte mir manches an Zeit erspart. Danke für den Hinweis.