Книга Bjarne Stroustrup - цикл Vector и For - не будет работать

У меня возникают трудности с конкретным фрагментом кода, который я изучаю из "Принципов программирования и практики с использованием С++".

Я не могу получить вывод из цикла, ссылающегося на вектор. Я использую std_lib_facilities и stdafx, потому что книга и MVS сказали мне это.

#include "stdafx.h"
#include "../../std_lib_facilities.h"


int main()
{
    vector<string>words;
    for(string temp; cin>>temp; )
        words.push_back(temp);
    cout << "Number of words: " << words.size() << '\n';
}

Это ничего не даст. Я получу приглашение, введите несколько слов, затем введите, затем ничего.

Пробовал некоторые варианты, которые я получил здесь и с других сайтов, например:

//here i tried the libraries the guy used in his code
#include <iostream>
#include <string>
#include <vector>

using namespace std;

int main()
{
    cout << "Please enter a series of words followed by End-of-File: ";
    vector<string> words;
    string word;
    string disliked = "Broccoli";

    while (cin >> word)
        words.push_back(word);

    cout << "\nNumber of words: " << words.size() << endl;

      // cycle through all strings in vector
    for (int i = 0; i < words.size(); ++i)
    {
      if (words[i] != disliked)
          cout << words[i] << endl;
      else
          cout << "BLEEP!\n";
    }
    return 0;
}

Все еще ничего.

После некоторых попыток, устраняя, я вполне уверен, что проблема связана с связью между векторами, потому что все они работают нормально:

int main()
{
    vector<string>words = { "hi" };
    words.push_back("hello");
    cout << words[1] << "\n"; // this will print hello

    for (int i = 0; i < words.size();++i) {
         cout << words[i] << "\n"; // this will print out all elements 
                                   // inside vector words, ( hi, hello)
         }

    cout << words.size();// this will print out number 2

    for (string temp; cin >> temp;) {
         words.push_back(temp);
        }

    cout << words.size();// this won't do anything after i type in some 
                         // words; shouldn't it increase the size of the 
                         // vector?
}

Также это не будет:

int main()
{
    vector<string>words = { "hi" };
    for (string temp; cin >> temp;) {
        words.push_back(temp);
        }
    cout << words.size();
}

Чего мне не хватает, пожалуйста? Заранее благодарю вас.

Ответ 1

Введите строки и, когда закончите, нажмите Ctrl + Z (затем Enter), если в Windows или Ctrl + D, если в Linux. Когда вы это сделаете, условие cin>>temp; внутри цикла for будет оцениваться как false, и ваша программа выйдет из цикла.

Ответ 2

Во-первых, нет необходимости использовать std_lib_facilities.h. Это просто что-то, что используется в книге, чтобы избежать того, чтобы каждый пример в книге регулярно включал набор стандартных заголовков или исправлял нестандартное поведение между компиляторами. Это также заголовок, который делает using namespace std - вы найдете множество примеров (как в SO, так и в более широком Интернете), объясняющих, почему в файле заголовка очень плохое использование using namespace std.

Во-вторых, нет необходимости использовать stdafx.h. Это то, что генерируется Microsoft IDE, и обеспечивает средство ускорения компиляции в больших проектах из-за того, как это заставляет компилятор работать с предварительно скомпилированными заголовками. Если вы только ожидаете использовать компиляторы Microsoft, тогда не стесняйтесь заполнять свои ботинки и использовать их. Однако он не является стандартным С++, может (в зависимости от IDE и параметров проекта) включать заголовки, специфичные для Windows, которые не будут работать с компиляторами, отличными от Microsoft, и на форумах, вероятно, будут препятствовать людям, которые используют другие компиляторы, помочь вам, поскольку они будут иметь что ваш код использует Microsoft-специфические расширения, что будет означать, что они, вероятно, не помогут вам.

Первый образец кода можно переписать в стандартном С++ (без использования заголовка выше) в качестве

 #include <vector>    // for std::vector
 #include <string>    // for std::string
 #include <iostream>   // std::cout and other I/O facilities

 int main()
 {
      std::vector<std::string> words;
      for(std::string temp; std::cin >> temp; )
           words.push_back(temp);
      std::cout << "Number of words: " << words.size() << '\n';
 }

Прежде чем вы будете взволнованы, у этой проблемы будет такая же проблема (видимо, не заканчивается). Причина в том, что на самом деле условие завершения цикла - std::cin >> temp завершает цикл только в том случае, если в потоке встречается конец файла или какая-либо другая ошибка.

Итак, если вы наберете

  The cow jumped over the moon

std::cin будет продолжать ждать ввода. Обычно USER запускает и завершает состояние файла. В окнах это требует, чтобы пользователь вводил CTRL-Z в пустую строку, за которой следует клавиша ввода.

Альтернативой было бы иметь некоторый предварительно согласованный текст, который заставляет цикл выйти, например

 #include <vector>    // for std::vector
 #include <string>    // for std::string
 #include <iostream>   // std::cout and other I/O facilities

 int main()
 {
      std::vector<std::string> words;
      for(std::string temp; std::cin >> temp && temp != "zzz"; )
           words.push_back(temp);
      std::cout << "Number of words: " << words.size() << '\n';
 }

что приведет к выходу программы, когда вход содержит слово zzz. Например

 The cow jumped over the moon  zzz

Существуют и другие методы, такие как чтение одного символа за раз и остановка, когда пользователь вводит две последовательные строки новой строки. Это требует, чтобы ваш код интерпретировал каждого персонажа и определял, что представляет собой слово. Я оставлю это как упражнение.

Обратите внимание, что в стандартном С++ нет средств для прямого чтения нажатий клавиш - описанные выше проблемы связаны с тем, как работают стандартные потоки и взаимодействуют с хост-системой.

Пользователь также может использовать программу "как есть", помещая один и тот же текст в фактический файл и (когда программа запускается) перенаправляет вход для вашей программы из этого файла. Например your_executable < filename.