C++ 从文件读取:C到C++;

C++ 从文件读取:C到C++;,c++,c,input,io,inputstream,C++,C,Input,Io,Inputstream,我一直试图在C/C++中读取一个文件,并且能够在C中读取,但是我在C++中遇到了一些问题 背景:我试图读取的文件具有以下结构 i = %3d; j = %3d; a = %3d; b = %3d; i = %3d; j = %3d; a = %3d; b = %3d; ... 在C中工作的代码如下: #include <stdio.h> #include <fstream> #define MAXSIZE 32 int main() { FILE* input

我一直试图在
C/C++
中读取一个文件,并且能够在
C
中读取,但是我在
C++
中遇到了一些问题

背景:我试图读取的文件具有以下结构

i = %3d; j = %3d; a = %3d; b = %3d;
i = %3d; j = %3d; a = %3d; b = %3d;
...
C
中工作的代码如下:

#include <stdio.h>
#include <fstream>
#define MAXSIZE 32

int main()
{
    FILE* inputfile = fopen("temp.txt","r");
    int i,j,a,b;

    while (!feof(inputfile))
    {
        fscanf(inputfile,
            "i = %3d; "
            "j = %3d; "
            "a = %3d; "
            "b = %3d;\n",
            &i, &j, &a, &b);

        printf("%3d %3d %3d %3d\n", i,j,a,b);
    }

    fclose(inputfile);
    return 0;
}
但我不太确定如何格式化
inputfile>>“i=“>>i>>”j=“>>j>>”a=“>>a>>”b=“>>b>>”;\n
任何帮助都将不胜感激。谢谢


编辑:我面临的问题是,最后一行的格式不正确。因为我的文件是问题中所述的格式,所以我不能写
inputfile>>I>>j>>a>>b

只需使用原始代码即可。在各方面都更好:

  • 它可以工作(除非文件以空行结尾,请参见下文)
  • 它经过测试
  • 它跑得更快
  • 在C和C++中都是完全有效的。
  • 它编译得更快
但是,我将提供一个改进:

while (4 == fscanf(inputfile,
        "i = %3d; "
        "j = %3d; "
        "a = %3d; "
        "b = %3d;\n",
        &i, &j, &a, &b))
{
    printf("%3d %3d %3d %3d\n", i,j,a,b);
}
if (!feof(inputfile)) {
    // read failed and the reason wasn't hitting the end of the file
    // maybe you've been keeping track of line numbers and
    // can report where the invalid input was found
}
在尝试读取之前测试EOF为时过早。EOF标志仅在读取到达文件末尾后设置。如果最后一次成功读取实际找到了
“\n”
,则不会设置EOF。iostreams代码也有同样的bug,除了处理中间文本的问题



注:您永远不会注意到用户输入的速度差,甚至终端输出的速度差。但是对于文件I/O(包括重定向的stdin或stdout),stdio.h函数比iostreams好得多。

只需使用原始代码即可。在各方面都更好:

  • 它可以工作(除非文件以空行结尾,请参见下文)
  • 它经过测试
  • 它跑得更快
  • 在C和C++中都是完全有效的。
  • 它编译得更快
但是,我将提供一个改进:

while (4 == fscanf(inputfile,
        "i = %3d; "
        "j = %3d; "
        "a = %3d; "
        "b = %3d;\n",
        &i, &j, &a, &b))
{
    printf("%3d %3d %3d %3d\n", i,j,a,b);
}
if (!feof(inputfile)) {
    // read failed and the reason wasn't hitting the end of the file
    // maybe you've been keeping track of line numbers and
    // can report where the invalid input was found
}
在尝试读取之前测试EOF为时过早。EOF标志仅在读取到达文件末尾后设置。如果最后一次成功读取实际找到了
“\n”
,则不会设置EOF。iostreams代码也有同样的bug,除了处理中间文本的问题



注:您永远不会注意到用户输入的速度差,甚至终端输出的速度差。但是对于文件I/O(包括重定向的stdin或stdout),stdio.h函数比iostreams好得多。

假设您可以忽略
I=
j=
等等,只需要读取数字,一种可能是创建一个将这些字符分类为空白的ctype方面。向流注入包含该方面的区域设置,然后读取您的数字:

#include <iostream>
#include <algorithm>
#include <locale>
#include <vector>
#include <sstream>

struct digits_only: std::ctype<char> {
    digits_only(): std::ctype<char>(get_table()) {}

    static std::ctype_base::mask const* get_table() {
        static std::vector<std::ctype_base::mask> 
            rc(std::ctype<char>::table_size,std::ctype_base::space);

        std::fill(&rc['0'], &rc['9'], std::ctype_base::digit);
        return &rc[0];
    }
};

class record {
    int i, j, a, b;
public:
    friend std::istream &operator>>(std::istream &is, record &r) {
        return is >> r.i >> r.j >> r.a >> r.b;
    }

    friend std::ostream &operator<<(std::ostream &os, record const &r) {
        return os << r.i << "\t" << r.j << "\t" << r.a << "\t" << r.b;
    }
};

int main() {
    std::stringstream in("i=1 j = 2 a = 10 b = 20\ni = 3 j = 4 a = 30 b = 40");
    std::locale numbers(std::locale(), new digits_only);
    in.imbue(numbers);

    std::vector<record> records{ std::istream_iterator<record>(in),
                                 std::istream_iterator<record>() };

    std::cout << "i\tj\ta\tb\n";
    for (auto const & r : records)
        std::cout << r << "\n";
}
#包括
#包括
#包括
#包括
#包括
仅限结构数字:std::ctype{
digits_only():std::ctype(get_table()){
静态std::ctype_base::mask const*get_table(){
静态std::vector
rc(std::ctype::table_size,std::ctype_base::space);
std::fill(&rc['0'],&rc['9'],std::ctype_base::digit);
返回&rc[0];
}
};
课堂记录{
int i,j,a,b;
公众:
friend std::istream&operator>>(std::istream&is,record&r){
返回值为>>r.i>>r.j>>r.a>>r.b;
}

friend std::ostream&operator假设您可以忽略
i=
j=
等等,只需要读取数字,一种可能是创建一个ctype方面,将这些字符分类为空白。在流中插入包含该方面的区域设置,然后读取您的数字:

#include <iostream>
#include <algorithm>
#include <locale>
#include <vector>
#include <sstream>

struct digits_only: std::ctype<char> {
    digits_only(): std::ctype<char>(get_table()) {}

    static std::ctype_base::mask const* get_table() {
        static std::vector<std::ctype_base::mask> 
            rc(std::ctype<char>::table_size,std::ctype_base::space);

        std::fill(&rc['0'], &rc['9'], std::ctype_base::digit);
        return &rc[0];
    }
};

class record {
    int i, j, a, b;
public:
    friend std::istream &operator>>(std::istream &is, record &r) {
        return is >> r.i >> r.j >> r.a >> r.b;
    }

    friend std::ostream &operator<<(std::ostream &os, record const &r) {
        return os << r.i << "\t" << r.j << "\t" << r.a << "\t" << r.b;
    }
};

int main() {
    std::stringstream in("i=1 j = 2 a = 10 b = 20\ni = 3 j = 4 a = 30 b = 40");
    std::locale numbers(std::locale(), new digits_only);
    in.imbue(numbers);

    std::vector<record> records{ std::istream_iterator<record>(in),
                                 std::istream_iterator<record>() };

    std::cout << "i\tj\ta\tb\n";
    for (auto const & r : records)
        std::cout << r << "\n";
}
#包括
#包括
#包括
#包括
#包括
仅限结构数字:std::ctype{
digits_only():std::ctype(get_table()){
静态std::ctype_base::mask const*get_table(){
静态std::vector
rc(std::ctype::table_size,std::ctype_base::space);
std::fill(&rc['0'],&rc['9'],std::ctype_base::digit);
返回&rc[0];
}
};
课堂记录{
int i,j,a,b;
公众:
friend std::istream&operator>>(std::istream&is,record&r){
返回值为>>r.i>>r.j>>r.a>>r.b;
}

friend std::ostream&operatorso您面临什么问题?您真的需要验证是否存在
i=
j=
,等等,还是忽略它们并读取数字就可以了?@jayeshbhoi嗨,我已经编辑了这个问题,希望能澄清问题的焦点。@JerryCoffin,我已经尝试了
inputfile>>i>>j>>a>>b;
,得到了一个具有恒定输出的无限循环
0-2 937351794 2007600341
。我认为缺少
\n
意味着它没有移动到下一行。@BlackAdder:那么倒数第二行是如何格式化的?如果没有我们真正应该读取的内容的线索,很难建议如何读取数据。那么问题是什么呢你面对的是什么?你真的需要验证
i=
j=
等等的存在吗?还是可以忽略它们并读取数字?@jayeshbhoi嗨,我编辑了这个问题,希望能澄清问题的焦点。@JerryCoffin,我试过
inputfile>>i>>j>>a>>b;
,有一个无限的厕所p具有恒定输出
0-2 937351794 2007600341
。我认为缺少
\n
意味着它没有移动到下一行。@BlackAdder:那么倒数第二行的格式是什么呢?在没有我们真正应该阅读的线索的情况下,很难建议如何读取数据。我只是想提到eof/feof的东西。打得好。我知道了It’我只想提一下eof/feof的事。打得好。