在 C++ 中仅解析 istream 中的数字

发布于 2024-11-30 03:48:01 字数 387 浏览 0 评论 0原文

我有一堆输入文件,如下所示:

(8,7,15)
(0,0,1) (0,3,2) (0,6,3)
(1,0,4) (1,1,5)

我需要编写一个函数,一次解析这些输入一个数字,所以我需要能够按数字分隔输入,例如:8,然后 7,然后15,然后是 0,再是 0,依此类推。

到目前为止我想到的唯一方法是使用 istream.get() 返回下一个字符的 ASCII 代码,我可以通过将其转换为 char 将其转换回其字符格式。然后我会检查该字符是否是数字(因此括号被忽略),但这样,任何双(或三)位数字一次只能读取一位数字。

实现这一目标的最佳方法是什么?

顺便说一下,我必须使用istream。这是规范的一部分,我不允许更改,

谢谢

I have a bunch of input files that look like the following:

(8,7,15)
(0,0,1) (0,3,2) (0,6,3)
(1,0,4) (1,1,5)

I need to write a function that parses these inputs one number at a time, so I need to be able to separate the input by numbers, e.g.: 8, then 7, then 15, then 0, another 0, so on.

The only way I've thought of so far is to use istream.get() which returns the next character's ASCII code, which I can convert back to its character format by casting it to char. Then I'd check if the character was a number or not (so the brackets are ignored) but this way, any double (or triple) digit numbers are only read one digit at a time.

What would be the best way to achieve this?

By the way, I must use istream. It's part of the specification that I'm not allowed to change

Thanks

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

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

发布评论

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

评论(6

暗藏城府 2024-12-07 03:48:01

这是一种解决方案:

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

int main() {
        std::cin.imbue(std::locale(std::locale(), new integer_only()));
        std::istream_iterator<int> begin(std::cin);
        std::istream_iterator<int> end;
        std::vector<int> vints(begin, end);
        std::copy(vints.begin(), vints.end(), std::ostream_iterator<int>(std::cout, "\n"));
        return 0;
}

输入:

(8,7,15)
(0,0,1) (0,3,2) (0,6,3)
(1,0,4) (1,1,5)

输出:

8 7 15 0 0 1 0 3 2 0 6 3 1 0 4 1 1 5 

在线演示: http://ideone.com/Lwx9y

在上面,成功打开文件后,您必须将 std::cin 替换为文件流,如下所示:

 std::ifstream file("file.txt");
 file.imbue(std::locale(std::locale(), new integer_only()));
 std::istream_iterator<int> begin(file);
 std::istream_iterator<int> end;
 std::vector<int> vints(begin, end); //container of integers!

这里,vints 是一个包含所有整数的向量。您希望与 vints 一起做一些有用的事情。另外,您可以在需要 int* 的地方使用它,如下所示:

void f(int *integers, size_t count) {}

f(&vints[0], vints.size()); //call a function which expects `int*`.

当仅从文件中读取单词时,可以应用类似的技巧。这是一个示例:

This is one solution:

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

int main() {
        std::cin.imbue(std::locale(std::locale(), new integer_only()));
        std::istream_iterator<int> begin(std::cin);
        std::istream_iterator<int> end;
        std::vector<int> vints(begin, end);
        std::copy(vints.begin(), vints.end(), std::ostream_iterator<int>(std::cout, "\n"));
        return 0;
}

Input:

(8,7,15)
(0,0,1) (0,3,2) (0,6,3)
(1,0,4) (1,1,5)

Output:

8 7 15 0 0 1 0 3 2 0 6 3 1 0 4 1 1 5 

Online demo : http://ideone.com/Lwx9y

In the above, you've to replace std::cin with the file stream after opening the file successfully, as:

 std::ifstream file("file.txt");
 file.imbue(std::locale(std::locale(), new integer_only()));
 std::istream_iterator<int> begin(file);
 std::istream_iterator<int> end;
 std::vector<int> vints(begin, end); //container of integers!

Here, vints is a vector which contains all the integers. You would like work with vints to do something useful. Also, you can use it where int* is expected as:

void f(int *integers, size_t count) {}

f(&vints[0], vints.size()); //call a function which expects `int*`.

Similar trick can be applied when reading only words from a file. Here is an example:

网白 2024-12-07 03:48:01

这是一些代码,您可以进行调整以满足您的精确需求

for (;;)
{
  int ch = in.get();
  if (ch == EOF)
    break;
  if (isdigit(ch))
  {
    int val = ch - '0';
    for (;;)
    {
      ch = in.get();
      if (!isdigit(ch))
        break;
      val *= 10;
      val += ch - '0';
    }
    // do something with val
  }
}

这是未经测试的代码。

Here's some code, you can adapt to meet your precise needs

for (;;)
{
  int ch = in.get();
  if (ch == EOF)
    break;
  if (isdigit(ch))
  {
    int val = ch - '0';
    for (;;)
    {
      ch = in.get();
      if (!isdigit(ch))
        break;
      val *= 10;
      val += ch - '0';
    }
    // do something with val
  }
}

This is untested code.

只有影子陪我不离不弃 2024-12-07 03:48:01

尝试读取一个数字。如果失败,请清除错误状态并尝试读取char(并忽略它)。重复这两个步骤,直到读取字符失败,在这种情况下,您处于 EOF 或真正的失败。

它可以通过识别“)”然后阅读直到“(”来优化。

但我认为这不值得。

干杯& hth。,

try to read a number. if that fails, clear error state and try to read a char (and ignore it). repeat these two steps until reading a char fails, in which case you are at EOF or true failure.

it might be optimized by recognizing ')' and then reading until '('.

but i don't think it's worth it.

cheers & hth.,

青春有你 2024-12-07 03:48:01

另一个解决方案:

#include <string>
#include <ostream>
#include <fstream>
#include <iostream>

struct triple
{
    long a;
    long b;
    long c;
};

std::ostream& operator << (std::ostream& os, const triple& value)
{
    return os << value.a << "/" << value.b << "/" << value.c;
}

int main()
{
    std::ifstream stream("Test.txt");
    if (!stream)
    {
        std::cout << "could not open the file" << std::endl;
    }

    std::string dummy;
    triple value;
    while (std::getline(stream, dummy, '(') >> value.a &&
           std::getline(stream, dummy, ',') >> value.b &&
           std::getline(stream, dummy, ',') >> value.c)
    {
        std::cout << value << std::endl;
    }
}

Another solution:

#include <string>
#include <ostream>
#include <fstream>
#include <iostream>

struct triple
{
    long a;
    long b;
    long c;
};

std::ostream& operator << (std::ostream& os, const triple& value)
{
    return os << value.a << "/" << value.b << "/" << value.c;
}

int main()
{
    std::ifstream stream("Test.txt");
    if (!stream)
    {
        std::cout << "could not open the file" << std::endl;
    }

    std::string dummy;
    triple value;
    while (std::getline(stream, dummy, '(') >> value.a &&
           std::getline(stream, dummy, ',') >> value.b &&
           std::getline(stream, dummy, ',') >> value.c)
    {
        std::cout << value << std::endl;
    }
}
|煩躁 2024-12-07 03:48:01
int getFirstPos(const string& str)

{
int pos=0,PosHit=0;
bool bfind=false;
if((PosHit=str.find(','))!=string::npos){
    if(!bfind)  pos=PosHit;
    pos=pos>PosHit?PosHit:pos;
    bfind=true;
}
if((PosHit=str.find('('))!=string::npos){
    if(!bfind)  pos=PosHit;
    pos=pos>PosHit?PosHit:pos;
    bfind=true;
}
if((PosHit=str.find(')'))!=string::npos){
    if(!bfind)  pos=PosHit;
    pos=pos>PosHit?PosHit:pos;
    bfind=true;
}
return bfind?pos:string::npos;

}

void main()

{
    ifstream ifile("C:\\iStream.txt");
    string strLine;
    vector<double> vecValue;    //store the datas
    while(getline(ifile,strLine)){
        if(strLine.size()==0)
            continue;
        int iPos=0;
        while((iPos=getFirstPos(strLine))!=string::npos)
            strLine[iPos]=' ';
        istringstream iStream(strLine);
        double dValue=0;
        while(iStream>>dValue)
            vecValue.push_back(dValue);
    }
    //output the result!
    vector<double>::iterator it;
    for (it=vecValue.begin(); it!=vecValue.end()  ; ++it){
        cout<<setprecision(3)<<*it<<endl;
    }
}
int getFirstPos(const string& str)

{
int pos=0,PosHit=0;
bool bfind=false;
if((PosHit=str.find(','))!=string::npos){
    if(!bfind)  pos=PosHit;
    pos=pos>PosHit?PosHit:pos;
    bfind=true;
}
if((PosHit=str.find('('))!=string::npos){
    if(!bfind)  pos=PosHit;
    pos=pos>PosHit?PosHit:pos;
    bfind=true;
}
if((PosHit=str.find(')'))!=string::npos){
    if(!bfind)  pos=PosHit;
    pos=pos>PosHit?PosHit:pos;
    bfind=true;
}
return bfind?pos:string::npos;

}

void main()

{
    ifstream ifile("C:\\iStream.txt");
    string strLine;
    vector<double> vecValue;    //store the datas
    while(getline(ifile,strLine)){
        if(strLine.size()==0)
            continue;
        int iPos=0;
        while((iPos=getFirstPos(strLine))!=string::npos)
            strLine[iPos]=' ';
        istringstream iStream(strLine);
        double dValue=0;
        while(iStream>>dValue)
            vecValue.push_back(dValue);
    }
    //output the result!
    vector<double>::iterator it;
    for (it=vecValue.begin(); it!=vecValue.end()  ; ++it){
        cout<<setprecision(3)<<*it<<endl;
    }
}
懒猫 2024-12-07 03:48:01

如今,到了 2022 年,我们有了更强大的语言元素。

我们可以使用带有初始化器的 if 语句,std::ifstream< /code> 它将使用其 构造函数 打开文件并自动关闭它, std::istreambuf_iterator 使其易于阅读std::string 范围内的完整文件 构造函数正则表达式库,尤其是std::sregex_token_iterator (请参阅此处)以及来自 algorithm_library, rg std::transform

通过上述语言元素,我们可以为您的任务提出一个非常简短而强大的解决方案。

这将使生活变得更简单。 。 。

请参阅:

#include <iostream>
#include <fstream>
#include <sstream>
#include <iterator>
#include <regex>
#include <algorithm>
#include <vector>

const std::regex re{ R"(\d+)" };

int main() {
    // Open file and check, if it could be opened
    if (std::ifstream ifs{ "r:\\numbers.txt" }; ifs) {

        // Read complete source file into string
        std::string text(std::istreambuf_iterator<char>(ifs), {});

        // Get numbers (digits only)
        std::vector<int> numbers{};
        std::transform(std::sregex_token_iterator(text.begin(), text.end(), re), {}, std::back_inserter(numbers), [](const std::string& s) {return stoi(s);});

        // Do something with those numbers
        // . . .

        // Debug output
        for (const int i : numbers) std::cout << i << ' ';
    }
    else std::cerr << "\n***Error: Could not open input file\n";
}

Nowadays, in the year 2022, we have more powerful language elements available.

We can use if statements with initializer, std::ifstream which will open the file with its constructor and close it automatically, the std::istreambuf_iterator which makes it easy to read a complete file through the std::strings range constructor, the regex library and especially the std::sregex_token_iterator (see here) and powerful algorithms from the algorithm_library, r.g. std::transform.

With the above mentioned language elements, we can come up with a very short and powerful solution for your task.

This will make life simpler . . .

Please see:

#include <iostream>
#include <fstream>
#include <sstream>
#include <iterator>
#include <regex>
#include <algorithm>
#include <vector>

const std::regex re{ R"(\d+)" };

int main() {
    // Open file and check, if it could be opened
    if (std::ifstream ifs{ "r:\\numbers.txt" }; ifs) {

        // Read complete source file into string
        std::string text(std::istreambuf_iterator<char>(ifs), {});

        // Get numbers (digits only)
        std::vector<int> numbers{};
        std::transform(std::sregex_token_iterator(text.begin(), text.end(), re), {}, std::back_inserter(numbers), [](const std::string& s) {return stoi(s);});

        // Do something with those numbers
        // . . .

        // Debug output
        for (const int i : numbers) std::cout << i << ' ';
    }
    else std::cerr << "\n***Error: Could not open input file\n";
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文