C Board  

Go Back   C Board > General Programming Boards > C Programming

Reply
 
LinkBack Thread Tools Display Modes
Old 05-18-2009, 08:19 AM   #1
* Death to Visual Basic *
 
Devil Panther's Avatar
 
Join Date: Aug 2001
Posts: 768
Question fwrite can't write dynamic strings???

Hello,

I would like to write an array of structs to a binary file.
But for some weird reason I'm having problems with the dynamically allocated string.
It seems to be writing the pointer's address to the file instead of the string itself.

The following code doesn't write the the struct correctly to the binary file.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct stuff {
	int nameSize;
	char *name;
	int num;
};

int main() {

	struct stuff *myStuff;

	myStuff = (struct stuff *)malloc(sizeof(struct stuff) * 3);

	myStuff[0].name = (char *)malloc(sizeof(char) * 4);
	strcpy(myStuff[0].name, "abc");

	myStuff[0].nameSize = strlen(myStuff[0].name);
	myStuff[0].num = 123;

	hFile = fopen("./file.bin", "wb");
	fwrite(myStuff, sizeof(struct stuff), 1, hFile);
	fclose(hFile);
	
	free(myStuff[0].name);
	free(myStuff);

	return(0);
}
While the below code, works great, except the fact that it writes the full size of the string... ignoring the \0.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct stuff {
	int nameSize;
	char name[10];
	int num;
};

int main() {

	FILE *hFile;
	struct stuff *myStuff;

	myStuff = (struct stuff *)malloc(sizeof(struct stuff) * 3);

	strcpy(myStuff[0].name, "abc");

	myStuff[0].nameSize = strlen(myStuff[0].name);
	myStuff[0].num = 123;

	hFile = fopen("./file.bin", "wb");
	fwrite(myStuff, sizeof(struct stuff), 1, hFile);
	fclose(hFile);
	
	free(myStuff);

	return(0);
}
What am I doing wrong?

Thank you.
__________________
"I don't suffer from insanity but enjoy every minute of it" - Edgar Allen Poe

http://www.Bloodware.net - Developing free software for the community.
Devil Panther is offline   Reply With Quote
Old 05-18-2009, 08:32 AM   #2
Kernel hacker
 
Join Date: Jul 2007
Location: Farncombe, Surrey, England
Posts: 15,686
fwrite writes whatever you tell it to write. If your struct contains a pointer to a character string, it will write the value of the pointer. Unfortunately, that doesn't work well, since when you read the struct back, the memory is unlikely to be allocated and hold the same value.

To solve that, you would have to EITHER use statically sized arrays, or use multiple write operations to store your struct, where one write stores the string content.

Of course, for binary files, it is highly beneficial to have a constant size for each record, so using a fixed size is a good plan in that respect. But it depends on what you are trying to achieve overall.

--
Mats
__________________
Compilers can produce warnings - make the compiler programmers happy: Use them!
Please don't PM me for help - and no, I don't do help over instant messengers.
matsp is offline   Reply With Quote
Old 05-18-2009, 08:43 AM   #3
Registered User
 
Join Date: Oct 2008
Location: TX
Posts: 1,262
How do you know what it is writing without first reading it back with fread()?
itCbitC is offline   Reply With Quote
Old 05-18-2009, 08:49 AM   #4
C++ Witch
 
laserlight's Avatar
 
Join Date: Oct 2003
Location: Singapore
Posts: 10,352
Quote:
Originally Posted by itCbitC
How do you know what it is writing without first reading it back with fread()?
Examine the file's contents by some other method
__________________
C + C++ Compiler: MinGW port of GCC
Build + Version Control System: SCons + Bazaar

Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
laserlight is offline   Reply With Quote
Old 05-18-2009, 08:59 AM   #5
and the hat of vanishing
 
Salem's Avatar
 
Join Date: Aug 2001
Location: The edge of the known universe
Posts: 21,214
> It seems to be writing the pointer's address to the file instead of the string itself.
Which is exactly what it should do, and exactly what is happening.

Serialisation needs to follow the structure of the data with an equivalent structure in the code. There's no automatic following of pointers.

Likewise when you read things in, you need to reallocate the memory for the pointer as you read in the "abc" string.
__________________
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
Up to 8Mb PlusNet broadband from only £5.99 a month!
Salem is offline   Reply With Quote
Old 05-18-2009, 09:01 AM   #6
* Death to Visual Basic *
 
Devil Panther's Avatar
 
Join Date: Aug 2001
Posts: 768
Quote:
Originally Posted by matsp View Post
fwrite writes whatever you tell it to write. If your struct contains a pointer to a character string, it will write the value of the pointer. Unfortunately, that doesn't work well, since when you read the struct back, the memory is unlikely to be allocated and hold the same value.

To solve that, you would have to EITHER use statically sized arrays, or use multiple write operations to store your struct, where one write stores the string content.

Of course, for binary files, it is highly beneficial to have a constant size for each record, so using a fixed size is a good plan in that respect. But it depends on what you are trying to achieve overall.

--
Mats
If I use a statically sized array, let say with 10 cells, and use only 3: abc\0
It ignores the \0, and writes the all 10 cells: junk.

Quote:
Originally Posted by itCbitC View Post
How do you know what it is writing without first reading it back with fread()?
It's a test program, a part of a larger application. I know for a fact that it doesn't work.
__________________
"I don't suffer from insanity but enjoy every minute of it" - Edgar Allen Poe

http://www.Bloodware.net - Developing free software for the community.
Devil Panther is offline   Reply With Quote
Old 05-18-2009, 09:03 AM   #7
* Death to Visual Basic *
 
Devil Panther's Avatar
 
Join Date: Aug 2001
Posts: 768
Quote:
Originally Posted by Salem View Post
> It seems to be writing the pointer's address to the file instead of the string itself.
Which is exactly what it should do, and exactly what is happening.

Serialisation needs to follow the structure of the data with an equivalent structure in the code. There's no automatic following of pointers.

Likewise when you read things in, you need to reallocate the memory for the pointer as you read in the "abc" string.
Ok, so what do you recommend I should do?
Is there a function that allows me to write a single variable to a binary file? I've looked but was unable to find any
__________________
"I don't suffer from insanity but enjoy every minute of it" - Edgar Allen Poe

http://www.Bloodware.net - Developing free software for the community.
Devil Panther is offline   Reply With Quote
Old 05-18-2009, 09:05 AM   #8
Registered User
 
Join Date: Oct 2008
Location: TX
Posts: 1,262
Quote:
Originally Posted by laserlight View Post
Examine the file's contents by some other method
I would like to know how without first rewinding the file and fread()'ing the binary image of the data structure stuff?
itCbitC is offline   Reply With Quote
Old 05-18-2009, 09:07 AM   #9
* Death to Visual Basic *
 
Devil Panther's Avatar
 
Join Date: Aug 2001
Posts: 768
Quote:
Originally Posted by itCbitC View Post
I would like to know how without first rewinding the file and fread()'ing the binary image of the data structure stuff?
A hex editor?
__________________
"I don't suffer from insanity but enjoy every minute of it" - Edgar Allen Poe

http://www.Bloodware.net - Developing free software for the community.
Devil Panther is offline   Reply With Quote
Old 05-18-2009, 09:09 AM   #10
Registered User
 
Join Date: Oct 2008
Location: TX
Posts: 1,262
Quote:
Originally Posted by Devil Panther View Post
If I use a statically sized array, let say with 10 cells, and use only 3: abc\0
It ignores the \0, and writes the all 10 cells: junk.
That's because fwrite() transfers the binary image of the stuff data structure and it doesn't care about how strings are represented.
itCbitC is offline   Reply With Quote
Old 05-18-2009, 09:10 AM   #11
C++ Witch
 
laserlight's Avatar
 
Join Date: Oct 2003
Location: Singapore
Posts: 10,352
Quote:
Originally Posted by Devil Panther
If I use a statically sized array, let say with 10 cells, and use only 3: abc\0
It ignores the \0, and writes the all 10 cells: junk.
That would be fine: after all, when you read back from file, you can ignore whatever is after the null character, as is the normal approach for null terminated strings. Alternatively, you can store the amount of space used.

Quote:
Originally Posted by itCbitC
I would like to know how without first rewinding the file and fread()'ing the binary image of the data structure stuff?
One way would be to open the file in a hex editor.
__________________
C + C++ Compiler: MinGW port of GCC
Build + Version Control System: SCons + Bazaar

Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
laserlight is offline   Reply With Quote
Old 05-18-2009, 09:18 AM   #12
Registered User
 
Join Date: Oct 2008
Location: TX
Posts: 1,262
Quote:
Originally Posted by laserlight View Post
One way would be to open the file in a hex editor.
Cool beans! do you know any good ones for the Unix platform?
itCbitC is offline   Reply With Quote
Old 05-18-2009, 09:21 AM   #13
C++ Witch
 
laserlight's Avatar
 
Join Date: Oct 2003
Location: Singapore
Posts: 10,352
Quote:
Originally Posted by itCbitC
do you know any good ones for the Unix platform?
Your favourite editor (including vi clones and emacs) may support hex editing, or just need a plugin to augment it with hex editing functionality.
__________________
C + C++ Compiler: MinGW port of GCC
Build + Version Control System: SCons + Bazaar

Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
laserlight is offline   Reply With Quote
Old 05-18-2009, 09:28 AM   #14
Kernel hacker
 
Join Date: Jul 2007
Location: Farncombe, Surrey, England
Posts: 15,686
Also, "od" works well for inspecting binary files - it supports printing in various display formats (e.g. octal, hex, decimal, float(? Never used that)) as well as showing records of various lengths.

Edit: Of course, it's only useful for VIEWING content. If you actually need to modify the content, I use "hexl-mode" in Emacs or write a program to make the modification (depending on what I'm actually doing...)

--
Mats
__________________
Compilers can produce warnings - make the compiler programmers happy: Use them!
Please don't PM me for help - and no, I don't do help over instant messengers.

Last edited by matsp; 05-18-2009 at 09:35 AM.
matsp is offline   Reply With Quote
Old 05-18-2009, 09:32 AM   #15
Registered User
 
Join Date: Oct 2008
Location: TX
Posts: 1,262
I'ave used xxd inside vi but it usually shows some mumbo jumbo, nothing intelligible (on my w/s at least).
itCbitC is offline   Reply With Quote
Reply

Tags
binary, file, fwrite, malloc, string

Thread Tools
Display Modes

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Need help with comparing strings (I'm a beginner C programmer) Bandizzle C Programming 2 04-29-2009 10:13 AM
Help with calloc and pointers to strings. sweetarg C Programming 1 10-24-2005 02:28 PM
operator overloading and dynamic memory program jlmac2001 C++ Programming 3 04-06-2003 11:51 PM
Dynamic Toolbars nvoigt Windows Programming 1 01-11-2002 10:21 AM
array of strings + more null C Programming 10 10-01-2001 03:39 PM


All times are GMT -6. The time now is 08:49 PM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.0 RC2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22