Более эффективный способ удаления пробелов

Я пытаюсь удалить пробелы и сохранить символы после пробелов.

Это файл, из которого я читаю:

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++ strings или Vectors. Я намерен использовать C Style strings


person Sam Thers    schedule 13.12.2014    source источник
comment
Каков результат, который вы на самом деле получаете?   -  person 0x499602D2    schedule 13.12.2014
comment
Ваш вопрос в настоящее время не очень ясен. Что именно вы получаете прямо сейчас и что вы хотите получить взамен?   -  person Jerry Coffin    schedule 13.12.2014
comment
@JerryCoffin, см. отредактированный вопрос.   -  person Sam Thers    schedule 13.12.2014
comment
@ 0x499602D2 См. отредактированный вопрос   -  person Sam Thers    schedule 13.12.2014
comment
Я вижу правки, но я нахожу это еще более запутанным. То, что вы показали как Конечный результат, действительно должно означать Это то, что я хочу?   -  person Jerry Coffin    schedule 13.12.2014
comment
@JerryCoffin Извините за путаницу, End result должно быть What I really want   -  person Sam Thers    schedule 13.12.2014


Ответы (3)


Манипулятор std::ws немедленно использует все начальные пробелы. Если вы хотите включить/отключить автоматический пропуск пробелов для форматированного ввода, используйте std::skipws или std::noskipws. По умолчанию пропуск пробелов включен. Однако это относится только к [правильно реализованным] операторам ввода (>>).

Чтобы пропустить пробел перед неформатированным вводом, вы должны использовать std::ws, например:

(std::cin >> std::ws).get(c);
person Dietmar Kühl    schedule 13.12.2014
comment
Как мне использовать его с моим c style string arrays? - person Sam Thers; 13.12.2014
comment
Что не так с (std::cin >> std::ws).getline(s, n)? - person Dietmar Kühl; 13.12.2014
comment
Все! Я использую istream operator, а не cin! Кроме того, что произойдет, если после разделителя : ничего нет. Он будет читать следующую строку, и я не хочу, чтобы это произошло - person Sam Thers; 13.12.2014
comment
Во-первых, вы можете использовать std::ws с любым std::istream, а не только с std::cin. Итак, вы просто заменяете std::cin любым потоком, который у вас есть. Затем вы попросили не использовать начальные пробелы, которые включают начальные символы новой строки. Если вы хотите, чтобы строки рассматривались независимо друг от друга, проще всего сначала прочитать строку, а затем раскодировать ее с помощью std::istringstream. Кроме того, вы можете изменить то, что считается пробелом, используя поток с std::locale с пользовательским аспектом std::ctype<char>, который не классифицирует '\n' как пробел. - person Dietmar Kühl; 13.12.2014
comment
Спасибо, так как мне включить это в мой код? Я считаю все пробелы в одной строке и не классифицирую '\n' как whitespace. Это действительно много значило бы, если бы вы могли изменить мой код, пожалуйста. - person Sam Thers; 13.12.2014
comment
Извините, но мне больше не нужно делать упражнения на C++ (ну, я делаю, например, в области параллелизма, но ничего, связанного с потоками). Судя по ответу и комментариям у вас есть все необходимые инструменты. Если вам нужна помощь в их применении, я уверен, что вы найдете ответ на stackoverflow. - person Dietmar Kühl; 13.12.2014
comment
Пример того, как добавить пользовательское пустое пространство с помощью локали. en.cppreference.com/w/cpp/locale/ctype#Example Список символов по умолчанию, которые считаются пробелами. cplusplus.com/reference/cctype/isspace - person user2913685; 10.04.2016

Не используйте массивы символов в первую очередь. Это можно легко очистить с помощью 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;
}

Демо

Вот некоторые другие альтернативы:

  1. Создайте фильтрующий буфер потока, который игнорирует первые символы, предшествующие :.
  2. Создайте итератор потока, который вызывает ignore(), как я делал для каждой итерации.
  3. Используйте регулярные выражения для сопоставления шаблонов для каждой строки и извлечения в строку.
person 0x499602D2    schedule 13.12.2014
comment
Спасибо, но возможно ли, если бы вы могли помочь мне с моим кодом, я намерен использовать массивы символов, поскольку я поклонник c strings. Я уверен, что это одна или две строки, которые нуждаются в настройке, но это будет много значить, если вы мне поможете. - person Sam Thers; 13.12.2014

Вы можете написать функцию, которая съедает пробелы перед вводом, как в других ответах.

Вы также можете написать функцию обрезки, чтобы обрезать пробелы в начале и в конце строк:

как это:

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>>, вы должны съесть пробелы в потоке.

person SHR    schedule 13.12.2014