1

I am tring to use seekg to move the pos and then read a line from the .txt. However, I can not get the same string(a completed line) after using seekp, though the pos is same.

The compiler is MinGW 11.2.0 64-bit on x86 windows 11

Here is the test.txt

2   33.10   30.10   29.90   33.00   33.20   33.00   32.90   33.10   40.20   40.20   40.00   39.90   40.30   37.20   40.30   36.70
4   33.00   30.10   29.90   33.00   33.10   32.90   32.90   33.00   40.30   40.20   40.00   40.00   40.30   37.30   40.20   36.70
6   33.00   30.10   29.90   33.00   33.10   33.00   32.90   33.00   40.20   40.30   40.10   40.00   40.20   37.20   40.10   36.90

Here is my code.

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main(){
string file_path = "./test.txt";
string s;
// don't use seekg
fstream f(file_path);
    getline(f, s);
    int p = f.tellg();
    cout << "the cur pos is:" << p << endl;
    getline(f, s);
    cout << s << endl;
    getline(f, s);
    cout << s << endl;
    f.close();

// use seekg
    fstream t(file_path);
    t.seekg(p, ios::beg);
    p = t.tellg();
    cout << "the cur pos is:" << p << endl;
    getline(t, s);
    cout << s << endl;
}

And the output

the cur pos is:139
2   33.10   30.10   29.90   33.00   33.20   33.00   32.90   33.10   40.20   40.20   40.00   39.90   40.30   37.20   40.30   36.70
4   33.00   30.10   29.90   33.00   33.10   32.90   32.90   33.00   40.30   40.20   40.00   40.00   40.30   37.30   40.20   36.70
the cur pos is:139
2.90    33.10   40.20   40.20   40.00   39.90   40.30   37.20   40.30   36.70

For supplement, here is the string s in memory.

2\t33.10\t30.10\t29.90\t33.00\t33.20\t33.00\t32.90\t33.10\t40.20\t40.20\t40.00\t39.90\t40.30\t37.20\t40.30\t36.70

4\t33.00\t30.10\t29.90\t33.00\t33.10\t32.90\t32.90\t33.00\t40.30\t40.20\t40.00\t40.00\t40.30\t37.30\t40.20\t36.70

2.90\t33.10\t40.20\t40.20\t40.00\t39.90\t40.30\t37.20\t40.30\t36.70

I don't know if it's the problem that there are \ts in the string.

So how can I solve this problem and get a completed line using seekg? It would be appreciated if someone can give me a hand.

Malloc
  • 41
  • 6
  • Could you please present a [Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example) or [SSCCE](http://sscce.org/) So we have something we can copy'n'paste, compile, run and reproduce? That makes it a *lot* easier to [debug](https://stackoverflow.com/questions/25385173/what-is-a-debugger-and-how-can-it-help-me-diagnose-problems) the code and help you. – Jesper Juhl Jun 13 '23 at 01:33
  • 1
    Ok, I'll do this.@JesperJuhl – Malloc Jun 13 '23 at 01:35
  • 1
    I create `test.txt` with the data you gave and copy your source to `test.cc`, compile as `$ g++ -Wall -Wextra -O3 test.cc` and then run `$ ./a.out` I get this output: `the cur pos is:130 4 33.00 30.10 29.90 33.00 33.10 32.90 32.90 33.00 40.30 40.20 40.00 40.00 40.30 37.30 40.20 36.70 6 33.00 30.10 29.90 33.00 33.10 33.00 32.90 33.00 40.20 40.30 40.10 40.00 40.20 37.20 40.10 36.90 the cur pos is:130 4 33.00 30.10 29.90 33.00 33.10 32.90 32.90 33.00 40.30 40.20 40.00 40.00 40.30 37.30 40.20 36.70` – Jesper Juhl Jun 13 '23 at 01:47
  • It's weird. You get the output that I need, maybe there is something else wrong with my code. Thanks for your test!@JesperJuhl – Malloc Jun 13 '23 at 01:54
  • What compiler are you using? What compiler version? What build flags? What operating system? I'm using `g++ (GCC) 13.1.1 20230429` with `-Wall -Wextra -O3` on Arch Linux. Don't answer in a comment, edit your question to add that extra info. – Jesper Juhl Jun 13 '23 at 01:59
  • I also tried building your code with both address sanitizer and undefined behaviour sanitizer and none of those complained either. – Jesper Juhl Jun 13 '23 at 02:01
  • I don't think it is relevant, but I *do* see one difference between the two halfs of your code; you explicitly `f.close();` but you don't do so for the `t` stream - it shouldn't matter since the stream will be `close()`d on destruction, but as a wild guess, maybe try making both explicitly close the stream? – Jesper Juhl Jun 13 '23 at 02:04
  • Actually, once I called the `f.close()` and I still used `f.seekg()`, I incidentally got a completed line.@JesperJuhl – Malloc Jun 13 '23 at 02:10
  • Side note (not relevant to your issue, just wanted to mention it), see [Why is "using namespace std;" considered bad practice?](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice). – Jesper Juhl Jun 13 '23 at 02:14
  • Ok, Thanks a lot!@JesperJuhl – Malloc Jun 13 '23 at 02:21

1 Answers1

1

Remember to specify the open mode, e.g. ios::binary.

I think I have found the problem. When I open the file, I should specific the mode, e.g., ios::binary. Without that specification, the offset which tellg() returns may be not accurate under some conditions.

So I change

fstream f(file_path);

to

fstream f(file_path, ios::in | ios::binary);

And the value of tellg() gets smaller, which works for me.

Jesper Juhl
  • 30,449
  • 3
  • 47
  • 70
Malloc
  • 41
  • 6
  • Ohh, that actually makes sense. I got different results than you since the file got interpreted differently on Linux and Windows. But, as a binary file, there's no difference - it's all just bytes. Damn, should have cought that. – Jesper Juhl Jun 13 '23 at 02:41
  • 1
    Hhh, really appreciate for your test which leads me to pay attention to the offset. Thanks!@JesperJuhl – Malloc Jun 13 '23 at 02:44