【问题标题】:c++ how to read input up to a certain pointc ++如何读取输入到某个点
【发布时间】:2014-04-20 01:56:27
【问题描述】:

您好,我有一些输入行,按以下顺序:

Date, Time, Price, Volume, Value,

日期格式为 DD/MM/YY 时间格式为 HH/MM/SS AM/PM 价格、数量和价值是用逗号分隔的数字。

此输入有 4000 行,偶尔还有一个共享代码,例如“CX” 或 'NXXT' 将出现在 'value' 逗号之后。

我的程序无法处理并崩溃。

我需要的是一种忽略“值”之后逗号之后的任何内容并继续阅读下一行的方法。这将在“Shares”类中。

这是来自我的课程的输入流:

类:“日期”

istream & operator >> (istream & input, Date & C) /// An input stream for the day, month and year
{
char delim;
input >> C.day >> delim >> C.month >> delim >> C.year;

return input;   /// Returning the input value
}

类“时间”

istream & operator >> (istream & input, Time & C) /// An input stream for the hour minutes and seconds
{
char delim;
input >> C.hour >> delim >> C.minute >> delim >> C.second;
getline(input,C.ampm,',');

return input;   /// Returning the input value
}

“共享”类

istream & operator >> (istream & input, Shares & C) /// An input stream for the day, month and year
{
char delim;
input >> C.price >> delim >> C.volume >> delim >> C.value >> delim;

return input;   /// Returning the input value
}

【问题讨论】:

  • 基本上为了让它更简单,我只需要一种方法来停止读取“值”逗号之后的任何内容,例如 250,CX,其中需要跳过“CX”。
  • 您能发布一个示例输入行吗? Shares 是一个静态类吗?为什么要将 Shares 作为参数传递给流运算符,而这可能是 Share 对象上的一个方法,该方法获取一行并解析它?

标签: c++ iostream delimiter


【解决方案1】:

看起来 Shares 是一种表示不同字段的数据结构。编写一个以更健壮的方式解析行的函数。理想情况下,如果 Shares 代表一行的数据,则只需将其包含在输入字符串的一行中。即使存在其他行,对象也不需要知道。

无论如何不要只写这样的流函数,它还不够健壮。 std::getline 将允许您在分隔符上拆分行。当然,即使使用“std::getline”,您最好还是进行适当的验证。您可以使用各种输入对其进行测试,例如,您可以为 Shares 提供一种方法来从字段中重构行,然后进行单元测试将其与输入进行比较,以验证它是否相同。

看看这个function from torset,它从tor 共识文件中解析行,并只提取IP 地址和端口。 它将结果集存储在数据成员std::string _set; 中,因为在这里将所有字段保留在数据结构中并不是目的。请注意,此函数不会进行验证,因为它假定 tor 共识文件已正确形成。原则上这是一个危险的假设,理想情况下你永远不会在生产中运行它:

IpsetRestore::IpsetRestore( const std::stringstream& consensusIn, const std::string& setName )

:   consensus    ( consensusIn.str() )
  , setName      ( setName           )
  , _errorCode   ( 0                 )

{
    std::string              line      ;
    std::vector<std::string> fields    ;
    std::string              field     ;
    std::stringstream        lineStream;

    // get each line separately
    //
    while( std::getline( consensus, line ) )
    {
        fields    .clear();
        lineStream.clear();
        lineStream.str  ( line );


        // get each field
        //
        while( std::getline( lineStream, field, ' ' ) )

            fields.push_back( std::string( field ) );


        // only work on lines that interest us
        // sample: "r Unnamed VLNV4cpI/C4jFPVQcWKBtO2EBV8 2013-11-04 22:38:31 76.100.70.54 9001 9030"
        //
        if( fields.size() != 8 || fields[ 0 ] != "r" )

            continue;


        // write add lines in the ipset format
        // add [setName] [ip]:[port]
        // tor uses tcp and ipset defaults to tcp, so we won't put it in
        // fields 6 and 7 are the port fields, so if it's port 0, don't bother
        //
        for( int i = 6; i <= 7; ++i )
        {
            if( fields[ i ] == "0" )

                continue;


            _set.append
            (
                std::string( "add "      )
                .append    ( setName     )
                .append    ( " "         )
                .append    ( fields[ 5 ] )
                .append    ( ":"         )
                .append    ( fields[ i ] )
                .append    ( " -exist\n" )
            );
        }



    if( _set.empty() )
    {
        std::cerr << "Something went wrong, _set is empty. Maybe you passed the wrong inputfile or it was not formatted correctly." << std::endl;

        ++_errorCode;
    }
}

【讨论】:

  • 行尾并不总是有多余的东西,它只出现在某些行上,但因为我不知道它什么时候会发生。我试图放置另一个分隔符,但程序仍然继续中断
  • 只要第一个字段都存在且有序,这意味着至少有你的逗号,即使它们之间没有任何内容,你很好,因为你可以计算字段并只得到那些你想要的。
【解决方案2】:

编写一个函数,该函数会一直跳到并包括行尾。

void skipEOL(std::istream& in)
{
  int c;
  while ( (c = in.getc()) != '\n' && c != EOF );
}

当您知道您需要跳过所有内容直到行尾(包括行尾)时使用它。

【讨论】:

  • 感谢的是,有些行有额外的字符串,即共享代码,有些则没有,所以我不确定何时需要跳过它,有数千行
  • 您可以在读取共享值后为每一行输入调用它。在最坏的情况下,它会跳过空格和换行符。
猜你喜欢
  • 1970-01-01
  • 2020-02-26
  • 1970-01-01
  • 2013-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-01
相关资源
最近更新 更多