【问题标题】:C++ formatted input: how to 'skip' tokens?C++ 格式化输入:如何“跳过”标记?
【发布时间】:2010-11-02 06:40:54
【问题描述】:

假设我有一个这种格式的输入文件:

VAL1 VAL2 VAL3
VAL1 VAL2 VAL3

我正在编写一个只对 VAL1 和 VAL3 感兴趣的程序。在 C 中,如果我想“跳过”第二个值,我会这样做:

char VAL1[LENGTH]; char VAL3[LENGTH];
FILE * input_file;
fscanf(input_file, "%s %*s %s", VAL1, VAL3);

意思是,我会使用“%*s”格式化程序让 fscanf() 读取这个标记并跳过它。 我如何使用 C++ 的 cin 来做到这一点? 有没有类似的命令?还是我必须读取一个虚拟变量?

提前致谢。

【问题讨论】:

  • 为什么不直接将令牌读入某个变量,而忽略它?
  • @Nixuz:请阅读我对丹尼尔回答的评论。

标签: c++ formatted-input


【解决方案1】:

我只是将它读入一个虚拟变量。如果您最终确实需要它,它将可用。

【讨论】:

  • 当然这是我的“默认”选择,但我愿意避免它,因为会有很多(大约 10 个)我不想要的令牌。另外,我也有自己的好奇心,想以“美丽”的方式做这件事。我有点拒绝相信 C 中已经存在的东西在 C++ 的设计中没有考虑到。
【解决方案2】:

您可以使用 getline() 以更简单的方式完成此操作。只需使用它来抓取整行,然后解析出标记之间的值(使用 strtok 吗?)

getline() 还有很多其他问题,但它应该可以解决您的问题。

【讨论】:

    【解决方案3】:

    你可以使用

    cin.ignore(256, ' ');
    

    这将忽略最多 256 个字符或空格的所有内容。

    编辑(格式化和...):您可以做的替代方案:

    int a, b;
    cin >> a >> b >> b;
    

    【讨论】:

    • 哇,不知道。好的! :)
    • 创意,但在这种情况下,虚拟变量实际上会更清晰 =)
    【解决方案4】:

    有一个ignore 函数可用:

    std::cin << val1;
    std::cin.ignore (9999, ' ');
    std::cin << val3;
    

    第一个参数定义要跳过的字符数,第二个参数是停止跳过的分隔符。

    您可以将其封装在用户定义的操纵器中,因为它很难看。


    这是自定义操纵器:

    template <class charT, class traits>
    inline std::basic_istream<charT, traits> &
    ignoreToken (std::basic_istream<charT, traits> &strm)
    {
        strm.ignore (9999, ' ');
        return strm;
    }
    

    你可以这样使用:

    cin >> val1 >> ignoreToken >> val3 >> ignoreToken >> val5;
    

    (ps——我没有编译这个,所以可能有错字)。

    【讨论】:

    • 这非常接近我想要的。但是有没有办法忽略任意数量的字符(或空格),而不是修复一个非常大的值?
    • 不。你必须提供一个很大的数字。我读过的一些文档建议使用“std::numerical_limits::max()”,但是(IMO)这很愚蠢。
    • std::numeric_limits<:streamsize>::max() PS。它并不傻,它的防御性编程。
    • 愚蠢的是强迫自己使用一些很臭的东西(C++ 流 IO),因为它就在那里。实际上,IMO 真正可怕的是输出格式,但即使是输入也不是那么好。
    【解决方案5】:

    C++ String Toolkit Library (StrTk) 对您的问题有以下解决方案:

    #include <string>
    #include <deque>
    #include "strtk.hpp"
    
    int main()
    {
       struct line_type
       {
          std::string val1;
          std::string val3;
       };
    
       std::deque<line_type> line_list;
    
       const std::string file_name = "data.txt";
    
       strtk::for_each_line(file_name,
                            [&line_list](const std::string& line)
                            {
                               strtk::ignore_token ignore;
                               line_type temp_line;
                               const bool result = strtk::parse(line,
                                                                " ",
                                                                temp_line.val1,
                                                                ignore,
                                                                temp_line.val3);
                               if (!result) return;
                               line_list.push_back(temp_line);
                            });
    
       return 0;
    }
    

    更多例子可以找到Here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-08
      • 2022-01-05
      相关资源
      最近更新 更多