Это ошибка C ++? (Книга < > может ошибся?) - PullRequest
2 голосов
/ 16 июня 2020
//Wrong Code
#include<iostream>
#include<iterator>
using namespace std;
int main(){
    istream_iterator<string> in_iter(cin),eof;
    ostream_iterator<string> out_iter(cout," ");
    while(in_iter!=eof)
        *out_iter++ = *in_iter++;
}

Ввод: (Запустите приведенный выше код в интерактивном режиме через "visual c ++" 、 "cpp. sh" 、 "onlinegdb" и любой другой инструмент вам нравится ...)

aa bb cc 6 dd ee

Вывод:

aa bb cc 6 dd

На самом деле правильный код должен быть:

#include<iostream>
#include<iterator>
using namespace std;
int main(){
    istream_iterator<string> in_iter(cin),eof;
    ostream_iterator<string> out_iter(cout," ");
    while(in_iter!=eof){
        *out_iter = *in_iter;
         out_iter++;
         in_iter++;
    }
}

Ввод:

aa bb cc 6 dd ee

Вывод:

aa bb cc 6 dd ee

Описание: Очень простой код. Просто для печати несколько символов и вывод будет таким же. Однако в книге «C ++ Primer», как показано на рисунке ниже, это дает нам неправильный код. Это ошибка C ++ или просто ошибка "C ++ Primer"? Изображение "C ++ Primer"

1 Ответ

1 голос
/ 16 июня 2020

Давайте разберем эту команду и посмотрим, что происходит:

*out_iter++ = *in_iter++;

Это также может быть записано следующим образом, в соответствии с приоритетом оператора :

// read next value, but return unmodified iterator (with the previous value)
// the first value is read when the iterator is constructed!
auto x = in_iter++; 

// get value that was previously read
const auto res = *x; 

// print this value
*out_iter++ = res;

Таким образом, в основном это печатает значение только после чтения следующего. Для ввода "a b c" происходит следующее:

  1. конструктор istream_iterator<string> in_iter(cin) читает "a"
  2. auto x = in_iter++; читает "b", но возвращает итератор, содержащий "a"
  3. const auto res = *x; приводит к "a", который затем печатается.
  4. auto x = in_iter++; читает "c", но возвращает итератор, содержащий "b"
  5. const auto res = *x; приводит к результату "b", который затем печатается.
  6. auto x = in_iter++; пытается что-то прочитать, но потоковый буфер пуст, поэтому он ожидает дальнейшего ввода.

Пока было напечатано только "a b", а "c" «застряло» в in_iter.

Если бы поток содержал [eof] (например, если бы вы каким-то образом завершили поток), шаг 6 был бы другим и шаг 7 (и 8) произойдет:

auto x = in_iter++; читает [eof], становится eof-итератором и возвращает итератор, содержащий "c" const auto res = *x;, в результате получается "c", который затем печатается. l oop завершается

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


Ваш код, с другой стороны, делает следующее :

// extract first value that was read by the constructor and "prepare" to print
*out_iter = *in_iter; 

// read next value
out_iter++;

// print value
in_iter++;

Это работает, как ожидалось, потому что оно печатает старое значение перед тем, как считывает новое.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...