标签: istream-iterator

带有copy_n()和朋友的std :: istream_iterator <>

下面的片段从中读取三个整数std::cin; 它写入两个numbers并丢弃第三个:

std::vector<int> numbers(2);
copy_n(std::istream_iterator<int>(std::cin), 2, numbers.begin());
Run Code Online (Sandbox Code Playgroud)

我希望代码能够准确地读取两个整数std::cin,但事实证明这是一个正确的,符合标准的行为.这是标准中的疏忽吗?这种行为的理由是什么?


从C++ 03标准中的24.5.1/1开始:

在构造之后,每次使用++时,迭代器都会读取并存储一个值T.

所以在上面的代码中,在调用时,流迭代器已经读取了一个整数.从那时起,算法中迭代器的每次读取都是预读,从而产生从先前读取缓存的值.

下一个标准的最新草案n3225似乎没有任何变化(24.6.1/1).

在相关的说明中,参考istream_iterator(istream_type& s)构造函数的当前标准的24.5.1.1/2 读取

效果:初始化in_streams.value可以在施工期间或第一次参考时初始化.

重点是" value 可以初始化......"而不是" 应该初始化".这听起来与24.5.1/1相矛盾,但也许这应该是一个自己的问题.

c++ istream-iterator

26
推荐指数
2
解决办法
2035
查看次数

使用std :: istream_iterator限制std :: copy的范围

我构建了一个最小的工作示例来显示我使用STL迭代器遇到的问题.我正在使用istream_iterator以下内容读取floatss(或其他类型)std::istream:

#include <iostream>
#include <iterator>
#include <algorithm>

int main() {
   float values[4];
   std::copy(std::istream_iterator<float>(std::cin), std::istream_iterator<float>(), values);
   std::cout << "Read exactly 4 floats" << std::endl; // Not true!
}
Run Code Online (Sandbox Code Playgroud)

这将读取所有可能的floatss,直到EOF为values固定大小,4,所以现在显然我想限制范围以避免溢出并准确读取/最多4个值.

使用更多"正常"迭代器(即RandomAccessIterator),提供begin+4的不是你要做的结束:

std::copy(begin, begin+4, out);
Run Code Online (Sandbox Code Playgroud)

准确阅读4个元素.

如何做到这一点std::istream_iterator?显而易见的想法是将呼叫更改std::copy为:

std::copy(std::istream_iterator<float>(std::cin), std::istream_iterator<float>(std::cin)+4, values);
Run Code Online (Sandbox Code Playgroud)

但(相当可以预见)这不编译,没有候选人operator+:

g++ -Wall -Wextra test.cc
test.cc: In function ‘int main()’:
test.cc:7: error: no match for ‘operator+’ in ‘std::istream_iterator<float, char, std::char_traits<char>, long int>(((std::basic_istream<char, std::char_traits<char> >&)(& std::cin))) …
Run Code Online (Sandbox Code Playgroud)

c++ iterator stl istream-iterator

23
推荐指数
2
解决办法
3990
查看次数

C++ istream_iterator不是std的成员

任何人都可以告诉我为什么编译时我写的下面的代码一直在抱怨istream_iterator is not a member of std请你告诉我吗?多谢你们

#include <cstdlib>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string.h>
#include <vector>
#include <fstream>
//#include<sstream>

struct field_reader: std::ctype<char> {

    field_reader(): std::ctype<char>(get_table()) {}

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

        rc[';'] = std::ctype_base::space;
        return &rc[0];
    }
};


struct Stud{
    double VehicleID;
    double FinancialYear;
    double VehicleType;
    double Manufacturer;
    double ConditionScore;


    friend std::istream &operator>>(std::istream &is, Stud &s) {
        return is >> s.VehicleID >> s.FinancialYear >> s.VehicleType >>      s.Manufacturer >> s.ConditionScore;
    }

    // …
Run Code Online (Sandbox Code Playgroud)

c++ istream-iterator

14
推荐指数
1
解决办法
1万
查看次数

多流迭代器c ++

我的程序的目的是打开m行相同长度的文本文件n,逐列读取文件并打印每列.

例如,对于此文本文件

abcd
efgh 
jklm
Run Code Online (Sandbox Code Playgroud)

我想打印

a e j
b f k
c g l
d h m
Run Code Online (Sandbox Code Playgroud)

由于一个行长度可以是200 000 000并且列长度可以超过10000,我无法在矩阵中打开内存中的所有文件.

从理论上讲,我希望有一个程序在空间中使用O(m)并在时间上使用O(m*n).

一开始,我不得不考虑这些解决方案:

  • 如果我看到每列的所有文件,复杂度为O(m*n²),
  • 如果我使用seekg和一组位置并从一个位置跳到另一个位置,则复杂度为O(m n log(n)).

最后一点,对于某些服务器问题,我只需要使用STL.

我的最后一个想法是创建一个文件的迭代器数组,并在每行的开头初始化这些迭代器.之后,要查看下一列,我只需要增加每个迭代器.这是我的代码

ifstream str2;
str2.open ("Input/test.data", ifstream::in);

int nbline = 3;
int nbcolumn = 4;
int x = 0;

istreambuf_iterator<char> istart (str2);
istreambuf_iterator<char> iend ;

istreambuf_iterator<char>* iarray;
iarray = new istreambuf_iterator<char>[nbline];


while (istart != iend){
    if (x % nbcolumn == 0){
        iarray[x/nbcolumn] = istart;
    }
    istart++;
    x++;
}

for …
Run Code Online (Sandbox Code Playgroud)

c++ stream istream-iterator

14
推荐指数
2
解决办法
366
查看次数

求istreambuf_iterator <wchar_t>澄清,阅读Unicode字符的完整文本文件

在Scott Meyers的"Effective STL"一书中,有一个将整个文本文件读入std :: string对象的好例子:

std::string sData; 

/*** Open the file for reading, binary mode ***/
std::ifstream ifFile (“MyFile.txt”, std::ios_base::binary); // Open for input, binary mode

/*** Read in all the data from the file into one string object ***/
sData.assign (std::istreambuf_iterator <char> (ifFile),
              std::istreambuf_iterator <char> ());
Run Code Online (Sandbox Code Playgroud)

请注意,它以8字节字符的形式读取.这非常有效.最近虽然我需要读取包含Unicode文本的文件(即每个字符两个字节).但是,当我尝试(天真地)更改它以将数据从Unicode文本文件读取到std :: wstring对象时,如下所示:

std::wstring wsData; 

/*** Open the file for reading, binary mode ***/
std::wifstream ifFile (“MyFile.txt”, std::ios_base::binary); // Open for input, binary mode

/*** Read in all the data from the file …
Run Code Online (Sandbox Code Playgroud)

c++ unicode istream-iterator wstring wifstream

11
推荐指数
1
解决办法
2544
查看次数

为什么没有范围 - 为std :: istream_iterator查找开始和结束的重载?

我有这样的代码

std::ifstream file(filename, std::ios_base::in);
if(file.good())
{
    file.imbue(std::locale(std::locale(), new delimeter_tokens()));
    for(auto& entry : std::istream_iterator<std::string>(file))
    {
        std::cout << entry << std::endl;    
    }
}
file.close();
Run Code Online (Sandbox Code Playgroud)

其中std::istream_iterator<std::string>begin()end() 定义如下

template<class T>
std::istream_iterator<T> begin(std::istream_iterator<T>& stream)
{
    return stream;
}

template<class T>
std::istream_iterator<T> end(std::istream_iterator<T>& stream)
{
    return std::istream_iterator<T>();
}
Run Code Online (Sandbox Code Playgroud)

这也是马克·尼尔森在Dobb博士这里所写的内容.唉,代码无法在我的Visual Studio 2012上使用错误消息进行编译

错误C3312:找不到类型'std :: istream_iterator <_Ty>'的可调用'begin'函数

错误C3312:找不到类型'std :: istream_iterator <_Ty>'的可调用'end'函数

问题:有没有我没有注意到的东西,编译器中的错误(不太可能,但只是以防万一)或......好吧,任何想法?


根据Xeo的建议,这些问题会得到很大的清理.为了提供更多的背景和参考,这与我在Stackoverflow上的另一个问题有关,我想知道如何使基于行的解析比通常的循环更清晰.从互联网上进行了一些编码和检查,我的工作草图如下

std::ifstream file(filename, std::ios_base::in);
if(file.good())
{               
    file.imbue(std::locale(std::locale(), new delimeter_tokens()));
    for(auto& entry …
Run Code Online (Sandbox Code Playgroud)

c++ istream-iterator visual-c++ c++11 visual-studio-2012

10
推荐指数
1
解决办法
2617
查看次数

constexpr结束istream(sentinel)迭代器有什么意义?

N2976建议添加constexpr标准库中的某些位置.它指出iostreams不适用于constexprEXCEPT结束迭代器.所以istream_iterator,istreambuf_iterator并给予constexpr默认构造函数,就是这样.例如,您可以在libstdc ++实现中看到constexpr只在整个文件中出现一次.引发这一变化的LWG是#1129.它说:

istream_iteratoristreambuf_iterator应支持文字哨兵价值观.默认构造函数经常用于终止范围istreambuf_iterator,并且istream_iterator在迭代值类型时很容易成为文字值 .[其余省略]

这对我来说并没有多大意义.有人能告诉我他们的意思吗?

N3308是另一篇提到但没有解释问题的论文:

某些istream_iterator<T>构造函数必须是 constexprif T是文字类型.目的是允许存储一种T内联类型的现有实现技术继续工作.[libstdc ++这样做,_Tp _M_value]但是,它实际上排除了这种技术:T不需要标记默认和复制构造函数constexpr,如果不是,则 istream_iterator<T>构造函数不能被实例化 constexpr.

上面解释了普通的复制构造函数和析构函数,但不是默认构造函数标记为constexpr的原因.

此外,在在线GCC 5.2.0上进行测试,我复制了libstdc ++的实现.唯一的变化是我删除了constexpr istream_iterator().在这两种情况下,组件都是相同的.

随着constexpr

没有constexpr

c++ istream-iterator constexpr c++11

10
推荐指数
1
解决办法
357
查看次数

在相同的输入迭代器范围内并排运行两个<algorithm>

如果我想计算从a中检索到的一堆数字的总和std::istream,我可以执行以下操作:

// std::istream & is = ...
int total = std::accumulate(std::istream_iterator<int>(is),
                            std::istream_iterator<int>(),
                            0);
Run Code Online (Sandbox Code Playgroud)

但是,如果我想计算它们的平均值,我需要累积两个不同的结果:

  • 总和(std::accumulate)
  • 总数(std::distance)

有没有办法"合并"这两种算法并在迭代器范围的单次传递中"并排"运行它们?我想做的事情如下:

using std::placeholders;
int total, count;
std::tie(total, count) = merge_somehow(std::istream_iterator<int>(is),
                                       std::istream_iterator<int>(),
                                       std::bind(std::accumulate, _1, _2, 0),
                                       std::distance);
double average = (double)total / count;
Run Code Online (Sandbox Code Playgroud)

这可能吗?

c++ algorithm iterator istream-iterator stl-algorithm

9
推荐指数
2
解决办法
281
查看次数

如何使用std :: copy读取任意数量的值?

我正在尝试对此进行相反的操作:

std::ostream outs; // properly initialized of course
std::set<int> my_set; // ditto

outs << my_set.size();
std::copy( my_set.begin(), my_set.end(), std::ostream_iterator<int>( outs ) );
Run Code Online (Sandbox Code Playgroud)

它应该是这样的:

std::istream ins;

std::set<int>::size_type size;
ins >> size;

std::copy( std::istream_iterator<int>( ins ), std::istream_iterator<int>( ins ) ???, std::inserter( my_set, my_set.end() ) );
Run Code Online (Sandbox Code Playgroud)

但是我坚持使用'end'迭代器 - 输入交互器不能使用std :: advance,我也不能使用两个具有相同源的流...

有什么优雅的方法如何解决这个问题?当然我可以用于循环,但也许有更好的东西:)

c++ iterator istream-iterator stl-algorithm

8
推荐指数
1
解决办法
1574
查看次数

使用istream_iterator并从标准输入或文件中读取

我正在使用Microsoft Visual C++编写,我希望我的程序可以使用标准输入或文件读取istream_iterator.谷歌搜索互联网并没有表明我认为它必须是多么简单.例如,我可以很容易地编写这个并从标准输入中读取:

#include <iostream>
#include <string>
#include <iterator>

using namespace std;

int main()
{
   istream_iterator<string> my_it(cin);
   for (; my_it != istream_iterator<string>(); my_it++)
      printf("%s\n", (*my_it).c_str());
}
Run Code Online (Sandbox Code Playgroud)

或者我可以写这个并从文件中读取:

#include <iostream>
#include <string>
#include <iterator>
#include <fstream>

using namespace std;

int main(int argc, char** argv)
{
   ifstream file(argv[1]);
   istream_iterator<string> my_it(file);
   for (; my_it != istream_iterator<string>(); my_it++)
      printf("%s\n", (*my_it).c_str());
}
Run Code Online (Sandbox Code Playgroud)

但是我如何将这两者结合起来以便简单的(argc == 2)检查让我用文件流或stdin初始化我的输入流迭代器并继续我的快乐方式?

c++ stdin file istream-iterator

6
推荐指数
1
解决办法
2万
查看次数