首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从文件读取:C到C++

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

Stack Overflow用户
提问于 2014-02-03 05:38:12
回答 2查看 232关注 0票数 0

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

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

代码语言:javascript
复制
i = %3d; j = %3d; a = %3d; b = %3d;
i = %3d; j = %3d; a = %3d; b = %3d;
...

C中工作的代码如下:

代码语言:javascript
复制
#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;
}

在尝试用C++编写这个程序时,我尝试过:

代码语言:javascript
复制
int main()
{
    ifstream inputfile( "temp.txt" ,ios::in);
    int i,j,a,b;

    while (!std::cin.eof())
    {
        inputfile >> "i = " >> i >> "; j = " >> j >> "; a = " >> a >> "; b = " >> b >> ";\n";
        printf("%3d %3d %3d %3d\n", i,j,a,b);
    }
    return 0;
}

但我不太确定该如何格式化

inputfile >> "i = " >> i >> "; j = " >> j >> "; a = " >> a >> "; b = " >> b >> ";\n";

任何帮助都将不胜感激。谢谢!

编辑:,我面临的问题是,最终的行没有以正确的方式格式化。因为我的文件是问题中所述的形式,所以我不能写inputfile >> i >> j >> a >> b;

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-02-03 07:08:58

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

代码语言:javascript
复制
#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";
}

至于这比仅仅使用scanf更好还是更糟,我想说,这是一个值得质疑的问题。这显然是更长的整体。OTOH,上面代码中的很多额外长度来自于我决定将ijab包装成自己的结构。虽然这只是猜测,但我的猜测是,在任何情况下,你都可能想这么做。

作为额外长度的交换,您可以获得类型安全性,如果您的代码中有几个不同的部分需要读取这样的记录,那么就更方便了。

与Ben的说法相反,实际测试表明,使用iostreams的I/O可以与C的stdio函数完全竞争(在某些情况下更快)。我还没有对这个特殊情况进行足够的测试,以确定它是更快、更慢还是差不多,但我已经做了足够多的其他测试,以合理肯定地说,C的stdio函数将大大加快的结论还远远没有定论。

底线:继续使用scanf可能是一个不错的选择--但话又说回来,它可能也不是。

票数 1
EN

Stack Overflow用户

发布于 2014-02-03 06:12:10

只需使用原始代码。从各个方面看都更好:

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

不过,我会提出一个改善:

代码语言:javascript
复制
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代码还有相同的错误。

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

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21520432

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档