如何使用 C++ 优雅地读取整数溪流?

发布于 2024-10-13 01:51:12 字数 121 浏览 4 评论 0原文

我有一个充满这种格式行的文件:

1 - 2: 3

我只想使用 C++ 流加载数字。最优雅的方法是什么?我只考虑了 cin.get() 并检查每个字符是否是数字。

I have a file full of lines in this format:

1 - 2: 3

I want to only load numbers using C++ streams. Whats the most elegant way to do it? I only thought about cin.get() and checikng each char if it is number or not.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

月竹挽风 2024-10-20 01:51:12

我认为这将是最快但又优雅的方式:

int a, b, c;
scanf("%d-%d:%d", &a, &b, &c);

I think this one would be the fastest -yet elegant- way:

int a, b, c;
scanf("%d-%d:%d", &a, &b, &c);
救星 2024-10-20 01:51:12

您可以使用 区域设置 来更改从文件中读取的内容读。也就是说,您将过滤掉所有非数字值:

struct numeric_only: std::ctype<char> 
{
    numeric_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[':'], std::ctype_base::digit);
        return &rc[0];
    }
};

std::fstream myFile("foo.txt");
myfile.imbue(std::locale(std::locale(), new numeric_only()));

然后,当您读取文件时,它会将所有非数字转换为空格,而只留下数字。之后,您可以简单地使用正常转换将正在读取的内容转换为整数。

std::vector<int> intFromFile;
std::istream_iterator<int> myFileIter(myFile);
std::istream_iterator<int> eos;
std::copy(myFileIter, eos, std::back_inserter(intFromFile));

对以下评论的回应:

这是我为使其发挥作用所做的工作

int main(int args, char** argv){
    std::fstream blah;
    blah.open("foo.txt", std::fstream::in);
    if(!blah.is_open()){
        std::cout << "no file";
        return 0;
    }
    blah.imbue(std::locale(std::locale(), new numeric_only()));

    std::vector<int> intFromFile;
    std::istream_iterator<int> myFileIter(blah);
    std::istream_iterator<int> eos;
    std::copy(myFileIter, eos, std::back_inserter(intFromFile));

   return 0;
}

,这仅将整数放入向量中,仅此而已。它之前不起作用的原因有两个:

  1. 我填充到“9”,但没有填充“9”本身。我已将填充更改为“:”
  2. 大于 int 可以容纳的数字是一个问题。我建议使用长整型。

You can use a locale to change what things are read from the file as it is being read. That is, you will filter out all non-numeric values:

struct numeric_only: std::ctype<char> 
{
    numeric_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[':'], std::ctype_base::digit);
        return &rc[0];
    }
};

std::fstream myFile("foo.txt");
myfile.imbue(std::locale(std::locale(), new numeric_only()));

Then when you read your file, it'll convert all non digits to spaces while leaving you only the numbers. After that, you can simply use your normal conversions to transform what is being read into ints.

std::vector<int> intFromFile;
std::istream_iterator<int> myFileIter(myFile);
std::istream_iterator<int> eos;
std::copy(myFileIter, eos, std::back_inserter(intFromFile));

Response to the comments below:

Here is what I did to get it to work

int main(int args, char** argv){
    std::fstream blah;
    blah.open("foo.txt", std::fstream::in);
    if(!blah.is_open()){
        std::cout << "no file";
        return 0;
    }
    blah.imbue(std::locale(std::locale(), new numeric_only()));

    std::vector<int> intFromFile;
    std::istream_iterator<int> myFileIter(blah);
    std::istream_iterator<int> eos;
    std::copy(myFileIter, eos, std::back_inserter(intFromFile));

   return 0;
}

And this put only the ints into the vector, nothing more, nothing less. The reason it wasn't working before was two fold:

  1. I was filling up to '9' but not '9' itself. I've changed the fill to ':'
  2. Numbers larger than what an int can hold are a problem. I'd suggest using longs.
橪书 2024-10-20 01:51:12

我建议在阅读本文时至少进行粗略完整性检查:

int a, b, c;
char dash, colon;

if (not (cin >> a >> dash >> b >> colon >> c) or dash != '-' or colon != ':')
    Failure. Do something.

I would recommend doing at least cursory sanity checks when reading this:

int a, b, c;
char dash, colon;

if (not (cin >> a >> dash >> b >> colon >> c) or dash != '-' or colon != ':')
    Failure. Do something.
慕巷 2024-10-20 01:51:12

简单地,

ifstream file("file.txt");
int n1, n2, n3;
char tmp;
while (file.good()) {
  file >> n1 >> tmp >> n2 >> tmp >> n3;
}

Simply,

ifstream file("file.txt");
int n1, n2, n3;
char tmp;
while (file.good()) {
  file >> n1 >> tmp >> n2 >> tmp >> n3;
}
动听の歌 2024-10-20 01:51:12
    int a,b,c;

    cin >> a;
    cin.ignore(100,'-');
    cin >> b;
    cin.ignore(100,':');
    cin >> c;

    cout << "a = "<< a <<endl;
    cout << "b = "<< b <<endl;
    cout << "c = "<< c <<endl;

输入:

1 - 2:3

输出:

a = 1
b = 2
c = 3

在这里查看自己: http://www.ideone.com/DT9KJ

注意:这可以还要处理额外的空格。所以你甚至可以阅读这个:

<前>1 - 2 : 3


类似主题:

使用 ifstream 作为 fscanf

    int a,b,c;

    cin >> a;
    cin.ignore(100,'-');
    cin >> b;
    cin.ignore(100,':');
    cin >> c;

    cout << "a = "<< a <<endl;
    cout << "b = "<< b <<endl;
    cout << "c = "<< c <<endl;

Input:

1 - 2: 3

Output:

a = 1
b = 2
c = 3

See yourself here : http://www.ideone.com/DT9KJ

Note: this can handle extra spaces also. So you can read even this:

 1     -        2      :      3

Similar topic:

Using ifstream as fscanf

焚却相思 2024-10-20 01:51:12

抱歉康拉德,但我建议:永远死亡的痛苦中,永远永远永远(这足够清楚了吗? :-) 从文件中读取格式化数据。只是不要。

输入格式化数据只有一种正确的方法:读取字符块(通常是行,但也可以读取固定长度的块)。

然后解析输入文本。您不会进行粗略的检查,您将使用一个解析器来保证捕获任何格式错误,并以可理解的方式报告该错误,采取适当的操作(终止、跳过行并继续,等等)。

将输入(I/O 操作)与解析分开。

这个建议来自数十年作为商业程序员的经验:读取格式化输入适用于米老鼠原理证明程序。即使您拥有文件创建的独占控制权,也始终要解析、检查并报告错误:毕竟,内容发生变化,它可能今天有效,但明天就不行了。

我编写 C++ 已有几十年了,但从未读过整数。

Sorry Konrad, but I recommend: never on pain of death, never never never (is that clear enough? :-) read formatted data from a file. Just don't.

There is only one correct way to do input of formatted data: read chunks of characters (typically lines but you can also read fixed length blocks).

Then parse the input text. You're not going to do a cursory check, you going to use a parser that guarantees to catch any formatting error, and report that error in a comprehensible way, take appropriate action (termination, skip the line and continue, whatever).

Separate input (the I/O operation) from parsing.

This advice from decades of experience as a commerical programmer: reading formatted input is for micky mouse proof-of-principal programs. Even if you have exclusive control of the creation of the file, always parse and check and report errors: after all, stuff changes, it may work today but not tomorrow.

I've been writing C++ for decades and I've never read an integer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文