【问题标题】:More efficient way of removing whitespace删除空格的更有效方法
【发布时间】:2015-02-12 06:10:34
【问题描述】:

我正在尝试删除空格并将字符存储在空格之后。

这是我正在读取的文件:

Map: Out of planet
Player:    Max

这是我的代码

istreams.get(characters, 50, ':');
istreams.get(c);
istreams.getline(kill.killMap, 35);
if(kill.killMap[0] = '\0)
{ 
   cout << "Error;
   break;
}
istreams >> ws;

istreams.get(characters, 50, ':');
istreams.get(c);
istreams.getline(kill.player, 35);
if(kill.player[0] = '\0)
{ 
   cout << "Error;
   break;
}

虽然ws 函数从流中删除空格,但我认为char 数组的作用不同。如果有人能告诉我一种让ws 工作的方法,或者只是一种删除空格的有效方法,我将不胜感激

这就是我得到的:

cout << kill.killMap << endl; 
  Out of planet  //THERE IS WHITESPACE
cout << kill.player << endl;   
      Max  //THERE IS WHITESPACE

我真正想要的:

cout << kill.killMap << endl; 
Out of planet    // NOTICE THERE IS NO WHITESPACE
cout << kill.player << endl;   
Max             // NOTICE THERE IS NO WHITESPACE

有没有办法在不使用C++ stringsVectors 的情况下做到这一点。我打算使用C Style strings

【问题讨论】:

  • 你实际得到的输出是什么?
  • 您的问题目前还不是很清楚。你现在到底得到了什么,你想得到什么?
  • @JerryCoffin,请查看已编辑的问题。
  • @0x499602D2 请查看已编辑的问题
  • 我看到了编辑,但我发现它更加混乱。你显示的“最终结果”真的应该意味着“这就是我想要的”吗?

标签: c++ arrays char istream removing-whitespace


【解决方案1】:

您可以编写函数来像其他答案一样在输入之前吃掉空格。

你还可以编写一个修剪函数来修剪字符串开头和结尾的空格:

像这样:

string trim(const string& s)
{
  string res;
  size_t pos1,pos2;
  pos1 = s.find_first_not_of(" \t\r\n");
  pos2 = s.find_last_not_of(" \t\r\n");
  if(pos2!=string::npos)
      pos2++;
  res = s.substr(pos1,pos2-pos1);
  return res;
}

在处理流时,您只能删除前导空格,而在处理字符串时,您还可以删除尾随空格。

请注意,在 get 之后的 cin&gt;&gt; 之前,您必须吃掉流中的空白。

【讨论】:

    【解决方案2】:

    操纵器std::ws 立即消耗所有前导空格。如果你想启用/禁用自动跳过格式化输入的空格,你可以使用std::skipwsstd::noskipws。默认情况下,跳过空白是启用的。不过,它仅适用于 [正确实施] 输入运算符 (&gt;&gt;)。

    要跳过未格式化输入前面的空格,您可以使用std::ws,例如:

    (std::cin >> std::ws).get(c);
    

    【讨论】:

    • 我的c style string arrays如何使用它?
    • (std::cin &gt;&gt; std::ws).getline(s, n) 有什么问题?
    • 一切!我使用的是istream operator 而不是cin!此外,如果在 : 分隔符之后没有任何内容,会发生什么情况。它将读取下一行,我不希望这种情况发生
    • 首先,您显然可以将std::ws 与任何std::istream 一起使用,而不仅仅是std::cin。因此,您只需将 std::cin 替换为您拥有的任何流。接下来,您要求不要使用包含前导换行符的前导 whitespace。如果您希望独立考虑行,最简单的方法是首先读取行,然后使用std::istringstream 对其进行解码。或者,您可以通过使用带有std::locale 的流和自定义std::ctype&lt;char&gt; 方面来更改被视为空白的内容,该方面不会将'\n' 归类为空白。
    • 谢谢,那么我该如何在我的代码中加入它呢?我将所有空格都放在一行中,而不是将'\n' 归类为whitespace。真的很重要,如果你能修改我的代码。
    【解决方案3】:

    首先不要使用字符数组。这可以用std::string 很好地清理。以下代码假设您已将成员变量从字符数组更改为标准字符串类:

    istreams.ignore(std::numeric_limits<std::streamsize>::max(), ':');
    if (!std::getline(istreams >> std::ws, kill.killMap) || kill.killMap.empty())
    {
        std::cerr << "There has been an error\n";
        break;
    }
    
    istreams.ignore(std::numeric_limits<std::streamsize>::max(), ':');
    if (!std::getline(istreams >> std::ws, kill.killMap) || kill.killMap.empty())
    {
        std::cerr << "There has been an error\n";
        break;
    }
    

    Demo

    这里有一些其他的选择:

    1. 创建一个过滤流缓冲区,忽略: 之前的第一个字符。
    2. 创建一个调用ignore() 的流迭代器,就像我为每次迭代所做的那样。
    3. 使用regular expressions 匹配每行的模式并提取到字符串。

    【讨论】:

    • 谢谢,如果你能帮我写代码,我打算使用字符数组,因为我是c strings 的粉丝。我敢肯定这是需要调整的一两行,但如果你能帮助我,这将意味着很多
    猜你喜欢
    • 1970-01-01
    • 2022-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-09
    • 1970-01-01
    相关资源
    最近更新 更多