C++ Outputting and Inputting form Txt

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:

main.cpp file

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <stdio.h>
#include <stdlib.h>


using namespace std;

int main()
{
    // Declare Variables
    unsigned long 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 (sizeof(char)*filesize);
    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);
    }

    printf("%s", buffer);

    fclose (dfile);
    free (buffer);
    return 0;
}




default.txt file

1
2
altitude 1000
speed 50

Last edited on
The problem is that you didnt set the last character of the buffer to be a null terminator '\0'
here is the new code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <stdio.h>
#include <stdlib.h>
using namespace std;

int main()
{
// Declare Variables
    unsigned long 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.
Hi

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().
Last edited on
Topic archived. No new replies allowed.