2014-02-16 5 views
0

Я пробовал манипулятор noskipws в C++, и я написал следующий код.Демонстрация noskipws в C++

#include <iostream> 
#include <sstream> 
#include <string> 
using namespace std; 

int main() 
{ 
    string first, middle, last; 

    istringstream("G B Shaw") >> first >> middle >> last; 
    cout << "Default behavior: First Name = " << first << ", Middle Name = " << middle << ", Last Name = " << last << '\n'; 
    istringstream("G B Shaw") >> noskipws >> first >> middle >> last; 
    cout << "noskipws behavior: First Name = " << first << ", Middle Name = " << middle << ", Last Name = " << last << '\n'; 
} 

Я ожидаю, что следующий вывод:

Ожидаемый выход

Default behavior: First Name = G, Middle Name = B, Last Name = Shaw 
noskipws behavior: First Name = G, Middle Name = , Last Name = B 

Выход

Default behavior: First Name = G, Middle Name = B, Last Name = Shaw 
noskipws behavior: First Name = G, Middle Name = , Last Name = Shaw 

Я изменил этот код, чтобы заставить его работать для символов, как это и он отлично работает.

#include <iostream> 
#include <sstream> 
#include <string> 
using namespace std; 

int main() 
{ 
    char first, middle, last; 

    istringstream("G B S") >> first >> middle >> last; 
    cout << "Default behavior: First Name = " << first << ", Middle Name = " << middle << ", Last Name = " << last << '\n'; 
    istringstream("G B S") >> noskipws >> first >> middle >> last; 
    cout << "noskipws behavior: First Name = " << first << ", Middle Name = " << middle << ", Last Name = " << last << '\n'; 
} 

Я знаю, как CIN работы, и я не мог понять, почему это работает таким образом, в случае string.

ответ

1

Основной алгоритм >> строки является:

1) пропуска пробельных
2) читать и не извлекать до следующего пробельных

Если вы используете noskipws, затем first step is skipped.

После первого чтения вы располагаетесь в пробеле, поэтому следующие (и все последующие) чтения немедленно прекратятся, не извлекая ничего.
Для получения дополнительной информации вы можете найти this.

Форма cplusplus.com,

многие операции экстракции рассмотреть пробельные себя в качестве завершающего символа, Therfore, с выключенным флагом skipws, некоторые операции извлечения не может извлечь никаких символов вообще из потока.
Итак, удалите noskipws при использовании со строками.

+0

В соответствии с этим сначала следует прочитать 'G', так как он встретит пространство, поэтому в' string middle' ничего не будет, а затем 'B' следует сохранить в' string last', но он сохраняет ' Shaw' в 'string last'. –

+0

@mozart: см. Мое редактирование и прочитайте приведенную ссылку, это решительно решит проблему. –

+0

Хорошо, я понял. Это означает, что 'string last' не меняется вообще? –

0

Причина в том, что во втором примере вы вообще не читаете последнюю переменную, и вместо этого вы печатаете ее старое значение.

std::string first, middle, last; 
std::istringstream iss("G B S"); 
          ^^^ 
iss >> first >> middle >> last; 
std::cout << "Default behavior: First Name = " << first 
      << ", Middle Name = " << middle << ", Last Name = " << last << '\n'; 
std::istringstream iss2("G B T"); 
          ^^^ 
iss2 >> std::noskipws >> first >> middle >> last; 
std::cout << "noskipws behavior: First Name = " << first 
      << ", Middle Name = " << middle << ", Last Name = " << last << '\n'; 

поведение по умолчанию: Имя = G, Middle Name = B, Фамилия = S

noskipws поведение: Имя = G, Middle Name =, Фамилия = S

Это произойдет потому что после второго чтения переменной переменной последний поток помещается в пробелы.

4
std::istringstream("G B S") >> std::noskipws >> first >> middle >> last; 

При экстракции выполняется на строках, строка сначала очищается и символы вставляются в его буфер.

21.4.8.9 Inserters и экстракторы

template<class charT, class traits, class Allocator> 
basic_istream<charT, traits>& 
    operator>>(basic_istream<charT, traits>& is, 
       basic_string<charT, traits, Allocator>& str); 

Effects: ведут себя как отформатированные функции входа (27.7.2.2.1). После создания объекта сторожевую, если караул превращается в true, называет str.erase(), а затем извлекает символы из is и присоединяет их к str как при вызове str.append(1, c). [...]

Первое чтение будет извлечь строка "G" в first. Для второго извлечения ничего не будет извлечено, потому что установлен флаг формата std::noskipws, отключив очистку ведущих пробелов. Из-за этого, строка очищается, а затем экстракция не удается, потому что никакие символы не были введены в действие Вот продолжение приведенного выше пункта:.

21.4.8.9 Inserters и экстракторы (прод.)

[...] символы извлекаются и добавляются, пока одно из следующих не происходит:

  • n символы сохраняются;

  • end-of-file происходит во входной последовательности;

  • isspace(c, is.getloc()) верно для следующего доступного ввода символов c.

Когда поток определяет сбой экстракции std::ios_base::failbit устанавливается в состояние потока, указывающий на ошибку.

С этой точки при любых попытках ввода/вывода произойдет сбой, если состояние потока не очищено. Экстрактор становится неработоспособным и не запускается, если состояние потока не очищено от всех его ошибок. Это означает, что извлечение в last ничего не делает, и оно сохраняет значение, имевшееся при предыдущем извлечении (одно без std::noskipws), потому что поток не очистил строку.


Что касается причины, почему с помощью char работы: Персонажи не имеют каких-либо требований форматирования в C или C++. Любые и все символы могут быть извлечены в объект типа char, что является причиной, почему вы видите правильный вывод, несмотря на std::noskipws быть установлены:

27.7.2.2.3/1 [IStream :: экстракторов ]

template<class charT, class traits> 
basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& in, 
             charT& c); 

эффектов: Работает как отформатированный входной элемент (как описано в 27.7.2.2.1) из в.После создания часового объекта символ извлекается из in, если он доступен, и сохраняется в c. В противном случае функция вызывает in.setstate(failbit).

Семантика экстрактор будет хранить символ в операнд , если он доступен. Он не ограничивает пробелы (или даже символ EOF!). Он будет извлекать его как обычный персонаж.

+0

Это звучит логичнее. Не могли бы вы привести несколько ссылок в поддержку вашего ответа? –

+0

@SumitGera Обновлено. :) – 0x499602D2

Смежные вопросы