在C++中只解析来自istream的数字

Arv*_*vin 6 c++ parsing input istream

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

(8,7,15)
(0,0,1) (0,3,2) (0,6,3)
(1,0,4) (1,1,5)
Run Code Online (Sandbox Code Playgroud)

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

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

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

顺便说一句,我必须使用istream.这是规范的一部分,我不允许改变

谢谢

Naw*_*waz 7

这是一个解决方案:

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;
}
Run Code Online (Sandbox Code Playgroud)

输入:

(8,7,15)
(0,0,1) (0,3,2) (0,6,3)
(1,0,4) (1,1,5)
Run Code Online (Sandbox Code Playgroud)

输出:

8 7 15 0 0 1 0 3 2 0 6 3 1 0 4 1 1 5 
Run Code Online (Sandbox Code Playgroud)

在线演示: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!
Run Code Online (Sandbox Code Playgroud)

vints是一个包含所有整数的向量.你vints想要做一些有用的事情.此外,您可以在int*预期的地方使用它:

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

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

当只读取文件中的单词时,可以应用类似的技巧.这是一个例子:


joh*_*ohn 3

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

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
  }
}
Run Code Online (Sandbox Code Playgroud)

这是未经测试的代码。