【问题标题】:How to remove the leading white spaces but keep middle spaces in C++ `ifstream`?如何删除前导空格但保留 C++ `ifstream` 中的中间空格?
【发布时间】:2014-08-22 04:38:19
【问题描述】:

例如,我有一个文件,内容如下:

     Hello John Smith
               Hello Jack Brown
                     OK I love you

请注意,每个句子都有一些前导空格。我想使用std::fstream逐行阅读它们,并希望删除前导空格但保留句子中单词之间的空格。

我想要的输出应该如下:

Hello John Smith
Hello Jack Brown
OK I love you

我还发现this post 为我的问题提供了许多简单的方法。但是,我认为就现代 C++ 而言,它们都不是优雅的。还有更优雅的方式吗?

【问题讨论】:

    标签: c++ character-encoding io iostream fstream


    【解决方案1】:
    std::ifstream file("input.txt");
    
    std::string line;
    
    while(std::getline(file,line))
    {
         auto isspace = [](unsigned char ch) { return std::isspace(ch); };
    
         //find the first non-space character
         auto it = std::find_if_not(line.begin(), line.end(), isspace);
    
         line.erase(line.begin(), it); //erase all till the first non-space
    
         std::cout << line << "\n";
    }
    

    请注意,我们可以将std::isspace 作为第三个参数传递给std::find_if_not,但有overloads of std::isspace 会导致编译错误——您可以使用强制转换来解决这个问题,如下所示:

    auto it = std::find_if_not(line.begin(), 
                               line.end(), 
                               static_cast<int(*)(int)>(std::isspace));
    

    看起来很丑。但是由于转换中的函数类型,编译器能够找出您打算在代码中使用的which overload

    【讨论】:

    • 几个 cmets:首先,你有未定义的行为。您不能用char 调用isspace 的一个参数版本。您应该声明 lambda 以采用 unsigned char(或使用 std::ctype&lt;char&gt;;有点棘手,但它允许您使用特定的语言环境而无需修改全局语言环境)。其次,为什么不将 lambda 指定为 find_if 的第三个参数(我会指定 lambda 以便 std::find_if 起作用)。最后:可能值得指出的是,这不适用于越来越普遍的多字节字符。
    • @JamesKanze:感谢您的评论。我使用std::find_if_not 只是为了演示它的用法,并且我想指出我们可以将std::isspace 作为第三个参数传递(在转换之后)。
    • 但它是一个 C++11 函数;如果你使用std::find_if,那么你就不需要 C++11。 (当然,无论如何您都不能使用 lambda,但您可能还是希望提供一个全局的 IsSpaceNotIsSpace 谓词,除非这是您唯一一次处理文本。)
    • 当然,虽然您可以直接传递std::isspace,但它会导致未定义的行为,因为std::find_if_not 最终会传递char。 (由于历史原因,C++ 中的字符处理比应有的复杂得多,并且有许多偷偷摸摸的陷阱。当我经常这样做时,我的测试输入之一总是巴黎郊区的列表。@987654342 @. 你会惊讶于有多少程序停在'ÿ'.Latin-1 中的字符代码 255。)
    • @JamesKanze:伟大的 cmets。希望此答案的观众也能阅读您的 cmets。
    【解决方案2】:

    作为对 Nawaz 回答的补充:值得指出的是 Boost 有一个 String_Algo 库,以及(以及许多其他 things) 函数,如trim,这将简化代码 很多。如果您正在做任何文本处理,并且您 不能或不想使用 Boost,你应该实现一些东西 与您的工具包相似(例如,一个函数 MyUtils::trim,基于 Nawaz 的算法)。

    最后,如果有一天您可能需要处理 UTF-8 输入,那么您 应该去ICU看看。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-10
      • 1970-01-01
      • 2013-06-03
      • 2014-12-11
      相关资源
      最近更新 更多