【问题标题】:Skip leading whitespaces but not the newline C++ istreams跳过前导空格,但不跳过换行符 C++ istreams
【发布时间】:2015-02-12 10:24:58
【问题描述】:

我正在尝试删除前导空格并将字符存储在空格之后。我不想考虑换行符

这是我正在读取的文件:

Map: Out of planet
Player:    Max

我的预期结果和我正在寻找的应该是

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

如果文件看起来像这样......

Map: 
Player:    Max

map 变量和 player 变量中不应存储任何内容。

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

这就是我得到的:

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

有没有办法在不使用 C++ 字符串或向量的情况下做到这一点。我打算使用 C 风格的字符串

这是我编辑的代码,但是如果在分隔符 : 之后有有效字符,它将不起作用...如果有人可以修复我的代码,我会非常感激,这对我来说意义重大。

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

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

【问题讨论】:

  • “我打算使用 C 风格的字符串” -- 请注意 std::string 的存在是有原因的。手动管理内存在理论上很简单,但在实践中很难做到正确,如果您需要 C 风格的字符串以实现互操作性,则可以使用 c_str()
  • std::ws 与字符数组无关。它所做的只是丢弃前导空格,以便下一个字符是有效字符或 EOF。
  • is.get(c) != "\n" 总是正确的,除非你有可以想象的最奇怪的内存布局。 "\n"char(&amp;)[2];很确定你想要'\n'。该代码甚至不应该编译,因为充其量您将charchar * 进行比较,这显然是不兼容的类型。

标签: c++ char whitespace delimiter istream


【解决方案1】:

你可以这样做:

void eatwhites(istream& stream)
{
  const string skip=" \t";//put here all wanted skip chars (here i put only SPACE and TAB
  while(string::npos != skip.find(stream.peek())){ //if next char in stream exist in skip string 
    stream.ignore();//then ignore it (1 character).
  }
}

编辑

这是我测试它的方法,它对我有用:

请注意,您仍然需要在阅读后修剪字符串,这意味着将 '\0' 放在最后一个非白色字符之后。

如果有问题,你可以告诉它是什么输入以及你得到了什么。

int main()
{ 
    string s1,s2;
    eatwhites(cin);
    getline(cin,s1, ':');//read until ":"
    eatwhites(cin);
    getline(cin,s2); //read until "\n"
    cout<<"'"<<s1<<"':'"<<s2<<"'"<<endl;
    return 0;
}

我尝试过的输入:

  • [SPACE] 123:[SPACE] 456 给出:'123':'456'
  • [SPACE] 123:[SPACE] 给出:'123':''

EDIT2:

char 数组一样可以使用,像这样:

#define MAX_FIELD 128
int main()
{ 
    char s1[MAX_FIELD],s2[MAX_FIELD];
    eatwhites(cin);
    cin.getline(s1, MAX_FIELD, ':');
    eatwhites(cin);
    cin.getline(s2, MAX_FIELD);
    cout<<"'"<<s1<<"':'"<<s2<<"'"<<endl;

    return 0;
}

相同的输入得到相同的结果。

【讨论】:

  • 谢谢,我已经编辑了我的代码,如果在分隔符 : 之后没有任何内容,它就可以工作。但是,如果:分隔符后面有东西,它不会存储分隔符后面的值
  • cplusplus.com/reference/ios/skipws 这可能对你也有用。
  • @SHR,所以如果: 分隔符之后没有任何内容,它不会存储任何内容?我不喜欢使用字符串,如果可能,请您提供一个字符版本或帮助我修改我的代码
  • @0x499602D2,谢谢,但有没有办法使用char arrays 编写eatwhites。我不想使用字符串。
猜你喜欢
  • 1970-01-01
  • 2013-12-18
  • 2019-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-29
  • 2014-12-14
  • 2015-03-11
  • 2015-01-11
相关资源
最近更新 更多