在文本文件中移动 C++

Moving through text file c++

我正在尝试以相反的顺序将数字从第一个 txt 文件保存到第二个文件。 需要明确的是,在 1st txt 中,我输入了从 1 到 10 的数字(十进制)。当我尝试计算它们时,我得到 5 或 7,具体取决于它们之间的值(space 或输入)。

然后,另一个错误是在第 2 个 txt 程序中保存了与 dl 的变量值相等的“0”,而不是按相反顺序加载的数字。

我粘贴了整个代码,因为我不知道文件操作规则是否足够好来确定哪个部分可能是问题的根源。提前谢谢你。

#include <fstream>
#include <iostream>

using namespace std;

int main() {
    fstream plik1;
    plik1.open("L8_F3_Z2a.txt", ios::in | ios::binary);
    fstream plik2;
    plik2.open("L8_F3_Z2b.txt", ios::out);

    if(!plik1.good() || !plik2.good()) {
        cout << "file(s) invalid" << endl;
        return 1;
    }

    plik1.seekg(0, ios::end);
    int dl = plik1.tellg() / sizeof(int);

    cout << "length = " << dl << endl;

    int a;
    for(int i = 0; i < dl; i++) {
        plik1.seekg((i + 1) * sizeof(int), ios::end);
        plik1 >> a;
        plik2 << a;
        cout << i + 1 << ". a = " << a << endl;
    }
    plik1.close();
    plik2.close();
    return 0;
}

编辑 输出为:

length = 7 1. a = 0 2. a = 0 3. a = 0 4. a = 0 5. a = 0 6. a = 0 7. a = 0 -------------------------------- Process exited after 0.03841 seconds with return value 0 Press any key to continue . . .

问题

当文件被编码为文本时,数据的二进制大小无关紧要。

int dl = plik1.tellg() / sizeof(int);

将为您提供文件的整数部分,但文件不存储整数。它正在存储字符流。例如,文件包含一个数字:

12345

长度为五个字符。假设文件使用良好的 ol ASCII,即 5 个字节。当 12345 转换为 int 时,它可能是 4 或 8 个字节,几乎肯定不是 5 个字节。假设普通32位(4字节)int

int dl = plik1.tellg() / sizeof(int);
int dl = 5 / 4;
int dl = 1;

耶!有效!但只有通过你崇拜的任何神灵或宇宙实体的恩典。要么不拜。我不会去评判。为了说明为什么你不能指望这个,让我们看看

123

这是三个字符和3个字节,所以

int dl = plik1.tellg() / sizeof(int);
int dl = 3 / 4;
int dl = 0;

糟糕。

同样

1 2 3 4 5

是五个数字。文件长度可能是每个数字一个字节和每个 space 一个字节的总和,9 个字节。

有些系统变得奇怪,看着你 Windows,使用两个字符的行尾标记、回车符 return 和换行符。这意味着

1 
2 
3 
4 
5

总计为 13 个字节。

这就是为什么您会看到不同大小的原因,具体取决于数字是用 space 还是换行分隔。

解决方案

找出文件中有多少数字的唯一方法是读取文件,将内容转换为数字,并在找到数字时计算数字。

怎么做:

int num;
int count = 0;
while (plik1 >> num) // read numbers until we can't read any more
{
    count++;
}

由此您可以确定所需数组的大小。然后你倒回文件,回到开头,分配数组并将文件再次读入数组。这是愚蠢的。文件 IO 非常慢。你不想做两次。您想读取文件一次并随时存储,而不关心文件中有多少数字。

幸运的是,C++ 中内置了许多工具,它们正是这样做的。我喜欢std::vector

std::vector<int> nums;
int num;
while (plik1 >> num)
{
    nums.push_back(num); 
}

vector 甚至为你数数。

接下来你可以

std::reverse(nums.begin(), nums.end());

并将结果写回。

for (int num: nums)
{
    plik2 << num << ' ';
}

Documentation for std::reverse

如果您的讲师没有 vector 政策,而 unfortunately 很多人有,那么最好的办法是编写自己的 vector 简单版本。 Stack Overflow 上已经有很多关于如何执行此操作的示例。

附录

在二进制中,5 个整数可能是 20 或 40 个字节,无论使用多少位并且不需要分隔符。

这听起来像蜜蜂膝盖一样将数据存储为二进制,对吧?就像它会变得容易得多。

但事实并非如此。不同的计算机和不同的编译器使用 different sizes for integers. All you are guaranteed is an int is at least 2 bytes and no larger than a long. All of the integer types could be exactly the same size at 64 bits. Blah. Worse, not all computers store integers in the same order. 因为如果数字向后存储,做一些操作会更容易,你猜怎么着?通常数字是倒着存储的。您必须非常非常小心地处理二进制数据,并建立一个数据协议(有关此主题的更多信息的搜索词:序列化)来定义每个人如何解释数据。