Hi, I'm trying to work on a program to read 'default' values from a txt document (conveniently named default.txt). However when I run the program it will print what is in the text document, and add an extra few random characters on the end. Here's my code so far:
#include <stdio.h>
#include <stdlib.h>
usingnamespace std;
int main()
{
// Declare Variables
unsignedlong filesize;
char* buffer;
size_t reading;
// Create File, if file exists open it with read+write abilities; else
// create a new file with read+write abilities
FILE *dfile;
fpos_t beginning;
dfile = fopen("default.txt", "rb+");
if (dfile == NULL)
dfile = fopen("default.txt", "wb+");
if (dfile == NULL)
{
printf ("Error 1: Could not open/create file");
exit(1);
}
fgetpos(dfile, &beginning);
// Find file size
fseek(dfile, beginning, SEEK_END);
filesize = ftell(dfile);
rewind(dfile);
// Create memory space for file
buffer = (char*)malloc(filesize);// No need to get size of char, sizeof(char)=1
if (buffer==NULL)
{
printf ("Error 2: Could not allocate memory to open file");
exit(2);
}
// Put file into buffer
reading = fread(buffer, 1, filesize, dfile);
if (reading!=filesize)
{
printf ("Error 3: Could not read file");
exit(3);
}
buffer[filesize]='\0'; // <<<------- Set the last char in the buffer to the null terminator
printf("%s",buffer);
fclose (dfile);
free (buffer);
return 0;
}
Thank you so much. I thought it was something to do with the nul character but i was thinking that i was reading it, not missing it. Can I ask you if this program is 'efficient'? I'm not the best programmer and am trying to learn to be efficient as i go.
Your title says "C++" but your code it pretty much all "C". Is this what you want? Or would you consider swapping to use the C++ std::fstream?
Also, you talk about reading default values from a text file. Is this file formatted in any particular way? Is it line based??
As you're reading the text as a single block, you're going to have to do your own per line parsing if necessary. If it is line based, it might be better to let the i/o library handle the buffering and just read a line at a time (using std::getline or even operator<< with C++, or fgets() for POSIX) and process the values as you go. Or do you need the complete file in one block for a particuar reason?
- Stream i/o (fopen, fclose, fread, fgets, ...) uses a buffering mechanism. So calls to fread/fgets for small amounts of data are efficient.
- Low level i/o (open, close, read, ...) are unbuffered. The stream i/o uses these calls to get the data and stores it in a buffer.
The buffer size is system dependent, but you can change it using setbuf and setvbuf. However, I'd expect a typical config file to be small enough for the default buffer size to be ok.
Andy
P.S. There is also a POSIX getline() call, for some variants of Linux, which works with stream i/o. It is a smarter version of fgets(), but I've not used it. I use std::getline().