Paul Ferris
Paul Ferris

Reputation: 346

Surprising results with std::fstream

I wrote a short program to generate evenly-spaced random digits and save them to a generic text file. If I ask it to generate exactly 786432 digits (spaces every six digits) the output displays as random Chinese and Japanese characters. Why? I'm using standard-library classes for file I/O and 64-bit Xorshift as my PRNG.

The program (compiled under MSVC):

#include <iostream>
#include <fstream>
#include <algorithm>

// From https://en.wikipedia.org/wiki/Xorshift
uint64_t xorsh64star(uint64_t* state)
{
    uint64_t x = *state;
    x ^= x >> 12;
    x ^= x << 25;
    x ^= x >> 27;
    state[0] = x;
    return x * 0x2545F4914F6CDD1D;
}

int main()
{
    uint64_t nDigits = 0;
    uint64_t wordLen = 1;
    std::cout << "How many digits?\n";
    std::cin >> nDigits;
    std::cout << "How many digits/word?\n";
    std::cin >> wordLen;
    std::fstream* txt = new std::fstream("randTxt.txt", std::ios::out);
    std::cout << "writing...";
    uint64_t charCtr = 0;
    uint64_t xorshState = 1103515245U; // GLIB C init constant, from https://www.shadertoy.com/view/XlXcW4
    for (uint64_t i = 0; i < nDigits; i += 1)
    {
        uint64_t rnd = xorsh64star(&xorshState) % uint64_t(9);
        *txt << rnd;
        charCtr += 1;
        if (!(charCtr % wordLen) && charCtr != 1)
        {
            *txt << ' ';
            charCtr += 1;
        }
    }
    std::cout << "finished! :D";
    return 0;
}

Output with 786431 digits: 786431 digits, six digits/space

Output with 786432 digits: 786432 digits, six digits/space

Output with 786433 digits: 786433 digits, six digits/space

Upvotes: 0

Views: 70

Answers (2)

Stefan Stanković
Stefan Stanković

Reputation: 636

Here is the fix. I'm not sure what causes the original problem, but once the if statement is changed to:

if (!(charCtr % wordLen) && charCtr != 1
{
    txt << ' ';
//  charCtr += 1;    // This makes each word after the first 1 digit shorter.
}

the final .txt file is now shown properly, which fixes your notepad viewing problem and all your words now have 6 digits, not just the first one.

enter image description here

Originally, I reproduced the same problem by compiling your code with MSVS17 on Win 10 64bit:

enter image description here

Upvotes: 1

Blastfurnace
Blastfurnace

Reputation: 18652

The answer below is helpful but didn't actually correct the reported issue. The problem was only seen with the Windows notepad.exe editor. It incorrectly displayed the file in a very specific instance. In any case I hope someone finds the answer below useful.


Using new to create the file stream looks unusual and isn't necessary in this code. Doing that also means you would need to use delete to properly flush, close, and destroy the stream object.

Replace this:

std::fstream* txt = new std::fstream("randTxt.txt", std::ios::out);

with:

std::fstream txt("randTxt.txt", std::ios::out);

and your writes will look like:

txt << rnd;

When the stream object goes out of scope it will nicely close the file and release any resources it held.

Upvotes: 1

Related Questions