【问题标题】:how does mnist file is read through following code.如何通过以下代码读取 mnist 文件。
【发布时间】:2016-07-10 13:37:02
【问题描述】:

我有一个关于阅读 MNIST 数据集的问题。我了解了如何构建 MNIST 数据集。但是,我不知道它是如何读取以下代码的。你们中的一些人可能认为 couts 的结果是显而易见的(我写了 values 作为评论)。但是对我来说这没有意义,因为它使用相同的输入四次使用相同的确切功能,但每次都会得到不同的输出。这怎么可能?如果我的问题有任何歧义,请告诉我。

谢谢。

代码开始:

    typedef unsigned char BYTE;

int main()
{

...

FILE *fp = fopen("MNIST/train-images.idx3-ubyte", "rb");

    // delcare function;
    int magicNumber = readFlippedInteger(fp);
    int numImages = readFlippedInteger(fp);
    int numRows = readFlippedInteger(fp);
    int numCols = readFlippedInteger(fp);

    cout << magicNumber << endl;   // 2051
    cout << numImages << endl;     // 60000
    cout << numRows << endl;       // 28
    cout << numCols << endl;       // 28
...

}

int readFlippedInteger(FILE *fp)
{
    int ret = 0;

    BYTE *temp;

    temp = (BYTE*)(&ret);
    fread(&temp[3], sizeof(BYTE), 1, fp);
    fread(&temp[2], sizeof(BYTE), 1, fp);
    fread(&temp[1], sizeof(BYTE), 1, fp);
    fread(&temp[0], sizeof(BYTE), 1, fp);

    return ret;
}

【问题讨论】:

  • readFlippedInteger 每次调用时都会从文件中读取 4 个字节。

标签: opencv c++11 mnist


【解决方案1】:

除非绝对必要,否则请不要混合使用 C 和 C++。潜在的混淆是对fread 的调用会为您在文件中“移动”文件指针。正如@RetiredNinja 指出的那样,您一次将文件指针推进4 个字节。这就是它“知道”如何读取下一个值的方式,即使您没有明确告诉它。你可以阅读所有关于文件指针here


使用更惯用的 C++ 的实现可能是

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

int readFlippedInteger(std::istream &in) {
    char temp[sizeof(int)];
    in.read(temp, sizeof(int));
    std::reverse(temp, temp+sizeof(int));
    return *reinterpret_cast<int*>(temp);
}

int main() {
    std::ifstream fin("MNIST/train-images.idx3-ubyte", std::ios::binary);

    if (!fin) {
        std::cerr << "Could not open file\n";
        return -1;
    }

    // delcare function;
    int magicNumber = readFlippedInteger(fin);
    int numImages = readFlippedInteger(fin);
    int numRows = readFlippedInteger(fin);
    int numCols = readFlippedInteger(fin);

    std::cout << magicNumber << std::endl // 2051
              << numImages << std::endl   // 60000
              << numRows << std::endl    // 28
              << numCols << std::endl;  // 28
}

使用用户定义的流操纵器的实现留给读者作为练习。

【讨论】:

  • 谢谢蒂姆!我什至不知道我在混合 C 和 C++。由于我正在从不同的项目中复制大部分代码,因此有时我真的很难理解.. 该链接真的很有帮助!非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-02-20
  • 1970-01-01
  • 2015-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-30
相关资源
最近更新 更多