low level datei io mit struktur
-
hallo,
#include <stdio.h> #include <conio.h> #include <io.h> #include <fcntl.h> #include <unistd.h> #include <sys\stat.h> #include <string.h> #define MAX 20 struct struktur { char name[100]; char street[100]; int alter; }; int main() { struct struktur a[100]; struct struktur b[100]; int i; int datei; if((datei=creat("datei.txt",S_IWRITE))==-1) { printf("fehler\n"); return -1; } for(i=0; i<MAX; i++) { ///////////////////////////////...................//////////////// a[i].alter=i; ////////////////////////////////.........................//////////// strcpy(a[i].name,"leer"); strcpy(a[i].street,"leer"); if((write(datei,&a[i].alter,sizeof(a[i].alter)))==-1) return -1; if((write(datei,&a[i].name,sizeof(a[i].name)))==-1) return -1; if((write(datei,&a[i].street,sizeof(a[i].street)))==-1) return -1; } close(datei); if((datei=open("datei.txt",O_RDONLY))==-1) { printf("fehler\n"); return -1; } for(i=0; i<MAX; i++) { if((read(datei,&b[i].alter,sizeof(b[i].alter)))==-1) return -1; if((read(datei,&b[i].name,sizeof(b[i].name)))==-1) return -1; if((read(datei,&b[i].street,sizeof(b[i].street)))==-1) return -1; } for(i=0; i<MAX; i++) { printf("%d\t%s\t%s\n",b[i].alter,b[i].name,b[i].street); } close(datei); return 0; }
die ausgabe von diesem programm sieht so aus:
0 leer leer 1 leer leer 2 leer leer 3 leer leer 4 leer leer 5 leer leer 6 leer leer 7 leer leer 8 leer leer 9 leer leer 10 leer 3071 leer 3327 leer 3583 leer 3839 leer 4095 leer 4351 leer 4607 leer 4863 leer 5119 leer "C:\lcc\lcc\test.exe" Return code 0 Execution time 0.011 seconds Press any key to continue...
veränder ich die zeile 30 so um:
a[i].alter=0;
im ganzen siehts dann so aus (mit "///....///" markiert)
#include <stdio.h> #include <conio.h> #include <io.h> #include <fcntl.h> #include <unistd.h> #include <sys\stat.h> #include <string.h> #define MAX 20 struct struktur { char name[100]; char street[100]; int alter; }; int main() { struct struktur a[100]; struct struktur b[100]; int i; int datei; if((datei=creat("datei.txt",S_IWRITE))==-1) { printf("fehler\n"); return -1; } for(i=0; i<MAX; i++) { ///////////////////////////////..................////////////////////// a[i].alter=0; /////////////////////////....................////////////////////////// strcpy(a[i].name,"leer"); strcpy(a[i].street,"leer"); if((write(datei,&a[i].alter,sizeof(a[i].alter)))==-1) return -1; if((write(datei,&a[i].name,sizeof(a[i].name)))==-1) return -1; if((write(datei,&a[i].street,sizeof(a[i].street)))==-1) return -1; } close(datei); if((datei=open("datei.txt",O_RDONLY))==-1) { printf("fehler\n"); return -1; } for(i=0; i<MAX; i++) { if((read(datei,&b[i].alter,sizeof(b[i].alter)))==-1) return -1; if((read(datei,&b[i].name,sizeof(b[i].name)))==-1) return -1; if((read(datei,&b[i].street,sizeof(b[i].street)))==-1) return -1; } for(i=0; i<MAX; i++) { printf("%d\t%s\t%s\n",b[i].alter,b[i].name,b[i].street); } close(datei); return 0; }
man erhält diese ausgabe;
0 leer leer 0 leer leer 0 leer leer 0 leer leer 0 leer leer 0 leer leer 0 leer leer 0 leer leer 0 leer leer 0 leer leer 0 leer leer 0 leer leer 0 leer leer 0 leer leer 0 leer leer 0 leer leer 0 leer leer 0 leer leer 0 leer leer 0 leer leer "C:\lcc\lcc\test.exe" Return code 0 Execution time 0.011 seconds Press any key to continue...
so und diese ausgabe ist mir schleierhaft, wieso fürht die 0 zu keinen problem, aber die 20 ? -> (i kann nicht größer als 20 sein ! )
was mach ich da falsch, vorallem verstehe ich nicht wieso da auf einmal solche otopischenwerte die 3071, 3327 usw rauskomen können ... was mach ich da falsch ?
ist das eine art sonderfall ... bug ??
please help
-
hm, versuchs nochmal mit dem code, den du gepostet hast.
Wenn das nicht geht, macht dein Compiler vielleicht Blödsinn. Bei mir funktionierts.
-
0 leer leer 1 leer leer 2 leer leer 3 leer leer 4 leer leer 5 leer leer 6 leer leer 7 leer leer 8 leer leer 9 leer leer 10 leer 3071 leer 3327 leer 3583 leer 3839 leer 4095 leer 4351 leer 4607 leer 4863 leer 5119 leer "C:\lcc\lcc\test.exe" Return code 0 Execution time 0.011 seconds Press any key to continue...
klar, der code lässt sich ausführen ... nur verstehe ich die ausgabe nicht ... ich bin der meinung die funktion write "versteht" mit der 10 was falsches ! und interpretier es demnach auch falsch, daher kommen auch solche seltsamen werte raus ...
-
wie gesagt, der erste Code funktioniert hier einwandfrei und ich kann auch keinen Fehler finden.
~% ./a.out 0 leer leer 1 leer leer 2 leer leer 3 leer leer 4 leer leer 5 leer leer 6 leer leer 7 leer leer 8 leer leer 9 leer leer 10 leer leer 11 leer leer 12 leer leer 13 leer leer 14 leer leer 15 leer leer 16 leer leer 17 leer leer 18 leer leer 19 leer leer
Mir scheint, da spinnt dein Compiler an irgendeiner Stelle. Was steht denn zB. in der Datei? Funktioniert das Lesen oder das Schreiben nicht?
Dann evtl. mal die Entwickler direkt anfragen.
-
ich bin nochmal mit dem debugger drüber, ich glaube das ist die zahl 10, die den "bug" verzrsacht ... bei jeder beliebeigen zahl passiert nichts böses, auser bei der 10 (hab im wertebereich von 0 bis 2 hoch 32 alles getestet ...)
mit MSVC der mir das progg als C++ prog verkauft, verusacht den fehler und lcc (als ansi c programm) verursacht den gleichen fehler.
unter linux mit gcc funktioniert es !!!
ist doch strange oder ?ps .. in der datei steht selbstverständlich auch was drinn
(ein paar hyroglyphen)
-
doomcalyptica schrieb:
ps .. in der datei steht selbstverständlich auch was drinn
(ein paar hyroglyphen)mit einem hexeditor kann man sich die Werte genauer angucken.
Das es bei zwei Compilern zum selben Fehler kommt, lässt vermuten, dass das Problem direkt bei den Windows POSIX-Wrappern liegt.
Vielleicht mal in einer der Microsoft-Newsgroups anfragen.
-
if((write(datei,&a[i].name,sizeof(a[i].name)))==-1) return -1;
Das ist auf jeden Fall ein Programmfehler.
Da "name" ein Array ist, ermittelt "&a[i].name" die Adresse der Adresse des Arrays. Mag sein, dass GCC bei solchen Sachen ein Auge zudrueckt, aber der Typ des Ausdrucks ist: char**. Eigentlich muesste eine Warnung beim Compilieren kommen, die besagt, dass beim Parameter 2 von write() ein anderer Indirection-Level als erwartet benutzt wird. Es handelt sich also bei beiden Compilern um einen Compiler-Bug.
Richtig muss die Zeile heissen:
// mit "[0]" nach "&a[i].name" if((write(datei,&a[i].name[0],sizeof(a[i].name)))==-1) return -1;
oder
// ohne "&" vor "a[i].name" if((write(datei,a[i].name,sizeof(a[i].name)))==-1) return -1;
Das gilt auch fuer die Read-Zugriffe mit "name" und "street".
-
ups, das habe ich übersehen. Der gcc liefert bei &char[] nochmal die Adresse von char[].
Eigentlich muesste eine Warnung beim Compilieren kommen, die besagt, dass beim Parameter 2 von write() ein anderer Indirection-Level als erwartet benutzt wird. Es handelt sich also bei beiden Compilern um einen Compiler-Bug.
naja, die funktion erwartet void*, da kann man ihr geben was man will.
-
DrGreenthumb schrieb:
naja, die funktion erwartet void*, da kann man ihr geben was man will.
Irrtum. void** != void*. Der Compiler muss eine Warnung ausgeben: "Warning: Different levels of indirection". Einige Compiler tun das auch.
-
DrGreenthumb
************Das mit der fehlerhaften Implementation scheint möglich, hab das mal mit dem Debugger durchgesteppt. Und mir die Datei angesehen. Wenn man das "Alter" auf einen festen Wert setzt dann werden die Daten schön "hintereinander" geschrieben, lässt man es auf den Schleifenwert setzen sieht die Datei mal richtig hässlich aus da ist es kein Wunder wenn Read fehlschlägt, bleibt nur noch zu ergründen wieso das so ist. Mich würde spontan interessieren ob der Fehler auch erzeugt wird wenn man die die Strukturen dynamisch erzeugt.
tt
EDIT: Power Off
****************Vielleicht bin ich ja auch mit Blindheit geschlagen aber das mit den Pointern dachte ich mir immer so.
Da feld[i], zu (feld + i) wird, was ja die Adresse des Feldelementes (nicht des Inhalts) an der Stelle i ist. Wenn man drauf zugreift wird ein (feld+i) daraus, was den Inhalt zurück gibt. Wendet man jetzt den Adressoperator darauf an (auf den Inhalt) bekommt man wieder die Feldadresse. Was mir auch einleuchtend mit char scheint. Ich hole mir die Feldadresse wo der char * steht, dann dereferenziere ich die Feldadresse um den char* zu bekommen, da das ja der Inhalt ist und wende ich jetzt & darauf an hole ich mir die Adresse des char* die ja die gleichzeitig die Adresse des Feldelementes sein sollte wo der char* steht.
Rein blauäugig meine ich das in dem gg. Bsp. unötige Konversionen stattfinden die aber nicht falsch sind. Mir fällt da nirgendwo eine doppelte Indirektion auf.tt