struct in datei schreiben

D

Dennis Schulz

hi alle,

ich bin blutiger C Anfänger und hier ist mein Versuch ein Strukt in
eine Datei zu schreiben, bzw anzuhängen.
Leider wird die datei zwar angelegt aber nichts reingeschrieben.
Besonders die Stelle mit dem Fischzeiger kommt mir komisch vor, aber
fwrite erwartet als ersten Parameter nunmal einen Zeiger und ich weiss
sonst nicht was ich machen soll. Bitte helft mir.

mfg Dennis


hier der Codeauszug:

#define dateiname "fischfile.dat"

// eigener Datentyp fis
typedef struct fis {
char besitzer[20];
char fischname[20];
int preis;
} Fischsatz;

int NeuerDatensatz(char besitzer[],char fisch[]) {
FILE *fischfile;
// pruefe ob datei schon existiert
if (DateiExistiert(dateiname)) {
// oeffne Datei zum anhaengen
fischfile =fopen(dateiname, "a");
} else {
// oeffne Datei zum schreiben
fischfile =fopen(dateiname, "w");
}

// lege neuen Fisch an
Fischsatz neufisch;
strcpy(neufisch.besitzer, besitzer);
strcpy(neufisch.fischname, fisch);
neufisch.preis = 17;

// fischzeiger auf neufisch
Fischsatz *fischzeiger;
fischzeiger = malloc(sizeof(struct fis));
fischzeiger = &neufisch;

// schreibe Fischstrukt in datei
fwrite(fischzeiger, sizeof (struct fis), 1, fischfile);

fclose(fischfile);
}
 
J

Joona I Palaste

Dennis Schulz said:
ich bin blutiger C Anfänger und hier ist mein Versuch ein Strukt in
eine Datei zu schreiben, bzw anzuhängen.
Leider wird die datei zwar angelegt aber nichts reingeschrieben.
Besonders die Stelle mit dem Fischzeiger kommt mir komisch vor, aber
fwrite erwartet als ersten Parameter nunmal einen Zeiger und ich weiss
sonst nicht was ich machen soll. Bitte helft mir.
mfg Dennis

hier der Codeauszug:
#define dateiname "fischfile.dat"
// eigener Datentyp fis
typedef struct fis {
char besitzer[20];
char fischname[20];
int preis;
} Fischsatz;
int NeuerDatensatz(char besitzer[],char fisch[]) {
FILE *fischfile;
// pruefe ob datei schon existiert
if (DateiExistiert(dateiname)) {

Woher haben Sie den Code zu DateiExistiert() versteckt?
// oeffne Datei zum anhaengen
fischfile =fopen(dateiname, "a");
} else {
// oeffne Datei zum schreiben
fischfile =fopen(dateiname, "w");
}
// lege neuen Fisch an
Fischsatz neufisch;
strcpy(neufisch.besitzer, besitzer);
strcpy(neufisch.fischname, fisch);
neufisch.preis = 17;
// fischzeiger auf neufisch
Fischsatz *fischzeiger;
fischzeiger = malloc(sizeof(struct fis));

Sie brauchen gar nicht den malloc()-anruf. Es gilt auch gerade
fischzeiger = &neufisch; zu laufen.
Sie haben sogar eine Probleme hier. Wenn sie die Zeiger fischzeiger
neuassignieren, haben sie den Speicher von malloc() vollkommig verloren.
Sie haben jetzt reservierter Speicher daß Sie nicht nutzen können.
fischzeiger = &neufisch;
// schreibe Fischstrukt in datei
fwrite(fischzeiger, sizeof (struct fis), 1, fischfile);
fclose(fischfile);

Dieses scheint alles gute zu sein. Sind Sie sicher daß nichts
geschriebt wird? Wie haben Sie es geprüft?

Schließlich scheint Ihre Code entweder C++ oder C99 zu sein. Es kann
nicht mit eine normale C90-compiler kompiliert werden.
 
A

Arthur J. O'Dwyer

Just out of morbid curiosity, what's "bzw"? I assume it's the
German equivalent of "thx", "u" or "b/c", since I don't think German
goes in for vowelless words too much. Even though I don't read
German, I still want to know. :)

#define DATEINAME "fischfile.dat"

Capitalize macro names. It saves time and effort for the maintenance
programmers, and maybe for yourself too.
// eigener Datentyp fis
typedef struct fis {
char besitzer[20];
char fischname[20];
int preis;
} Fischsatz;
int NeuerDatensatz(char besitzer[], char fisch[]) {
FILE *fischfile;
// pruefe ob datei schon existiert
if (DateiExistiert(dateiname)) {

Woher haben Sie den Code zu DateiExistiert() versteckt?

That must be real German, because I don't understand it. ;-)
Probably just

int DateiExistiert(const char *fname) {
FILE *fp = fopen(fname, "rb");
if (fp == NULL) return 0;
fclose(fp); return 1;
}


In both cases, "ab" and "wb". 'fwrite' expects a binary file,
not a text file.
Sie brauchen gar nicht den malloc()-anruf. Es gilt auch gerade
fischzeiger = &neufisch; zu laufen.
Sie haben sogar eine Probleme hier. Wenn sie die Zeiger fischzeiger
neuassignieren, haben sie den Speicher von malloc() vollkommig verloren.
Sie haben jetzt reservierter Speicher daß Sie nicht nutzen können.

I assume Joona said: "Something's up with that malloc. You're
overwriting the result with &neufisch on the very next line. That's
a memory leak."
But I want to make sure somebody has said: Why'd you switch from
'Fischsatz' to 'struct fis' here? Be consistent! And anyway, you
could have written

fischzeiger = malloc(sizeof *fischzeiger);

and been absolutely correct, with no types in sight.


This line, I do not think it does what you think it does. You
should be writing

*fischzeiger = neufisch;

or, in pre-C89 idiom,

memcpy(fischzeiger, &neufisch, sizeof neufisch);

Maybe this is what you meant when you mentioned "Stelle" above.

Dieses scheint alles gute zu sein. Sind Sie sicher daß nichts
geschriebt wird? Wie haben Sie es geprüft?

Return an 'int' from this function, as you promised you were
going to, in the prototype.
Schließlich scheint Ihre Code entweder C++ oder C99 zu sein. Es kann
nicht mit eine normale C90-compiler kompiliert werden.


-Arthur
 
J

Jens.Toerring

Dennis Schulz said:
ich bin blutiger C Anfänger und hier ist mein Versuch ein Strukt in
eine Datei zu schreiben, bzw anzuhängen.
Leider wird die datei zwar angelegt aber nichts reingeschrieben.
Besonders die Stelle mit dem Fischzeiger kommt mir komisch vor, aber
fwrite erwartet als ersten Parameter nunmal einen Zeiger und ich weiss
sonst nicht was ich machen soll. Bitte helft mir.

Hi Dennis,

this isn't de.comp.lang.c, so the language used here is english.
For the benefit of the people here not that fluent in german here's
a short translation:

Dennis wants to write a structure to a file and is wondering why
nothing gets written into the file (no information supplied about
how he knows). He's also a bit concerned about the use of the
'Fischzeiger' pointer, but thinks he needs it because fwrite()
expects a pointer to the data as the first argument.
hier der Codeauszug:
#define dateiname "fischfile.dat"
// eigener Datentyp fis
typedef struct fis {
char besitzer[20];
char fischname[20];
int preis;
} Fischsatz;
int NeuerDatensatz(char besitzer[],char fisch[]) {
FILE *fischfile;
// pruefe ob datei schon existiert
if (DateiExistiert(dateiname)) {
// oeffne Datei zum anhaengen
fischfile =fopen(dateiname, "a");
} else {
// oeffne Datei zum schreiben
fischfile =fopen(dateiname, "w");
}

That check is rather useless, just open with "a" in both cases,
if the file didn't already exist "a" has the same meaning as "w".
But you better check that fopen() did succeed!
// lege neuen Fisch an
Fischsatz neufisch;

Unless you're using a C99 compiler (or a C++ compiler) this
isn't allowed - all declarations must come before the first
executable statement. But let's assume you have a C99 compliant
compiler...
strcpy(neufisch.besitzer, besitzer);
strcpy(neufisch.fischname, fisch);
neufisch.preis = 17;
// fischzeiger auf neufisch
Fischsatz *fischzeiger;

Same problem here.
fischzeiger = malloc(sizeof(struct fis));
fischzeiger = &neufisch;

Here it gets wrong. You declare a new pointer, allocate memory
for it but then assign the address of the structure to it, losing
all information about the memory you just allocated. You just
just created a memory leak. If you really want to copy the
structure to the new memory use

*fischzeiger = neufisch;
// schreibe Fischstrukt in datei
fwrite(fischzeiger, sizeof (struct fis), 1, fischfile);

Why not simply use

fwrite( &neufisch, sizeof neufisch, 1, fischfile );

skipping all the useless memory allocation and copying? Next
question: why bother with creating a typedef when you don't
seem to have any problems with using the struct fis it's
typedef'ed to? At least try to stay consistent.
fclose(fischfile);
}

Since I have my doubts that you really have a C99 compliant
compiler I would recommend that you correct that program and
compile it again, making sure you don't invoke the compiler
in C++ mode. Then look again at the output file and see if
it's still empty. If yes ask here again.

Regards, Jens
 
J

Joona I Palaste

Just out of morbid curiosity, what's "bzw"? I assume it's the
German equivalent of "thx", "u" or "b/c", since I don't think German
goes in for vowelless words too much. Even though I don't read
German, I still want to know. :)

Beziehungsweise. If I remember my German right it means more-or-less
"and".
int NeuerDatensatz(char besitzer[], char fisch[]) {
FILE *fischfile;
// pruefe ob datei schon existiert
if (DateiExistiert(dateiname)) {

Woher haben Sie den Code zu DateiExistiert() versteckt?
That must be real German, because I don't understand it. ;-)

"Where have you hidden the code to DateiExistiert()?" But that should
be "wohin", not "woher". Sorry about that.
Probably just
int DateiExistiert(const char *fname) {
FILE *fp = fopen(fname, "rb");
if (fp == NULL) return 0;
fclose(fp); return 1;
}
I assume Joona said: "Something's up with that malloc. You're
overwriting the result with &neufisch on the very next line. That's
a memory leak."

Yes, it was to that effect. On the first paragraph I told him he does
not need to call malloc() at all.
But I want to make sure somebody has said: Why'd you switch from
'Fischsatz' to 'struct fis' here? Be consistent! And anyway, you
could have written
fischzeiger = malloc(sizeof *fischzeiger);
and been absolutely correct, with no types in sight.
This line, I do not think it does what you think it does. You
should be writing
*fischzeiger = neufisch;
or, in pre-C89 idiom,
memcpy(fischzeiger, &neufisch, sizeof neufisch);
Maybe this is what you meant when you mentioned "Stelle" above.

Um, if he does not call malloc(), fischzeiger = &neufisch; should work
all OK. I think.
 
J

Jens.Toerring

Beziehungsweise. If I remember my German right it means more-or-less
"and".

More like "or" or "alternatively".
int NeuerDatensatz(char besitzer[], char fisch[]) {
FILE *fischfile;
// pruefe ob datei schon existiert
if (DateiExistiert(dateiname)) {

Woher haben Sie den Code zu DateiExistiert() versteckt?
That must be real German, because I don't understand it. ;-)
"Where have you hidden the code to DateiExistiert()?" But that should
be "wohin", not "woher". Sorry about that.

"Wo haben Sie den Code fuer DateiExistiert() versteckt?" would be
correct (or, if you don't want to be that formal, "Wo hast du den
Code...").

I guess I have to get my brother to translate me something to japanese
just to see how Joona reacts;-)
Regards, Jens
 
J

Joona I Palaste

(e-mail address removed)-berlin.de scribbled the following:
I guess I have to get my brother to translate me something to japanese
just to see how Joona reacts;-)

Well, if he calls himself or me cute, or sliced raw fish, then I'll be
able to understand it. Otherwise I most probably won't.
 
J

Joona I Palaste

bis zu weiter or something like. Approximately "otherwise"

Actually, you're wrong. It's "beziehungsweise" and means "or" or
something, I'm told. The reason it's abbreviated is not because it's
k3wl to abbreviate words but because "beziehungsweise" takes too long
to type.
Shortening "beziehungsweise" to "bzw" saves 78.6% of the letters.
Whereas shortening "thanks" to "thx" only saves 50% and even
shortening "you" to "u" saves 66.7%.
 
R

Richard Bos

ich bin blutiger C Anfänger

Auai, was ist passiert! War die Compiler scharf?

[ BTW, this is an English-language newsgroup. I'll continue in that
language. ]
#define dateiname "fischfile.dat"

It's generally considered wiser to make macro names all-caps. This isn't
as important for object-like macros as for function-like ones, though.
// eigener Datentyp fis
typedef struct fis {
char besitzer[20];
char fischname[20];
int preis;
} Fischsatz;

int NeuerDatensatz(char besitzer[],char fisch[]) {
FILE *fischfile;
// pruefe ob datei schon existiert

BTW, it's generally better not to write comments that literally say the
same thing as your code does. Comments should explicate, not duplicate.
if (DateiExistiert(dateiname)) {
// oeffne Datei zum anhaengen
fischfile =fopen(dateiname, "a");
} else {
// oeffne Datei zum schreiben
fischfile =fopen(dateiname, "w");
}

Wrong. Even if the file exists, you still don't know that you can write
to it; even if it doesn't exist, you still don't know that you can
create it. Moreover, you're writing binary data, and you're opening a
text stream.

Simply open the file with the mode "ab". This will create the file when
it doesn't exist, just like "w" does, so you won't have to check whether
it does. Then check that fischfile isn't null, because if it is, you
won't be able to write to it.

fischfile=fopen(dateiname, "ab");
if (!fischfile)
return -1;
// lege neuen Fisch an
Fischsatz neufisch;

You can't mix declarations and executable code in C89; however, you can
in C99 or (horror of horrors!) C++. Since you do not cast malloc(), I'm
assuming you have a C99 compiler, in which case this is correct.
strcpy(neufisch.besitzer, besitzer);
strcpy(neufisch.fischname, fisch);
neufisch.preis = 17;

// fischzeiger auf neufisch
Fischsatz *fischzeiger;

This is not necessary...
fischzeiger = malloc(sizeof(struct fis));
fischzeiger = &neufisch;

....and this is plain wrong. You've just leaked a whole struct fis' worth
of memory. There's no need at all to call malloc() when you're going to
assign the address of an existing object to a pointer - and doing so in
just before reassigning that pointer, without free()ing the memory you
got, leaks that memory. After all, how are you now going to free() it?
// schreibe Fischstrukt in datei
fwrite(fischzeiger, sizeof (struct fis), 1, fischfile);

Why you don't need an explicit pointer: &neufisch will do here just as
well.
Secondly, you want to check that something _did_ get written. If there's
something wrong with your disk, rather than with your code, you want to
be able to check. The return value of fwrite() is designed to give you
exactly that.
Also, when passing sizes of pointed-at objects, it's generally more
solid to pass sizeof *pointer than sizeof (explicit_type); the former is
always correct, the latter only as long as the type of the pointer
doesn't change. This is also true of the malloc() call above, albeit
that you don't want malloc() there at all.
Similarly, if you pass &object, and need to pass a size as well, sizeof
object is more solid than sizeof (type_of_object), for the same reasons.
Since that's what you want to do here, rather than use an intermediate
pointer, the whole line comes to:

int fische_geschrieben;
fische_geschrieben =
fwrite(&neufisch, sizeof neufisch, 1, fischfile);
fclose(fischfile);

Similarly, you want to check that your fclose() call succeeded. It's
never happened to me, but files _do_ sometimes refuse to be closed
correctly.

Finally, you declared your function to return an int, so you must return
one. A good value would be to return 0 for success, and various kinds of
non-0 for failure. (If your function wrote more than one fish, a good
value could, e.g., be a positive number for the number of fish written,
and zero for failure; or even several negative numbers for specific
failures.) So:

/* We do these in this order because we need to try and close the
file even if the write did not quite succeed. */
if (fclose(fischfile)==EOF) return -3;
if (fisch_geschrieben!=1) return -2;
return 0;
}

Richard
 
I

Irrwahn Grausewitz

Joona I Palaste said:
Actually, you're wrong. It's "beziehungsweise" and means "or" or
something, I'm told.

To be precise, it's more like: "... or ..., respectively".
The reason it's abbreviated is not because it's
k3wl to abbreviate words but because "beziehungsweise" takes too long
to type.

I'll bet the use of the (even in formal documents) very common
abbreviation "bzw." predates the concept of k3wlness significantly.
;-)

Regards
 
M

Martin Dickopp

Joona I Palaste said:
Actually, you're wrong. It's "beziehungsweise" and means "or" or
something, I'm told.

I'd translate it with "or rather". The OP's sentence would then mean
"[...] here is my attempt to write, or rather append, a struct to a
file."

(Funny, I wouldn't have thought that German has (single) word where
English doesn't -- it's usually the other way around. Okay, we have
"Bremsstrahlung" (for which the English translation is
"bremsstrahlung"), but that's a rather specialized technical term.)
The reason it's abbreviated is not because it's k3wl to abbreviate
words but because "beziehungsweise" takes too long to type.

In fact, it's an official abbreviation similar to "i.e." or "e.g.", only
it's not Latin. E.g., "bzw." can be used in letters to government
agencies or job applications.

Martin
 
M

Mabden

Martin Dickopp said:
Joona I Palaste said:
Actually, you're wrong. It's "beziehungsweise" and means "or" or
something, I'm told.

I'd translate it with "or rather". The OP's sentence would then mean
"[...] here is my attempt to write, or rather append, a struct to a
file."

(Funny, I wouldn't have thought that German has (single) word where
English doesn't -- it's usually the other way around. Okay, we have
"Bremsstrahlung" (for which the English translation is
"bremsstrahlung"), but that's a rather specialized technical term.)
The reason it's abbreviated is not because it's k3wl to abbreviate
words but because "beziehungsweise" takes too long to type.

In fact, it's an official abbreviation similar to "i.e." or "e.g.", only
it's not Latin. E.g., "bzw." can be used in letters to government
agencies or job applications.


Literally: "relationship - point"

It loses something in the translation, of course.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top