• Advertisement
Sign in to follow this  

sscanf EOF equivalent?

This topic is 3571 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm trying to load a text file in memory which I then want to read. I looked around on the web for a trick/workaround to still use fread etc. I assume it's not possible (however in Turbo Pascal you could change the function pointers of open, inout, flush and close inside the TextRec, like C's FILE struct, to let Tubo Pascal's equivalent of fread act on a file in memory. C's FILE struct doesn't contain function pointers however). I think a way to get this accomplished is to load a text file in memory binairically and to use sscanf:
	FILE* fp;
	char buffer[200];
	char token[100];
	char token2[100];
	memset(token, 0, 100);
	fp = fopen("test.txt", "rb");
	int a = fread(buffer, 1, 200, fp);
	if (feof(fp))
	{
		buffer[a] = '\0';
	}
        // gives 1 back, since the only thing in the text file is the text "cpp"
	int h = sscanf(buffer, "%s %s", token, token2);

	// EOF for sscanf?

	fclose(fp);
	return 0;


But how can I detect a EOF-like (end of buffer) for sscanf? I used a NULL terminator to mark the end of the buffer/text. But there's no thing that reacts on that as far as know. To compare how much should have been read is no option for me since I don't know how large the file is/what comes. Thanks

Share this post


Link to post
Share on other sites
Advertisement
Well, fread returns the size of what was read, so if it hit an EOF then the return value is going to be smaller than the buffer you asked it to read (so you will know if the fread return is smaller than size*count, you hit an EOF or an error).

You could also use fseek with SEEK_END to determine how big the file is in the first place.

It might be easier for you to use fscanf (the file version of sscanf) in the first place, though. Or you might consider using iostream's fstream and use getline to go line by line (assuming you don't mind using STL) if that's of interest.

Share this post


Link to post
Share on other sites
My idea is to read it from memory because it's part from a large file that contains all files (like textures) so I can't use fscanf etc. I don't want to use STL.

The sizes of the buffer in the sample code is to explain, normally I would allocate the size of the file (for example 120 kb) in memory for the file.

Or can I try to see if sscanf returs zero (or a few times)? In that case sscanf shouldn't go beyond the NULL terminator to let the detection work.

Share this post


Link to post
Share on other sites
IIRC a unix system using fread is buffered, but windows is not; if you are looking for a multi platform method then you may be buffering the data twice. If the file is large then you may want to look a VirualAlloc or mmap.

Share this post


Link to post
Share on other sites
Ah. Okay.

I guess I'm not really sure why you would care. If there's no data, it won't pull that data out in the sscanf. Granted you might have some issues due to the fact that fread doesn't bother clearing the buffer post-EOF, but you can fix that by either using a memset of \0 to the entire buffer prior to doing the fread, or by setting the entire rest of the buffer to \0 if you hit an EOF (really, the former is probably a better idea).

If you're worried about significant differences between the size of the buffer you allocated and the actual size read, then you might try using fseek to figure out how big your buffer needs to be, and dynamically allocate it for your fread.

Share this post


Link to post
Share on other sites
Quote:
Original post by rmdeboer82
My idea is to read it from memory because it's part from a large file that contains all files (like textures) so I can't use fscanf etc. I don't want to use STL.

The sizes of the buffer in the sample code is to explain, normally I would allocate the size of the file (for example 120 kb) in memory for the file.

Or can I try to see if sscanf returs zero (or a few times)? In that case sscanf shouldn't go beyond the NULL terminator to let the detection work.



Why is fscanf not an option? It's effectively the same thing as loading the file into a buffer and using sscanf... except it doesn't have the memory overhead of the buffer.

Anyways, if you insist on using the buffer, use stat to get the file size - it's a little nicer than using fseek and checking the offset.


(And, by the way, refusing to use STL is pointless and unwise. Why why why do you want to avoid a wonderful tool that helps you work faster and more safely?)

Share this post


Link to post
Share on other sites
Quote:
Original post by ApochPiQ
Why is fscanf not an option? It's effectively the same thing as loading the file into a buffer and using sscanf... except it doesn't have the memory overhead of the buffer.


I want to encrypt the contents of the main file containing all other files (preventing messing around with the data by users). So I want it just like D3DXCreateTextureFromFileInMemory().

Quote:
Original post by ApochPiQ
Anyways, if you insist on using the buffer, use stat to get the file size - it's a little nicer than using fseek and checking the offset.


I'm using VC++ Visual Studio for Windows, I assume it shouldn't be a problem. However http://www.codeproject.com/KB/files/filesize.aspx notes a pitfall "stat() isn't necessarily precise."

Quote:
Original post by ApochPiQ
(And, by the way, refusing to use STL is pointless and unwise. Why why why do you want to avoid a wonderful tool that helps you work faster and more safely?)


I tried using some STL functions but somehow memory was gone so I sticked to simpler methods (I don't know that much about STL).

felisandria: sscanf will not read beyond \0 (it returns -1 reading a \0), so there's a way to detect the end of the buffer (only in the case of text files). However, sscanf doesn't use an internal offset within the buffer that should be incremented after a read. So I guess one will need to adjust a pointer to a location within the buffer like:


char* AdjustOffset(char* lpszOffset)
{
char *lpszIndex = lpszOffset;

// Invalid pointer?
if(lpszIndex == NULL) return NULL;

// Skip preceding white space
while(isspace(*lpszIndex))
{
lpszIndex++;

// Since sscanf will be used to determine completion
// Letting sscanf checking the NULL terminator will be sufficient
// The NULL terminator will act as a non-space
if(*lpszIndex == '\0') return lpszIndex;
}

// Skip the non-space sequence that sscanf will find
while(!isspace(*lpszIndex))
{
lpszIndex++;

// Since sscanf will be used to determine completion
// letting sscanf checking the NULL terminator will be sufficient
// The NULL terminator will act as a non-space
if(*lpszIndex == '\0') return lpszIndex;
}

// The index will be after the non-space sequence
return lpszIndex;
}

.
:
:
.
char* bufloc = &buffer[0];

int q = sscanf(bufloc, "%s", token2);

// End of buffer (NULL terminator) or error? -> Done reading file from
// memory
if (q == -1) return;

// Let the index run parallely
bufloc = AdjustOffset(bufloc);

q = sscanf(bufloc, "%s", token2);

// End of buffer (NULL terminator) or error? -> Done reading file from
// memory
if (q == -1) return;

// Let the index run parallely
bufloc = AdjustOffset(bufloc);
.
:
:
.






[Edited by - rmdeboer82 on July 12, 2008 6:07:48 AM]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement