1

Here's all the code

#include <iostream>
#include <string>
#include <windows.h>
#include <stdlib.h>
using namespace std;

void Pdelay(string str)
{
    for (char c : str)
    {
        std::cout << "" << c << "";
        Sleep(100);
    }
    std::cout << '\n';
}


int main()
{
    int exit = 1;
    while (exit == 1)
    {

        cout<< "Type something\n:";
        string str;
        str.clear();
        getline(cin,str);
        Pdelay(str);

        cout << "\n\n[1]Type something again"<< endl;
        cout << "[2]Exit\n:";

        cin >> exit;
    }
    return 0;
}

Whenever I run it, it works properly the first time round, when it loops back it skips the getline and continues with the two cout statements.

Mr_Pouet
  • 3,322
  • 7
  • 32
  • 45
S muller
  • 31
  • 3
  • how is this relevant? – xaxxon Jan 08 '16 at 01:55
  • Side comment: `int exit = 1;` use a different name, as it may clash with [`std::exit`](http://en.cppreference.com/w/cpp/utility/program/exit), especially after `using namespace std;` (which you should also try to avoid). – vsoftco Jan 08 '16 at 02:00
  • 1
    There is little point in calling `clear()` on an already empty string. – molbdnilo Jan 08 '16 at 02:14

1 Answers1

4

Immediately after you use cin, the newline remains in the buffer and is being "eaten" by the subsequent getline. You need to clear the buffer of that additional newline:

// immediately after cin (need to #include <limits>)
std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');

That's why it's not a very good idea to combine std::cin and std::getline. BTW, you can write your code in fully standard compliant C++11, with no additional non-library headers:

#include <chrono>
#include <iostream>
#include <limits>
#include <string>
#include <thread>

void Pdelay(std::string str)
{
    for (char c : str)
    {
        std::cout << "" << c << "" << std::flush;
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
    std::cout << '\n';
}

int main()
{
    int ext = 1;
    while (ext == 1)
    {
        std::cout << "Type something\n:";
        std::string str;
        str.clear();

        std::getline(std::cin, str);
        Pdelay(str);

        std::cout << "\n\n[1]Type something again" << std::endl;
        std::cout << "[2]Exit\n:";

        std::cin >> ext;
        if(!std::cin) // extraction failed
        {
            std::cin.clear(); // clear the stream
            ext = 1;
        }
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
    }
}

I just realized that this question has been asked (in a slightly modified form) before, and the answers are great:

Why does std::getline() skip input after a formatted extraction?

Community
  • 1
  • 1
vsoftco
  • 52,188
  • 7
  • 109
  • 221
  • this works for the most part, but now when I try give input, I have to press enter first. *edit: I hadn't reloaded the page and didn't see your edit. – S muller Jan 08 '16 at 02:15
  • 1
    @Smuller You always have to press ENTER for input in standard C++, unless you use a specialized library like [ncurses](https://www.gnu.org/software/ncurses/). – vsoftco Jan 08 '16 at 02:18
  • What i mean is I have to press enter _before_ i start giving input else it just does nothing or prints blank. – S muller Jan 08 '16 at 02:19
  • Not sure what is happening in your case. Works on my side. Where and when exactly do you need to press an additional enter? – vsoftco Jan 08 '16 at 02:25
  • `std::cin >> ext; std::cin.ignore(...::max(),'\n'); std::cin.clear();` is bodgy - if the extraction fails you'll need to call `clear` *before* you can `ignore`. Of course, the whole program isn't doing input robustly, but you might as well put these functions you're actively recommending in an order that "works". Bit strange to `clear()` unconditionally anyway. – Tony Delroy Jan 08 '16 at 02:25
  • P.S. I used your edited version and it states that "std::this_thread is not declared", I'm new to c++ and I'm not familiar with this statement and what it does. – S muller Jan 08 '16 at 02:26
  • @Smuller: try adding `-std=c++11` to your compilation line (e.g. `clang|gcc -std=c++11 myprogram.cpp ...`). If you're using an old Visual Studio version, upgrade. – Tony Delroy Jan 08 '16 at 02:27
  • @vsoftco I have to press enter at the very beginning when it asks for input the first time. – S muller Jan 08 '16 at 02:31
  • 1
    @Smuller I think it may be an IDE issue. Try running from a command prompt. It works just fine for me, it asks for input at the beginning, I enter the input, press ENTER, then the program continues. About `-std=c++11`, search for "compiler flags/options" in Codeblocks, there should be an option (I'm not familiar with Codeblocks though, but you can easily find more info via a search engine). – vsoftco Jan 08 '16 at 02:33
  • 1
    @Smuller see [this answer](http://stackoverflow.com/questions/18174988/how-can-i-add-c11-support-to-codeblocks-compiler) – Tony Delroy Jan 08 '16 at 02:38
  • @TonyD I've done all this and it still doesn't seem to work :/ – S muller Jan 08 '16 at 02:47
  • @Smuller You probably have an old compiler then. Try to comment that line and use your own sleep function. – vsoftco Jan 08 '16 at 02:56
  • @Smuller: ...or just install Linux, or Visual Studio if you want to wimp out of that ;-). If you're serious about learning C++, you should get a >= C++11-capable compiler, one way or another - there are new, simpler ways to do very powerful things, and much of the code you come across online these days will assume C++11. – Tony Delroy Jan 08 '16 at 03:15